Completed
Push — master ( 67caf0...bdc372 )
by Dmitry
13:07 queued 04:28
created

framework/base/ActionFilter.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\base;
9
use yii\helpers\StringHelper;
10
11
/**
12
 * ActionFilter is the base class for action filters.
13
 *
14
 * An action filter will participate in the action execution workflow by responding to
15
 * the `beforeAction` and `afterAction` events triggered by modules and controllers.
16
 *
17
 * Check implementation of [[\yii\filters\AccessControl]], [[\yii\filters\PageCache]] and [[\yii\filters\HttpCache]] as examples on how to use it.
18
 *
19
 * For more details and usage information on ActionFilter, see the [guide article on filters](guide:structure-filters).
20
 *
21
 * @author Qiang Xue <[email protected]>
22
 * @since 2.0
23
 */
24
class ActionFilter extends Behavior
25
{
26
    /**
27
     * @var array list of action IDs that this filter should apply to. If this property is not set,
28
     * then the filter applies to all actions, unless they are listed in [[except]].
29
     * If an action ID appears in both [[only]] and [[except]], this filter will NOT apply to it.
30
     *
31
     * Note that if the filter is attached to a module, the action IDs should also include child module IDs (if any)
32
     * and controller IDs.
33
     *
34
     * Since version 2.0.9 action IDs can be specified as wildcards, e.g. `site/*`.
35
     *
36
     * @see except
37
     */
38
    public $only;
39
    /**
40
     * @var array list of action IDs that this filter should not apply to.
41
     * @see only
42
     */
43
    public $except = [];
44
45
46
    /**
47
     * {@inheritdoc}
48
     */
49 61
    public function attach($owner)
50
    {
51 61
        $this->owner = $owner;
52 61
        $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
53 61
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function detach()
59
    {
60
        if ($this->owner) {
61
            $this->owner->off(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
62
            $this->owner->off(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter']);
63
            $this->owner = null;
64
        }
65
    }
66
67
    /**
68
     * @param ActionEvent $event
69
     */
70 61
    public function beforeFilter($event)
71
    {
72 61
        if (!$this->isActive($event->action)) {
73
            return;
74
        }
75
76 61
        $event->isValid = $this->beforeAction($event->action);
77 59
        if ($event->isValid) {
78
            // call afterFilter only if beforeFilter succeeds
79
            // beforeFilter and afterFilter should be properly nested
80 59
            $this->owner->on(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter'], null, false);
81
        } else {
82 1
            $event->handled = true;
83
        }
84 59
    }
85
86
    /**
87
     * @param ActionEvent $event
88
     */
89 59
    public function afterFilter($event)
90
    {
91 59
        $event->result = $this->afterAction($event->action, $event->result);
92 59
        $this->owner->off(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter']);
93 59
    }
94
95
    /**
96
     * This method is invoked right before an action is to be executed (after all possible filters.)
97
     * You may override this method to do last-minute preparation for the action.
98
     * @param Action $action the action to be executed.
99
     * @return bool whether the action should continue to be executed.
100
     */
101
    public function beforeAction($action)
102
    {
103
        return true;
104
    }
105
106
    /**
107
     * This method is invoked right after an action is executed.
108
     * You may override this method to do some postprocessing for the action.
109
     * @param Action $action the action just executed.
110
     * @param mixed $result the action execution result
111
     * @return mixed the processed action result.
112
     */
113 58
    public function afterAction($action, $result)
0 ignored issues
show
The parameter $action is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
114
    {
115 58
        return $result;
116
    }
117
118
    /**
119
     * Returns an action ID by converting [[Action::$uniqueId]] into an ID relative to the module.
120
     * @param Action $action
121
     * @return string
122
     * @since 2.0.7
123
     */
124 75
    protected function getActionId($action)
125
    {
126 75
        if ($this->owner instanceof Module) {
127
            $mid = $this->owner->getUniqueId();
128
            $id = $action->getUniqueId();
129
            if ($mid !== '' && strpos($id, $mid) === 0) {
130
                $id = substr($id, strlen($mid) + 1);
131
            }
132
        } else {
133 75
            $id = $action->id;
134
        }
135
136 75
        return $id;
137
    }
138
139
    /**
140
     * Returns a value indicating whether the filter is active for the given action.
141
     * @param Action $action the action being filtered
142
     * @return bool whether the filter is active for the given action.
143
     */
144 73
    protected function isActive($action)
145
    {
146 73
        $id = $this->getActionId($action);
147
148 73
        if (empty($this->only)) {
149 71
            $onlyMatch = true;
150
        } else {
151 69
            $onlyMatch = false;
152 69
            foreach ($this->only as $pattern) {
153 69
                if (StringHelper::matchWildcard($pattern, $id)) {
154 69
                    $onlyMatch = true;
155 69
                    break;
156
                }
157
            }
158
        }
159
160 73
        $exceptMatch = false;
161 73
        foreach ($this->except as $pattern) {
162 67
            if (StringHelper::matchWildcard($pattern, $id)) {
163 12
                $exceptMatch = true;
164 67
                break;
165
            }
166
        }
167
168 73
        return !$exceptMatch && $onlyMatch;
169
    }
170
}
171