Completed
Push — master ( f6398b...2050be )
by Vitaly
40:08
created

Module::compiler()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 11
Bugs 0 Features 2
Metric Value
c 11
b 0
f 2
dl 0
loc 22
ccs 0
cts 10
cp 0
rs 9.2
cc 3
eloc 9
nc 4
nop 4
crap 12
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
    /** LESS resource importing dependencies file name */
20
    const DEPENDENCY_CACHE = 'dependencies';
21
22
    /** @var array LESS resources dependencies */
23
    public $dependencies = [];
24
25
    /** @var  Path to LESS resources dependencies cache file */
26
    protected $dependencyCache;
27
28
    /** @var \lessc LESS compiler */
29
    protected $less;
30
31
    /** SamsonFramework load preparation stage handler */
32 6
    public function prepare(array $params = [])
33
    {
34 6
        $moduleCachePath = array_key_exists('cachePath', $params) ? $params['cachePath'] : $this->cache_path;
35 6
        $this->dependencyCache = $moduleCachePath.self::DEPENDENCY_CACHE;
0 ignored issues
show
Documentation Bug introduced by
It seems like $moduleCachePath . self::DEPENDENCY_CACHE of type string is incompatible with the declared type object<samsonphp\less\Path> of property $dependencyCache.

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...
36
37
        // Read previous cache file
38 6
        if (file_exists($this->dependencyCache)) {
39
            $this->dependencies = unserialize(file_get_contents($this->dependencyCache));
40
        }
41
42 6
        $this->less = new \lessc;
43
44 6
        Event::subscribe(Router::E_RESOURCE_COMPILE, [$this, 'compiler']);
45 6
        Event::subscribe(Router::E_FINISHED, [$this, 'cacheDependencies']);
46
47 6
        return parent::prepare();
48
    }
49
50
    /**
51
     * Cache LESS resources importing dependency trees.
52
     */
53 1
    public function cacheDependencies()
54
    {
55 1
        file_put_contents($this->dependencyCache, serialize($this->dependencies));
56 1
    }
57
58
    /**
59
     * Recursively replace @import in content of the LESS file
60
     *
61
     * @param string $resource Resource full path
62
     * @param string $content  less file content
63
     *
64
     * @return string Content of LESS file with included @imported resources
65
     * @throws ResourceNotFound If importing resource could not be found
66
     */
67
    protected function readImport($resource, $content)
68
    {
69
        // Rewrite imports
70
        $matches = [];
71
        if (preg_match_all(self::P_IMPORT_DECLARATION, $content, $matches)) {
72
            for ($i=0, $size = count($matches[0]); $i < $size; $i++) {
73
                // Build absolute path to imported resource
74
                $path = dirname($resource).DIRECTORY_SEPARATOR.$matches['path'][$i];
75
76
                // Append .less extension according to standard
77
                if (false === ($path = realpath(is_file($path)?$path:$path.'.less'))) {
78
                    throw new ResourceNotFound('Cannot import file: '.$matches['path'][$i]);
79
                }
80
81
                // Add parent to child dependency
82
                $this->dependencies[$path][$resource] = [];
83
84
                // Replace path in LESS @import command with recursive call to this function
85
                $content = str_replace($matches[0][$i], $this->readImport($path, file_get_contents($path)), $content);
86
            }
87
        }
88
89
        return $content;
90
    }
91
92
    /**
93
     * LESS resource compiler.
94
     *
95
     * @param string $resource  Resource full path
96
     * @param string $extension Resource extension
97
     * @param string $content   Compiled output resource content
98
     * @param array $dependencies Collection of compiled resource dependent modules
99
     *
100
     * @throws \Exception
101
     */
102
    public function compiler($resource, &$extension, &$content, &$dependencies)
103
    {
104
        if ($extension === 'less') {
105
            try {
106
                // Rewrite imports
107
                $content = $this->readImport($resource, $content);
108
109
                // Compile LESS content to CSS
110
                $content = $this->less->compile($content);
111
112
                // Switch extension
113
                $extension = 'css';
114
115
                // Store dependencies
116
                $dependencies = $this->dependencies;
117
            } catch (\Exception $e) {
118
                //$errorFile = 'cache/error_resourcer'.microtime(true).'.less';
119
                //file_put_contents($errorFile, $output);
120
                throw new \Exception('Failed compiling LESS in "' . $resource . '":' . "\n" . $e->getMessage());
121
            }
122
        }
123
    }
124
}
125