These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * @package WordPress Dynamic CSS |
||
4 | * @version 1.0.5 |
||
5 | * @author Askupa Software <[email protected]> |
||
6 | * @link https://github.com/askupasoftware/wp-dynamic-css |
||
7 | * @copyright 2016 Askupa Software |
||
8 | */ |
||
9 | |||
10 | /** |
||
11 | * Dynamic CSS Compiler Utility Class |
||
12 | * |
||
13 | * |
||
14 | * Dynamic CSS Syntax |
||
15 | * ------------------ |
||
16 | * <pre> |
||
17 | * body {color: $body_color;} |
||
18 | * </pre> |
||
19 | * In the above example, the variable $body_color is replaced by a value |
||
20 | * retrieved by the value callback function. The function is passed the variable |
||
21 | * name without the dollar sign, which can be used with get_option() or |
||
22 | * get_theme_mod() etc. |
||
23 | */ |
||
24 | class DynamicCSSCompiler |
||
0 ignored issues
–
show
|
|||
25 | { |
||
26 | /** |
||
27 | * @var Singleton The reference to *Singleton* instance of this class |
||
28 | */ |
||
29 | private static $instance; |
||
30 | |||
31 | /** |
||
32 | * @var array The list of dynamic styles paths to compile |
||
33 | */ |
||
34 | private $stylesheets = array(); |
||
35 | |||
36 | /** |
||
37 | * @var array |
||
38 | */ |
||
39 | private $callbacks = array(); |
||
40 | |||
41 | /** |
||
42 | * Returns the *Singleton* instance of this class. |
||
43 | * |
||
44 | * @return Singleton The *Singleton* instance. |
||
45 | */ |
||
46 | public static function get_instance() |
||
47 | { |
||
48 | if (null === static::$instance) |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() |
|||
49 | { |
||
50 | static::$instance = new static(); |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() It seems like
new static() of type this<DynamicCSSCompiler> is incompatible with the declared type object<Singleton> of property $instance .
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.. ![]() |
|||
51 | } |
||
52 | return static::$instance; |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() |
|||
53 | } |
||
54 | |||
55 | /** |
||
56 | * Enqueue the PHP script used for compiling dynamic stylesheets that are |
||
57 | * loaded externally |
||
58 | */ |
||
59 | public function wp_enqueue_style() |
||
60 | { |
||
61 | // Only enqueue if there is at least one dynamic stylesheet that is |
||
62 | // set to be loaded externally |
||
63 | if( 0 < count( array_filter($this->stylesheets, array( $this, 'filter_external' ) ) ) ) |
||
64 | { |
||
65 | wp_enqueue_style( 'wp-dynamic-css', admin_url( 'admin-ajax.php?action=wp_dynamic_css' ) ); |
||
66 | } |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * Parse all styles in $this->stylesheets and print them if the flag 'print' |
||
71 | * is set to true. Used for printing styles to the document head. |
||
72 | */ |
||
73 | public function compile_printed_styles() |
||
74 | { |
||
75 | // Compile only if there are styles to be printed |
||
76 | if( 0 < count( array_filter($this->stylesheets, array( $this, 'filter_print' ) ) ) ) |
||
77 | { |
||
78 | $compiled_css = $this->get_compiled_styles( true ); |
||
79 | |||
80 | echo "<style id=\"wp-dynamic-css\">\n"; |
||
81 | include 'style.phtml'; |
||
82 | echo "</style>"; |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Parse all styles in $this->stylesheets and print them if the flag 'print' |
||
88 | * is not set to true. Used for loading styles externally via an http request. |
||
89 | */ |
||
90 | public function compile_external_styles() |
||
91 | { |
||
92 | header( "Content-type: text/css; charset: UTF-8" ); |
||
93 | |||
94 | $compiled_css = $this->get_compiled_styles( false ); |
||
95 | |||
96 | include 'style.phtml'; |
||
97 | wp_die(); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Add a style path to the pool of styles to be compiled |
||
102 | * |
||
103 | * @param string $handle The stylesheet's name/id |
||
104 | * @param string $path The absolute path to the dynamic style |
||
105 | * @param boolean $print Whether to print the compiled CSS to the document |
||
106 | * head, or include it as an external CSS file |
||
107 | * @param boolean $minify Whether to minify the CSS output |
||
108 | * @param boolean $cache Whether to store the compiled version of this |
||
109 | * stylesheet in cache to avoid compilation on every page load. |
||
110 | */ |
||
111 | public function enqueue_style( $handle, $path, $print, $minify, $cache ) |
||
112 | { |
||
113 | $this->stylesheets[] = array( |
||
114 | 'handle'=> $handle, |
||
115 | 'path' => $path, |
||
116 | 'print' => $print, |
||
117 | 'minify'=> $minify, |
||
118 | 'cache' => $cache |
||
119 | ); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Register a value retrieval function and associate it with the given handle |
||
124 | * |
||
125 | * @param type $handle The stylesheet's name/id |
||
126 | * @param type $callback |
||
127 | */ |
||
128 | public function register_callback( $handle, $callback ) |
||
129 | { |
||
130 | $this->callbacks[$handle] = $callback; |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * Compile multiple dynamic stylesheets |
||
135 | * |
||
136 | * @param boolean $printed |
||
137 | * @return string Compiled CSS |
||
138 | */ |
||
139 | protected function get_compiled_styles( $printed ) |
||
140 | { |
||
141 | $compiled_css = ''; |
||
142 | foreach( $this->stylesheets as $style ) |
||
143 | { |
||
144 | if( $style['print'] === $printed ) |
||
145 | { |
||
146 | $compiled_css .= $this->get_compiled_style( $style )."\n"; |
||
147 | } |
||
148 | } |
||
149 | return $compiled_css; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Get the compiled CSS for the given style. Skips compilation if the compiled |
||
154 | * version can be found in cache. |
||
155 | * |
||
156 | * @param array $style List of styles with the same structure as they are |
||
157 | * stored in $this->stylesheets |
||
158 | * @return type |
||
159 | */ |
||
160 | protected function get_compiled_style( $style ) |
||
161 | { |
||
162 | $cache = DynamicCSSCache::get_instance(); |
||
163 | |||
164 | if( $style['cache'] ) |
||
165 | { |
||
166 | $cached_css = $cache->get( $style['handle'] ); |
||
167 | if( false !== $cached_css ) |
||
168 | { |
||
169 | return $cached_css; |
||
170 | } |
||
171 | } |
||
172 | |||
173 | $css = file_get_contents( $style['path'] ); |
||
174 | if( $style['minify'] ) $css = $this->minify_css( $css ); |
||
175 | $compiled_css = $this->compile_css( $css, $this->callbacks[$style['handle']] ); |
||
176 | $cache->update( $style['handle'], $compiled_css ); |
||
177 | return $compiled_css; |
||
0 ignored issues
–
show
The return type of
return $compiled_css; (string ) is incompatible with the return type documented by DynamicCSSCompiler::get_compiled_style of type type .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Minify a given CSS string by removing comments, whitespaces and newlines |
||
182 | * |
||
183 | * @see http://stackoverflow.com/a/6630103/1096470 |
||
184 | * @param string $css CSS style to minify |
||
185 | * @return string Minified CSS |
||
186 | */ |
||
187 | protected function minify_css( $css ) |
||
188 | { |
||
189 | return preg_replace( '@({)\s+|(\;)\s+|/\*.+?\*\/|\R@is', '$1$2 ', $css ); |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * This filter is used to return only the styles that are set to be printed |
||
194 | * in the document head |
||
195 | * |
||
196 | * @param array $style |
||
197 | * @return boolean |
||
198 | */ |
||
199 | protected function filter_print( $style ) |
||
200 | { |
||
201 | return true === $style['print']; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * This filter is used to return only the styles that are set to be loaded |
||
206 | * externally |
||
207 | * |
||
208 | * @param array $style |
||
209 | * @return boolean |
||
210 | */ |
||
211 | protected function filter_external( $style ) |
||
212 | { |
||
213 | return true !== $style['print']; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Parse the given CSS string by converting the variables to their |
||
218 | * corresponding values retrieved by applying the callback function |
||
219 | * |
||
220 | * @param callable $callback A function that replaces the variables with |
||
221 | * their values. The function accepts the variable's name as a parameter |
||
222 | * @param string $css A string containing dynamic CSS (pre-compiled CSS with |
||
223 | * variables) |
||
224 | * @return string The compiled CSS after converting the variables to their |
||
225 | * corresponding values |
||
226 | */ |
||
227 | protected function compile_css( $css, $callback ) |
||
228 | { |
||
229 | return preg_replace_callback( "#\\$([\\w-]+)((?:\\['?[\\w-]+'?\\])*)#", function( $matches ) use ( $callback ) { |
||
230 | // If this variable is an array, get the subscripts |
||
231 | if( '' !== $matches[2] ) |
||
232 | { |
||
233 | preg_match_all('/[\w-]+/i', $matches[2], $subscripts); |
||
234 | } |
||
235 | return call_user_func_array( $callback, array($matches[1],@$subscripts[0]) ); |
||
0 ignored issues
–
show
The variable
$subscripts does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
236 | }, $css); |
||
237 | } |
||
238 | } |
||
239 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.