Completed
Push — master ( ef6d2a...77139e )
by Vitaly
09:28
created

Core::template()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 9
Bugs 1 Features 4
Metric Value
cc 3
eloc 4
c 9
b 1
f 4
nc 3
nop 2
dl 0
loc 10
ccs 2
cts 2
cp 1
crap 3
rs 9.4285
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 Doctrine\Common\Annotations\AnnotationReader;
12
use samsonframework\container\Builder;
13
use samsonframework\container\metadata\ClassMetadata;
14
use samsonframework\container\metadata\MethodMetadata;
15
use samsonframework\containerannotation\AnnotationClassResolver;
16
use samsonframework\containerannotation\AnnotationMetadataCollector;
17
use samsonframework\containerannotation\AnnotationMethodResolver;
18
use samsonframework\containerannotation\AnnotationPropertyResolver;
19
use samsonframework\containerannotation\AnnotationResolver;
20
use samsonframework\containerannotation\Inject;
21
use samsonframework\containerannotation\Injectable;
22
use samsonframework\core\SystemInterface;
23
use samsonframework\di\ContainerInterface;
24
use samsonframework\resource\ResourceMap;
25
use samsonphp\config\Scheme;
26
use samsonphp\core\exception\CannotLoadModule;
27
use samsonphp\core\exception\ViewPathNotFound;
28
use samsonphp\event\Event;
29
use samsonframework\container\ContainerBuilderInterface;
30
31
/**
32
 * SamsonPHP Core.
33
 *
34
 * @author Vitaly Iegorov <[email protected]>
35
 */
