Completed
Push — master ( cbc143...48298c )
by Misbahul D
06:23 queued 04:21
created

components/Helper.php (1 issue)

Labels
Severity

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
namespace mdm\admin\components;
4
5
use mdm\admin\models\Route;
6
use Yii;
7
use yii\caching\TagDependency;
8
use yii\helpers\ArrayHelper;
9
use yii\web\User;
10
11
/**
12
 * Description of Helper
13
 *
14
 * @author Misbahul D Munir <[email protected]>
15
 * @since 2.3
16
 */
17
class Helper
18
{
19
    private static $_userRoutes = [];
20
    private static $_defaultRoutes;
21
    private static $_routes;
22
23
    public static function getRegisteredRoutes()
24
    {
25
        if (self::$_routes === null) {
26
            self::$_routes = [];
27
            $manager = Configs::authManager();
28
            foreach ($manager->getPermissions() as $item) {
29
                if ($item->name[0] === '/') {
30
                    self::$_routes[$item->name] = $item->name;
31
                }
32
            }
33
        }
34
        return self::$_routes;
35
    }
36
37
    /**
38
     * Get assigned routes by default roles
39
     * @return array
40
     */
41
    protected static function getDefaultRoutes()
42
    {
43
        if (self::$_defaultRoutes === null) {
44
            $manager = Configs::authManager();
45
            $roles = $manager->defaultRoles;
46
            $cache = Configs::cache();
47
            if ($cache && ($routes = $cache->get($roles)) !== false) {
48
                self::$_defaultRoutes = $routes;
49
            } else {
50
                $permissions = self::$_defaultRoutes = [];
51
                foreach ($roles as $role) {
52
                    $permissions = array_merge($permissions, $manager->getPermissionsByRole($role));
53
                }
54
                foreach ($permissions as $item) {
55
                    if ($item->name[0] === '/') {
56
                        self::$_defaultRoutes[$item->name] = true;
57
                    }
58
                }
59
                if ($cache) {
60
                    $cache->set($roles, self::$_defaultRoutes, Configs::cacheDuration(), new TagDependency([
61
                        'tags' => Configs::CACHE_TAG,
62
                    ]));
63
                }
64
            }
65
        }
66
        return self::$_defaultRoutes;
67
    }
68
69
    /**
70
     * Get assigned routes of user.
71
     * @param integer $userId
72
     * @return array
73
     */
74
    public static function getRoutesByUser($userId)
75
    {
76
        if (!isset(self::$_userRoutes[$userId])) {
77
            $cache = Configs::cache();
78
            if ($cache && ($routes = $cache->get([__METHOD__, $userId])) !== false) {
79
                self::$_userRoutes[$userId] = $routes;
80
            } else {
81
                $routes = static::getDefaultRoutes();
82
                $manager = Configs::authManager();
83
                foreach ($manager->getPermissionsByUser($userId) as $item) {
84
                    if ($item->name[0] === '/') {
85
                        $routes[$item->name] = true;
86
                    }
87
                }
88
                self::$_userRoutes[$userId] = $routes;
89
                if ($cache) {
90
                    $cache->set([__METHOD__, $userId], $routes, Configs::cacheDuration(), new TagDependency([
91
                        'tags' => Configs::CACHE_TAG,
92
                    ]));
93
                }
94
            }
95
        }
96
        return self::$_userRoutes[$userId];
97
    }
98
99
    /**
100
     * Check access route for user.
101
     * @param string|array $route
102
     * @param integer|User $user
103
     * @return boolean
104
     */
105
    public static function checkRoute($route, $params = [], $user = null)
106
    {
107
        $config = Configs::instance();
108
        $r = static::normalizeRoute($route, $config->advanced);
0 ignored issues
show
It seems like $route defined by parameter $route on line 105 can also be of type array; however, mdm\admin\components\Helper::normalizeRoute() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
109
        if ($config->onlyRegisteredRoute && !isset(static::getRegisteredRoutes()[$r])) {
110
            return true;
111
        }
112
113
        if ($user === null) {
114
            $user = Yii::$app->getUser();
115
        }
116
        $userId = $user instanceof User ? $user->getId() : $user;
117
118
        if ($config->strict) {
119
            if ($user->can($r, $params)) {
120
                return true;
121
            }
122 View Code Duplication
            while (($pos = strrpos($r, '/')) > 0) {
123
                $r = substr($r, 0, $pos);
124
                if ($user->can($r . '/*', $params)) {
125
                    return true;
126
                }
127
            }
128
            return $user->can('/*', $params);
129
        } else {
130
            $routes = static::getRoutesByUser($userId);
131
            if (isset($routes[$r])) {
132
                return true;
133
            }
134 View Code Duplication
            while (($pos = strrpos($r, '/')) > 0) {
135
                $r = substr($r, 0, $pos);
136
                if (isset($routes[$r . '/*'])) {
137
                    return true;
138
                }
139
            }
140
            return isset($routes['/*']);
141
        }
142
    }
143
144
    /**
145
     * Normalize route
146
     * @param  string  $route    Plain route string
147
     * @param  boolean|array $advanced Array containing the advanced configuration. Defaults to false.
148
     * @return string            Normalized route string
149
     */
150
    protected static function normalizeRoute($route, $advanced = false)
151
    {
152
        if ($route === '') {
153
            $normalized = '/' . Yii::$app->controller->getRoute();
154
        } elseif (strncmp($route, '/', 1) === 0) {
155
            $normalized = $route;
156
        } elseif (strpos($route, '/') === false) {
157
            $normalized = '/' . Yii::$app->controller->getUniqueId() . '/' . $route;
158
        } elseif (($mid = Yii::$app->controller->module->getUniqueId()) !== '') {
159
            $normalized = '/' . $mid . '/' . $route;
160
        } else {
161
            $normalized = '/' . $route;
162
        }
163
        // Prefix @app-id to route.
164
        if ($advanced) {
165
            $normalized = Route::PREFIX_ADVANCED . Yii::$app->id . $normalized;
166
        }
167
        return $normalized;
168
    }
169
170
    /**
171
     * Filter menu items
172
     * @param array $items
173
     * @param integer|User $user
174
     */
175
    public static function filter($items, $user = null)
176
    {
177
        if ($user === null) {
178
            $user = Yii::$app->getUser();
179
        }
180
        return static::filterRecursive($items, $user);
181
    }
182
183
    /**
184
     * Filter menu recursive
185
     * @param array $items
186
     * @param integer|User $user
187
     * @return array
188
     */
189
    protected static function filterRecursive($items, $user)
190
    {
191
        $result = [];
192
        foreach ($items as $i => $item) {
193
            $url = ArrayHelper::getValue($item, 'url', '#');
194
            $allow = is_array($url) ? static::checkRoute($url[0], array_slice($url, 1), $user) : true;
195
196
            if (isset($item['items']) && is_array($item['items'])) {
197
                $subItems = self::filterRecursive($item['items'], $user);
198
                if (count($subItems)) {
199
                    $allow = true;
200
                }
201
                $item['items'] = $subItems;
202
            }
203
            if ($allow && !($url == '#' && empty($item['items']))) {
204
                $result[$i] = $item;
205
            }
206
        }
207
        return $result;
208
    }
209
210
    /**
211
     * Filter action column button. Use with [[yii\grid\GridView]]
212
     * ```php
213
     * 'columns' => [
214
     *     ...
215
     *     [
216
     *         'class' => 'yii\grid\ActionColumn',
217
     *         'template' => Helper::filterActionColumn(['view','update','activate'])
218
     *     ]
219
     * ],
220
     * ```
221
     * @param array|string $buttons
222
     * @param integer|User $user
223
     * @return string
224
     */
225
    public static function filterActionColumn($buttons = [], $user = null)
226
    {
227
        if (is_array($buttons)) {
228
            $result = [];
229
            foreach ($buttons as $button) {
230
                if (static::checkRoute($button, [], $user)) {
231
                    $result[] = "{{$button}}";
232
                }
233
            }
234
            return implode(' ', $result);
235
        }
236
        return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($user) {
237
            return static::checkRoute($matches[1], [], $user) ? "{{$matches[1]}}" : '';
238
        }, $buttons);
239
    }
240
241
    /**
242
     * Use to invalidate cache.
243
     */
244
    public static function invalidate()
245
    {
246
        if (Configs::cache() !== null) {
247
            TagDependency::invalidate(Configs::cache(), Configs::CACHE_TAG);
248
        }
249
    }
250
}
251