Completed
Push — master ( 8c074e...d10230 )
by Vitaly
09:11 queued 05:58
created

Module::readImport()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 21
ccs 11
cts 11
cp 1
rs 8.7624
cc 5
eloc 9
nc 3
nop 2
crap 5
1
<?php
2
namespace samsonphp\less;
3
4
use samson\core\ExternalModule;
5
use samsonphp\event\Event;
6
use samsonphp\resource\exception\ResourceNotFound;
7
use samsonphp\resource\Router;
8
9
/**
10
 * SamsonPHP LESS compiler module.
11
 *
12
 * @author Vitaly Iegorov <[email protected]>
13
 */
14
class Module extends ExternalModule
15
{
16
    /** LESS mixin declaration pattern */
17
    const P_IMPORT_DECLARATION = '/@import\s+(\'|\")(?<path>[^\'\"]+)(\'|\");/';
18
19
    /** @var \lessc LESS compiler */
20
    protected $less;
21
22
    /** @var array Collection of LESS variables */
23
    protected $variables = [];
24
25
    /** @var array Collection of LESS mixins */
26
    protected $mixins = [];
27
28
    /** @var string Cached LESS code */
29
    protected $lessCode;
30
31
    /** SamsonFramework load preparation stage handler */
32 4
    public function prepare()
33
    {
34 4
        Event::subscribe(Router::E_RESOURCE_COMPILE, [$this, 'compiler']);
35
36 4
        $this->less = new \lessc;
37
38 4
        return true;
39
    }
40
41
    /**
42
     * Recursively replace @import in content of the LESS file
43
     *
44
     * @param string $resource Resource full path
45
     * @param string $content  less file content
46
     *
47
     * @return string Content of LESS file with included @imported resources
48
     * @throws ResourceNotFound If importing resource could not be found
49
     */
50 3
    protected function readImport($resource, $content)
51
    {
52
        // Rewrite imports
53 3
        $matches = [];
54 3
        if (preg_match_all(self::P_IMPORT_DECLARATION, $content, $matches)) {
55 2
            for ($i=0, $size = count($matches[0]); $i < $size; $i++) {
56
                // Build absolute path to imported resource
57 2
                $path = dirname($resource).DIRECTORY_SEPARATOR.$matches['path'][$i];
58
59
                // Append .less extension according to standard
60 2
                if (false === ($path = realpath(is_file($path)?$path:$path.'.less'))) {
61 1
                    throw new ResourceNotFound('Cannot import file: '.$matches['path'][$i]);
62
                }
63
64
                // Replace path in LESS @import command with recursive call to this function
65 1
                $content = str_replace($matches[0][$i], $this->readImport($path, file_get_contents($path)), $content);
66 1
            }
67 1
        }
68
69 2
        return $content;
70
    }
71
72
    /**
73
     * LESS resource compiler.
74
     *
75
     * @param string $resource  Resource full path
76
     * @param string $extension Resource extension
77
     * @param string $content   Compiled output resource content
78
     *
79
     * @throws \Exception
80
     */
81 3
    public function compiler($resource, &$extension, &$content)
82
    {
83 3
        if ($extension === 'less') {
84
            try {
85
                // Rewrite imports
86 3
                $content = $this->readImport($resource, $content);
87
88
                // Compile LESS content to CSS
89 2
                $content = $this->less->compile($content);
90
91
                // Switch extension
92 1
                $extension = 'css';
93 3
            } catch (\Exception $e) {
94
                //$errorFile = 'cache/error_resourcer'.microtime(true).'.less';
95
                //file_put_contents($errorFile, $output);
96 2
                throw new \Exception('Failed compiling LESS in "' . $resource . '":' . "\n" . $e->getMessage());
97
            }
98 1
        }
99 1
    }
100
}
101