| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- <?php
- /**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- namespace yii\base;
- use yii\helpers\StringHelper;
- /**
- * ActionFilter is the base class for action filters.
- *
- * An action filter will participate in the action execution workflow by responding to
- * the `beforeAction` and `afterAction` events triggered by modules and controllers.
- *
- * Check implementation of [[\yii\filters\AccessControl]], [[\yii\filters\PageCache]] and [[\yii\filters\HttpCache]] as examples on how to use it.
- *
- * For more details and usage information on ActionFilter, see the [guide article on filters](guide:structure-filters).
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @since 2.0
- */
- class ActionFilter extends Behavior
- {
- /**
- * @var array list of action IDs that this filter should apply to. If this property is not set,
- * then the filter applies to all actions, unless they are listed in [[except]].
- * If an action ID appears in both [[only]] and [[except]], this filter will NOT apply to it.
- *
- * Note that if the filter is attached to a module, the action IDs should also include child module IDs (if any)
- * and controller IDs.
- *
- * Since version 2.0.9 action IDs can be specified as wildcards, e.g. `site/*`.
- *
- * @see except
- */
- public $only;
- /**
- * @var array list of action IDs that this filter should not apply to.
- * @see only
- */
- public $except = [];
- /**
- * {@inheritdoc}
- */
- public function attach($owner)
- {
- $this->owner = $owner;
- $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
- }
- /**
- * {@inheritdoc}
- */
- public function detach()
- {
- if ($this->owner) {
- $this->owner->off(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
- $this->owner->off(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter']);
- $this->owner = null;
- }
- }
- /**
- * @param ActionEvent $event
- */
- public function beforeFilter($event)
- {
- if (!$this->isActive($event->action)) {
- return;
- }
- $event->isValid = $this->beforeAction($event->action);
- if ($event->isValid) {
- // call afterFilter only if beforeFilter succeeds
- // beforeFilter and afterFilter should be properly nested
- $this->owner->on(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter'], null, false);
- } else {
- $event->handled = true;
- }
- }
- /**
- * @param ActionEvent $event
- */
- public function afterFilter($event)
- {
- $event->result = $this->afterAction($event->action, $event->result);
- $this->owner->off(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter']);
- }
- /**
- * This method is invoked right before an action is to be executed (after all possible filters.)
- * You may override this method to do last-minute preparation for the action.
- * @param Action $action the action to be executed.
- * @return bool whether the action should continue to be executed.
- */
- public function beforeAction($action)
- {
- return true;
- }
- /**
- * This method is invoked right after an action is executed.
- * You may override this method to do some postprocessing for the action.
- * @param Action $action the action just executed.
- * @param mixed $result the action execution result
- * @return mixed the processed action result.
- */
- public function afterAction($action, $result)
- {
- return $result;
- }
- /**
- * Returns an action ID by converting [[Action::$uniqueId]] into an ID relative to the module.
- * @param Action $action
- * @return string
- * @since 2.0.7
- */
- protected function getActionId($action)
- {
- if ($this->owner instanceof Module) {
- $mid = $this->owner->getUniqueId();
- $id = $action->getUniqueId();
- if ($mid !== '' && strpos($id, $mid) === 0) {
- $id = substr($id, strlen($mid) + 1);
- }
- } else {
- $id = $action->id;
- }
- return $id;
- }
- /**
- * Returns a value indicating whether the filter is active for the given action.
- * @param Action $action the action being filtered
- * @return bool whether the filter is active for the given action.
- */
- protected function isActive($action)
- {
- $id = $this->getActionId($action);
- if (empty($this->only)) {
- $onlyMatch = true;
- } else {
- $onlyMatch = false;
- foreach ($this->only as $pattern) {
- if (StringHelper::matchWildcard($pattern, $id)) {
- $onlyMatch = true;
- break;
- }
- }
- }
- $exceptMatch = false;
- foreach ($this->except as $pattern) {
- if (StringHelper::matchWildcard($pattern, $id)) {
- $exceptMatch = true;
- break;
- }
- }
- return !$exceptMatch && $onlyMatch;
- }
- }
|