Completed
Push — master ( 762e5a...3d8bf3 )
by Vitaly
37:47
created

Core::module()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 7
Bugs 1 Features 3
Metric Value
cc 6
eloc 11
nc 8
nop 1
dl 0
loc 20
ccs 0
cts 12
cp 0
crap 42
rs 8.8571
c 7
b 1
f 3
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of the SamsonPHP\Core package.
4
 * (c) 2013 Vitaly Iegorov <[email protected]>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
namespace samson\core;
10
11
use samsonframework\container\Builder;
12
use samsonframework\container\metadata\ClassMetadata;
13
use samsonframework\container\metadata\MethodMetadata;
14
use samsonframework\core\SystemInterface;
15
use samsonframework\di\ContainerInterface;
16
use samsonframework\resource\ResourceMap;
17
use samsonphp\config\Scheme;
18
use samsonphp\core\exception\CannotLoadModule;
19
use samsonphp\core\exception\ViewPathNotFound;
20
use samsonphp\event\Event;
21
use samsonframework\container\ContainerBuilderInterface;
22
23
/**
24
 * SamsonPHP Core.
25
 *
26
 * @author Vitaly Iegorov <[email protected]>
27
 */
28
class Core implements SystemInterface
29
{
30
    /** @var ContainerInterface */
31
    protected $container;
32
33
    /** @var ClassMetadata[] */
34
    protected $metadataCollection = [];
35
36
    /** @var ContainerBuilderInterface */
37
    protected $builder;
38
39
    /** @var string Current system environment */
40
    protected $environment;
41
42
    /* Rendering models */
43
    /** @deprecated Standard algorithm for view rendering */
44
    const RENDER_STANDART = 1;
45
    /** @deprecated View rendering algorithm from array of view variables */
46
    const RENDER_VARIABLE = 3;
47
48
    /** @deprecated @var  ResourceMap Current web-application resource map */
49
    public $map;
50
   
51
    /** @deprecated @var string Path to current web-application */
52
    public $system_path = __SAMSON_CWD__;
53
    /** @deprecated @var string View path loading mode */
54
    public $render_mode = self::RENDER_STANDART;
55
    /** @var Module Pointer to current active module */
56
    protected $active = null;
57
    /** @var bool Flag for outputting layout template, used for asynchronous requests */
58
    protected $async = false;
59
    /** @var string Path to main system template */
60
    protected $template_path = __SAMSON_DEFAULT_TEMPLATE;
61
62
    /** @return ContainerInterface Get system container */
63
    public function getContainer()
64
    {
65
        return $this->container;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->container; (samsonframework\di\ContainerInterface) is incompatible with the return type declared by the interface samsonframework\core\SystemInterface::getContainer of type samsonframework\container\ContainerInterface.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
66
    }
67
68
    /**
69
     * Core constructor.
70
     *
71
     * @param ContainerBuilderInterface $builder Container builder
72
     * @param ResourceMap|null $map system resources
73
     */
74
    public function __construct(ContainerBuilderInterface $builder, ResourceMap $map = null)
75
    {
76
        $this->builder = $builder;
77
78
        if (!isset($map)) {
79
            // Get correct web-application path
80
            $this->system_path = __SAMSON_CWD__;
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
81
82
            // Get web-application resource map
83
            $this->map = ResourceMap::get($this->system_path, false, array('src/'));
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$map has been deprecated with message: @var ResourceMap Current web-application resource map

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
84
        } else { // Use data from passed map
85
            $this->map = $map;
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$map has been deprecated with message: @var ResourceMap Current web-application resource map

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
86
            $this->system_path = $map->entryPoint;
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
87
        }
88
89
        // Temporary add template worker
90
        $this->subscribe('core.rendered', array($this, 'generateTemplate'));
91
92
        // TODO: Shoud be configurable not fixed integration
93
        $whoops = new \Whoops\Run;
94
        $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
0 ignored issues
show
Documentation introduced by
new \Whoops\Handler\PrettyPageHandler() is of type object<Whoops\Handler\PrettyPageHandler>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
95
        $whoops->register();
96
97
        // Fire core creation event
98
        Event::fire('core.created', array(&$this));
99
100
        // Signal core configure event
101
        Event::signal('core.configure', array($this->system_path . __SAMSON_CONFIG_PATH));
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
102
    }
103
104
    /**
105
     * Generic wrap for Event system subscription.
106
     * @see \samson\core\\samsonphp\event\Event::subscribe()
107
     *
108
     * @param string   $key     Event identifier
109
     * @param callable $handler Event handler
110 1
     * @param array    $params  Event parameters
111
     *
112
     * @return $this Chaining
113
     */
114
    public function subscribe($key, $handler, $params = array())
115
    {
116
        Event::subscribe($key, $handler, $params);
117
118
        return $this;
119
    }
120
121 1
    /**
122
     * Change current system working environment or receive
123
     * current system enviroment if no arguments are passed.
124
     *
125
     * @param string $environment Environment identifier
126
     *
127
     * TODO: Function has two different logics - needs to be changed!
128
     * @return $this|string Chaining or current system environment
129
     */
130
    public function environment($environment = Scheme::BASE)
131
    {
132
        if (func_num_args() !== 0) {
133
            $this->environment = $environment;
134
135
            // Signal core environment change
136
            Event::signal('core.environment.change', array($environment, &$this));
137
            return $this;
138
        }
139
140
        return $this->environment;
141
    }
142
143
    /**
144
     * Generate special response header triggering caching mechanisms
145
     * @param int $cacheLife Amount of seconds for cache(default 3600 - 1 hour)
146
     * @param string $accessibility Cache-control accessibility value(default public)
147
     */
148
    public function cached($cacheLife = 3600, $accessibility = 'public')
149
    {
150
        static $cached;
151
        // Protect sending cached headers once
152
        if (!isset($cached) or $cached !== true) {
153
            header('Expires: ' . gmdate('D, d M Y H:i:s T', time() + $cacheLife));
154
            header('Cache-Control: ' . $accessibility . ', max-age=' . $cacheLife);
155
            header('Pragma: cache');
156
157
            $cached = true;
158
        }
159
    }
160
161
    /**
162
     * Set asynchronous mode.
163
     * This mode will not output template and will just path everything that
164
     * was outputted to client.
165
     *
166
     * @param bool $async True to switch to asynchronous output mode
167
     *
168
     * @return $this Chaining
169
     */
170
    public function async($async)
171
    {
172
        $this->async = $async;
173
174
        return $this;
175
    }
176
177
    /** @see iCore::path() */
178
    public function path($path = null)
179
    {
180
        // Если передан аргумент
181
        if (func_num_args()) {
182
            // Сформируем новый относительный путь к главному шаблону системы
183
            $this->template_path = $path . $this->template_path;
184
185
            // Сохраним относительный путь к Веб-приложению
186
            $this->system_path = $path;
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
187
188
            // Продолжил цепирование
189
            return $this;
190
        }
191
192
        // Вернем текущее значение
193
        return $this->system_path;
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
194
    }
195
196
    /**    @see iModule::active() */
197
    public function &active(&$module = null)
198
    {
199
        // Сохраним старый текущий модуль
200
        $old = &$this->active;
201
202
        // Если передано значение модуля для установки как текущий - проверим и установим его
203
        if (isset($module)) {
204
            $this->active = &$module;
205
        }
206
207
        // Вернем значение текущего модуля
208
        return $old;
209
    }
210
211
    /**
212
     * Retrieve module instance by identifier.
213
     *
214
     * @param string|null $module Module identifier
215
     *
216
     * @return null|Module Found or active module
217
     */
218
    public function &module($module = null)
219
    {
220
        $return = null;
221
222
        // Ничего не передано - вернем текущуй модуль системы
223
        if (!isset($module) && isset($this->active)) {
224
            $return = &$this->active;
225
        } elseif (is_object($module)) {
226
            $return = &$module;
227
        } elseif (is_string($module)) {
228
            $return = $this->container->get($module);
229
        }
230
231
        // Ничего не получилось вернем ошибку
232
        if ($return === null) {
233
            e('Не возможно получить модуль(##) системы', E_SAMSON_CORE_ERROR, array($module));
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
234
        }
235
236
        return $return;
237
    }
238
239
    /**
240
     * Unload module from core.
241
     *
242
     * @param string $moduleID Module identifier
243
     */
244
    public function unload($moduleID)
245
    {
246
        if (isset($this->module_stack[$moduleID])) {
0 ignored issues
show
Bug introduced by
The property module_stack does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
247
            unset($this->module_stack[$moduleID]);
248
        }
249
    }
250
251
    /**
252
     * Insert generic html template tags and data
253
     *
254
     * @param string $templateHtml Generated HTML
255
     *
256
     * @deprecated Must be moved to a new HTML output object
257
     * @return mixed Changed HTML template
258
     */
259
    public function generateTemplate(&$templateHtml)
260
    {
261
        // Добавим путь к ресурсам для браузера
262
        $headHtml = "\n" . '<base href="' . url()->base() . '">';
263
        // Добавим отметку времени для JavaScript
264 2
        $headHtml .= "\n" . '<script type="text/javascript">var __SAMSONPHP_STARTED = new Date().getTime();</script>';
265
266
        // Добавим поддержку HTML для старых IE
267
        $headHtml .= "\n" . '<!--[if lt IE 9]>';
268
        $headHtml .= "\n" . '<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>';
269
        $headHtml .= "\n" . '<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>';
270
        $headHtml .= "\n" . '<![endif]-->';
271 2
272
        // Выполним вставку главного тега <base> от которого зависят все ссылки документа
273
        // также подставим МЕТА-теги для текущего модуля и сгенерированный минифицированный CSS
274 2
        $templateHtml = str_ireplace('<head>', '<head>' . $headHtml, $templateHtml);
275
276
        // Вставим указатель JavaScript ресурсы в конец HTML документа
277
        $templateHtml = str_ireplace('</html>', '</html>' . __SAMSON_COPYRIGHT, $templateHtml);
278 2
279
        return $templateHtml;
280 2
    }
281
282 2
    /**
283 2
     * Start SamsonPHP framework.
284
     *
285
     * @param string $default Default module identifier
286 2
     *
287
     * @throws ViewPathNotFound
288 2
     */
289
    public function start($default)
290 2
    {
291
        // TODO: Change ExternalModule::init() signature
292
        // Fire core started event
293
        Event::fire('core.started');
294
295 2
        // TODO: Does not see why it should be here
296
        // Set main template path
297
        $this->template($this->template_path);
298
299
        // Security layer
300
        $securityResult = true;
301
        // Fire core security event
302
        Event::fire('core.security', array(&$this, &$securityResult));
303
304
        /** @var mixed $result External route controller action result */
305
        $result = false;
306
307
        // If we have passed security application layer
308
        if ($securityResult) {
309
            // Fire core routing event - go to routing application layer
310
            Event::signal('core.routing', array(&$this, &$result, $default));
311
        }
312
313
        // If no one has passed back routing callback
314
        if (!isset($result) || $result === false) {
315
            // Fire core e404 - routing failed event
316
            $result = Event::signal('core.e404', array(url()->module, url()->method));
317
        }
318
319
        // Response
320 2
        $output = '';
321
322
        // If this is not asynchronous response and controller has been executed
323 2
        if (!$this->async && ($result !== false)) {
324
            // Store module data
325
            $data = $this->active->toView();
326 2
327
            // Render main template
328
            $output = $this->render($this->template_path, $data);
329 2
330
            // Fire after render event
331
            Event::fire('core.rendered', array(&$output));
332 2
        }
333
334
        // Output results to client
335 2
        echo $output;
336
337
        // Fire ended event
338 2
        Event::fire('core.ended', array(&$output));
339
    }
340
341
    /**	@see iCore::template() */
342
    public function template( $template = NULL, $absolutePath = false )
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces between opening bracket and argument "$template"; 1 found
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
Coding Style introduced by
Expected 0 spaces between argument "$absolutePath" and closing bracket; 1 found
Loading history...
343
    {
344
        // Если передан аргумент
345
        if( func_num_args() ){
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
Coding Style introduced by
Expected 0 spaces before closing bracket; 1 found
Loading history...
346
            $this->template_path = ($absolutePath)?$template:$this->active->path().$template;
347
        }
348
349
        // Аргументы не переданы - вернем текущий путь к шаблону системы
350
        return $this->template_path;
351
    }
352 7
353
    /**
354 7
     * Render file to a buffer.
355
     *
356 7
     * @param string $view Path to file
357
     * @param array  $data Collection of variables to path to file
358
     *
359
     * @return string Rendered file contents
360
     * @throws ViewPathNotFound
361
     */
362
    public function render($view, $data = array())
363
    {
364
        // TODO: Make rendering as external system, to split up these 3 rendering options
365
366
        // Объявить ассоциативный массив переменных в данном контексте
367
        if (is_array($data)) {
368
            extract($data);
369
        }
370
371
        // Начать вывод в буффер
372
        ob_start();
373
374
        // Path to another template view, by default we are using default template folder path,
375
        // for meeting first condition
376
        $templateView = $view;
377
378
        if (locale() != SamsonLocale::DEF) {
379
            // Modify standard view path with another template
380
            $templateView = str_replace(__SAMSON_VIEW_PATH, __SAMSON_VIEW_PATH . locale() . '/', $templateView);
381
        }
382
383
        // Depending on core view rendering model
384
        switch ($this->render_mode) {
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$render_mode has been deprecated with message: @var string View path loading mode

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
385
            // Standard algorithm for view rendering
386
            case self::RENDER_STANDART:
0 ignored issues
show
Deprecated Code introduced by
The constant samson\core\Core::RENDER_STANDART has been deprecated with message: Standard algorithm for view rendering

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
387
                // Trying to find another template path, by default it's an default template path
388
                if (file_exists($templateView)) {
389
                    include($templateView);
390
                } elseif (file_exists($view)) {
391
                    // If another template wasn't found - we will use default template path
392
                    include($view);
393
                } else { // Error no template view was found
394
                    throw(new ViewPathNotFound($view));
395
                }
396
                break;
397
398
            // View rendering algorithm from array of view variables
399
            case self::RENDER_VARIABLE:
0 ignored issues
show
Deprecated Code introduced by
The constant samson\core\Core::RENDER_VARIABLE has been deprecated with message: View rendering algorithm from array of view variables

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
400
                // Collection of views
401
                $views = &$GLOBALS['__compressor_files'];
402
                // Trying to find another template path, by default it's an default template path
403 2
                if (isset($views[$templateView])) {
404
                    eval(' ?>' . $views[$templateView] . '<?php ');
405
                } elseif (isset($views[$view])) {
406 2
                    // If another template wasn't found - we will use default template path
407
                    eval(' ?>' . $views[$view] . '<?php ');
408
                } else { // Error no template view was found
409 2
                    throw(new ViewPathNotFound($view));
410 2
                }
411 2
                break;
412
        }
413
414 2
        // Получим данные из буффера вывода
415
        $html = ob_get_contents();
416
417
        // Очистим буффер
418
        ob_end_clean();
419
420
        // Fire core render event
421
        Event::fire('core.render', array(&$html, &$data, &$this->active));
422
423
        ////elapsed('End rendering '.$__view);
424
        return $html;
425
    }
426
427
    //[PHPCOMPRESSOR(remove,start)]
428
429
    /**
430
     * Load system from composer.json
431
     * @param string $dependencyFilePath Path to dependencies file
432
     * @return $this Chaining
433
     */
434
    public function composer($dependencyFilePath = null)
435
    {
436
        $composerModules = array();
437
438
        Event::fire(
439
            'core.composer.create',
440
            array(
441
                &$composerModules,
442
                isset($dependencyFilePath) ? $dependencyFilePath : $this->system_path,
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
443
                array(
444
                    'vendorsList' => array('samsonphp/', 'samsonos/', 'samsoncms/', 'samsonjavascript/'),
445
                    'ignoreKey' => 'samson_module_ignore',
446
                    'includeKey' => 'samson_module_include'
447
                )
448
            )
449
        );
450
451
        $modulesToLoad = [];
452
453
        // Iterate requirements
454
        foreach ($composerModules as $requirement => $parameters) {
455
            $moduleName = $this->load(__SAMSON_CWD__ . __SAMSON_VENDOR_PATH . $requirement,
456
            array_merge(
457
                is_array($parameters) ? $parameters : array($parameters),
458
                array('module_id' => $requirement)
459
            ));
460
461
            $modulesToLoad[$moduleName] = $parameters;
462
        }
463
464
        $localModulesPath = '../src';
465
        ResourceMap::get('cache');
466
        // TODO: Nested modules relation
467
        for ($i = 0; $i < 2; $i++) {
468
            $resourceMap = ResourceMap::get($localModulesPath);
469
470
            foreach ($resourceMap->modules as $moduleFile) {
471
                $modulePath = str_replace(realpath($localModulesPath), '', $moduleFile[1]);
472
                $modulePath = explode('/', $modulePath);
473
                $modulePath = $localModulesPath . '/' . $modulePath[1];
474
                $moduleName = $this->load($modulePath, $parameters);
0 ignored issues
show
Bug introduced by
The variable $parameters seems to be defined by a foreach iteration on line 454. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
475
                $modulesToLoad[$moduleName] = $parameters;
476
            }
477
        }
478
479
        //$this->active = new VirtualModule($this->system_path, $this->map, $this, 'local');
480
481
        // Create local module and set it as active
482
        $this->createMetadata(VirtualModule::class, 'local', $this->system_path);
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
483
484
        // TODO: This should be changed to one single logic
485
        // Require all local module model files
486
        foreach ($this->map->models as $model) {
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$map has been deprecated with message: @var ResourceMap Current web-application resource map

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
487
            // TODO: Why have to require once?
488
            require_once($model);
489
        }
490
491
        // Create all local modules
492
        foreach ($this->map->controllers as $controller) {
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$map has been deprecated with message: @var ResourceMap Current web-application resource map

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
493
            // Require class into PHP
494
            require($controller);
495
496
            //new VirtualModule($this->system_path, $this->map, $this, basename($controller, '.php'));
497
498
            $this->createMetadata(VirtualModule::class, basename($controller, '.php'), $this->system_path);
0 ignored issues
show
Deprecated Code introduced by
The property samson\core\Core::$system_path has been deprecated with message: @var string Path to current web-application

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
499
        }
500
501
        $metadata = new ClassMetadata();
502
        $metadata->className = get_class($this);
503
        $metadata->name = 'core';
504
        $metadata->scopes[] = Builder::SCOPE_SERVICES;
505
        $metadata->methodsMetadata['__construct'] = new MethodMetadata($metadata);
506
        $metadata->methodsMetadata['__construct']->dependencies['map'] = ResourceMap::class;
507
508
        $this->metadataCollection[$metadata->name] = $metadata;
509
510
        $metadata = new ClassMetadata();
511
        $metadata->className = ResourceMap::class;
512
        $metadata->name = 'resource_map';
513
        $metadata->scopes[] = Builder::SCOPE_SERVICES;
514
515
        $this->metadataCollection[$metadata->name] = $metadata;
516
517
        // Load container class
518
        $containerPath = $this->path().'www/cache/Container.php';
519
        file_put_contents($containerPath, $this->builder->build($this->metadataCollection));
520
        require_once($containerPath);
521
522
        // Inject current core into container
523
        $this->container = new \Container();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Container() of type object<Container> is incompatible with the declared type object<samsonframework\di\ContainerInterface> of property $container.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
524
        $containerReflection = new \ReflectionClass(get_class($this->container));
525
        $serviceProperty = $containerReflection->getProperty(Builder::DI_FUNCTION_SERVICES);
526
        $serviceProperty->setAccessible(true);
527
        $containerServices = $serviceProperty->getValue($this->container);
528
        $containerServices['core'] = $this;
529
        $serviceProperty->setValue($this->container, $containerServices);
530
        $serviceProperty->setAccessible(false);
531
532
        foreach ($modulesToLoad as $name => $parameters) {
533
            $instance = $this->container->get($name);
534
535
            $identifier = $instance->id();
536
537
            // Set composer parameters
538
            $instance->composerParameters = $parameters;
539
540
            // TODO: Change event signature to single approach
541
            // Fire core module load event
542
            Event::fire('core.module_loaded', [$identifier, &$instance]);
543
544
            // Signal core module configure event
545
            Event::signal('core.module.configure', [&$instance, $identifier]);
546
547
            // Call module preparation handler
548
            if (!$instance->prepare()) {
549
                // Handle module failed preparing
550
            }
551
        }
552
553
        $this->active = $this->container->getLocal();
554
555
        return $this;
556
    }
557
558 7
    /**
559
     * Load module from path to core.
560
     *
561 7
     * @param string $path       Path for module loading
562
     * @param array  $parameters Collection of loading parameters
563
     *
564 7
     * @return string module name
565
     * @throws \samsonphp\core\exception\CannotLoadModule
566
     */
567 7
    public function load($path, $parameters = array())
568
    {
569
        $name = '';
570 7
        // Check path
571
        if (file_exists($path)) {
572
            /** @var ResourceMap $resourceMap Gather all resources from path */
573 7
            $resourceMap = ResourceMap::get($path);
574
            if (isset($resourceMap->module[0])) {
575
576 7
                /** @var string $controllerPath Path to module controller file */
577 7
                $controllerPath = $resourceMap->module[1];
578
579
                /** @var string $moduleClass Name of module controller class to load */
580
                $moduleClass = $resourceMap->module[0];
581
582
                // Require module controller class into PHP
583
                if (file_exists($controllerPath)) {
584
                    require_once($controllerPath);
585
                }
586
587
                // TODO: this should be done via composer autoload file field
588
                // Iterate all function-style controllers and require them
589
                foreach ($resourceMap->controllers as $controller) {
590
                    require_once($controller);
591
                }
592
593
                $reflection = new \ReflectionClass($moduleClass);
594
                $name = $reflection->getDefaultProperties();
595
                $name = $this->createMetadata($moduleClass, $name['id'] ?? $moduleClass, $path);
596
597
                /*$this->initModule(
598
                    new $moduleClass($path, $resourceMap, $this),
599
                    $parameters
600
                );*/
601
            } elseif (is_array($parameters) && isset($parameters['samsonphp_package_compressable']) && ($parameters['samsonphp_package_compressable'] == 1)) {
602
                $name = $this->createMetadata(VirtualModule::class, $parameters['module_id'], $path);
603
604
                /*$this->initModule(
605
                    new VirtualModule($path, $resourceMap, $this, str_replace('/', '', $parameters['module_id'])),
606
                    $parameters
607
                );*/
608
            }
609
//            elseif (count($resourceMap->classes)) {
610
//                /** Update for future version: Search classes that implement LoadableInterface */
611
//                foreach ($resourceMap->classes as $classPath => $class) {
612
//                    // This class implements LoadableInterface LoadableInterface::class
613
//                    if (in_array('\samsonframework\core\LoadableInterface', $resourceMap->classData[$classPath]['implements'])) {
614
//
615
//                        $name =  str_replace('/', '', $parameters['module_id']);
616
//
617
//                        $this->createMetadata(VirtualModule::class, str_replace('/', '', $parameters['module_id']), $path);
618
//
619
//                        /*$this->initModule(
620
//                            new VirtualModule(
621
//                                $path,
622
//                                $resourceMap,
623
//                                $this,
624
//                                str_replace('/', '', $resourceMap->classData[$classPath]['className'])
625
//                            ),
626
//                            $parameters
627
//                        );*/
628
//                    }
629
//                }
630
//            }
631
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
632
        } else {
633
            throw new CannotLoadModule($path);
634
        }
635
636
        return $name;
637
    }
638
    //[PHPCOMPRESSOR(remove,end)]
639
640
    /** Магический метод для десериализации объекта */
641
    public function __wakeup()
642
    {
643
        $this->active = &$this->module_stack['local'];
644
    }
645
646
    /** Магический метод для сериализации объекта */
647
    public function __sleep()
648
    {
649
        return array('module_stack', 'render_mode');
650
    }
651
652
    protected function createMetadata($class, $name, $path, $scope = 'module')
653
    {
654
        $metadata = new ClassMetadata();
655
        $class = ltrim($class, '\\');
656
        $name = strtolower(ltrim($name, '\\'));
657
        $metadata->className = $class;
658
        $metadata->name = str_replace(['\\', '/'], '_', $name ?? $class);
659
        $metadata->scopes[] = Builder::SCOPE_SERVICES;
660
        $metadata->scopes[] = $scope;
661
        $metadata->methodsMetadata['__construct'] = new MethodMetadata($metadata);
662
        $metadata->methodsMetadata['__construct']->dependencies['path'] = $path;
663
        $metadata->methodsMetadata['__construct']->dependencies['resources'] = 'resource_map';
664
        $metadata->methodsMetadata['__construct']->dependencies['system'] = 'core';
665
666
        $this->metadataCollection[$metadata->name] = $metadata;
667
668
        return $metadata->name;
669
    }
670
}
671