Completed
Push — master ( d10230...3a05b0 )
by Vitaly
16:33
created

Module   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 20
Bugs 2 Features 7
Metric Value
wmc 12
c 20
b 2
f 7
lcom 1
cbo 4
dl 0
loc 105
ccs 33
cts 33
cp 1
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A prepare() 0 17 3
A cacheDependencies() 0 4 1
B readImport() 0 21 5
A compiler() 0 19 3
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 1
            $this->dependencies = unserialize(file_get_contents($this->dependencyCache));
40 1
        }
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 2
    public function cacheDependencies()
54
    {
55 2
        file_put_contents($this->dependencyCache, serialize($this->dependencies));
56 2
    }
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
     * @param array  $tree LESS Tree array pointer
64
     *
65
     * @return string Content of LESS file with included @imported resources
66
     * @throws ResourceNotFound If importing resource could not be found
67
     */
68 4
    protected function readImport($resource, $content, &$tree)
69
    {
70
        // Rewrite imports
71 4
        $matches = [];
72 4
        if (preg_match_all(self::P_IMPORT_DECLARATION, $content, $matches)) {
73 3
            for ($i=0, $size = count($matches[0]); $i < $size; $i++) {
74
                // Build absolute path to imported resource
75 3
                $path = dirname($resource).DIRECTORY_SEPARATOR.$matches['path'][$i];
76
77
                // Append .less extension according to standard
78 3
                if (false === ($path = realpath(is_file($path)?$path:$path.'.less'))) {
79 1
                    throw new ResourceNotFound('Cannot import file: '.$matches['path'][$i]);
80
                }
81
82
                // Replace path in LESS @import command with recursive call to this function
83 2
                $content = str_replace($matches[0][$i], $this->readImport($path, file_get_contents($path), $tree[$path]), $content);
84 2
            }
85 2
        }
86
87 3
        return $content;
88
    }
89
90
    /**
91
     * LESS resource compiler.
92
     *
93
     * @param string $resource  Resource full path
94
     * @param string $extension Resource extension
95
     * @param string $content   Compiled output resource content
96
     *
97
     * @throws \Exception
98
     */
99 4
    public function compiler($resource, &$extension, &$content)
100
    {
101 4
        if ($extension === 'less') {
102
            try {
103
                // Rewrite imports
104 4
                $content = $this->readImport($resource, $content, $this->dependencies[$resource]);
105
106
                // Compile LESS content to CSS
107 3
                $content = $this->less->compile($content);
108
109
                // Switch extension
110 2
                $extension = 'css';
111 4
            } catch (\Exception $e) {
112
                //$errorFile = 'cache/error_resourcer'.microtime(true).'.less';
113
                //file_put_contents($errorFile, $output);
114 2
                throw new \Exception('Failed compiling LESS in "' . $resource . '":' . "\n" . $e->getMessage());
115
            }
116 2
        }
117 2
    }
118
}
119