1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by Vitaly Iegorov <[email protected]>. |
4
|
|
|
* on 07.07.16 at 18:19 |
5
|
|
|
*/ |
6
|
|
|
namespace samsonphp\css; |
7
|
|
|
|
8
|
|
|
use samson\core\ExternalModule; |
9
|
|
|
use samsonphp\event\Event; |
10
|
|
|
use samsonphp\resource\exception\ResourceNotFound; |
11
|
|
|
use samsonphp\resource\ResourceValidator; |
12
|
|
|
use samsonphp\resource\Router; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* CSS assets handling class |
16
|
|
|
* |
17
|
|
|
* @author Vitaly Iegorov <[email protected]> |
18
|
|
|
* @package samsonphp\resource |
19
|
|
|
* TODO: Remove ResourceValidator as it is unnecessary |
20
|
|
|
*/ |
21
|
|
|
class CSS extends ExternalModule |
22
|
|
|
{ |
23
|
|
|
/** @var string Module identifer */ |
24
|
|
|
protected $id = 'resource_css'; |
25
|
|
|
|
26
|
|
|
/** Pattern for matching CSS url */ |
27
|
|
|
const P_URL = '/url\s*\(\s*(\'|\")?([^\)\s\'\"]+)(\'|\")?\s*\)/i'; |
28
|
|
|
|
29
|
|
|
/** Event for firing before handling CSS resource */ |
30
|
|
|
const E_BEFORE_HANDLER = 'samsonphp.css.before_handle'; |
31
|
|
|
|
32
|
|
|
/** Event for firing after handling CSS resource */ |
33
|
|
|
const E_AFTER_HANDLER = 'samsonphp.css.after_handle'; |
34
|
|
|
|
35
|
|
|
/** @var string Path to current resource file */ |
36
|
|
|
protected $currentResource; |
37
|
|
|
|
38
|
|
|
/** Module preparation stage handler */ |
39
|
5 |
|
public function prepare(array $params = []) |
40
|
|
|
{ |
41
|
|
|
// Subscribe for CSS handling |
42
|
5 |
|
Event::subscribe(Router::E_RESOURCE_COMPILE, [$this, 'compile']); |
43
|
|
|
|
44
|
5 |
|
return parent::prepare($params); |
|
|
|
|
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* LESS resource compiler. |
49
|
|
|
* |
50
|
|
|
* @param string $resource Resource full path |
51
|
|
|
* @param string $extension Resource extension |
52
|
|
|
* @param string $content Compiled output resource content |
53
|
|
|
*/ |
54
|
5 |
|
public function compile($resource, $extension, &$content) |
55
|
|
|
{ |
56
|
5 |
|
if ($extension === 'css') { |
57
|
5 |
|
$this->currentResource = $resource; |
58
|
|
|
|
59
|
|
|
// Fire event |
60
|
5 |
|
Event::fire(self::E_BEFORE_HANDLER, [&$content, $resource]); |
61
|
|
|
|
62
|
|
|
// Rewrite Urls |
63
|
5 |
|
$content = preg_replace_callback(self::P_URL, [$this, 'rewriteUrls'], $content); |
64
|
|
|
|
65
|
|
|
// Fire event |
66
|
4 |
|
Event::fire(self::E_AFTER_HANDLER, [&$content, $resource]); |
67
|
4 |
|
} |
68
|
4 |
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Callback for CSS url(...) rewriting. |
72
|
|
|
* |
73
|
|
|
* @param array $matches Regular expression matches collection |
74
|
|
|
* |
75
|
|
|
* @return string Rewritten url(..) with static resource handler url |
76
|
|
|
* @throws ResourceNotFound |
77
|
|
|
*/ |
78
|
5 |
|
public function rewriteUrls($matches) |
79
|
|
|
{ |
80
|
|
|
// Store static resource path |
81
|
5 |
|
$url = $matches[2]; |
82
|
|
|
|
83
|
|
|
// Ignore inline resources |
84
|
5 |
|
if (strpos($url, 'data/') === false && strpos($url, 'data:') === false) { |
85
|
|
|
// Remove possible GET, HASH parameters from resource path |
86
|
4 |
|
$url = $this->getOnlyUrl($this->getOnlyUrl($url, '#'), '?'); |
87
|
|
|
|
88
|
|
|
// Try to find resource and output full error |
89
|
|
|
try { |
90
|
4 |
|
$path = ResourceValidator::getProjectRelativePath($url, dirname($this->currentResource)); |
91
|
4 |
|
} catch (ResourceNotFound $e) { |
92
|
1 |
|
throw new ResourceNotFound('Cannot find resource "' . $url . '" in "' . $this->currentResource . '"'); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
// Build path to static resource handler |
96
|
3 |
|
return 'url("/' . STATIC_RESOURCE_HANDLER . '/?p=' . $path . '")'; |
97
|
|
|
} |
98
|
|
|
|
99
|
1 |
|
return $matches[0]; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Get only path or URL before marker. |
104
|
|
|
* |
105
|
|
|
* @param string $path Full URL with possible unneeded data |
106
|
|
|
* @param string $marker Marker for separation |
107
|
|
|
* |
108
|
|
|
* @return string Filtered asset URL |
109
|
|
|
*/ |
110
|
4 |
|
protected function getOnlyUrl($path, $marker) |
111
|
|
|
{ |
112
|
|
|
// Remove possible GET parameters from resource path |
113
|
4 |
|
if (($getStart = strpos($path, $marker)) !== false) { |
114
|
3 |
|
return substr($path, 0, $getStart); |
115
|
|
|
} |
116
|
|
|
|
117
|
4 |
|
return $path; |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.