36
class Core implements SystemInterface
37
{
38
    /** @var ContainerInterface */
39
    protected $container;
40
41
    /** @var ClassMetadata[] */
42
    protected $metadataCollection = [];
43
44
    /** @var ContainerBuilderInterface */
45
    protected $builder;
46
47
    /** @var string Current system environment */
48
    protected $environment;
49
50
    /* Rendering models */
51
    /** @deprecated Standard algorithm for view rendering */
52
    const RENDER_STANDART = 1;
53
    /** @deprecated View rendering algorithm from array of view variables */
54
    const RENDER_VARIABLE = 3;
55
56
    /** @deprecated @var  ResourceMap Current web-application resource map */
57
    public $map;
58
   
59
    /** @deprecated @var string Path to current web-application */
60
    public $system_path = __SAMSON_CWD__;
61
    /** @deprecated @var string View path loading mode */
62
    public $render_mode = self::RENDER_STANDART;
63
    /** @var Module Pointer to current active module */
64
    protected $active = null;
65
    /** @var bool Flag for outputting layout template, used for asynchronous requests */
66
    protected $async = false;
67
    /** @var string Path to main system template */
68
    protected $template_path = __SAMSON_DEFAULT_TEMPLATE;
69
70
    /** @return \Container Get system container */
71
    public function getContainer()
72
    {
73
        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...
74
    }
75
76
    /**
77
     * Core constructor.
78
     *
79
     * @param ContainerBuilderInterface $builder Container builder
80
     * @param ResourceMap|null $map system resources
81
     */
82
    public function __construct(ContainerBuilderInterface $builder, ResourceMap $map = null)
83
    {
84
        $this->builder = $builder;
85
86
        if (!isset($map)) {
87
            // Get correct web-application path
88
            $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...
89
90
            // Get web-application resource map
91
            $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...
92
        } else { // Use data from passed map
93
            $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...
94
            $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...
95
        }
96
97
        // Temporary add template worker
98
        $this->subscribe('core.rendered', array($this, 'generateTemplate'));
99
100
        // Fire core creation event
101
        Event::fire('core.created', array(&$this));
102
103
        // Signal core configure event
104
        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...
105
    }
106
107
    /**
108
     * Generic wrap for Event system subscription.
109
     * @see \samson\core\\samsonphp\event\Event::subscribe()
110 1
     *
111
     * @param string   $key     Event identifier
112
     * @param callable $handler Event handler
113
     * @param array    $params  Event parameters
114
     *
115
     * @return $this Chaining
116
     */
117
    public function subscribe($key, $handler, $params = array())
118
    {
119
        Event::subscribe($key, $handler, $params);
120
121 1
        return $this;
122
    }
123
124
    /**
125
     * Change current system working environment or receive
126
     * current system enviroment if no arguments are passed.
127
     *
128
     * @param string $environment Environment identifier
129
     *
130
     * TODO: Function has two different logics - needs to be changed!
131
     * @return $this|string Chaining or current system environment
132
     */
133
    public function environment($environment = Scheme::BASE)
134
    {
135
        if (func_num_args() !== 0) {
136
            $this->environment = $environment;
137
138
            // Signal core environment change
139
            Event::signal('core.environment.change', array($environment, &$this));
140
            return $this;
141
        }
142
143
        return $this->environment;
144
    }
145
146
    /**
147
     * Generate special response header triggering caching mechanisms
148
     * @param int $cacheLife Amount of seconds for cache(default 3600 - 1 hour)
149
     * @param string $accessibility Cache-control accessibility value(default public)
150
     */
151
    public function cached($cacheLife = 3600, $accessibility = 'public')
152
    {
153
        static $cached;
154
        // Protect sending cached headers once
155
        if (!isset($cached) or $cached !== true) {
156
            header('Expires: ' . gmdate('D, d M Y H:i:s T', time() + $cacheLife));
157
            header('Cache-Control: ' . $accessibility . ', max-age=' . $cacheLife);
158
            header('Pragma: cache');
159
160
            $cached = true;
161
        }
162
    }
163
164
    /**
165
     * Set asynchronous mode.
166
     * This mode will not output template and will just path everything that
167
     * was outputted to client.
168
     *
169
     * @param bool $async True to switch to asynchronous output mode
170
     *
171
     * @return $this Chaining
172
     */
173
    public function async($async)
174
    {
175
        $this->async = $async;
176
177
        return $this;
178
    }
179
180
    /** @see iCore::path() */
181
    public function path($path = null)
182
    {
183
        // Если передан аргумент
184
        if (func_num_args()) {
185
            // Сформируем новый относительный путь к главному шаблону системы
186
            $this->template_path = $path . $this->template_path;
187
188
            // Сохраним относительный путь к Веб-приложению
189
            $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...
190
191
            // Продолжил цепирование
192
            return $this;
193
        }
194
195
        // Вернем текущее значение
196
        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...
197
    }
198
199
    /**    @see iModule::active() */
200
    public function &active(&$module = null)
201
    {
202
        // Сохраним старый текущий модуль
203
        $old = &$this->active;
204
205
        // Если передано значение модуля для установки как текущий - проверим и установим его
206
        if (isset($module)) {
207
            $this->active = &$module;
208
        }
209
210
        // Вернем значение текущего модуля
211
        return $old;
212
    }
213
214
    /**
215
     * Retrieve module instance by identifier.
216
     *
217
     * @param string|null $module Module identifier
218
     *
219
     * @return null|Module Found or active module
220
     */
221
    public function &module($module = null)
222
    {
223
        $return = null;
224
225
        // Ничего не передано - вернем текущуй модуль системы
226
        if (!isset($module) && isset($this->active)) {
227
            $return = &$this->active;
228
        } elseif (is_object($module)) {
229
            $return = &$module;
230
        } elseif (is_string($module)) {
231
            $return = $this->container->get($module);
232
        }
233
234
        // Ничего не получилось вернем ошибку
235
        if ($return === null) {
236
            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...
237
        }
238
239
        return $return;
240
    }
241
242
    /**
243
     * Unload module from core.
244
     *
245
     * @param string $moduleID Module identifier
246
     */
247
    public function unload($moduleID)
248
    {
249
        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...
250
            unset($this->module_stack[$moduleID]);
251
        }
252
    }
253
254
    /**
255
     * Insert generic html template tags and data
256
     *
257
     * @param string $templateHtml Generated HTML
258
     *
259
     * @deprecated Must be moved to a new HTML output object
260
     * @return mixed Changed HTML template
261
     */
262
    public function generateTemplate(&$templateHtml)
