Component::paths()   C
last analyzed

Complexity

Conditions 14
Paths 90

Size

Total Lines 67
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 61
CRAP Score 14

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 67
ccs 61
cts 61
cp 1
rs 5.8135
cc 14
eloc 52
nc 90
nop 1
crap 14

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BootPress\Asset;
4
5
use BootPress\Page\Component as Page;
6
use BootPress\SQLite\Component as SQLite;
7
use Symfony\Component\HttpFoundation\Response;
8
use Symfony\Component\HttpFoundation\StreamedResponse;
9
use Symfony\Component\HttpFoundation\BinaryFileResponse;
10
use League\Glide\Responses\SymfonyResponseFactory;
11
use League\Glide\ServerFactory;
12
use MatthiasMullie\Minify;
13
use phpUri;
14
15
class Component
16
{
17
    const PREG_TYPES = 'jpe?g|gif|png|ico|js|css|pdf|ttf|otf|svg|eot|woff2?|swf|tar|t?gz|g?zip|csv|xls?x?|word|docx?|pptx?|psd|ogg|wav|mp3|mp4|mpeg?|mpg|mov|qt';
18
    public static $instance; // made public to facilitate testing
19
    public static $not_found = array();
20
    public static $urls = array();
21
    private $cached = null;
22
    private $db = null;
23
24
    /**
25
     * Prepares a Symfony Response for you to send.
26
     * 
27
     * @param string       $file     Either a file location, or the type of file you are sending eg. html, txt, less, scss, json, xml, rdf, rss, atom, js, css
28
     * @param array|string $options  An array of options if ``$file`` is a location, or the string of data you want to send.  The available options are:
29
     * 
30
     * - '**name**' - changes a downloadable asset's file name
31
     * - 
32
     * - 
33
     * 
34
     * @return object  A Symfony\Component\HttpFoundation\Response
35
     */
36 8
    public static function dispatch($file, $options = array())
37
    {
38 8
        $set = array_merge(array(
39 8
            'name' => '',
40 8
            'expires' => 0,
41 8
            'xsendfile' => false,
42 8
        ), (array) $options);
43 8
        $page = Page::html();
44 8
        if (preg_match('/^(html|txt|less|scss|json|xml|rdf|rss|atom|js|css)$/', $file)) {
45 4
            if (is_array($options)) {
46 3
                foreach ($options as $updated => $content) {
47 3
                    if (is_numeric($updated)) {
48 3
                        break;
49
                    }
50 3
                }
51 3
            } else {
52 3
                $content = (string) $options;
53
            }
54 4
            $response = new Response($content, Response::HTTP_OK, array(
0 ignored issues
show
Bug introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
55 4
                'Content-Type' => static::mime($file),
56 4
                'Content-Length' => mb_strlen($content),
57 4
            ));
58 4
            if (isset($updated) && (int) $updated > 631152000) { // 01-01-1990
59 3
                $response->setCache(array(
60 3
                    'public' => true,
61 3
                    'max_age' => $set['expires'],
62 3
                    's_maxage' => $set['expires'],
63 3
                    'last_modified' => \DateTime::createFromFormat('U', (int) $updated),
64 3
                ))->isNotModified($page->request);
65 3
            }
66
67 4
            return $response;
68
        }
69 5
        $type = strtolower(pathinfo($file, PATHINFO_EXTENSION));
70 5
        if (is_null($file) || !is_file($file)) {
71 2
            return new Response('', Response::HTTP_NOT_FOUND);
72
        }
73 4
        if (null === $mime = static::mime($type)) {
74 1
            return new Response('', Response::HTTP_NOT_IMPLEMENTED);
75
        }
76 4
        if (preg_match('/^('.implode('|', array(
77 4
            '(?P<download>tar|t?gz|g?zip|csv|xls?x?|word|docx?|pptx?|psd)',
78 4
            '(?P<stream>ogg|wav|mp3|mp4|mpeg?|mpg|mov|qt)',
79 4
        )).')$/', $type, $matches)) {
80 2
            $response = new BinaryFileResponse($file);
81 2
            $response->headers->set('Content-Type', $mime);
82 2
            $response->setContentDisposition(isset($matches['download']) ? 'attachment' : 'inline', $set['name']);
83 2
            if ($set['xsendfile']) {
84 1
                BinaryFileResponse::trustXSendfileTypeHeader();
85 1
            }
86
87 2
            return $response;
88
        }
89 3
        $file = new \SplFileInfo($file);
90
        $response = new StreamedResponse(function () use ($file) {
91 1
            if ($fp = fopen($file->getPathname(), 'rb')) {
92 1
                rewind($fp);
93 1
                fpassthru($fp);
94 1
                fclose($fp);
95 1
            }
96 3
        }, 200, array(
97 3
            'Content-Type' => $mime,
98 3
            'Content-Length' => $file->getSize(),
99 3
        ));
100 3
        $response->setCache(array(
101 3
            'public' => true,
102 3
            'max_age' => $set['expires'],
103 3
            's_maxage' => $set['expires'],
104 3
            'last_modified' => \DateTime::createFromFormat('U', $file->getMTime()),
105 3
        ));
106 3
        $response->isNotModified($page->request);
107
108 3
        return $response;
109
    }
110
111 6
    public static function cached($dir, array $glide = array())
112
    {
113 6
        $page = Page::html();
114 6
        static::$instance = new static();
115 6
        $asset = static::$instance;
116 6
        $asset->cached = $page->dir($dir);
117 6
        $type = strtolower($page->url['format']);
118 6
        if ($type == 'html') {
119 2
            $page->filter('page', array($asset, 'urls'), 'this');
120
121 2
            return false;
122 5
        } elseif (!preg_match('/^'.implode('', array(
123 5
            '(?P<paths>([1-9a-z]{5}[0]?)+)',
124 5
            '(\/.*)?',
125 5
            '\.('.self::PREG_TYPES.')',
126 5
        )).'$/i', $page->url['path'], $matches)) {
127 1
            return false;
128
        }
129 5
        $paths = explode('0', rtrim($matches['paths'], '0'));
130 5
        foreach ($paths as $key => $value) {
131 5
            $paths[$key] = '"'.$value.'"';
132 5
        }
133 5
        $minify = array();
134 5
        $image = null;
135 5
        $file = null;
136 5
        $asset->openDatabase();
137 5
        if ($stmt = $asset->db->query(array(
138 5
            'SELECT p.tiny, f.file, f.query',
139 5
            'FROM paths as p',
140 5
            'INNER JOIN files AS f ON p.file_id = f.id',
141 5
            'WHERE p.tiny IN('.implode(', ', $paths).')',
142 5
            $asset->db->orderIn('p.tiny', $paths),
143 5
        ), '', 'assoc')) {
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a array.

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...
144 5
            while ($row = $asset->db->fetch($stmt)) {
145 4
                if ($type == strtolower(pathinfo($row['file'], PATHINFO_EXTENSION))) {
146
                    switch ($type) {
147 4
                        case 'js':
148 4
                        case 'css':
149 2
                            if (is_file($row['file'])) {
150 2
                                $minify[$row['file']] = $row;
151 2
                            }
152 2
                            break 1;
153 2
                        case 'jpeg':
154 2
                        case 'jpg':
155 2
                        case 'gif':
156 2
                        case 'png':
157 1
                            if (!empty($row['query'])) {
158 1
                                parse_str($row['query'], $params);
159 1
                                $setup = $glide;
160
                                $glide = array(
161 1
                                    'cache' => $asset->cached.'glide/',
162 1
                                    'source' => dirname($row['file']),
163 1
                                    'response' => new SymfonyResponseFactory($page->request),
164 1
                                );
165 1
                                if (isset($setup['group_cache_in_folders']) && is_bool($setup['group_cache_in_folders'])) {
166 1
                                    $glide['group_cache_in_folders'] = $setup['group_cache_in_folders'];
167 1
                                }
168 1
                                if (isset($setup['watermarks'])) {
169 1
                                    $glide['watermarks'] = rtrim(str_replace('\\', '/', $setup['watermarks']), '/');
170 1
                                }
171 1
                                if (isset($setup['driver']) && in_array($setup['driver'], array('gd', 'imagick'))) {
172 1
                                    $glide['driver'] = $setup['driver'];
173 1
                                }
174 1
                                if (isset($setup['max_image_size']) && is_numeric($setup['max_image_size'])) {
175 1
                                    $glide['max_image_size'] = (int) $setup['max_image_size'];
176 1
                                }
177 1
                                $glide = ServerFactory::create($glide);
178 1
                                $image = $glide->getImageResponse(basename($row['file']), $params);
0 ignored issues
show
Bug introduced by
It seems like $params can also be of type null; however, League\Glide\Server::getImageResponse() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
179 1
                                break 2;
180
                            }
181 1
                        default:
182 1
                            $file = $row['file'];
183 1
                            break 2;
184 1
                    }
185 2
                }
186 2
            }
187 5
            $asset->db->close($stmt);
188 5
        }
189 5
        $asset->closeDatabase();
190 5
        if (!empty($minify)) {
191 2
            $paths = array();
192 2
            foreach ($minify as $row) {
193 2
                $paths[] = $row['tiny'];
194 2
            }
195 2
            $file = implode('/', array(
196 2
                $asset->cached.'minify',
197 2
                md5($page->url['base']),
198 2
                implode('0', $paths),
199 2
            )).'.'.$type;
200 2
            if (!is_dir(dirname($file))) {
201 1
                mkdir(dirname($file), 0755, true);
202 1
            }
203 2
            if (!is_file($file)) {
204
                switch ($type) {
205 2
                    case 'js':
206 1
                        $minifier = new Minify\JS();
207 1
                        foreach ($minify as $js => $row) {
208 1
                            $minifier->add($js);
209 1
                        }
210 1
                        $minifier->minify($file);
211 1
                        break;
212 1
                    case 'css':
213 1
                        $minifier = new Minify\CSS();
214 1
                        foreach ($minify as $css => $row) {
215 1
                            $minifier->add($asset->css($css, $row));
216 1
                        }
217 1
                        $minifier->minify($file);
218 1
                        break;
219
                }
220 2
            }
221 2
        }
222
223 5
        return ($image) ? $image : static::dispatch($file, array('expires' => 31536000));
224
    }
225
226 2
    public static function urls($html)
227
    {
228 2
        if (is_null(static::$instance) || empty($html)) {
229 1
            return $html;
230
        }
231 2
        $asset = static::$instance;
232 2
        $page = Page::html();
233 2
        $array = (is_array($html)) ? $html : false;
234 2
        if ($array) {
235 1
            $html = array();
236
            array_walk_recursive($array, function ($value) use (&$html) {
237 1
                $html[] = $value;
238 1
            });
239 1
            $html = implode(' ', $html);
240 1
        }
241 2
        preg_match_all('/'.implode('', array(
242 2
            '('.$page->url['preg'].')',
243 2
            '(?P<dir>['.$page->url['chars'].']+)\/',
244 2
            '(?P<file>['.$page->url['chars'].'.\/]+\.(?P<ext>'.self::PREG_TYPES.'))',
245 2
            '(?P<query>\?['.$page->url['chars'].'&;=.\/]+)?',
246 2
            '(#(?P<frag>['.$page->url['chars'].'.\/#]+))?',
247 2
        )).'/i', $html, $matches, PREG_SET_ORDER);
248 2
        if (empty($matches)) {
249 1
            return $array ? $array : $html;
250
        }
251 2
        $asset->openDatabase();
252 2
        $cache = array();
253 2
        $assets = array();
254 2
        $found = $page->dir; // in PHP7 isset($page->dir[$url]) will not work on a private property retrieved via ``__get()``
255 2
        foreach ($matches as $url) {
256 2
            $dir = $url['dir'];
257 2
            if (!isset($found[$dir])) {
258 1
                static::$not_found[] = substr($url[0], strlen($page->url['base']));
259 1
                continue;
260
            }
261 2
            $ext = strtolower($url['ext']);
262 2
            $file = $url['file'];
263 2
            if (isset($url['query']) && in_array($ext, array('jpeg', 'jpg', 'gif', 'png'))) {
264 2
                $file .= $url['query'];
265 2
            }
266 2
            $files = array();
267 2
            $files[$file] = pathinfo($url['file'], PATHINFO_FILENAME);
268 2
            if (isset($url['frag'])) {
269 1
                $frag = explode('#', $url['frag']);
270 1
                if ($ext == 'js' || $ext == 'css') {
271 1
                    $base = phpUri::parse($page->dir[$dir].$file);
272 1
                    foreach ($frag as $file) {
273 1
                        $file = $base->join($file);
274 1
                        $info = pathinfo($file);
275 1
                        if (is_file($file) && $info['extension'] == $ext) {
276 1
                            $file = substr($file, strlen($page->dir[$dir]));
277 1
                            $files[$file] = $info['filename'];
278 1
                        }
279 1
                    }
280 1
                } else {
281 1
                    $files[$file] = pathinfo(array_shift($frag), PATHINFO_FILENAME);
282
                }
283 1
            }
284 2
            foreach ($files as $file => $name) {
285 2
                $cache[$dir][$file] = array();
286 2
            }
287 2
            $assets[$url[0]] = array(
288 2
                'dir' => $dir,
289 2
                'file' => array_keys($files),
290 2
                'name' => implode('-', $files),
291 2
                'ext' => '.'.$ext,
292
            );
293 2
        }
294 2
        $asset->paths($cache);
295 2
        $asset->closeDatabase();
296 2
        $rnr = array();
297 2
        $base = strlen($page->url['base']);
298 2
        foreach ($assets as $match => $url) {
299 2
            $cached = array();
300 2
            foreach ($url['file'] as $file) {
301 2
                $cached[] = $cache[$url['dir']][$file];
302 2
            }
303 2
            $cached = implode(0, $cached);
304 2
            if (!is_numeric($url['name'])) {
305 2
                $cached .= '/'.$url['name'];
306 2
            }
307 2
            $cached .= $url['ext'];
308 2
            $rnr[$page->url['base'].$cached] = $match; // replace => remove
309 2
            static::$urls[substr($match, $base)] = $cached;
310 2
        }
311 2
        ksort(static::$urls);
312 2
        uasort($rnr, function($a, $b) { // ORDER BY strlen(remove) DESC so we don't step on any toes
313 2
            return mb_strlen($b) - mb_strlen($a);
314 2
        });
315 2
        $rnr = array_flip($rnr); // remove => replace
316 2
        return str_replace(array_keys($rnr), array_values($rnr), $array ? $array : $html);
317
    }
318
319 8
    public static function mime($type)
320
    {
321 8
        $mime = null;
322 8
        $single = (is_array($type)) ? false : true;
323 8
        if (is_array($type)) {
324 1
            $type = array_shift($type);
325 1
        }
326 8
        switch (strtolower($type)) {
327 8
            case 'html':
328 3
                $mime = array('text/html', 'application/xhtml+xml', 'text/plain');
329 3
                break;
330 8
            case 'txt':
331 2
                $mime = array('text/plain');
332 2
                break;
333 8
            case 'less':
334 1
                $mime = array('text/x-less', 'text/css', 'text/plain', 'application/octet-stream');
335 1
                break;
336 8
            case 'scss':
337 1
                $mime = array('text/css', 'text/plain', 'application/octet-stream');
338 1
                break;
339 8
            case 'json':
340 1
                $mime = array('application/json', 'application/x-json', 'text/json', 'text/plain');
341 1
                break;
342 8
            case 'xml':
343 3
                $mime = array('application/xml', 'application/x-xml', 'text/xml', 'text/plain');
344 3
                break;
345 6
            case 'rdf':
346 1
                $mime = array('application/rdf+xml');
347 1
                break;
348 6
            case 'rss':
349 2
                $mime = array('application/rss+xml');
350 2
                break;
351 5
            case 'atom':
352 1
                $mime = array('application/atom+xml');
353 1
                break;
354 5
            case 'jpeg':
355 5
            case 'jpg':
356 2
                $mime = array('image/jpeg', 'image/pjpeg');
357 2
                break;
358 5
            case 'gif':
359 1
                $mime = array('image/gif');
360 1
                break;
361 5
            case 'png':
362 1
                $mime = array('image/png',  'image/x-png');
363 1
                break;
364 5
            case 'ico':
365 1
                $mime = array('image/x-icon', 'image/vnd.microsoft.icon');
366 1
                break;
367 5
            case 'js':
368 2
                $mime = array('application/javascript', 'application/x-javascript', 'text/javascript', 'text/plain');
369 2
                break;
370 4
            case 'css':
371 2
                $mime = array('text/css', 'text/plain');
372 2
                break;
373 3
            case 'pdf':
374 1
                $mime = array('application/pdf', 'application/force-download', 'application/x-download', 'binary/octet-stream');
375 1
                break;
376 3
            case 'ttf':
377 1
                $mime = array('application/font-sfnt', 'application/font-ttf', 'application/x-font-ttf', 'font/ttf', 'font/truetype', 'application/octet-stream');
378 1
                break;
379 3
            case 'otf':
380 1
                $mime = array('application/font-sfnt', 'application/font-otf', 'application/x-font-otf', 'font/opentype', 'application/octet-stream');
381 1
                break;
382 3
            case 'svg':
383 1
                $mime = array('image/svg+xml', 'application/xml', 'text/xml');
384 1
                break;
385 3
            case 'eot':
386 1
                $mime = array('application/vnd.ms-fontobject', 'application/octet-stream');
387 1
                break;
388 3
            case 'woff':
389 1
                $mime = array('application/font-woff', 'application/x-woff', 'application/x-font-woff', 'font/x-woff', 'application/octet-stream');
390 1
                break;
391 3
            case 'woff2':
392 1
                $mime = array('application/font-woff2', 'font/woff2', 'application/octet-stream');
393 1
                break;
394 3
            case 'swf':
395 1
                $mime = array('application/x-shockwave-flash');
396 1
                break;
397 3
            case 'tar':
398 1
                $mime = array('application/x-tar');
399 1
                break;
400 3
            case 'tgz':
401 1
                $mime = array('application/x-tar', 'application/x-gzip-compressed');
402 1
                break;
403 3
            case 'gz':
404 3
            case 'gzip':
405 1
                $mime = array('application/x-gzip');
406 1
                break;
407 3
            case 'zip':
408 1
                $mime = array('application/x-zip', 'application/zip', 'application/x-zip-compressed', 'application/s-compressed', 'multipart/x-zip');
409 1
                break;
410 3
            case 'csv':
411 3
                $mime = array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain');
412 3
                break;
413 2
            case 'xl':
414 1
                $mime = array('application/excel');
415 1
                break;
416 2
            case 'xls':
417 1
                $mime = array('application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'application/x-ms-excel', 'application/x-excel', 'application/x-dos_ms_excel', 'application/xls', 'application/x-xls', 'application/excel', 'application/download', 'application/vnd.ms-office', 'application/msword');
418 1
                break;
419 2
            case 'xlsx':
420 1
                $mime = array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip', 'application/vnd.ms-excel', 'application/msword', 'application/x-zip');
421 1
                break;
422 2
            case 'word':
423 1
                $mime = array('application/msword', 'application/octet-stream');
424 1
                break;
425 2
            case 'doc':
426 1
                $mime = array('application/msword', 'application/vnd.ms-office');
427 1
                break;
428 2
            case 'docx':
429 1
                $mime = array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword', 'application/x-zip');
430 1
                break;
431 2
            case 'ppt':
432 1
                $mime = array('application/powerpoint', 'application/vnd.ms-powerpoint', 'application/vnd.ms-office', 'application/msword');
433 1
                break;
434 2
            case 'pptx':
435 1
                $mime = array('application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/x-zip', 'application/zip');
436 1
                break;
437 2
            case 'psd':
438 1
                $mime = array('application/x-photoshop', 'image/vnd.adobe.photoshop');
439 1
                break;
440 2
            case 'ogg':
441 1
                $mime = array('audio/ogg');
442 1
                break;
443 2
            case 'wav':
444 1
                $mime = array('audio/x-wav', 'audio/wave', 'audio/wav');
445 1
                break;
446 2
            case 'mp3':
447 1
                $mime = array('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3');
448 1
                break;
449 2
            case 'mp4':
450 1
                $mime = array('video/mp4');
451 1
                break;
452 2
            case 'mpe':
453 2
            case 'mpeg':
454 2
            case 'mpg':
455 1
                $mime = array('video/mpeg');
456 1
                break;
457 2
            case 'mov':
458 2
            case 'qt':
459 1
                $mime = array('video/quicktime');
460 1
                break;
461 8
        }
462
463 8
        return ($mime && $single) ? array_shift($mime) : $mime;
464
    }
465
466 1
    private function css($file, $row)
467
    {
468 1
        $page = Page::html();
469 1
        $css = file_get_contents($file);
470 1
        if (substr($css, 0, 3) == "\xef\xbb\xbf") {
471 1
            $css = substr($css, 3); // strip BOM, if any
472 1
        }
473 1
        $matches = array();
474
        foreach (array(
475 1
            '/url\(\s*(?P<quotes>["\'])?(?P<path>(?!(\s?["\']?(data:|https?:|\/\/))).+?)(?(quotes)(?P=quotes))\s*\)/ix', // url(xxx)
476 1
            '/@import\s+(?P<quotes>["\'])(?P<path>(?!(["\']?(data:|https?:|\/\/))).+?)(?P=quotes)/ix', // @import "xxx"
477 1
        ) as $regex) {
478 1
            if (preg_match_all($regex, $css, $match, PREG_SET_ORDER)) {
479 1
                $matches = array_merge($matches, $match);
480 1
            }
481 1
        }
482 1
        $rnr = array();
483 1
        $base = phpUri::parse($row['file']);
484 1
        $common = dirname($row['file']) . '/';
485 1
        foreach ($matches as $match) {
486 1
            if (preg_match('/(?P<file>[^#\?]*)(?P<extra>.*)/', ltrim($match['path'], '/'), $path)) {
487 1
                if (static::mime(pathinfo($path['file'], PATHINFO_EXTENSION))) {
488 1
                    $file = $base->join($path['file']).$path['extra'];
489 1
                    if ($dir = $page->commonDir(array($common, $file))) {
490 1
                        $common = $dir;
491 1
                        if (strpos($match[0], '@import') === 0) {
492 1
                            $rnr[$match[0]] = '@import "'.$file.'"';
493 1
                        } else {
494 1
                            $rnr[$match[0]] = 'url("'.$file.'")';
495
                        }
496 1
                    }
497 1
                }
498 1
            }
499 1
        }
500 1
        if (!empty($rnr)) {
501 1
            $page->dir('set', 'css-dir', $common);
502 1
            $url = $page->url['base'].'css-dir/';
503 1
            foreach ($rnr as $remove => $replace) {
504 1
                $rnr[$remove] = str_replace($common, $url, $replace);
505 1
            }
506 1
            $css = static::urls(str_replace(array_keys($rnr), array_values($rnr), $css));
507 1
        }
508
        
509 1
        return $css;
510
    }
511
512 2
    private function paths(&$cache)
513
    {
514 2
        $page = Page::html();
515 2
        $count = 0;
516 2
        foreach ($cache as $dir => $files) {
517 2
            $count += count($files);
518 2
        }
519 2
        $ids = $this->ids($count);
520 2
        $insert = array();
521 2
        $update = array();
522 2
        $stmt = $this->db->prepare(array(
523 2
            'SELECT f.id AS file_id, f.updated, p.tiny, p.id AS path_id',
524 2
            'FROM files AS f INNER JOIN paths AS p ON f.id = p.file_id',
525 2
            'WHERE f.file = ? AND f.query = ?',
526 2
        ), 'assoc');
527 2
        foreach ($cache as $dir => $files) {
528 2
            foreach ($files as $path => $tiny) {
529 2
                list($file, $query) = explode('?', $path.'?');
530 2
                $file = $page->dir[$dir].$file;
531 2
                $updated = filemtime($file);
532 2
                $this->db->execute($stmt, array($file, $query));
533 2
                if ($row = $this->db->fetch($stmt)) {
534 2
                    if ($row['updated'] == $updated) {
535 2
                        $tiny = $row['tiny'];
536 2
                    } else {
537 1
                        list($path_id, $tiny) = each($ids);
538 1
                        $update[$row['file_id']] = array($path_id, $updated);
539
                    }
540 2
                } else {
541 2
                    list($path_id, $tiny) = each($ids);
542 2
                    $insert[] = array($path_id, $file, $query, $updated);
543
                }
544 2
                $cache[$dir][$path] = $tiny;
545 2
            }
546 2
        }
547 2
        $this->db->close($stmt);
548 2
        if (empty($insert) && empty($update)) {
549 1
            return;
550
        }
551 2
        $this->db->exec('BEGIN IMMEDIATE');
552 2
        $paths = array();
553 2
        if (!empty($insert)) {
554 2
            $stmt = $this->db->insert('files', array('path_id', 'file', 'query', 'updated'));
555 2
            foreach ($insert as $array) {
556 2
                $paths[$array[0]] = $this->db->insert($stmt, $array);
557 2
            }
558 2
            $this->db->close($stmt);
559 2
        }
560 2
        if (!empty($update)) {
561 1
            $stmt = $this->db->update('files', 'id', array('path_id', 'updated'));
562 1
            foreach ($update as $file_id => $array) {
563 1
                $this->db->update($stmt, $file_id, $array);
564 1
                $paths[$array[0]] = $file_id;
565 1
            }
566 1
            $this->db->close($stmt);
567 1
        }
568 2
        if (!empty($paths)) {
569 2
            $stmt = $this->db->update('paths', 'id', array('file_id'));
570 2
            foreach ($paths as $path_id => $file_id) {
571 2
                $this->db->update($stmt, $path_id, array($file_id));
572 2
            }
573 2
            $this->db->close($stmt);
574 2
        }
575 2
        $this->db->exec('COMMIT');
576
577 2
        return;
578
    }
579
580 2
    private function ids($count)
581
    {
582 2
        $ids = array();
583 2
        if ($stmt = $this->db->query(array(
584 2
            'SELECT id, tiny',
585 2
            'FROM paths',
586 2
            'WHERE file_id = ?',
587 2
            'ORDER BY id DESC LIMIT '.$count,
588 2
        ), 0, 'row')) {
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a array.

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...
589 2
            while (list($id, $tiny) = $this->db->fetch($stmt)) {
590 2
                $ids[$id] = $tiny;
591 2
            }
592 2
            $this->db->close($stmt);
593 2
        }
594 2
        if (count($ids) == $count) {
595 2
            return $ids;
596
        }
597 1
        $this->db->exec('BEGIN IMMEDIATE');
598 1
        $stmt = $this->db->insert('OR IGNORE INTO paths', array('tiny'));
599 1
        $string = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
600 1
        for ($i = 0; $i < $count + 100; ++$i) {
601 1
            $tiny_id = ''; // 60 (characters) ^ 5 (length) gives 777,600,000 possible combinations
602 1
            while (strlen($tiny_id) < 5) {
603 1
                $tiny_id .= $string[mt_rand(0, 60)];
604 1
            }
605 1
            $this->db->insert($stmt, array($tiny_id));
606 1
        }
607 1
        $this->db->close($stmt);
608 1
        $this->db->exec('COMMIT');
609
610 1
        return $this->ids($count);
611
    }
612
613 6
    private function openDatabase()
614
    {
615 6
        if (is_null($this->db)) {
616 6
            $this->db = new SQLite($this->cached.'Assets.db');
617 6
            if ($this->db->created) {
618 1
                $this->db->create('paths', array(
619 1
                    'id' => 'INTEGER PRIMARY KEY',
620 1
                    'tiny' => 'TEXT UNIQUE NOT NULL DEFAULT ""',
621 1
                    'file_id' => 'INTEGER NOT NULL DEFAULT 0',
622 1
                ));
623 1
                $this->db->create('files', array(
624 1
                    'id' => 'INTEGER PRIMARY KEY',
625 1
                    'path_id' => 'INTEGER NOT NULL DEFAULT 0',
626 1
                    'file' => 'TEXT NOT NULL DEFAULT ""',
627 1
                    'query' => 'TEXT NOT NULL DEFAULT ""',
628 1
                    'updated' => 'INTEGER NOT NULL DEFAULT 0',
629 1
                ), array('unique' => 'file, query'));
630 1
            }
631 6
        }
632 6
    }
633
634 6
    private function closeDatabase()
635
    {
636 6
        if (!is_null($this->db)) {
637 6
            $this->db->connection()->close();
638 6
        }
639 6
        $this->db = null;
640 6
    }
641
642 6
    private function __construct()
643
    {
644 6
    }
645
}
646