GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 32f4b0...61806a )
by Askupa
02:38
created

DynamicCSSCompiler   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 330
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 16
Bugs 3 Features 7
Metric Value
c 16
b 3
f 7
dl 0
loc 330
rs 8.6
wmc 37
lcom 2
cbo 1

15 Methods

Rating   Name   Duplication   Size   Complexity  
A get_instance() 0 8 2
A enqueue_styles() 0 10 3
A enqueue_style() 0 19 3
A ajax_callback() 0 15 3
A register_style() 0 10 1
A register_callback() 0 4 1
A register_filter() 0 8 2
B get_compiled_style() 0 27 5
A add_meta_info() 0 8 1
A get_ajax_callback_url() 0 10 1
A minify_css() 0 4 1
A callback_exists() 0 12 2
B compile_css() 0 36 3
B apply_filters() 0 22 4
B strtoval() 0 7 5
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
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
25
{
26
    /**
27
     * @var DynamicCSSCompiler 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 The list of registered callbacks
38
     */
39
    private $callbacks = array();
40
    
41
    /**
42
     * @var aray The list of registered filters
43
     */
44
    private $filters = array();
45
    
46
    /**
47
     * Returns the *Singleton* instance of this class.
48
     *
49
     * @return DynamicCSSCompiler The *Singleton* instance.
50
     */
51
    public static function get_instance()
52
    {
53
        if (null === static::$instance) 
0 ignored issues
show
Bug introduced by
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 getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
54
        {
55
            static::$instance = new static();
0 ignored issues
show
Bug introduced by
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 getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
56
        }
57
        return static::$instance;
0 ignored issues
show
Bug introduced by
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 getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
58
    }
59
    
60
    /**
61
     * Enqueue the stylesheets that are registered to be loaded externally
62
     */
63
    public function enqueue_styles()
64
    {
65
        foreach( $this->stylesheets as $stylesheet )
66
        {
67
            if( $this->callback_exists( $stylesheet['handle'] ) )
68
            {
69
                $this->enqueue_style( $stylesheet );
70
            }
71
        }
72
    }
73
    
74
    /**
75
     * 
76
     * @param type $stylesheet
77
     */
78
    public function enqueue_style( $stylesheet )
79
    {
80
        $handle = 'wp-dynamic-css-'.$stylesheet['handle'];
81
        $print  = $stylesheet['print'];
82
        
83
        wp_register_style( 
84
            $handle,
85
            // Don't pass a URL if this style is to be printed
86
            $print ? false : $this->get_ajax_callback_url( $stylesheet['handle'] )
87
        );
88
89
        wp_enqueue_style( $handle );
90
        
91
        if( $stylesheet['print'] )
92
        {
93
            // Inline styles only work if the handle has already been registered and enqueued
94
            wp_add_inline_style( $handle, $this->get_compiled_style( $stylesheet ) );
95
        }
96
    }
97
    
98
    /**
99
     * This is the AJAX callback used for loading styles externally via an http 
100
     * request.
101
     */
102
    public function ajax_callback()
103
    {
104
        header( "Content-type: text/css; charset: UTF-8" );
105
        $handle = filter_input( INPUT_GET, 'handle' );
106
        
107
        foreach( $this->stylesheets as $stylesheet )
108
        {
109
            if( $handle === $stylesheet['handle'] )
110
            {
111
                echo $this->get_compiled_style( $stylesheet );
112
            }
113
        }
114
        
115
        wp_die();
116
    }
117
    
118
    /**
119
     * Add a style path to the pool of styles to be compiled
120
     * 
121
     * @param string $handle The stylesheet's name/id
122
     * @param string $path The absolute path to the dynamic style
123
     * @param boolean $print Whether to print the compiled CSS to the document
124
     * head, or include it as an external CSS file
125
     * @param boolean $minify Whether to minify the CSS output
126
     * @param boolean $cache Whether to store the compiled version of this 
127
     * stylesheet in cache to avoid compilation on every page load.
128
     */
129
    public function register_style( $handle, $path, $print, $minify, $cache )
130
    {
131
        $this->stylesheets[] = array(
132
            'handle'=> $handle,
133
            'path'  => $path,
134
            'print' => $print,
135
            'minify'=> $minify,
136
            'cache' => $cache
137
        );
138
    }
139
    
140
    /**
141
     * Register a value retrieval function and associate it with the given handle
142
     * 
143
     * @param type $handle The stylesheet's name/id
144
     * @param type $callback
145
     */
146
    public function register_callback( $handle, $callback )
147
    {
148
        $this->callbacks[$handle] = $callback;
149
    }
150
    
151
    /**
152
     * Register a filter function for a given stylesheet handle.
153
     */
154
    public function register_filter( $handle, $filter_name, $callback )
155
    {
156
        if( !array_key_exists( $handle, $this->filters ) )
157
        {
158
            $this->filters[$handle] = array();
159
        }
160
        $this->filters[$handle][$filter_name] = $callback;
161
    }
162
    
163
    /**
164
     * Get the compiled CSS for the given style. Skips compilation if the compiled
165
     * version can be found in cache.
166
     * 
167
     * @param array $style List of styles with the same structure as they are 
168
     * stored in $this->stylesheets
169
     * @return string The compiled CSS for this stylesheet
170
     */
171
    protected function get_compiled_style( $style )
172
    {
173
        $cache = DynamicCSSCache::get_instance();
174
        
175
        // Use cached compiled CSS if applicable
176
        if( $style['cache'] )
177
        {
178
            $cached_css = $cache->get( $style['handle'] );
179
            if( false !== $cached_css )
180
            {
181
                return $cached_css;
182
            }
183
        }
184
185
        $css = file_get_contents( $style['path'] );
186
        if( $style['minify'] ) $css = $this->minify_css( $css );
187
        
188
        // Compile the dynamic CSS
189
        $compiled_css = $this->compile_css( 
190
            $css, 
191
            $this->callbacks[$style['handle']], 
192
            key_exists( $style['handle'], $this->filters ) ? $this->filters[$style['handle']] : array()
193
        );
194
        
195
        $cache->update( $style['handle'], $compiled_css );
0 ignored issues
show
Documentation introduced by
$compiled_css is of type string, but the function expects a object<type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
196
        return $this->add_meta_info( $compiled_css );
197
    }
198
    
199
    /**
200
     * Add meta information to the compiled CSS
201
     * 
202
     * @param string $compiled_css The compiled CSS
203
     * @return string The compiled CSS with the meta information added to it
204
     */
205
    protected function add_meta_info( $compiled_css )
206
    {
207
        return "/**\n".
208
               " * Compiled using wp-dynamic-css\n".
209
               " * https://github.com/askupasoftware/wp-dynamic-css\n".
210
               " */\n\n".
211
               $compiled_css;
212
    }
213
    
214
    /**
215
     * Get the callback URL for enqueuing the stylesheet extrnally
216
     * 
217
     * @param string $handle The stylesheet's handle
218
     * @return string The URL for the given handle
219
     */
220
    protected function get_ajax_callback_url( $handle )
221
    {
222
        return esc_url_raw( 
223
            add_query_arg(array(
224
                'action' => 'wp_dynamic_css',
225
                'handle' => $handle
226
            ), 
227
            admin_url( 'admin-ajax.php'))
228
        );
229
    }
230
    
231
    /**
232
     * Minify a given CSS string by removing comments, whitespaces and newlines
233
     * 
234
     * @see http://stackoverflow.com/a/6630103/1096470
235
     * @param string $css CSS style to minify
236
     * @return string Minified CSS
237
     */
238
    protected function minify_css( $css )
239
    {
240
        return preg_replace( '@({)\s+|(\;)\s+|/\*.+?\*\/|\R@is', '$1$2 ', $css );
241
    }
242
    
243
    /**
244
     * Check if a callback function has been register for the given handle.
245
     * 
246
     * @param string $handle 
247
     * @return boolean
248
     */
249
    protected function callback_exists( $handle )
250
    {
251
        if( array_key_exists( $handle, $this->callbacks ) )
252
        {
253
            return true;
254
        }
255
        trigger_error( 
256
            "There is no callback function associated with the handle '$handle'. ".
257
            "Use <b>wp_dynamic_css_set_callback()</b> to register a callback function for this handle." 
258
        );
259
        return false;
260
    }
261
    
262
    /**
263
     * Parse the given CSS string by converting the variables to their 
264
     * corresponding values retrieved by applying the callback function
265
     * 
266
     * @param callable $callback A function that replaces the variables with 
267
     * their values. The function accepts the variable's name as a parameter
268
     * @param string $css A string containing dynamic CSS (pre-compiled CSS with 
269
     * variables)
270
     * @return string The compiled CSS after converting the variables to their 
271
     * corresponding values
272
     */
273
    protected function compile_css( $css, $callback, $filters )
274
    {
275
        return preg_replace_callback( 
276
                
277
            "#".                        // Begin
278
            "\\$".                      // Must start with $
279
            "([\\w-]+)".                // Match alphanumeric characters and dashes
280
            "((?:\\['?[\\w-]+'?\\])*)". // Optionally match array subscripts i.e. $myVar['index']
281
            "((?:".                     // Optionally match pipe filters i.e. $myVar|myFilter
282
                "\\|[\\w-]+".           // Starting with the | character
283
                "(\([\w\.,']+\))?".     // Filters can have strings and numbers i.e myFilter('string',1,2.5)
284
            ")*)".                      // Allow for 0 or more piped filters
285
            "#",                        // End
286
            
287
            function( $matches ) use ( $callback, $filters ) 
288
            {
289
                $subscripts = array();
290
                
291
                // If this variable is an array, get the subscripts
292
                if( '' !== $matches[2] )
293
                {
294
                    preg_match_all('/[\w-]+/i', $matches[2], $subscripts);
295
                }
296
                
297
                $val = call_user_func_array( $callback, array( $matches[1],@$subscripts[0] ) );
298
                
299
                // If there are filters, apply them
300
                if( '' !== $matches[3] )
301
                {
302
                    $val = $this->apply_filters( substr( $matches[3], 1 ), $val, $filters );
303
                }
304
                
305
                return $val;
306
            }, $css
307
        );
308
    }
309
    
310
    /**
311
     * Apply the filters specified in $filters_string to the given $value.
312
     * 
313
     * @param string $filters_string 
314
     * @param string $value
315
     * @param array $filters Array of callback functions
316
     * @return string The value after all filters have been applied
317
     */
318
    protected function apply_filters( $filters_string, $value, $filters )
319
    {
320
        foreach( explode( '|', $filters_string) as $filter )
321
        {
322
            $args = array( $value );
323
            
324
            if( false !== strrpos( $filters_string, "(" ) )
325
            {
326
                $pieces = explode( '(', $filter );
327
                $filter = $pieces[0];
328
                $params = explode( ',', str_replace( ')', '', $pieces[1] ) );
329
                array_walk( $params, array( $this, 'strtoval' ) ); // Convert string values to actual values
330
                $args = array_merge( $args, $params );
331
            }
332
            
333
            if( key_exists( $filter, $filters ) )
334
            {
335
                $value = call_user_func_array( $filters[$filter], $args );
336
            }
337
        }
338
        return $value;
339
    }
340
    
341
    /**
342
     * Convert the given string to its actual value.
343
     * 
344
     * @param string $str The string to be converted (passed by reference)
345
     */
346
    protected function strtoval( &$str )
347
    {
348
        if( 'false' === strtolower($str) ) $str = false;
349
        if( 'true' === strtolower($str) ) $str = true;
350
        if( false !== strrpos( $str, "'" ) ) $str = str_replace ( "'", "", $str );
351
        if( is_numeric( $str ) ) $str = floatval( $str );
352
    }
353
}
354