Completed
Push — master ( 735fe4...23bc65 )
by Vitaly
03:16
created

Router::init()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 16
Bugs 3 Features 9
Metric Value
cc 1
eloc 10
c 16
b 3
f 9
nc 1
nop 1
dl 0
loc 24
rs 8.9713
ccs 0
cts 10
cp 0
crap 2
1
<?php
2
namespace samsonphp\resource;
3
4
use samson\core\ExternalModule;
5
use samsonphp\event\Event;
6
7
/**
8
 * Resource router for serving static resource from unreachable web-root paths.
9
 *
10
 * TODO: Validate old files that do not exists anymore to remove them
11
 *
12
 * @author Vitaly Iegorov <[email protected]>
13
 */
14
class Router extends ExternalModule
15
{
16
    /** @deprecated Use E_MODULES */
17
    const EVENT_START_GENERATE_RESOURCES = 'resourcer.modulelist';
18
    /** Event for modifying modules */
19
    const E_MODULES = 'resourcer.modulelist';
20
    /** Event for resources preloading */
21
    const E_RESOURCE_PRELOAD = ResourceManager::E_ANALYZE;
22
    /** Event for resources compiling */
23
    const E_RESOURCE_COMPILE = ResourceManager::E_COMPILE;
24
    /** Event when recourse management is finished */
25
    const E_FINISHED = 'resourcer.finished';
26
27
    /** Assets types */
28
    const T_CSS = 'css';
29
    const T_LESS = 'less';
30
    const T_SCSS = 'scss';
31
    const T_SASS = 'sass';
32
    const T_JS = 'js';
33
    const T_TS = 'ts';
34
    const T_COFFEE = 'coffee';
35
36
    /** Assets types collection */
37
    const TYPES = [
38
        self::T_CSS,
39
        self::T_LESS,
40
        self::T_SCSS,
41
        self::T_SASS,
42
        self::T_JS,
43
        self::T_TS,
44
        self::T_COFFEE
45
    ];
46
47
    /** Assets converter */
48
    const CONVERTER = [
49
        self::T_JS => self::T_JS,
50
        self::T_TS => self::T_JS,
51
        self::T_COFFEE => self::T_JS,
52
        self::T_CSS => self::T_CSS,
53
        self::T_LESS => self::T_CSS,
54
        self::T_SCSS => self::T_CSS,
55
        self::T_SASS => self::T_CSS,
56
    ];
57
58
    /** @deprecated Identifier */
59
    protected $id = STATIC_RESOURCE_HANDLER;
60
61
    /** Collection of registered resource types */
62
    protected $types = [
63
        self::T_CSS,
64
        self::T_JS,
65
        self::T_LESS,
66
        self::T_SCSS,
67
        self::T_SASS,
68
        self::T_COFFEE,
69
        self::T_TS
70
    ];
71
72
    /** @var array Assets cache */
73
    protected $cache = [];
74
75
    /** @var array Template markers for inserting assets */
76
    protected $templateMarkers = [
77
        'css' => '</head>',
78
        'js' => '</body>'
79
    ];
80
    /** @var array Collection of static resources */
81
    protected $resources = [];
82
83
    /** @var array Collection of static resource URLs */
84
    protected $resourceUrls = [];
85
86
    /**
87
     * Module initialization stage.
88
     *
89
     * @see ModuleConnector::init()
90
     *
91
     * @param array $params Initialization parameters
92
     *
93
     * @return bool True if resource successfully initialized
94
     */
95
    public function init(array $params = array())
96
    {
97
        // Subscribe for CSS handling
98
        //Event::subscribe(self::E_RESOURCE_COMPILE, [new CSS(), 'compile']);
99
100
        // Subscribe to core template rendering event
101
        Event::subscribe('core.rendered', [$this, 'renderTemplate']);
102
103
        $resourceManager = new ResourceManager(new FileManager());
104
        $resourceManager::$cacheRoot = $this->cache_path;
105
        $resourceManager::$webRoot = getcwd();
106
        $resourceManager::$projectRoot = dirname($resourceManager::$webRoot) . '/';
107
108
        // Get assets
109
        $this->resources = $resourceManager->manage($this->getAssets());
110
        // Get asset URLs
111
        $this->resourceUrls = array_map([$this, 'getAssetCachedUrl'], $this->resources);
112
113
        // Fire completion event
114
        Event::fire(self::E_FINISHED);
115
116
        // Continue parent initialization
117
        return parent::init($params);
118
    }
119
120
    /**
121
     * Get asset files from modules.
122
     */
123
    private function getAssets()
124
    {
125
        // Get loaded modules
126
        $moduleList = $this->system->module_stack;
0 ignored issues
show
Bug introduced by
Accessing module_stack on the interface samsonframework\core\SystemInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
127
128
        // Event for modification of resource list
129
        Event::fire(self::E_MODULES, array(&$moduleList));
130
131
        $projectRoot = dirname(getcwd()) . '/';
132
133
        // Add resource paths
134
        $paths = [];
135
        foreach ($moduleList as $module) {
136
            /**
137
             * We need to exclude project root because vendor folder will be scanned
138
             * and all assets from there would be added.
139
             */
140
            if ($module->path() !== $projectRoot) {
141
                $paths[] = $module->path();
142
            }
143
        }
144
145
        // Add web-root as last path
146
        $paths[] = getcwd();
147
148
        return $paths;
149
    }
150
151
    /**
152
     * Template rendering handler by injecting static assets url
153
     * in appropriate.
154
     *
155
     * @param $view
156
     *
157
     * @return mixed
158
     */
159
    public function renderTemplate(&$view)
160
    {
161
        foreach ($this->resourceUrls as $type => $urls) {
162
            if (array_key_exists($type, $this->templateMarkers)) {
163
                // Replace template marker by type with collection of links to resources of this type
164
                $view = str_ireplace(
165
                    $this->templateMarkers[$type],
166
                    implode("\n", array_map(function ($value) use ($type) {
167
                        if ($type === 'css') {
168
                            return '<link type="text/css" rel="stylesheet" property="stylesheet" href="' . $value . '">';
169
                        } elseif ($type === 'js') {
170
                            return '<script type="text/javascript" src="' . $value . '"></script>';
171
                        }
172
                    }, $urls)) . "\n" . $this->templateMarkers[$type],
173
                    $view
174
                );
175
            }
176
        }
177
178
        return $view;
179
    }
180
181
    /**
182
     * Get cached asset URL.
183
     *
184
     * @param string $cachedAsset Full path to cached asset
185
     *
186
     * @return mixed Cached asset URL
187
     */
188
    private function getAssetCachedUrl($cachedAsset)
189
    {
190
        return str_replace(ResourceManager::$webRoot, '', $cachedAsset);
191
    }
192
}
193