263
    {
264 2
        // Добавим путь к ресурсам для браузера
265
        $headHtml = "\n" . '<base href="' . url()->base() . '">';
266
        // Добавим отметку времени для JavaScript
267
        $headHtml .= "\n" . '<script type="text/javascript">var __SAMSONPHP_STARTED = new Date().getTime();</script>';
268
269
        // Добавим поддержку HTML для старых IE
270
        $headHtml .= "\n" . '<!--[if lt IE 9]>';
271 2
        $headHtml .= "\n" . '<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>';
272
        $headHtml .= "\n" . '<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>';
273
        $headHtml .= "\n" . '<![endif]-->';
274 2
275
        // Выполним вставку главного тега <base> от которого зависят все ссылки документа
276
        // также подставим МЕТА-теги для текущего модуля и сгенерированный минифицированный CSS
277
        $templateHtml = str_ireplace('<head>', '<head>' . $headHtml, $templateHtml);
278 2
279
        // Вставим указатель JavaScript ресурсы в конец HTML документа
280 2
        $templateHtml = str_ireplace('</html>', '</html>' . __SAMSON_COPYRIGHT, $templateHtml);
281
282 2
        return $templateHtml;
283 2
    }
284
285
    /**
286 2
     * Start SamsonPHP framework.
287
     *
288 2
     * @param string $default Default module identifier
289
     *
290 2
     * @throws ViewPathNotFound
291
     */
292
    public function start($default)
293
    {
294
        // TODO: Change ExternalModule::init() signature
295 2
        // Fire core started event
296
        Event::fire('core.started');
297
298
        // TODO: Does not see why it should be here
299
        // Set main template path
300
        $this->template($this->template_path);
301
302
        // Security layer
303
        $securityResult = true;
304
        // Fire core security event
305
        Event::fire('core.security', array(&$this, &$securityResult));
306
307
        /** @var mixed $result External route controller action result */
308
        $result = false;
309
310
        // If we have passed security application layer
311
        if ($securityResult) {
312
            // Fire core routing event - go to routing application layer
313
            Event::signal('core.routing', array(&$this, &$result, $default));
314
        }
315
316
        // If no one has passed back routing callback
317
        if (!isset($result) || $result === false) {
318
            // Fire core e404 - routing failed event
319
            $result = Event::signal('core.e404', array(url()->module, url()->method));
320 2
        }
321
322
        // Response
323 2
        $output = '';
324
325
        // If this is not asynchronous response and controller has been executed
326 2
        if (!$this->async && ($result !== false)) {
327
            // Store module data
328
            $data = $this->active->toView();
329 2
330
            // Render main template
331
            $output = $this->render($this->template_path, $data);
332 2
333
            // Fire after render event
334
            Event::fire('core.rendered', array(&$output));
335 2
        }
336
337
        // Output results to client
338 2
        echo $output;
339
340
        // Fire ended event
341
        Event::fire('core.ended', array(&$output));
342
    }
343
344
    /**	@see iCore::template() */
345
    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...
346
    {
347
        // Если передан аргумент
348
        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...
349
            $this->template_path = ($absolutePath)?$template:$this->active->path().$template;
350
        }
351
352 7
        // Аргументы не переданы - вернем текущий путь к шаблону системы
353
        return $this->template_path;
354 7
    }
355
356 7
    /**
357
     * Render file to a buffer.
358
     *
359
     * @param string $view Path to file
360
     * @param array  $data Collection of variables to path to file
361
     *
362
     * @return string Rendered file contents
363
     * @throws ViewPathNotFound
364
     */
365
    public function render($view, $data = array())
