Просмотр исходного кода

Add new hook: `Minz_HookType::ActionExecute` (#8599)

* Add new hook: `Minz_HookType::ActionExecute`

* Move down `ActionExecute`
Inverle 2 недель назад
Родитель
Сommit
3bb16b0a53

+ 3 - 0
docs/en/developers/03_Backend/05_Extensions.md

@@ -167,6 +167,9 @@ final class HelloWorldExtension extends Minz_Extension
 
 The following events are available:
 
+* `action_execute` (`function(Minz_Controller $controller): bool`): Called before an action is executed in `Minz_Dispatcher::launchAction()`.
+	By returning `true`, you allow the original action to proceed further; `false` stops further execution of the action.
+	This hook can be used for adding extra functionality to an existing action. See also: `Minz_Request::is()`, `Minz_Request::controllerName()`, `Minz_Request::actionName()`.
 * `api_misc` (`function(): void`): to allow extensions to have their own API endpoint
 	on `/api/misc.php/Extension%20Name/` or `/api/misc.php?ext=Extension%20Name`.
 * `before_login_btn` (`function(): string`): Allows to insert HTML before the login button. Applies to the create button on the register page as well. Example use case is inserting a captcha widget.

+ 1 - 1
lib/Minz/ActionController.php

@@ -87,7 +87,7 @@ abstract class Minz_ActionController {
 	 *
 	 * @param array<string,string> $policies An array where keys are directives and values are sources.
 	 */
-	protected function _csp(array $policies): void {
+	public function _csp(array $policies): void {
 		if (!isset($policies['default-src']) || !isset($policies['frame-ancestors'])) {
 			$action = Minz_Request::controllerName() . '#' . Minz_Request::actionName();
 			Minz_Log::warning(

+ 3 - 1
lib/Minz/Dispatcher.php

@@ -114,7 +114,9 @@ final class Minz_Dispatcher {
 				Minz_Exception::ERROR
 			);
 		}
-		call_user_func($call);
+		if (Minz_ExtensionManager::callHook(Minz_HookType::ActionExecute, $this->controller) !== false) {
+			call_user_func($call);
+		}
 	}
 
 	/**

+ 2 - 2
lib/Minz/ExtensionManager.php

@@ -332,7 +332,7 @@ final class Minz_ExtensionManager {
 	 * hook will receive the initial argument and return a result which will be
 	 * passed as an argument to the next extension hook and so on.
 	 *
-	 * If a hook return a null value, the method is stopped and return null.
+	 * If a hook return a null or false value, the method is stopped and that value is returned.
 	 *
 	 * @param Minz_HookType $hook_type is the hook type to call.
 	 * @param mixed $arg is the argument to pass to the first extension hook.
@@ -344,7 +344,7 @@ final class Minz_ExtensionManager {
 		foreach (self::retrieveHookList($hook_type) as $hook) {
 			$result = call_user_func($hook->getFunction(), $arg);
 
-			if ($result === null) {
+			if ($result === null || $result === false) {
 				break;
 			}
 

+ 3 - 0
lib/Minz/HookType.php

@@ -2,6 +2,7 @@
 declare(strict_types=1);
 
 enum Minz_HookType: string {
+	case ActionExecute = 'action_execute'; // function(Minz_ActionController $controller): bool
 	case ApiMisc = 'api_misc';	// function(): void
 	case BeforeLoginBtn = 'before_login_btn';	// function(): string
 	case CheckUrlBeforeAdd = 'check_url_before_add';	// function(string $url) -> string | null
@@ -53,6 +54,8 @@ enum Minz_HookType: string {
 			case self::FeedBeforeInsert:
 			case self::JsVars:
 			case self::NavReadingModes:
+			case self::ActionExecute:
+				return Minz_HookSignature::OneToOne;
 			case self::ViewModes:
 				return Minz_HookSignature::OneToOne;
 			case self::CustomFaviconBtnUrl: