Passed
Push — master ( 8ea9d3...4c87c8 )
by Fran
02:50
created

AssetsParser::setHash()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PSFS\base\extension;
4
5
use PSFS\base\Cache;
6
use PSFS\base\config\Config;
7
use PSFS\base\exception\ConfigException;
8
use PSFS\base\extension\traits\CssTrait;
9
use PSFS\base\extension\traits\JsTrait;
10
use PSFS\base\Logger;
11
use PSFS\base\Request;
12
use PSFS\base\Template;
13
use PSFS\base\types\helpers\GeneratorHelper;
14
use PSFS\base\types\helpers\Inspector;
15
16
defined('CSS_SRI_FILENAME') or define('CSS_SRI_FILENAME', CACHE_DIR . DIRECTORY_SEPARATOR . 'css.sri.json');
17
defined('JS_SRI_FILENAME') or define('JS_SRI_FILENAME', CACHE_DIR . DIRECTORY_SEPARATOR . 'js.sri.json');
18
/**
19
 * Class AssetsParser
20
 * @package PSFS\base\extension
21
 */
22
class AssetsParser
23
{
24
    use CssTrait;
25
    use JsTrait;
26
27
    /**
28
     * @var array
29
     */
30
    protected $files = [];
31
    /**
32
     * @var string
33
     */
34
    protected $hash;
35
    /**
36
     * @var array
37
     */
38
    protected $compiledFiles = [];
39
    /**
40
     * @var string
41
     */
42
    protected $type;
43
    /**
44
     * @var array
45
     */
46
    protected $domains = [];
47
    /**
48
     * @var string
49
     */
50
    private $cdnPath = null;
51
    /**
52
     * @var array
53
     */
54
    protected $sri = [];
55
56
    /**
57
     * @var string
58
     */
59
    protected $sriFilename;
60
61
    /**
62
     * @param string $type
63
     */
64 1
    public function init($type) {
65 1
        $this->sriFilename = $type === 'js' ? JS_SRI_FILENAME : CSS_SRI_FILENAME;
66
        /** @var Cache $cache */
67 1
        $cache = Cache::getInstance();
68 1
        $this->sri = $cache->getDataFromFile($this->sriFilename, Cache::JSON, true);
69 1
        if(empty($this->sri)) {
70 1
            $this->sri = [];
71
        }
72 1
    }
73
74
    /**
75
     * Constructor por defecto
76
     *
77
     * @param string $type
78
     */
79 1
    public function __construct($type = 'js')
80
    {
81 1
        $this->type = $type;
82 1
        $this->path = WEB_DIR . DIRECTORY_SEPARATOR;
83 1
        $this->domains = Template::getDomains(true);
84 1
        $this->cdnPath = Config::getParam('resources.cdn.url', Request::getInstance()->getRootUrl());
85 1
    }
86
87
    /**
88
     * Método que añade un nuevo fichero al proceso de generación de los assets
89
     * @param $filename
90
     * @return AssetsParser
91
     * @internal param string $type
92
     */
93 1
    public function addFile($filename)
94
    {
95 1
        if (file_exists($this->path . $filename) && preg_match('/\.' . $this->type . '$/i', $filename)) {
96
            $this->files[] = $filename;
97 1
        } elseif (!empty($this->domains)) {
98 1
            foreach ($this->domains as $domain => $paths) {
99 1
                $domainFilename = str_replace($domain, $paths["public"], $filename);
100 1
                if (file_exists($domainFilename) && preg_match('/\.' . $this->type . '$/i', $domainFilename)) {
101 1
                    $this->files[] = $domainFilename;
102
                }
103
            }
104
        }
105 1
        return $this;
106
    }
107
108
    /**
109
     * Método que establece el hash con el que compilar los assets
110
     * @param string $hash
111
     *
112
     * @return AssetsParser
113
     */
114 1
    public function setHash($hash)
115
    {
116 1
        $cache = Config::getParam('cache.var', '');
117 1
        $this->hash = $hash . (strlen($cache) ? '.' : '') . $cache;
118 1
        return $this;
119
    }
120
121
    /**
122
     * Método que procesa los ficheros solicitados en función del modo de ejecución
123
     * @return AssetsParser
124
     * @internal param string $type
125
     * @throws ConfigException
126
     * @throws \PSFS\base\exception\GeneratorException
127
     */
128 1
    public function compile()
129
    {
130
        //Unificamos ficheros para que no se retarde mucho el proceso
131 1
        $this->files = array_unique($this->files);
132 1
        switch ($this->type) {
133
            default:
134 1
            case "js":
135 1
                $this->compileJs($this->files, $this->path, $this->hash, $this->compiledFiles);
136 1
                break;
137 1
            case "css":
138 1
                $this->compileCss($this->path, $this->hash);
139 1
                break;
140
        }
141
142 1
        return $this;
143
    }
144
145
    /**
146
     * Método que imprime el resultado de la generación de los assets
147
     */
148 1
    public function printHtml()
149
    {
150 1
        $baseUrl = $this->cdnPath ?: '';
151 1
        $sri = ''; //Config::getParam('debug') ? '' : $this->getSriHash($this->hash, $this->type);
152 1
        switch ($this->type) {
153
            default:
154 1
            case "js":
155 1
                $this->printJs($this->compiledFiles, $baseUrl, $this->hash, $sri);
156 1
                break;
157 1
            case "css":
158 1
                $this->printCss($this->compiledFiles, $baseUrl, $this->hash, $sri);
159 1
                break;
160
        }
161 1
    }
162
163
    /**
164
     * Método que calcula el path completo a copiar un recurso
165
     * @param string $filenamePath
166
     * @param string[] $source
167
     * @return string
168
     */
169
    protected static function calculateResourcePathname($filenamePath, $source)
170
    {
171
        $sourceFile = preg_replace("/'/", "", $source[1]);
172
        if (preg_match('/\#/', $sourceFile)) {
173
            $sourceFile = explode("#", $sourceFile);
174
            $sourceFile = $sourceFile[0];
175
        }
176
        if (preg_match('/\?/', $sourceFile)) {
177
            $sourceFile = explode("?", $sourceFile);
178
            $sourceFile = $sourceFile[0];
179
        }
180
        $orig = realpath(dirname($filenamePath) . DIRECTORY_SEPARATOR . $sourceFile);
181
        return $orig;
182
    }
183
184
    /**
185
     * Método que extrae el recurso css de una línea de estilos css
186
     * @param $handle
187
     * @param string $filenamePath
188
     * @throws \PSFS\base\exception\GeneratorException
189
     */
190
    public static function extractCssLineResource($handle, $filenamePath)
191
    {
192
        $line = fgets($handle);
193
        $urls = array();
194
        if (preg_match_all('#url\((.*?)\)#', $line, $urls, PREG_SET_ORDER)) {
195
            foreach ($urls as $source) {
196
                $orig = self::calculateResourcePathname($filenamePath, $source);
197
                if(!empty($orig)) {
198
                    $orig_part = preg_split("/Public/i", $orig);
199
                    $dest = WEB_DIR . $orig_part[1];
200
                    GeneratorHelper::createDir(dirname($dest));
201
                    if (@copy($orig, $dest) === false) {
202
                        throw new ConfigException("Can't copy " . $orig . " to " . $dest);
203
                    }
204
                } else {
205
                    Logger::log($filenamePath . ' has an empty origin with the url ' . $source, LOG_WARNING);
206
                }
207
            }
208
        }
209
    }
210
211
    /**
212
     * @param $hash
213
     * @param string $type
214
     * @return mixed|string
215
     * @throws \PSFS\base\exception\GeneratorException
216
     */
217
    protected function getSriHash($hash, $type = 'js') {
218
        if(array_key_exists($hash, $this->sri)) {
219
            $sriHash = $this->sri[$hash];
220
        } else {
221
            Inspector::stats('[SRITrait] Generating SRI for ' . $hash, Inspector::SCOPE_DEBUG);
222
            $filename = WEB_DIR . DIRECTORY_SEPARATOR . $type . DIRECTORY_SEPARATOR . $hash . '.' . $type;
223
            $sriHash = base64_encode(hash("sha384", file_get_contents($filename), true));
224
            $this->sri[$hash] = $sriHash;
225
            Cache::getInstance()->storeData($this->sriFilename, $this->sri, Cache::JSON, true);
226
        }
227
        return $sriHash;
228
    }
229
230
}
231