366
    {
367
        // TODO: Make rendering as external system, to split up these 3 rendering options
368
369
        // Объявить ассоциативный массив переменных в данном контексте
370
        if (is_array($data)) {
371
            extract($data);
372
        }
373
374
        // Начать вывод в буффер
375
        ob_start();
376
377
        // Path to another template view, by default we are using default template folder path,
378
        // for meeting first condition
379
        $templateView = $view;
380
381
        if (locale() != SamsonLocale::DEF) {
382
            // Modify standard view path with another template
383
            $templateView = str_replace(__SAMSON_VIEW_PATH, __SAMSON_VIEW_PATH . locale() . '/', $templateView);
384
        }
385
386
        // Depending on core view rendering model
387
        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...
388
            // Standard algorithm for view rendering
389
            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...
390
                // Trying to find another template path, by default it's an default template path
391
                if (file_exists($templateView)) {
392
                    include($templateView);
393
                } elseif (file_exists($view)) {
394
                    // If another template wasn't found - we will use default template path
395
                    include($view);
396
                } else { // Error no template view was found
397
                    throw(new ViewPathNotFound($view));
398
                }
399
                break;
400
401
            // View rendering algorithm from array of view variables
402
            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...
403 2
                // Collection of views
404
                $views = &$GLOBALS['__compressor_files'];
405
                // Trying to find another template path, by default it's an default template path
406 2
                if (isset($views[$templateView])) {
407
                    eval(' ?>' . $views[$templateView] . '<?php ');
408
                } elseif (isset($views[$view])) {
409 2
                    // If another template wasn't found - we will use default template path
410 2
                    eval(' ?>' . $views[$view] . '<?php ');
411 2
                } else { // Error no template view was found
412
                    throw(new ViewPathNotFound($view));
413
                }
414 2
                break;
415
        }
416
417
        // Получим данные из буффера вывода
418
        $html = ob_get_contents();
419
420
        // Очистим буффер
421
        ob_end_clean();
422
423
        // Fire core render event
424
        Event::fire('core.render', array(&$html, &$data, &$this->active));
425
426
        ////elapsed('End rendering '.$__view);
427
        return $html;
428
    }
429
430
    //[PHPCOMPRESSOR(remove,start)]
431
432
    /**
433
     * Load system from composer.json
434
     * @param string $dependencyFilePath Path to dependencies file
435
     * @return $this Chaining
436
     */
437
    public function composer($dependencyFilePath = null)
438
    {
439
        $composerModules = array();
440
441
        Event::fire(
442
            'core.composer.create',
443
            array(
444
                &$composerModules,
445
                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...
446
                array(
447
                    'vendorsList' => array('samsonphp/', 'samsonos/', 'samsoncms/', 'samsonjavascript/'),
448
                    'ignoreKey' => 'samson_module_ignore',
449
                    'includeKey' => 'samson_module_include'
450
                )
451
            )
452
        );
453
454
        $modulesToLoad = [];
455
456
        // Iterate requirements
457
        foreach ($composerModules as $requirement => $parameters) {
458
            $moduleName = $this->load(__SAMSON_CWD__ . __SAMSON_VENDOR_PATH . $requirement,
459
            array_merge(
460
                is_array($parameters) ? $parameters : array($parameters),
461
                array('module_id' => $requirement)
462
            ));
463
464
            $modulesToLoad[$moduleName] = $parameters;
465
        }
466
467
        $localModulesPath = '../src';
468
        ResourceMap::get('cache');
469
        // TODO: Nested modules relation
470
        for ($i = 0; $i < 2; $i++) {
471
            $resourceMap = ResourceMap::get($localModulesPath);
472
473
            foreach ($resourceMap->modules as $moduleFile) {
474
                $modulePath = str_replace(realpath($localModulesPath), '', $moduleFile[1]);
475
                $modulePath = explode('/', $modulePath);
476
                $modulePath = $localModulesPath . '/' . $modulePath[1];
477
                $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 457. 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...
478
                $modulesToLoad[$moduleName] = $parameters;
479
            }
480
        }
481
482
        //$this->active = new VirtualModule($this->system_path, $this->map, $this, 'local');
483
484
        // Create local module and set it as active
485
        $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...
486
487
        // TODO: This should be changed to one single logic
488
        // Require all local module model files
489
        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...
490
            // TODO: Why have to require once?
491
            require_once($model);
492
        }
493
494
        // Create all local modules
495
        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...
496
            // Require class into PHP
497
            require($controller);
498
499
            //new VirtualModule($this->system_path, $this->map, $this, basename($controller, '.php'));
