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 |
||
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) |
||
49 | { |
||
50 | static::$instance = new static(); |
||
51 | } |
||
52 | return static::$instance; |
||
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
|
|||
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]) ); |
||
236 | }, $css); |
||
237 | } |
||
238 | } |
||
239 |
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:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.