PluginProbe
CoolClock / 4.3.4
CoolClock v4.3.4
4.3.8 trunk 0.1 2.0 2.9.8 3.0 3.1 3.2 3.3 4.0 4.1 4.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7
coolclock / includes / class-coolclock.php

class-coolclock.php in CoolClock 4.3.4, at includes/class-coolclock.php

467 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * CoolClock Class
5 */
6
7 class CoolClock {
8
9 static $plugin_version;
10
11 static $script_version = '3.2.2';
12
13 private static $plugin_url;
14
15 private static $plugin_basename;
16
17 private static $min = '.min';
18
19 static $add_script = false;
20
21 private static $done_excanvas = false;
22
23 static $defaults = array(
24 'skin' => 'swissrail',
25 'radius' => 100,
26 'noseconds' => false, // true to hide second hand
27 'gmtoffset' => '', // GMT offset
28 'showdigital' => '', // show digital time or date
29 'scale' => '', // Define alternative clock type: 'logClock' logarithmic or 'logClockRev' reversed
30 'font' => '', // Define font size and family for digital time, default '15px monospace'
31 'fontcolor' => '' // Define font color for digital time, default '#333'
32 );
33
34 static $showdigital_options = array(
35 '' => '',
36 'digital12' => 'showDigital'
37 );
38
39 static $advanced_defaults = array(
40 'subtext' => '',
41 'align' => 'center'
42 );
43
44 static $more_skins_config = array();
45
46 static $advanced_skins_config = array();
47
48 static $skins_config = array();
49
50 /**
51 * DEPRICATED ARGUMENTS
52 * keep these for backward compatibility with old advanced extension
53 */
54 static $default_skins = array('swissRail');
55 static $more_skins = array();
56 static $advanced_skins = array();
57 static $advanced = false;
58 /* end unused arguments */
59
60 static $clock_types = array(
61 'linear' => '',
62 'logclock' => 'logClock',
63 'logclockrev' => 'logClockRev'
64 );
65
66 static $allowed_tags = array(
67 'a' => array(
68 'href' => array(),
69 'title' => array(),
70 'target' => array()
71 ),
72 'br' => array(),
73 'em' => array(),
74 'strong' => array(),
75 );
76
77 /**
78 * INIT
79 */
80
81 public function __construct( $plugin_file, $plugin_version )
82 {
83 // VARS
84 self::$plugin_url = plugins_url( '/', $plugin_file );
85 self::$plugin_basename = plugin_basename( $plugin_file );
86 self::$plugin_version = $plugin_version;
87
88 if ( defined('WP_DEBUG') && WP_DEBUG ) {
89 self::$min = '';
90 }
91
92 // text domain
93 add_action( 'plugins_loaded', array( __CLASS__, 'textdomain' ) );
94
95 // widgets
96 add_action( 'widgets_init', array( __CLASS__, 'register_widget' ) );
97
98 // enqueue scripts but only if shortcode or widget has been used
99 // so it has to be done as late as the wp_footer action
100 add_action( 'wp_footer', array( __CLASS__, 'enqueue_scripts' ), 1 );
101
102 add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_meta_links' ), 10, 2);
103
104 // backward compat
105 add_filter( 'coolclock_shortcode', array( __CLASS__, 'filter_shortcode'), 10, 3 );
106 add_filter( 'coolclock_widget', array( __CLASS__, 'filter_widget'), 10, 3 );
107
108 /**************
109 * SHORTCODE
110 **************/
111
112 add_shortcode( 'coolclock', array( 'CoolClock_Shortcode', 'handle_shortcode' ) );
113
114 // prevent texturizing shortcode content
115 add_filter( 'no_texturize_shortcodes', array( 'CoolClock_Shortcode', 'no_wptexturize') );
116 }
117
118 /**
119 * METHODS
120 */
121
122 /**
123 * Build canvas output
124 *
125 * @since 2.0
126 *
127 * @param array $atts Array of sanitized attributes
128 *
129 * @return string Canvas tag
130 */
131
132 public static function canvas( $atts )
133 {
134 /**
135 * ARRAY VALUES
136 * skin @param string Skin ID. Must be one of these: 'swissRail' (default skin), 'chunkySwiss', 'chunkySwissOnBlack', 'fancy', 'machine', 'simonbaird_com', 'classic', 'modern', 'simple', 'securephp', 'Tes2', 'Lev', 'Sand', 'Sun', 'Tor', 'Cold', 'Babosa', 'Tumb', 'Stone', 'Disc', 'watermelon' or 'mister'.
137 * If the Advanced extension is activated, there is also 'minimal' available.
138 * radius @param int Define the clock radius.
139 * noseconds @param bool True to hide the second hand.
140 * gmtoffset @param float Timezone offset relative the Greenwhich Mean Time
141 * showdigital @param string|bool Set to 'digital12' to show the time in 12h digital format (with am/pm).
142 * font @param string Set to a font size, family and style for the digital time
143 * fontcolor @param string Set to a color value to change the digital time color
144 * scale @param string Optional alternative clock scale 'logClock' or 'logClockRev'
145 * subtext @param string Optional text, centered below the clock
146 * align @param string Sets floating of the clock: 'left', 'right' or 'center'
147 */
148
149 // get defaults for missing attributes
150 $defaults = array_merge( self::$defaults, self::$advanced_defaults );
151
152 $atts = apply_filters( 'coolclock_atts', $atts, $defaults );
153
154 // CoolClock fields array
155 $fields = array();
156 $fields[] = 'CoolClock';
157 // skin id
158 $fields[] = !empty( $atts['skin'] ) ? $atts['skin'] : $defaults['skin'];
159 // radius
160 $fields[] = !empty( $atts['radius'] ) && is_numeric($atts['radius']) ? (int) $atts['radius'] : $defaults['radius'];
161 // noseconds
162 $noseconds = isset( $atts['noseconds'] ) ? (bool) $atts['noseconds'] : $defaults['noseconds'];
163 $fields[] = $noseconds ? 'noSeconds' : '';
164 // gmt offset
165 $fields[] = isset( $atts['gmtoffset'] ) && is_numeric( $atts['gmtoffset'] ) ? (float) $atts['gmtoffset'] : $defaults['gmtoffset'];
166 // show digital
167 $showdigital = isset($atts['showdigital']) ? $atts['showdigital'] : $defaults['showdigital'];
168 if ( true === $showdigital )
169 $showdigital = 'digital12';
170 $fields[] = isset( self::$showdigital_options[$showdigital] ) ? self::$showdigital_options[$showdigital] : '';
171 // clock type
172 $scale = isset( $atts['scale'] ) ? strtolower( $atts['scale'] ) : $defaults['scale'];
173 $fields[] = isset( self::$clock_types[$scale] ) ? self::$clock_types[$scale] : '';
174 // set font color
175 $fields[] = isset( $atts['fontcolor'] ) ? $atts['fontcolor'] : $defaults['fontcolor'];
176
177 $fields = apply_filters( 'coolclock_fields_array', $fields, $atts, $defaults );
178
179 // build output
180 $output = '';
181
182 if ( ! self::$done_excanvas ){
183 $output .= '<!--[if lte IE 8]>';
184 $output .= '<script type="text/javascript" src="'. self::$plugin_url . 'js/excanvas' . self::$min . '.js"></script>';
185 $output .= '<![endif]-->' . PHP_EOL;
186 self::$done_excanvas = true;
187 }
188
189 $styles = apply_filters( 'coolclock_canvas_styles', array(), $atts, $defaults );
190
191 // canvas parameters
192 $output .= '<canvas class="' . implode(':',$fields) . '"' . CoolClock::inline_style( $styles ) . '></canvas>';
193
194 // sub text
195 $subtext = ( isset( $atts['subtext'] ) ) ? $atts['subtext'] : $defaults['subtext'];
196 if ( !empty( $subtext ) )
197 $output .= '<div class="coolclock-subtext">' . $subtext . '</div>';
198
199 return $output;
200 }
201
202 /**
203 * Create inline style attribute from array
204 *
205 * @since 4.3
206 *
207 * @param array $styles array with style parameters and their values
208 *
209 * @return string inline style attribute style="..." complete with leading space
210 */
211
212 public static function inline_style( $styles )
213 {
214 $style_arr = array();
215
216 foreach ( $styles as $key => $value ) {
217 $style_arr[] = $key . ':' . $value;
218 }
219
220 $style = ! empty($style_arr) ? ' style="' . implode( ';', $style_arr ) . '"' : '';
221
222 return $style;
223 }
224
225 /**
226 * Parse skin name and user skin parameters
227 *
228 * @since 3.2.0
229 *
230 * @param string $skin_name skin name
231 * @param string $skin_parms skin parameters, preferably in JSON format
232 *
233 * @return string either found matching skin name or 'invalid_or_missing_skin' on failure
234 */
235
236 public static function parse_skin( $skin_name, $skin_parms = '' )
237 {
238 $skin = strtolower($skin_name);
239 $skin_array = array();
240
241 // check for empty or default skin first
242 if ( empty($skin) || $skin == self::$defaults['skin'] )
243 // return the matching skin name
244 return self::$defaults['skin'];
245
246 // short-circuit if skin name is already in the config array
247 if ( array_key_exists( $skin, self::$skins_config ) )
248 // return the matching skin name
249 return $skin;
250
251 // search in the more_skins and advanced_skins arrays
252 $all_skins = self::get_all_skins();
253 if ( array_key_exists( $skin, $all_skins ) ) {
254 // fetch parameters from skins array
255 $skin_array = is_array( $all_skins[$skin] ) ? $all_skins[$skin] : self::skin_array( $all_skins[$skin] );
256 }
257 // try to build a skin config from passed parameters
258 else {
259 // fetch parameters from custom skin user input
260 $skin_array = self::skin_array( $skin_parms );
261
262 if ( empty( $skin_array ) )
263 // set faulty skin name
264 return 'no_skin_found';
265 }
266
267 // add found skin parameters to the config array
268 self::$skins_config[$skin] = $skin_array;
269
270 // return the matching skin name
271 return $skin;
272 }
273
274 public static function get_all_skins() {
275
276 if ( empty( self::$more_skins_config ) ) {
277
278 include COOLCLOCK_DIR . 'includes/moreskins.php';
279
280 self::$more_skins_config = $more_skins;
281
282 }
283
284 return array_merge( self::$more_skins_config, self::$advanced_skins_config );
285 }
286
287 public static function enqueue_scripts() {
288 // bail if we don't need script
289 if ( ! self::$add_script )
290 return;
291
292 $script = '';
293
294 if ( !empty( self::$skins_config ) ) {
295
296 /**
297 * Load IE 6/7 specific JSON polyfill
298 */
299 wp_enqueue_script( 'json2' );
300
301 $script .= 'CoolClock.config.skins = JSON.parse(\'' . json_encode( self::$skins_config ) . '\');';
302
303 }
304
305 $script .= PHP_EOL . 'if(document.readyState!="loading"&&document.addEventListener){document.addEventListener("DOMContentLoaded",function(){CoolClock.findAndCreateClocks();})}else{CoolClock.findAndCreateClocks();};';
306
307 wp_enqueue_script( 'coolclock', self::$plugin_url . 'js/coolclock' . self::$min . '.js', false, self::$script_version, true );
308
309 wp_add_inline_script( 'coolclock', $script );
310
311 // called late so should end up in the footer
312 wp_enqueue_style( 'coolclock', self::$plugin_url . 'css/coolclock' . self::$min . '.css' );
313 }
314
315 public static function textdomain() {
316 load_plugin_textdomain( 'coolclock', false, dirname(self::$plugin_basename).'/languages' );
317 }
318
319 public static function register_widget() {
320 register_widget("CoolClock_Widget");
321 }
322
323 // add links to plugin's description
324 public static function plugin_meta_links($links, $file) {
325 $support_link = '<a target="_blank" href="https://wordpress.org/support/plugin/coolclock/">' . __('Support','coolclock') . '</a>';
326 $rate_link = '<a target="_blank" href="https://wordpress.org/support/plugin/coolclock/reviews/?filter=5#new-post">' . __('Rate �
327 �
328 �
329 �
330 �
331 ','coolclock') . '</a>';
332
333 if ( $file == self::$plugin_basename ) {
334 $links[] = $support_link;
335 $links[] = $rate_link;
336 }
337
338 return $links;
339 }
340
341 /**
342 * Turn custom skin user input into an array
343 *
344 * @since 2.0
345 *
346 * @param string $skin
347 *
348 * @return array array of skin parameters
349 */
350
351 public static function skin_array( $skin )
352 {
353 // remove everything following a ; to thwart any script injection
354 $parts = explode( ';', $skin, 2 );
355 $sanitized = $parts[0];
356 // strip all kind of whitespace
357 $sanitized = preg_replace("/\s+/", '', $sanitized);;
358 $sanitized = ltrim( $sanitized, '{' );
359 $sanitized = rtrim( $sanitized, '}' ) . '}';
360 // by now, the string should start with a double quote
361 if ( 0 !== strpos( $sanitized, '"' ) ) {
362 // regex for (re)wrapping all keys in double quotes
363 $sanitized = preg_replace( "/(['\"])?([a-zA-Z0-9_]+)(['\"])?:([^\/])/", '"$2":$4', $sanitized );
364 }
365
366 // fist attempt to decode json string
367 $skin_array = json_decode( '{' . $sanitized . '}', true );
368
369 // not valid json? then do it the hard way
370 if ( null === $skin_array ) :
371
372 // remove all spaces and tabs
373 $sanitized = str_replace( array( ' ', "\t", '"', "'" ), '', $sanitized );
374
375 // break it all up in little parts
376 // this converts valid skin javascript object into json, but messes up all else :/
377 $elements = explode( '},', $sanitized );
378
379 // start fresh
380 $skin_array = array();
381
382 // and build array
383 foreach( $elements as $element ) {
384 $pair = explode( ':{', $element );
385 // validate key
386 $part = str_replace( '{', '', $pair[0] );
387 if ( ! in_array( $part, array('outerBorder','smallIndicator','largeIndicator','hourHand','minuteHand','secondHand','secondDecoration') ) )
388 continue;
389 // constuct value
390 $value = array();
391 $parameters = explode( ',', $pair[1] );
392 for( $i=0; $i < count( $parameters ); $i++ ) {
393 $pairs = explode( ':', $parameters[$i] );
394 $parm_val = str_replace( '}', '', $pairs[1] );
395 $value[$pairs[0]] = is_numeric($parm_val) ? (float) $parm_val : (string) $parm_val;
396 }
397 $skin_array[$part] = $value;
398 }
399
400 endif;
401
402 return $skin_array;
403 }
404
405 /**
406 * Sanitize color value user input
407 *
408 * @since 4.2
409 *
410 * @param string $color
411 *
412 * @return string hex color value or text for named color
413 */
414
415 public static function colorval( $color )
416 {
417 $color = wp_strip_all_tags( $color );
418 $color = trim( $color );
419
420 if ( substr($color, 0, 1) == '#' ) {
421 if ( ctype_xdigit( substr( $color, 1 ) ) )
422 return $color;
423
424 return substr( $color, 1 );
425 }
426
427 return ctype_xdigit( $color ) ? '#'.$color : $color;
428 }
429
430 /**
431 * Filter shortcode output
432 *
433 * @since 4.3
434 *
435 * @param string $output output
436 * @param array $atts array of shortcode attributes
437 * @param string $content shortcode content
438 *
439 * @return string output
440 */
441
442 public static function filter_shortcode( $output, $atts, $content )
443 {
444 // add backward compat filter
445 return apply_filters( 'coolclock_shortcode_advanced', $output, $atts, $content );
446 }
447
448 /**
449 * Filter widget output
450 *
451 * @since 4.3
452 *
453 * @param string $output output
454 * @param array $args array of widget parameters
455 * @param array $instance widget instance array parameters
456 *
457 * @return string output
458 */
459
460 public static function filter_widget( $output, $args, $instance )
461 {
462 // add backward compat filter
463 return apply_filters( 'coolclock_widget_advanced', $output, $args, $instance );
464 }
465
466 }
467