500
501
            $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...
502
        }
503
504
        $metadata = new ClassMetadata();
505
        $metadata->className = get_class($this);
506
        $metadata->name = 'core';
507
        $metadata->scopes[] = Builder::SCOPE_SERVICES;
508
        $metadata->methodsMetadata['__construct'] = new MethodMetadata($metadata);
509
        $metadata->methodsMetadata['__construct']->dependencies['map'] = ResourceMap::class;
510
511
        $this->metadataCollection[$metadata->name] = $metadata;
512
513
        $metadata = new ClassMetadata();
514
        $metadata->className = ResourceMap::class;
515
        $metadata->name = 'resource_map';
516
        $metadata->scopes[] = Builder::SCOPE_SERVICES;
517
518
        $this->metadataCollection[$metadata->name] = $metadata;
519
520
        // Load annotations
521
        $classes = [];
522
        foreach ($this->metadataCollection as $metadata) {
523
            $classes[] = $metadata->className;
524
        }
525
526
        new Injectable();
527
528
        $reader = new AnnotationReader();
529
        $resolver = new AnnotationResolver(
530
            new AnnotationClassResolver($reader),
531
            new AnnotationPropertyResolver($reader),
532
            new AnnotationMethodResolver($reader)
533
        );
534
        $annotationCollector = new AnnotationMetadataCollector($resolver);
535
        $this->metadataCollection = $annotationCollector->collect($classes, $this->metadataCollection);
536
537
        // Load container class
538
        $containerPath = $this->path().'www/cache/Container.php';
539
        file_put_contents($containerPath, $this->builder->build($this->metadataCollection));
540
        require_once($containerPath);
541
542
        // Inject current core into container
543
        $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...
544
        $containerReflection = new \ReflectionClass(get_class($this->container));
545
        $serviceProperty = $containerReflection->getProperty(Builder::DI_FUNCTION_SERVICES);
546
        $serviceProperty->setAccessible(true);
547
        $containerServices = $serviceProperty->getValue($this->container);
548
        $containerServices['core'] = $this;
549
        $serviceProperty->setValue($this->container, $containerServices);
550
        $serviceProperty->setAccessible(false);
551
552
        foreach ($modulesToLoad as $name => $parameters) {
553
            $instance = $this->container->get($name);
554
555
            $identifier = $instance->id();
556
557
            // Set composer parameters
558 7
            $instance->composerParameters = $parameters;
559
560
            // TODO: Change event signature to single approach
561 7
            // Fire core module load event
562
            Event::fire('core.module_loaded', [$identifier, &$instance]);
563
564 7
            // Signal core module configure event
565
            Event::signal('core.module.configure', [&$instance, $identifier]);
566
567 7
            // Call module preparation handler
568
            if (!$instance->prepare()) {
569
                // Handle module failed preparing
570 7
            }
571
572
            // Trying to find parent class for connecting to it to use View/Controller inheritance
573 7
            $parentClass = get_parent_class($instance);
574
            if (!in_array($parentClass, [ExternalModule::class, CompressableExternalModule::class, Service::class, CompressableService::class], true)) {
575
                // Переберем загруженные в систему модули
576 7
                foreach ($this->getContainer()->getServices('module') as $m) {
577 7
                    // Если в систему был загружен модуль с родительским классом
578
                    if (get_class($m) === $parentClass) {
579
                        $instance->parent = $m;
580
                        //elapsed('Parent connection for '.$moduleClass.'('.$connector->uid.') with '.$parent_class.'('.$m->uid.')');
581
                    }
582
                }
583
            }
584
        }
585
586
587
        $this->active = $this->container->getLocal();
588
589
        return $this;
590
    }
591
592
    /**
593
     * Load module from path to core.
594
     *
595
     * @param string $path       Path for module loading
596
     * @param array  $parameters Collection of loading parameters
597
     *
598
     * @return string module name
599
     * @throws \samsonphp\core\exception\CannotLoadModule
600
     */
601
    public function load($path, $parameters = array())
