Completed
Push — master ( df5dfe...8c074e )
by Vitaly
09:48
created

Module   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 87
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 95.83%

Importance

Changes 18
Bugs 2 Features 5
Metric Value
wmc 9
c 18
b 2
f 5
lcom 1
cbo 4
dl 0
loc 87
ccs 23
cts 24
cp 0.9583
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A prepare() 0 8 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
    /** @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 3
    public function prepare()
33
    {
34 3
        Event::subscribe(Router::E_RESOURCE_COMPILE, [$this, 'compiler']);
35
36 3
        $this->less = new \lessc;
37
38 3
        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 2
    protected function readImport($resource, $content)
51
    {
52
        // Rewrite imports
53 2
        $matches = [];
54 2
        if (preg_match_all(self::P_IMPORT_DECLARATION, $content, $matches)) {
55 1
            for ($i=0, $size = count($matches[0]); $i < $size; $i++) {
56
                // Build absolute path to imported resource
57 1
                $path = dirname($resource).DIRECTORY_SEPARATOR.$matches['path'][$i];
58
59
                // Append .less extension according to standard
60 1
                if (false === ($path = realpath(is_file($path)?$path:$path.'.less'))) {
61
                    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 2
    public function compiler($resource, &$extension, &$content)
82
    {
83 2
        if ($extension === 'less') {
84
            try {
85
                // Rewrite imports
86 2
                $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 2
            } catch (\Exception $e) {
94
                //$errorFile = 'cache/error_resourcer'.microtime(true).'.less';
95
                //file_put_contents($errorFile, $output);
96 1
                throw new \Exception('Failed compiling LESS in "' . $resource . '":' . "\n" . $e->getMessage());
97
            }
98 1
        }
99 1
    }
100
}
101