1 | <?php |
||||||||||
2 | |||||||||||
3 | namespace Inji; |
||||||||||
4 | /** |
||||||||||
5 | * Module |
||||||||||
6 | * |
||||||||||
7 | * @author Alexey Krupskiy <[email protected]> |
||||||||||
8 | * @link http://inji.ru/ |
||||||||||
9 | * @copyright 2015 Alexey Krupskiy |
||||||||||
10 | * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE |
||||||||||
11 | */ |
||||||||||
12 | class Module { |
||||||||||
13 | |||||||||||
14 | /** |
||||||||||
15 | * Storage of cur requested module |
||||||||||
16 | * |
||||||||||
17 | * @var Module |
||||||||||
18 | */ |
||||||||||
19 | public static $cur = null; |
||||||||||
20 | |||||||||||
21 | /** |
||||||||||
22 | * Module name |
||||||||||
23 | * |
||||||||||
24 | * @var string |
||||||||||
25 | */ |
||||||||||
26 | public $name = ''; |
||||||||||
27 | |||||||||||
28 | /** |
||||||||||
29 | * Module config |
||||||||||
30 | * |
||||||||||
31 | * @var array |
||||||||||
32 | */ |
||||||||||
33 | public $config = []; |
||||||||||
34 | |||||||||||
35 | /** |
||||||||||
36 | * Module info |
||||||||||
37 | * |
||||||||||
38 | * @var array |
||||||||||
39 | */ |
||||||||||
40 | public $info = []; |
||||||||||
41 | |||||||||||
42 | /** |
||||||||||
43 | * Requested module params |
||||||||||
44 | * |
||||||||||
45 | * @var array |
||||||||||
46 | */ |
||||||||||
47 | public $params = []; |
||||||||||
48 | |||||||||||
49 | /** |
||||||||||
50 | * Module directory path |
||||||||||
51 | * |
||||||||||
52 | * @var string |
||||||||||
53 | */ |
||||||||||
54 | public $path = ''; |
||||||||||
55 | |||||||||||
56 | /** |
||||||||||
57 | * Module app |
||||||||||
58 | * |
||||||||||
59 | * @var App |
||||||||||
60 | */ |
||||||||||
61 | public $app = null; |
||||||||||
62 | |||||||||||
63 | /** |
||||||||||
64 | * Parse cur module |
||||||||||
65 | * |
||||||||||
66 | * @param App $app |
||||||||||
67 | */ |
||||||||||
68 | 1 | public function __construct($app) { |
|||||||||
69 | 1 | $this->app = $app; |
|||||||||
70 | 1 | if (!$this->name) { |
|||||||||
71 | $this->name = get_class($this); |
||||||||||
72 | } |
||||||||||
73 | 1 | $this->path = Router::getLoadedClassPath(get_class($this)); |
|||||||||
74 | 1 | $this->info = $this->getInfo(); |
|||||||||
75 | 1 | $this->config = Config::module($this->name, !empty($this->info['systemConfig'])); |
|||||||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||||||
76 | 1 | $that = $this; |
|||||||||
77 | 1 | \Inji::$inst->listen('Config-change-module-' . $this->app->name . '-' . $this->name, $this->app->name . '-' . $this->name . 'config', function ($event) use ($that) { |
|||||||||
0 ignored issues
–
show
function(...) { /* ... */ } of type callable is incompatible with the type string|array|closure expected by parameter $callback of Inji::listen() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||||
78 | $that->config = $event['eventObject']; |
||||||||||
79 | return $event['eventObject']; |
||||||||||
80 | 1 | }); |
|||||||||
81 | 1 | } |
|||||||||
82 | |||||||||||
83 | /** |
||||||||||
84 | * Get all posible directorys for module files |
||||||||||
85 | * |
||||||||||
86 | * @param string $moduleName |
||||||||||
87 | * @return array |
||||||||||
88 | */ |
||||||||||
89 | 1 | public static function getModulePaths($moduleName) { |
|||||||||
90 | 1 | $moduleName = ucfirst($moduleName); |
|||||||||
91 | 1 | $paths = []; |
|||||||||
92 | 1 | if (App::$cur !== App::$primary) { |
|||||||||
93 | $paths['primaryAppPath'] = App::$primary->path . '/modules/' . $moduleName; |
||||||||||
94 | } |
||||||||||
95 | 1 | $paths['curAppPath'] = App::$cur->path . '/modules/' . $moduleName; |
|||||||||
96 | 1 | $paths['systemPath'] = INJI_SYSTEM_DIR . '/modules/' . $moduleName; |
|||||||||
97 | 1 | return $paths; |
|||||||||
98 | } |
||||||||||
99 | |||||||||||
100 | /** |
||||||||||
101 | * Return directory where places module file |
||||||||||
102 | * |
||||||||||
103 | * @param string $moduleName |
||||||||||
104 | * @return string |
||||||||||
105 | */ |
||||||||||
106 | public static function getModulePath($moduleName) { |
||||||||||
107 | $moduleName = ucfirst($moduleName); |
||||||||||
108 | $paths = Module::getModulePaths($moduleName); |
||||||||||
109 | foreach ($paths as $path) { |
||||||||||
110 | if (file_exists($path . '/' . $moduleName . '.php')) { |
||||||||||
111 | return $path; |
||||||||||
112 | } |
||||||||||
113 | } |
||||||||||
114 | } |
||||||||||
115 | |||||||||||
116 | /** |
||||||||||
117 | * Check module for installed |
||||||||||
118 | * |
||||||||||
119 | * @param string $moduleName |
||||||||||
120 | * @param \Inji\App $app |
||||||||||
121 | * @return boolean |
||||||||||
122 | */ |
||||||||||
123 | public static function installed($moduleName, $app) { |
||||||||||
124 | if (in_array($moduleName, self::getInstalled($app))) { |
||||||||||
125 | return true; |
||||||||||
126 | } |
||||||||||
127 | return false; |
||||||||||
128 | } |
||||||||||
129 | |||||||||||
130 | /** |
||||||||||
131 | * Get installed modules for app |
||||||||||
132 | * |
||||||||||
133 | * @param \Inji\App $app |
||||||||||
134 | * @param App $primary |
||||||||||
135 | * @return array |
||||||||||
136 | */ |
||||||||||
137 | 1 | public static function getInstalled($app, $primary = false) { |
|||||||||
138 | 1 | if (!$primary) { |
|||||||||
139 | 1 | $primary = \Inji\App::$primary; |
|||||||||
140 | } |
||||||||||
141 | 1 | $system = !empty(\Inji::$config['modules']) ? \Inji::$config['modules'] : []; |
|||||||||
142 | 1 | $primary = !empty($primary->config['modules']) ? $primary->config['modules'] : []; |
|||||||||
143 | 1 | $actual = $app !== $primary && !empty($app->config['modules']) ? $app->config['modules'] : []; |
|||||||||
144 | 1 | $modules = array_unique(array_merge($system, $primary, $actual)); |
|||||||||
145 | 1 | return $modules; |
|||||||||
146 | } |
||||||||||
147 | |||||||||||
148 | /** |
||||||||||
149 | * Find module controllers |
||||||||||
150 | * |
||||||||||
151 | * @param string $moduleName |
||||||||||
152 | * @return array |
||||||||||
153 | */ |
||||||||||
154 | public static function getModuleControllers($moduleName) { |
||||||||||
155 | $controllers = []; |
||||||||||
156 | $moduleDirs = static::getModulePaths($moduleName); |
||||||||||
157 | foreach ($moduleDirs as $moduleDir) { |
||||||||||
158 | if (is_dir($moduleDir)) { |
||||||||||
159 | foreach (scandir($moduleDir) as $dir) { |
||||||||||
160 | if (preg_match('!Controllers$!', $dir) && is_dir($moduleDir . '/' . $dir)) { |
||||||||||
161 | $path = $moduleDir . '/' . $dir; |
||||||||||
162 | foreach (scandir($path) as $file) { |
||||||||||
163 | if (preg_match('!Controller\.php$!', $file) && is_file($path . '/' . $file)) { |
||||||||||
164 | $controllerName = preg_replace('!Controller\.php$!', '', $file); |
||||||||||
165 | $controllers[preg_replace('!Controllers$!', '', $dir)][$controllerName] = $path . '/' . $file; |
||||||||||
166 | } |
||||||||||
167 | } |
||||||||||
168 | } |
||||||||||
169 | } |
||||||||||
170 | } |
||||||||||
171 | } |
||||||||||
172 | return $controllers; |
||||||||||
173 | } |
||||||||||
174 | |||||||||||
175 | /** |
||||||||||
176 | * Find module by request |
||||||||||
177 | * |
||||||||||
178 | * @param \Inji\App $app |
||||||||||
179 | * @param array|null $params |
||||||||||
180 | * @return \Inji\Module |
||||||||||
181 | */ |
||||||||||
182 | public static function resolveModule($app, $params = null) { |
||||||||||
183 | $search = is_array($params) ? $params : $app->params; |
||||||||||
184 | if (!empty($search[0]) && $app->{$search[0]}) { |
||||||||||
185 | $module = $app->{$search[0]}; |
||||||||||
186 | $module->params = array_slice($search, 1); |
||||||||||
187 | return $module; |
||||||||||
188 | } |
||||||||||
189 | if (!empty($app->config['defaultModule']) && $app->{$app->config['defaultModule']}) { |
||||||||||
190 | $module = $app->{$app->config['defaultModule']}; |
||||||||||
191 | $module->params = $app->params; |
||||||||||
192 | return $module; |
||||||||||
193 | } |
||||||||||
194 | |||||||||||
195 | if ($app->Main) { |
||||||||||
0 ignored issues
–
show
The property
Main does not exist on Inji\App . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||||||
196 | $module = $app->Main; |
||||||||||
197 | $module->params = $app->params; |
||||||||||
198 | return $module; |
||||||||||
199 | } |
||||||||||
200 | return null; |
||||||||||
201 | } |
||||||||||
202 | |||||||||||
203 | /** |
||||||||||
204 | * Get posible path for controller |
||||||||||
205 | * |
||||||||||
206 | * @return array |
||||||||||
207 | */ |
||||||||||
208 | public function getPossibleControllers() { |
||||||||||
209 | $possibleClasses = []; |
||||||||||
210 | if (!empty($this->params[0]) && ucfirst($this->params[0]) != $this->name) { |
||||||||||
211 | $possibleClasses['curApp_slice'] = $this->app->namespace . '\\' . $this->name . '\\' . ucfirst($this->params[0]) . ucfirst($this->app->type) . 'Controller'; |
||||||||||
212 | $possibleClasses['system_slice'] = 'Inji\\' . $this->name . '\\' . ucfirst($this->params[0]) . ucfirst($this->app->type) . 'Controller'; |
||||||||||
213 | $possibleClasses['universal_curApp_slice'] = $this->app->namespace . '\\' . $this->name . '\\' . ucfirst($this->params[0]) . 'Controller'; |
||||||||||
214 | $possibleClasses['universal_system_slice'] = 'Inji\\' . $this->name . '\\' . ucfirst($this->params[0]) . 'Controller'; |
||||||||||
215 | } |
||||||||||
216 | $possibleClasses['curApp'] = $this->app->namespace . '\\' . $this->name . '\\' . $this->name . ucfirst($this->app->type) . 'Controller'; |
||||||||||
217 | $possibleClasses['system'] = 'Inji\\' . $this->name . '\\' . $this->name . ucfirst($this->app->type) . 'Controller'; |
||||||||||
218 | |||||||||||
219 | $possibleClasses['universal_curApp'] = $this->app->namespace . '\\' . $this->name . '\\' . $this->name . 'Controller'; |
||||||||||
220 | $possibleClasses['universal_system'] = 'Inji\\' . $this->name . '\\' . $this->name . 'Controller'; |
||||||||||
221 | return $possibleClasses; |
||||||||||
222 | } |
||||||||||
223 | |||||||||||
224 | /** |
||||||||||
225 | * Find controller by request |
||||||||||
226 | * |
||||||||||
227 | * @return \Inji\Controller |
||||||||||
228 | */ |
||||||||||
229 | public function findController() { |
||||||||||
230 | $possibleClasses = $this->getPossibleControllers(); |
||||||||||
231 | foreach ($possibleClasses as $possibleClassType => $possibleClass) { |
||||||||||
232 | if (class_exists($possibleClass)) { |
||||||||||
233 | if (strpos($possibleClassType, 'slice')) { |
||||||||||
234 | $controllerName = ucfirst($this->params[0]); |
||||||||||
235 | $params = array_slice($this->params, 1); |
||||||||||
236 | } else { |
||||||||||
237 | $controllerName = $this->name; |
||||||||||
238 | $params = $this->params; |
||||||||||
239 | } |
||||||||||
240 | $controller = new $possibleClass(); |
||||||||||
241 | $controller->params = $params; |
||||||||||
242 | $controller->module = $this; |
||||||||||
243 | $controller->path = Router::getLoadedClassPath($possibleClass); |
||||||||||
244 | $controller->name = $controllerName; |
||||||||||
245 | return $controller; |
||||||||||
246 | } |
||||||||||
247 | } |
||||||||||
248 | } |
||||||||||
249 | |||||||||||
250 | /** |
||||||||||
251 | * Return module info |
||||||||||
252 | * |
||||||||||
253 | * @param string $moduleName |
||||||||||
254 | * @return array |
||||||||||
255 | */ |
||||||||||
256 | 1 | public static function getInfo($moduleName = '') { |
|||||||||
257 | 1 | if (!$moduleName && get_called_class()) { |
|||||||||
258 | 1 | $moduleName = get_called_class(); |
|||||||||
259 | } elseif (!$moduleName) { |
||||||||||
260 | return []; |
||||||||||
261 | } |
||||||||||
262 | 1 | $paths = Module::getModulePaths($moduleName); |
|||||||||
263 | 1 | foreach ($paths as $path) { |
|||||||||
264 | 1 | if (file_exists($path . '/info.php')) { |
|||||||||
265 | 1 | return include $path . '/info.php'; |
|||||||||
266 | } |
||||||||||
267 | } |
||||||||||
268 | 1 | return []; |
|||||||||
269 | } |
||||||||||
270 | |||||||||||
271 | /** |
||||||||||
272 | * Return snippets by name |
||||||||||
273 | * |
||||||||||
274 | * @param string $snippetsPath |
||||||||||
275 | * @param boolean $extensions |
||||||||||
276 | * @param string $dir |
||||||||||
277 | * @param string $moduleName |
||||||||||
278 | * @return array |
||||||||||
279 | */ |
||||||||||
280 | public function getSnippets($snippetsPath, $extensions = true, $dir = '/snippets', $moduleName = '') { |
||||||||||
281 | $moduleName = $moduleName ? $moduleName : $this->name; |
||||||||||
282 | $modulePaths = Module::getModulePaths($moduleName); |
||||||||||
283 | $modulePaths = array_reverse($modulePaths); |
||||||||||
284 | $modulePaths['templatePath'] = App::$cur->view->template->path . '/modules/' . ucfirst($moduleName); |
||||||||||
0 ignored issues
–
show
The property
view does not exist on Inji\App . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||||||
285 | $snippets = []; |
||||||||||
286 | foreach ($modulePaths as $path) { |
||||||||||
287 | if (file_exists($path . $dir . '/' . $snippetsPath)) { |
||||||||||
288 | $snippetsPaths = array_slice(scandir($path . $dir . '/' . $snippetsPath), 2); |
||||||||||
289 | foreach ($snippetsPaths as $snippetPath) { |
||||||||||
290 | if (is_dir($path . $dir . '/' . $snippetsPath . '/' . $snippetPath)) { |
||||||||||
291 | $snippets[$snippetPath] = include $path . $dir . '/' . $snippetsPath . '/' . $snippetPath . '/info.php'; |
||||||||||
292 | } else { |
||||||||||
293 | $snippets[pathinfo($snippetPath, PATHINFO_FILENAME)] = include $path . $dir . '/' . $snippetsPath . '/' . $snippetPath; |
||||||||||
294 | } |
||||||||||
295 | } |
||||||||||
296 | } |
||||||||||
297 | } |
||||||||||
298 | if ($extensions) { |
||||||||||
299 | $snippets = array_merge($snippets, $this->getExtensions('snippets', $snippetsPath)); |
||||||||||
300 | } |
||||||||||
301 | return $snippets; |
||||||||||
302 | } |
||||||||||
303 | |||||||||||
304 | /** |
||||||||||
305 | * Return module objects |
||||||||||
306 | * |
||||||||||
307 | * @return array |
||||||||||
308 | */ |
||||||||||
309 | public function getObjects($filterNamespace = '') { |
||||||||||
310 | $moduleName = $this->name; |
||||||||||
311 | $modulePaths = Module::getModulePaths($moduleName); |
||||||||||
312 | $modulePaths = array_reverse($modulePaths); |
||||||||||
313 | $scanFn = function ($path, $namespace, &$files = []) use (&$scanFn, $filterNamespace) { |
||||||||||
314 | if (file_exists($path)) { |
||||||||||
315 | foreach (scandir($path) as $item) { |
||||||||||
316 | if (in_array($item, ['..', '.'])) { |
||||||||||
317 | continue; |
||||||||||
318 | } |
||||||||||
319 | $filename = pathinfo($item)['filename']; |
||||||||||
320 | if (is_dir($path . '/' . $item)) { |
||||||||||
321 | $scanFn($path . '/' . $item, $namespace . '\\' . $filename, $files); |
||||||||||
322 | } else { |
||||||||||
323 | if (!$filterNamespace || strpos($namespace, $filterNamespace) === 0) { |
||||||||||
324 | $files[$path . '/' . $item] = $namespace . '\\' . $filename; |
||||||||||
325 | } |
||||||||||
326 | } |
||||||||||
327 | } |
||||||||||
328 | } |
||||||||||
329 | return $files; |
||||||||||
330 | }; |
||||||||||
331 | $files = []; |
||||||||||
332 | foreach ($modulePaths as $path) { |
||||||||||
333 | $scanFn($path . '/objects', $moduleName, $files); |
||||||||||
334 | } |
||||||||||
335 | return $files; |
||||||||||
336 | } |
||||||||||
337 | |||||||||||
338 | /** |
||||||||||
339 | * Return module models |
||||||||||
340 | * |
||||||||||
341 | * @return array |
||||||||||
342 | */ |
||||||||||
343 | public static function getModels($moduleName, $filterNamespace = '') { |
||||||||||
344 | $modulePaths = Module::getModulePaths($moduleName); |
||||||||||
345 | $modulePaths = array_reverse($modulePaths); |
||||||||||
346 | $scanFn = function ($path, $namespace, &$files = []) use (&$scanFn, $filterNamespace) { |
||||||||||
347 | if (file_exists($path)) { |
||||||||||
348 | foreach (scandir($path) as $item) { |
||||||||||
349 | if (in_array($item, ['..', '.'])) { |
||||||||||
350 | continue; |
||||||||||
351 | } |
||||||||||
352 | $filename = pathinfo($item)['filename']; |
||||||||||
353 | if (is_dir($path . '/' . $item)) { |
||||||||||
354 | $scanFn($path . '/' . $item, $namespace . '\\' . $filename, $files); |
||||||||||
355 | } else { |
||||||||||
356 | if (!$filterNamespace || strpos($namespace, $filterNamespace) === 0) { |
||||||||||
357 | $files[$path . '/' . $item] = $namespace . '\\' . $filename; |
||||||||||
358 | } |
||||||||||
359 | } |
||||||||||
360 | } |
||||||||||
361 | } |
||||||||||
362 | return $files; |
||||||||||
363 | }; |
||||||||||
364 | $files = []; |
||||||||||
365 | foreach ($modulePaths as $path) { |
||||||||||
366 | $scanFn($path . '/models', $moduleName, $files); |
||||||||||
367 | } |
||||||||||
368 | return $files; |
||||||||||
369 | } |
||||||||||
370 | |||||||||||
371 | /** |
||||||||||
372 | * Return extensions for type |
||||||||||
373 | * |
||||||||||
374 | * @param string $extensionType |
||||||||||
375 | * @param string $request |
||||||||||
376 | * @return array |
||||||||||
377 | */ |
||||||||||
378 | public function getExtensions($extensionType, $request) { |
||||||||||
379 | $extensions = []; |
||||||||||
380 | $modules = Module::getInstalled(App::$cur); |
||||||||||
381 | $method = 'get' . ucfirst($extensionType); |
||||||||||
382 | foreach ($modules as $module) { |
||||||||||
383 | $extensions = array_merge($extensions, $this->{$method}($request, false, "/extensions/{$this->name}/" . $extensionType, $module)); |
||||||||||
384 | } |
||||||||||
385 | return $extensions; |
||||||||||
386 | } |
||||||||||
387 | |||||||||||
388 | 1 | public function checkDbMigration() { |
|||||||||
389 | 1 | if (empty($this->info['migrations'])) { |
|||||||||
390 | 1 | return true; |
|||||||||
391 | } |
||||||||||
392 | $code = 'module:' . get_called_class(); |
||||||||||
393 | $newMigrations = App::$cur->db->compareMigrations($code, $this->info['migrations']); |
||||||||||
0 ignored issues
–
show
The method
compareMigrations() does not exist on Inji\Module . It seems like you code against a sub-type of Inji\Module such as Inji\Db .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The property
db does not exist on Inji\App . Since you implemented __get , consider adding a @property annotation.
![]() The method
compareMigrations() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||||||||
394 | foreach ($newMigrations as $version => $migrationOption) { |
||||||||||
395 | $migration = include $this->path . '/migrations/' . $migrationOption . '.php'; |
||||||||||
396 | App::$cur->db->makeMigration($code, $version, $migration); |
||||||||||
0 ignored issues
–
show
The method
makeMigration() does not exist on Inji\Module . It seems like you code against a sub-type of Inji\Module such as Inji\Db .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||||
397 | } |
||||||||||
398 | } |
||||||||||
399 | |||||||||||
400 | public function sitemap() { |
||||||||||
401 | return []; |
||||||||||
402 | } |
||||||||||
403 | } |