602
    {
603
        $name = '';
604
        // Check path
605
        if (file_exists($path)) {
606
            /** @var ResourceMap $resourceMap Gather all resources from path */
607
            $resourceMap = ResourceMap::get($path);
608
            if (isset($resourceMap->module[0])) {
609
610
                /** @var string $controllerPath Path to module controller file */
611
                $controllerPath = $resourceMap->module[1];
612
613
                /** @var string $moduleClass Name of module controller class to load */
614
                $moduleClass = $resourceMap->module[0];
615
616
                // Require module controller class into PHP
617
                if (file_exists($controllerPath)) {
618
                    require_once($controllerPath);
619
                }
620
621
                // TODO: this should be done via composer autoload file field
622
                // Iterate all function-style controllers and require them
623
                foreach ($resourceMap->controllers as $controller) {
624
                    require_once($controller);
625
                }
626
627
                $reflection = new \ReflectionClass($moduleClass);
628
                $name = $reflection->getDefaultProperties();
629
                $name = $this->createMetadata($moduleClass, $name['id'] ?? $moduleClass, $path);
630
631
                /*$this->initModule(
632
                    new $moduleClass($path, $resourceMap, $this),
633
                    $parameters
634
                );*/
635
            } elseif (is_array($parameters) && isset($parameters['samsonphp_package_compressable']) && ($parameters['samsonphp_package_compressable'] == 1)) {
636
                $name = $this->createMetadata(VirtualModule::class, $parameters['module_id'], $path);
637
638
                /*$this->initModule(
639
                    new VirtualModule($path, $resourceMap, $this, str_replace('/', '', $parameters['module_id'])),
640
                    $parameters
641
                );*/
642
            }
643
//            elseif (count($resourceMap->classes)) {
644
//                /** Update for future version: Search classes that implement LoadableInterface */
645
//                foreach ($resourceMap->classes as $classPath => $class) {
646
//                    // This class implements LoadableInterface LoadableInterface::class
647
//                    if (in_array('\samsonframework\core\LoadableInterface', $resourceMap->classData[$classPath]['implements'])) {
648
//
649
//                        $name =  str_replace('/', '', $parameters['module_id']);
650
//
651
//                        $this->createMetadata(VirtualModule::class, str_replace('/', '', $parameters['module_id']), $path);
652
//
653
//                        /*$this->initModule(
654
//                            new VirtualModule(
655
//                                $path,
656
//                                $resourceMap,
657
//                                $this,
658
//                                str_replace('/', '', $resourceMap->classData[$classPath]['className'])
659
//                            ),
660
//                            $parameters
661
//                        );*/
662
//                    }
663
//                }
664
//            }
665
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
666
        } else {
667
            throw new CannotLoadModule($path);
668
        }
669
670
        return $name;
671
    }
672
    //[PHPCOMPRESSOR(remove,end)]
673
674
    /** Магический метод для десериализации объекта */
675
    public function __wakeup()
676
    {
677
        $this->active = &$this->module_stack['local'];
678
    }
679
680
    /** Магический метод для сериализации объекта */
681
    public function __sleep()
682
    {
683
        return array('module_stack', 'render_mode');
684
    }
685
686
    protected function createMetadata($class, $name, $path, $scope = 'module')
687
    {
688
        $metadata = new ClassMetadata();
689
        $class = ltrim($class, '\\');
690
        $name = strtolower(ltrim($name, '\\'));
691
        $metadata->className = $class;
692
        $metadata->name = str_replace(['\\', '/'], '_', $name ?? $class);
693
        $metadata->scopes[] = Builder::SCOPE_SERVICES;
694
        $metadata->scopes[] = $scope;
695
        $metadata->methodsMetadata['__construct'] = new MethodMetadata($metadata);
696
        $metadata->methodsMetadata['__construct']->dependencies['path'] = $path;
697
        $metadata->methodsMetadata['__construct']->dependencies['resources'] = 'resource_map';
698
        $metadata->methodsMetadata['__construct']->dependencies['system'] = 'core';
699
700
        $this->metadataCollection[$metadata->name] = $metadata;
701
702
        return $metadata->name;
703
    }
704
}
705