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\models; |
||
4 | |||
5 | use Exception; |
||
6 | use mdm\admin\components\Configs; |
||
7 | use mdm\admin\components\Helper; |
||
8 | use mdm\admin\components\RouteRule; |
||
9 | use Yii; |
||
10 | use yii\caching\TagDependency; |
||
11 | use yii\helpers\VarDumper; |
||
12 | |||
13 | /** |
||
14 | * Description of Route |
||
15 | * |
||
16 | * @author Misbahul D Munir <[email protected]> |
||
17 | * @since 1.0 |
||
18 | */ |
||
19 | class Route extends \yii\base\Object |
||
20 | { |
||
21 | const CACHE_TAG = 'mdm.admin.route'; |
||
22 | |||
23 | const PREFIX_ADVANCED = '@'; |
||
24 | const PREFIX_BASIC = '/'; |
||
25 | |||
26 | private $_routePrefix; |
||
27 | |||
28 | /** |
||
29 | * Assign or remove items |
||
30 | * @param array $routes |
||
31 | * @return array |
||
32 | */ |
||
33 | public function addNew($routes) |
||
34 | { |
||
35 | $manager = Configs::authManager(); |
||
36 | foreach ($routes as $route) { |
||
37 | try { |
||
38 | $r = explode('&', $route); |
||
39 | $item = $manager->createPermission($this->getPermissionName($route)); |
||
40 | if (count($r) > 1) { |
||
41 | $action = '/' . trim($r[0], '/'); |
||
42 | if (($itemAction = $manager->getPermission($action)) === null) { |
||
43 | $itemAction = $manager->createPermission($action); |
||
44 | $manager->add($itemAction); |
||
45 | } |
||
46 | unset($r[0]); |
||
47 | View Code Duplication | foreach ($r as $part) { |
|
48 | $part = explode('=', $part); |
||
49 | $item->data['params'][$part[0]] = isset($part[1]) ? $part[1] : ''; |
||
50 | } |
||
51 | $this->setDefaultRule(); |
||
52 | $item->ruleName = RouteRule::RULE_NAME; |
||
53 | $manager->add($item); |
||
54 | $manager->addChild($item, $itemAction); |
||
55 | } else { |
||
56 | $manager->add($item); |
||
57 | } |
||
58 | } catch (Exception $exc) { |
||
59 | Yii::error($exc->getMessage(), __METHOD__); |
||
60 | } |
||
61 | } |
||
62 | Helper::invalidate(); |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Assign or remove items |
||
67 | * @param array $routes |
||
68 | * @return array |
||
69 | */ |
||
70 | public function remove($routes) |
||
71 | { |
||
72 | $manager = Configs::authManager(); |
||
73 | foreach ($routes as $route) { |
||
74 | try { |
||
75 | $item = $manager->createPermission($this->getPermissionName($route)); |
||
76 | $manager->remove($item); |
||
77 | } catch (Exception $exc) { |
||
78 | Yii::error($exc->getMessage(), __METHOD__); |
||
79 | } |
||
80 | } |
||
81 | Helper::invalidate(); |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * Returns route prefix depending on the configuration. |
||
86 | * @return string Route prefix |
||
87 | */ |
||
88 | public function getRoutePrefix() |
||
89 | { |
||
90 | if (!$this->_routePrefix) { |
||
91 | $this->_routePrefix = Configs::instance()->advanced ? self::PREFIX_ADVANCED : self::PREFIX_BASIC; |
||
92 | } |
||
93 | return $this->_routePrefix; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Returns the correct permission name depending on the configuration. |
||
98 | * @param string $route Route |
||
99 | * @return string Permission name |
||
100 | */ |
||
101 | public function getPermissionName($route) |
||
102 | { |
||
103 | if (self::PREFIX_BASIC == $this->routePrefix) { |
||
0 ignored issues
–
show
|
|||
104 | return self::PREFIX_BASIC . trim($route, self::PREFIX_BASIC); |
||
105 | } else { |
||
106 | return self::PREFIX_ADVANCED . ltrim(trim($route, self::PREFIX_BASIC), self::PREFIX_ADVANCED); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Get available and assigned routes |
||
112 | * @return array |
||
113 | */ |
||
114 | public function getRoutes() |
||
115 | { |
||
116 | $manager = Configs::authManager(); |
||
117 | // Get advanced configuration |
||
118 | $advanced = Configs::instance()->advanced; |
||
119 | if ($advanced) { |
||
120 | // Use advanced route scheme. |
||
121 | // Set advanced route prefix. |
||
122 | $this->_routePrefix = self::PREFIX_ADVANCED; |
||
123 | // Create empty routes array. |
||
124 | $routes = []; |
||
125 | // Save original app. |
||
126 | $yiiApp = Yii::$app; |
||
127 | // Step through each configured application |
||
128 | foreach ($advanced as $id => $configPaths) { |
||
129 | // Force correct id string. |
||
130 | $id = $this->routePrefix . ltrim(trim($id), $this->routePrefix); |
||
0 ignored issues
–
show
The property
routePrefix does not seem to exist. Did you mean _routePrefix ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.
Loading history...
|
|||
131 | // Create empty config array. |
||
132 | $config = []; |
||
133 | // Assemble configuration for current app. |
||
134 | foreach ($configPaths as $configPath) { |
||
135 | // Merge every new configuration with the old config array. |
||
136 | $config = yii\helpers\ArrayHelper::merge($config, require (Yii::getAlias($configPath))); |
||
137 | } |
||
138 | // Create new app using the config array. |
||
139 | unset($config['bootstrap']); |
||
140 | $app = new yii\web\Application($config); |
||
141 | // Get all the routes of the newly created app. |
||
142 | $r = $this->getAppRoutes($app); |
||
143 | // Dump new app |
||
144 | unset($app); |
||
145 | // Prepend the app id to all routes. |
||
146 | foreach ($r as $route) { |
||
147 | $routes[$id . $route] = $id . $route; |
||
148 | } |
||
149 | } |
||
150 | // Switch back to original app. |
||
151 | Yii::$app = $yiiApp; |
||
152 | unset($yiiApp); |
||
153 | } else { |
||
154 | // Use basic route scheme. |
||
155 | // Set basic route prefix |
||
156 | $this->_routePrefix = self::PREFIX_BASIC; |
||
157 | // Get basic app routes. |
||
158 | $routes = $this->getAppRoutes(); |
||
159 | } |
||
160 | $exists = []; |
||
161 | foreach (array_keys($manager->getPermissions()) as $name) { |
||
162 | if ($name[0] !== $this->routePrefix) { |
||
0 ignored issues
–
show
The property
routePrefix does not seem to exist. Did you mean _routePrefix ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.
Loading history...
|
|||
163 | continue; |
||
164 | } |
||
165 | $exists[] = $name; |
||
166 | unset($routes[$name]); |
||
167 | } |
||
168 | return [ |
||
169 | 'available' => array_keys($routes), |
||
170 | 'assigned' => $exists, |
||
171 | ]; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Get list of application routes |
||
176 | * @return array |
||
177 | */ |
||
178 | public function getAppRoutes($module = null) |
||
179 | { |
||
180 | if ($module === null) { |
||
181 | $module = Yii::$app; |
||
182 | } elseif (is_string($module)) { |
||
183 | $module = Yii::$app->getModule($module); |
||
184 | } |
||
185 | $key = [__METHOD__, Yii::$app->id, $module->getUniqueId()]; |
||
186 | $cache = Configs::instance()->cache; |
||
187 | if ($cache === null || ($result = $cache->get($key)) === false) { |
||
188 | $result = []; |
||
189 | $this->getRouteRecursive($module, $result); |
||
190 | if ($cache !== null) { |
||
191 | $cache->set($key, $result, Configs::instance()->cacheDuration, new TagDependency([ |
||
192 | 'tags' => self::CACHE_TAG, |
||
193 | ])); |
||
194 | } |
||
195 | } |
||
196 | |||
197 | return $result; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Get route(s) recursive |
||
202 | * @param \yii\base\Module $module |
||
203 | * @param array $result |
||
204 | */ |
||
205 | protected function getRouteRecursive($module, &$result) |
||
206 | { |
||
207 | $token = "Get Route of '" . get_class($module) . "' with id '" . $module->uniqueId . "'"; |
||
208 | Yii::beginProfile($token, __METHOD__); |
||
209 | try { |
||
210 | foreach ($module->getModules() as $id => $child) { |
||
211 | if (($child = $module->getModule($id)) !== null) { |
||
212 | $this->getRouteRecursive($child, $result); |
||
213 | } |
||
214 | } |
||
215 | |||
216 | foreach ($module->controllerMap as $id => $type) { |
||
217 | $this->getControllerActions($type, $id, $module, $result); |
||
218 | } |
||
219 | |||
220 | $namespace = trim($module->controllerNamespace, '\\') . '\\'; |
||
221 | $this->getControllerFiles($module, $namespace, '', $result); |
||
222 | $all = '/' . ltrim($module->uniqueId . '/*', '/'); |
||
223 | $result[$all] = $all; |
||
224 | } catch (\Exception $exc) { |
||
225 | Yii::error($exc->getMessage(), __METHOD__); |
||
226 | } |
||
227 | Yii::endProfile($token, __METHOD__); |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Get list controller under module |
||
232 | * @param \yii\base\Module $module |
||
233 | * @param string $namespace |
||
234 | * @param string $prefix |
||
235 | * @param mixed $result |
||
236 | * @return mixed |
||
237 | */ |
||
238 | protected function getControllerFiles($module, $namespace, $prefix, &$result) |
||
239 | { |
||
240 | $path = Yii::getAlias('@' . str_replace('\\', '/', $namespace), false); |
||
241 | $token = "Get controllers from '$path'"; |
||
242 | Yii::beginProfile($token, __METHOD__); |
||
243 | try { |
||
244 | if (!is_dir($path)) { |
||
245 | return; |
||
246 | } |
||
247 | foreach (scandir($path) as $file) { |
||
248 | if ($file == '.' || $file == '..') { |
||
249 | continue; |
||
250 | } |
||
251 | if (is_dir($path . '/' . $file) && preg_match('%^[a-z0-9_/]+$%i', $file . '/')) { |
||
252 | $this->getControllerFiles($module, $namespace . $file . '\\', $prefix . $file . '/', $result); |
||
253 | } elseif (strcmp(substr($file, -14), 'Controller.php') === 0) { |
||
254 | $baseName = substr(basename($file), 0, -14); |
||
255 | $name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $baseName)); |
||
256 | $id = ltrim(str_replace(' ', '-', $name), '-'); |
||
257 | $className = $namespace . $baseName . 'Controller'; |
||
258 | if (strpos($className, '-') === false && class_exists($className) && is_subclass_of($className, 'yii\base\Controller')) { |
||
259 | $this->getControllerActions($className, $prefix . $id, $module, $result); |
||
260 | } |
||
261 | } |
||
262 | } |
||
263 | } catch (\Exception $exc) { |
||
264 | Yii::error($exc->getMessage(), __METHOD__); |
||
265 | } |
||
266 | Yii::endProfile($token, __METHOD__); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Get list action of controller |
||
271 | * @param mixed $type |
||
272 | * @param string $id |
||
273 | * @param \yii\base\Module $module |
||
274 | * @param string $result |
||
275 | */ |
||
276 | protected function getControllerActions($type, $id, $module, &$result) |
||
277 | { |
||
278 | $token = "Create controller with cofig=" . VarDumper::dumpAsString($type) . " and id='$id'"; |
||
279 | Yii::beginProfile($token, __METHOD__); |
||
280 | try { |
||
281 | /* @var $controller \yii\base\Controller */ |
||
282 | $controller = Yii::createObject($type, [$id, $module]); |
||
283 | $this->getActionRoutes($controller, $result); |
||
284 | $all = "/{$controller->uniqueId}/*"; |
||
285 | $result[$all] = $all; |
||
286 | } catch (\Exception $exc) { |
||
287 | Yii::error($exc->getMessage(), __METHOD__); |
||
288 | } |
||
289 | Yii::endProfile($token, __METHOD__); |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * Get route of action |
||
294 | * @param \yii\base\Controller $controller |
||
295 | * @param array $result all controller action. |
||
296 | */ |
||
297 | protected function getActionRoutes($controller, &$result) |
||
298 | { |
||
299 | $token = "Get actions of controller '" . $controller->uniqueId . "'"; |
||
300 | Yii::beginProfile($token, __METHOD__); |
||
301 | try { |
||
302 | $prefix = '/' . $controller->uniqueId . '/'; |
||
303 | foreach ($controller->actions() as $id => $value) { |
||
304 | $result[$prefix . $id] = $prefix . $id; |
||
305 | } |
||
306 | $class = new \ReflectionClass($controller); |
||
307 | foreach ($class->getMethods() as $method) { |
||
308 | $name = $method->getName(); |
||
309 | if ($method->isPublic() && !$method->isStatic() && strpos($name, 'action') === 0 && $name !== 'actions') { |
||
310 | $name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', substr($name, 6))); |
||
311 | $id = $prefix . ltrim(str_replace(' ', '-', $name), '-'); |
||
312 | $result[$id] = $id; |
||
313 | } |
||
314 | } |
||
315 | } catch (\Exception $exc) { |
||
316 | Yii::error($exc->getMessage(), __METHOD__); |
||
317 | } |
||
318 | Yii::endProfile($token, __METHOD__); |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * Ivalidate cache |
||
323 | */ |
||
324 | public static function invalidate() |
||
325 | { |
||
326 | if (Configs::cache() !== null) { |
||
327 | TagDependency::invalidate(Configs::cache(), self::CACHE_TAG); |
||
328 | } |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Set default rule of parameterize route. |
||
333 | */ |
||
334 | protected function setDefaultRule() |
||
335 | { |
||
336 | if (Configs::authManager()->getRule(RouteRule::RULE_NAME) === null) { |
||
337 | Configs::authManager()->add(new RouteRule()); |
||
338 | } |
||
339 | } |
||
340 | } |
||
341 |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.