Favicon Rotator - Version 1.1

Version Description

  • Added: Generate icon file from uploaded images
  • Added: Settings link from plugins page
  • Optimized: File path resolution
Download this release

Release Info

Developer Archetyped
Plugin Icon wp plugin Favicon Rotator
Version 1.1
Comparing to
See all releases

Code changes from version 1.0 to 1.1

css/media.css ADDED
@@ -0,0 +1 @@
 
1
+ .ml-submit { display: none !important; }
includes/class.base.php CHANGED
@@ -9,6 +9,18 @@ require_once 'class.utilities.php';
9
  */
10
  class FVRT_Base {
11
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Prefix for Cornerstone-related data (attributes, DB tables, etc.)
14
  * @var string
@@ -21,6 +33,12 @@ class FVRT_Base {
21
  */
22
  var $util;
23
 
 
 
 
 
 
 
24
  /**
25
  * Legacy constructor
26
  */
@@ -33,6 +51,7 @@ class FVRT_Base {
33
  */
34
  function __construct() {
35
  $this->util =& new FVRT_Utilities();
 
36
  }
37
 
38
  /**
9
  */
10
  class FVRT_Base {
11
 
12
+ /**
13
+ * Size to use for icon attachment
14
+ * @var string
15
+ */
16
+ var $icon_size = 'favicon';
17
+
18
+ /**
19
+ * Favicon Dimensions
20
+ * @var array
21
+ */
22
+ var $icon_dimensions = array('w' => '16', 'h' => '16');
23
+
24
  /**
25
  * Prefix for Cornerstone-related data (attributes, DB tables, etc.)
26
  * @var string
33
  */
34
  var $util;
35
 
36
+ /**
37
+ * Debug instance
38
+ * @var FVRT_Debug
39
+ */
40
+ var $debug;
41
+
42
  /**
43
  * Legacy constructor
44
  */
51
  */
52
  function __construct() {
53
  $this->util =& new FVRT_Utilities();
54
+ $this->debug =& new FVRT_Debug();
55
  }
56
 
57
  /**
includes/class.media.php CHANGED
@@ -65,11 +65,18 @@ class FVRT_Media extends FVRT_Base {
65
  /* Methods */
66
 
67
  function register_hooks() {
 
 
 
68
  //Register handler for custom media requests
69
  add_action('media_upload_' . $this->add_prefix('icon'), $this->m('upload_icon'));
70
- //Display 'Set as...' button in media item box
 
71
  add_filter('attachment_fields_to_edit', $this->m('attachment_fields_to_edit'), 11, 2);
72
 
 
 
 
73
  //Modify tabs in upload popup for fields
74
  add_filter('media_upload_tabs', $this->m('field_upload_tabs'));
75
 
@@ -77,6 +84,23 @@ class FVRT_Media extends FVRT_Base {
77
  add_filter('upload_file_glob', $this->m('upload_file_types'));
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  /**
81
  * Initialize value of instance variables
82
  */
@@ -117,6 +141,34 @@ class FVRT_Media extends FVRT_Base {
117
  return $url;
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  /**
121
  * Handles upload/selecting of an icon
122
  */
@@ -131,11 +183,15 @@ class FVRT_Media extends FVRT_Base {
131
  $field_var = $this->add_prefix('field');
132
  $args = new stdClass();
133
  $args->id = array_shift( array_keys($_POST[$this->var_setmedia]) );
134
- $a =& get_post($args->id);
135
- //Build object of properties to send to parent page
136
- if ( ! empty($a) && wp_attachment_is_image($a->ID) ) {
137
- $args->url = wp_get_attachment_url($a->ID);
138
- $args->name = basename($args->url);
 
 
 
 
139
  }
140
  //Build JS Arguments string
141
  $arg_string = array();
@@ -175,6 +231,14 @@ class FVRT_Media extends FVRT_Base {
175
  return wp_iframe( $upload_form, $type, $errors, $id );
176
  }
177
 
 
 
 
 
 
 
 
 
178
  /**
179
  * Modifies array of form fields to display on Attachment edit form
180
  * Array items are in the form:
@@ -236,18 +300,16 @@ class FVRT_Media extends FVRT_Base {
236
  function is_custom_media() {
237
  $ret = false;
238
  $action = $this->var_action;
239
- $upload = false;
240
- if (isset($_REQUEST[$action]))
241
  $ret = true;
242
  else {
243
  $qs = array();
244
- $ref = parse_url($_SERVER['HTTP_REFERER']);
245
  if ( isset($ref['query']) )
246
  parse_str($ref['query'], $qs);
247
  if (array_key_exists($action, $qs))
248
  $ret = true;
249
  }
250
-
251
  return $ret;
252
  }
253
 
65
  /* Methods */
66
 
67
  function register_hooks() {
68
+ //Modify layout on media upload page
69
+ add_action('admin_print_styles-media-upload-popup', $this->m('upload_styles'));
70
+
71
  //Register handler for custom media requests
72
  add_action('media_upload_' . $this->add_prefix('icon'), $this->m('upload_icon'));
73
+
74
+ //Display custom UI in media item box
75
  add_filter('attachment_fields_to_edit', $this->m('attachment_fields_to_edit'), 11, 2);
76
 
77
+ //Resize icons
78
+ add_filter('intermediate_image_sizes', $this->m('add_intermediate_image_size'));
79
+
80
  //Modify tabs in upload popup for fields
81
  add_filter('media_upload_tabs', $this->m('field_upload_tabs'));
82
 
84
  add_filter('upload_file_glob', $this->m('upload_file_types'));
85
  }
86
 
87
+ /**
88
+ * Adds icon size to intermediate images
89
+ * Only added when image is uploaded by plugin
90
+ * @param array $sizes Names of intermediate sizes
91
+ * @return array Updated sizes
92
+ */
93
+ function add_intermediate_image_size($sizes) {
94
+ $img = array('width' => 0, 'height' => 0, 'crop' => true);
95
+ if ( $this->is_custom_media() ) {
96
+ $img['width'] = $this->icon_dimensions['w'];
97
+ $img['height'] = $this->icon_dimensions['h'];
98
+ }
99
+ add_image_size($this->icon_size, $img['width'], $img['height'], $img['crop']);
100
+ $sizes[] = $this->icon_size;
101
+ return $sizes;
102
+ }
103
+
104
  /**
105
  * Initialize value of instance variables
106
  */
141
  return $url;
142
  }
143
 
144
+ /**
145
+ * Retrieve source data for icon media
146
+ * @param int $icon_id Attachment ID
147
+ * @return array Image data (src, width, height)
148
+ */
149
+ function get_icon_src($icon_id) {
150
+ $this->update_attachment_metadata($icon_id);
151
+ $icon = ( wp_attachment_is_image($icon_id) ) ? wp_get_attachment_image_src($icon_id, $this->icon_size) : wp_get_attachment_url($icon_id);
152
+ if ( is_string($icon) )
153
+ $icon = array($icon, 0, 0);
154
+ return $icon;
155
+ }
156
+
157
+ /**
158
+ * Updates image thumbnail if necessary
159
+ * @param int $id Attachment ID
160
+ */
161
+ function update_attachment_metadata($id) {
162
+ //Generate favicon image file (if necessary)
163
+ if ( ( $meta = wp_get_attachment_metadata($id) ) && !isset($meta['sizes'][$this->icon_size]) && wp_attachment_is_image($id) ) {
164
+ //Full metadata update
165
+ if ( function_exists('wp_generate_attachment_metadata') ) {
166
+ $data = wp_generate_attachment_metadata($id, get_attached_file($id));
167
+ wp_update_attachment_metadata( $id, $data );
168
+ }
169
+ }
170
+ }
171
+
172
  /**
173
  * Handles upload/selecting of an icon
174
  */
183
  $field_var = $this->add_prefix('field');
184
  $args = new stdClass();
185
  $args->id = array_shift( array_keys($_POST[$this->var_setmedia]) );
186
+ //Make sure post is valid
187
+ if ( wp_attachment_is_image($args->id) ) {
188
+ //Build object of properties to send to parent page
189
+ $icon = $this->get_icon_src($args->id);
190
+ if ( !empty($icon) ) {
191
+ $args->url = $icon[0];
192
+ $meta = wp_get_attachment_metadata($args->id);
193
+ $args->name = basename( ( isset($meta['file']) && !empty($meta['file']) ) ? $meta['file'] : wp_get_attachment_url($args->id) );
194
+ }
195
  }
196
  //Build JS Arguments string
197
  $arg_string = array();
231
  return wp_iframe( $upload_form, $type, $errors, $id );
232
  }
233
 
234
+ /**
235
+ * Loads CSS Styles for media upload pages
236
+ */
237
+ function upload_styles() {
238
+ if ( $this->is_custom_media() )
239
+ wp_enqueue_style($this->add_prefix('media'), $this->util->get_file_url('css/media.css'));
240
+ }
241
+
242
  /**
243
  * Modifies array of form fields to display on Attachment edit form
244
  * Array items are in the form:
300
  function is_custom_media() {
301
  $ret = false;
302
  $action = $this->var_action;
303
+ if ( isset($_REQUEST[$action]) || ( isset($_REQUEST['type']) && $_REQUEST['type'] == $this->var_type ) )
 
304
  $ret = true;
305
  else {
306
  $qs = array();
307
+ $ref = parse_url(wp_get_referer());
308
  if ( isset($ref['query']) )
309
  parse_str($ref['query'], $qs);
310
  if (array_key_exists($action, $qs))
311
  $ret = true;
312
  }
 
313
  return $ret;
314
  }
315
 
includes/class.utilities.php CHANGED
@@ -3,7 +3,8 @@
3
  /**
4
  * Utility methods
5
  *
6
- * @package Redactor
 
7
  * @author Archetyped
8
  *
9
  */
@@ -103,14 +104,32 @@ class FVRT_Utilities {
103
  } else {
104
  $trailing_slash = false;
105
  }
 
106
  //Trim trailing slashes from path parts
107
  foreach ( $parts as $key => $part ) {
108
  $part = trim($part);
 
109
  $parts[$key] = trim($part, $sl_f . $sl_b);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
  }
 
112
  $parts = implode($sl_b, $parts);
113
  $parts = str_replace($sl_b, $sl_f, $parts);
 
114
  if ( $trailing_slash )
115
  $parts . $sl_f;
116
  return $parts;
@@ -123,12 +142,34 @@ class FVRT_Utilities {
123
  */
124
  function get_file_url($file) {
125
  if (is_string($file) && '' != trim($file)) {
126
- $file = ltrim(trim($file), '/');
127
- $file = sprintf('%s/%s', $this->get_url_base(), $file);
128
  }
129
  return $file;
130
  }
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  /**
133
  * Retrieve base URL for plugin-specific files
134
  * @return string Base URL
@@ -256,9 +297,10 @@ class FVRT_Utilities {
256
  * - If the current item's value OR the corresponding item in the base array is NOT an array, current item overwrites base item
257
  * @todo Append numerical elements (as opposed to overwriting element at same index in base array)
258
  * @param array Variable number of arrays
 
259
  * @return array Merged array
260
  */
261
- function array_merge_recursive_distinct() {
262
  //Get all arrays passed to function
263
  $args = func_get_args();
264
  if (empty($args))
@@ -418,12 +460,68 @@ class FVRT_Utilities {
418
  return $ret;
419
  }
420
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
  /*-** Admin **-*/
422
 
423
  /**
424
  * Add submenu page in the admin menu
425
  * Adds ability to set the position of the page in the menu
426
- * @see add_submin_menu (Wraps functionality)
427
  *
428
  * @param $parent
429
  * @param $page_title
@@ -435,30 +533,29 @@ class FVRT_Utilities {
435
  *
436
  * @global array $submenu Admin page submenus
437
  */
438
- function add_submenu_page($parent, $page_title, $menu_title, $access_level, $file, $function = '', $pos = false) {
439
- global $submenu;
440
-
441
  //Add submenu page as usual
442
  $args = func_get_args();
443
  $hookname = call_user_func_array('add_submenu_page', $args);
444
-
445
  if ( is_int($pos) ) {
 
446
  //Get last submenu added
447
  $parent = $this->get_submenu_parent_file($parent);
448
- $subs =& $submenu[$parent];
449
-
450
- //Make sure menu isn't already in the desired position
451
- if ( $pos <= ( count($subs) - 1 ) ) {
452
- //Get submenu that was just added
453
- $sub = array_pop($subs);
454
- //Insert into desired position
455
- if ( 0 == $pos ) {
456
- array_unshift($subs, $sub);
457
- } else {
458
- $top = array_slice($subs, 0, $pos);
459
- $bottom = array_slice($subs, $pos);
460
- array_push($top, $sub);
461
- $subs = array_merge($top, $bottom);
 
462
  }
463
  }
464
  }
@@ -541,4 +638,164 @@ class FVRT_Utilities {
541
  $parent = $_wp_real_parent_file[$parent];
542
  return $parent;
543
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544
  }
3
  /**
4
  * Utility methods
5
  *
6
+ * @package Favicon Rotator
7
+ * @subpackage Utilities
8
  * @author Archetyped
9
  *
10
  */
104
  } else {
105
  $trailing_slash = false;
106
  }
107
+ $first = true;
108
  //Trim trailing slashes from path parts
109
  foreach ( $parts as $key => $part ) {
110
  $part = trim($part);
111
+ //Special Trim
112
  $parts[$key] = trim($part, $sl_f . $sl_b);
113
+ //Verify path still contains value
114
+ if ( empty($parts[$key]) ) {
115
+ unset($parts[$key]);
116
+ continue;
117
+ }
118
+ //Only continue processing the first valid path segment
119
+ if ( $first )
120
+ $first = !$first;
121
+ else
122
+ continue;
123
+ //Add back leading slash if necessary
124
+ if ( $part[0] == $sl_f || $part[0] == $sl_b )
125
+ $parts[$key] = $sl_f . $parts[$key];
126
+
127
  }
128
  }
129
+ //Join path parts together
130
  $parts = implode($sl_b, $parts);
131
  $parts = str_replace($sl_b, $sl_f, $parts);
132
+ //Add trailing slash (if necessary)
133
  if ( $trailing_slash )
134
  $parts . $sl_f;
135
  return $parts;
142
  */
143
  function get_file_url($file) {
144
  if (is_string($file) && '' != trim($file)) {
145
+ $file = $this->normalize_path($this->get_url_base(), $file);
 
146
  }
147
  return $file;
148
  }
149
 
150
+ /**
151
+ * Retrieves file extension
152
+ * @param string $file file name/path
153
+ * @return string File's extension
154
+ */
155
+ function get_file_extension($file) {
156
+ $ret = '';
157
+ $sep = '.';
158
+ if ( is_string($icon) && ( $rpos = strrpos($file, $sep) ) !== false )
159
+ $ret = substr($file, $rpos + 1);
160
+ return $ret;
161
+ }
162
+
163
+ /**
164
+ * Checks if file has specified extension
165
+ * @param string $file File name/path
166
+ * @param string $extension File ending to check $file for
167
+ * @return bool TRUE if file has extension
168
+ */
169
+ function has_file_extension($file, $extension) {
170
+ return ( $this->get_file_extension($file) == $extension ) ? true : false;
171
+ }
172
+
173
  /**
174
  * Retrieve base URL for plugin-specific files
175
  * @return string Base URL
297
  * - If the current item's value OR the corresponding item in the base array is NOT an array, current item overwrites base item
298
  * @todo Append numerical elements (as opposed to overwriting element at same index in base array)
299
  * @param array Variable number of arrays
300
+ * @param array $arr1 Default array
301
  * @return array Merged array
302
  */
303
+ function array_merge_recursive_distinct($arr1) {
304
  //Get all arrays passed to function
305
  $args = func_get_args();
306
  if (empty($args))
460
  return $ret;
461
  }
462
 
463
+ /**
464
+ * Generate external stylesheet element
465
+ * @param $url Stylesheet URL
466
+ * @return string Stylesheet element
467
+ */
468
+ function build_stylesheet_element($url = '') {
469
+ $attributes = array('href' => $url, 'type' => 'text/css', 'rel' => 'stylesheet');
470
+ return $this->build_html_element(array('tag' => 'link', 'wrap' => false, 'attributes' => $attributes));
471
+ }
472
+
473
+ /**
474
+ * Generate external script element
475
+ * @param $url Script URL
476
+ * @return string Script element
477
+ */
478
+ function build_ext_script_element($url = '') {
479
+ $attributes = array('src' => $url, 'type' => 'text/javascript');
480
+ return $this->build_html_element(array('tag' => 'script', 'attributes' => $attributes));
481
+ }
482
+
483
+ /**
484
+ * Generate HTML element based on values
485
+ * @param $args Element arguments
486
+ * @return string Generated HTML element
487
+ */
488
+ function build_html_element($args) {
489
+ $defaults = array(
490
+ 'tag' => 'span',
491
+ 'wrap' => true,
492
+ 'content' => '',
493
+ 'attributes' => array()
494
+ );
495
+ $el_start = '<';
496
+ $el_end = '>';
497
+ $el_close = '/';
498
+ extract(wp_parse_args($args, $defaults), EXTR_SKIP);
499
+ $content = trim($content);
500
+
501
+ if ( !$wrap && strlen($content) > 0 )
502
+ $wrap = true;
503
+
504
+ $attributes = $this->build_attribute_string($attributes);
505
+ if ( strlen($attributes) > 0 )
506
+ $attributes = ' ' . $attributes;
507
+
508
+ $ret = $el_start . $tag . $attributes;
509
+
510
+ if ( $wrap )
511
+ $ret .= $el_end . $content . $el_start . $el_close . $tag;
512
+ else
513
+ $ret .= ' ' . $el_close;
514
+
515
+ $ret .= $el_end;
516
+ return $ret;
517
+ }
518
+
519
  /*-** Admin **-*/
520
 
521
  /**
522
  * Add submenu page in the admin menu
523
  * Adds ability to set the position of the page in the menu
524
+ * @see add_submenu_page (Wraps functionality)
525
  *
526
  * @param $parent
527
  * @param $page_title
533
  *
534
  * @global array $submenu Admin page submenus
535
  */
536
+ function add_submenu_page($parent, $page_title, $menu_title, $capability, $file, $function = '', $pos = false) {
 
 
537
  //Add submenu page as usual
538
  $args = func_get_args();
539
  $hookname = call_user_func_array('add_submenu_page', $args);
 
540
  if ( is_int($pos) ) {
541
+ global $submenu;
542
  //Get last submenu added
543
  $parent = $this->get_submenu_parent_file($parent);
544
+ if ( isset($submenu[$parent]) ) {
545
+ $subs =& $submenu[$parent];
546
+ //Make sure menu isn't already in the desired position
547
+ if ( $pos <= ( count($subs) - 1 ) ) {
548
+ //Get submenu that was just added
549
+ $sub = array_pop($subs);
550
+ //Insert into desired position
551
+ if ( 0 == $pos ) {
552
+ array_unshift($subs, $sub);
553
+ } else {
554
+ $top = array_slice($subs, 0, $pos);
555
+ $bottom = array_slice($subs, $pos);
556
+ array_push($top, $sub);
557
+ $subs = array_merge($top, $bottom);
558
+ }
559
  }
560
  }
561
  }
638
  $parent = $_wp_real_parent_file[$parent];
639
  return $parent;
640
  }
641
+ }
642
+
643
+ class FVRT_Debug {
644
+ /**
645
+ * @var array Associative array of debug messages
646
+ */
647
+ var $msgs = array();
648
+
649
+ /**
650
+ * @var array Holds various timer objects
651
+ */
652
+ var $timers = array();
653
+
654
+ /* Constructor */
655
+
656
+ function CNR_Debug() {
657
+ $this->__construct();
658
+ }
659
+
660
+ function __construct() {
661
+
662
+ }
663
+
664
+ /**
665
+ * Adds debug data to object
666
+ * @return void
667
+ * @param String $title Title of debug message
668
+ * @param mixed $message value to store in message for debugging purposes
669
+ */
670
+ function add_message($title, $message) {
671
+ $this->msgs[$title] = $message;
672
+ }
673
+
674
+ /**
675
+ * Returns debug message array
676
+ * @return array Debug message array
677
+ */
678
+ function get_messages() {
679
+ return $this->msgs;
680
+ }
681
+
682
+ function show_messages() {
683
+ echo '<pre>';
684
+ var_dump($this->get_messages());
685
+ echo '</pre>';
686
+ }
687
+
688
+ function print_message($msg) {
689
+ foreach (func_get_args() as $msg) {
690
+ echo '<pre>';
691
+ if (is_scalar($msg) && !is_bool($msg)) {
692
+ echo htmlspecialchars($msg) . "<br />";
693
+ } else {
694
+ var_dump($msg);
695
+ }
696
+ echo '</pre>';
697
+ }
698
+ }
699
+
700
+ function microtime_float() {
701
+ list($usec, $sec) = explode(' ', microtime());
702
+ return (float)$usec + (float)$sec;
703
+ }
704
+
705
+ function timer_start($name = 'default', $time = null) {
706
+ if (empty($time)) $time = $this->microtime_float();
707
+ $this->timers[$name] = new stdClass();
708
+ $this->timers[$name]->start = $time;
709
+ $this->timers[$name]->end = $time;
710
+ }
711
+
712
+ function timer_stop($name = 'default') {
713
+ $time = $this->microtime_float();
714
+ if (!isset($this->timers[$name])
715
+ || !is_object($this->timers[$name])
716
+ ) {
717
+ $this->timer_start($name, $time);
718
+ } else {
719
+ $this->timers[$name]->end = $time;
720
+ }
721
+ }
722
+
723
+ function timer_show($name = 'default', $format = 'Elapsed time: %s') {
724
+ if (!isset($this->timers[$name])
725
+ || !is_object($this->timers[$name])
726
+ || $this->timers[$name]->end < $this->timers[$name]->start
727
+ ) {
728
+ $this->timer_start($name);
729
+ }
730
+ //Get difference in times
731
+ $res = (float)$this->timers[$name]->end - (float)$this->timers[$name]->start;
732
+ $this->print_message(sprintf($format, $res));
733
+ }
734
+
735
+ /**
736
+ * Retrieve current function name
737
+ * @param string|array $properties (optional) Properties to retrieve for current function
738
+ * @return string|array Current function properties. Default: function name. Will return array if multiple properties are requested
739
+ * @see CNR_Debug::backtrace
740
+ */
741
+ function get_current($properties = 'function') {
742
+ return $this->backtrace($properties, 1, 2);
743
+ }
744
+
745
+ /**
746
+ * Retrieves calling function name
747
+ * @param string|array $properties (optional) Properties to retrieve for caller
748
+ * @return string|array Calling function properties. Default: function name. Will return array if multiple properties are requested
749
+ * @see CNR_Debug::backtrace
750
+ */
751
+ function get_caller($properties = 'function') {
752
+ return $this->backtrace($properties, 1, 3);
753
+ }
754
+
755
+ /**
756
+ * Return customized backtrace
757
+ * @param string|array $properties (optional) Properties to retrieve for each level (Default: all properties) Can be comma-delimited string or array
758
+ * @param int $levels (optional) Number of levels to retrieve (Default: entire backtrace)
759
+ * @param int $offset (optional) Where to start backtrace output (e.g. Remove current/wrapper functions from output, etc.)
760
+ * @return array|string Backtrace output as Array. Will output string if only one level with one property is in output
761
+ */
762
+ function backtrace($properties = null, $levels = null, $offset = 1) {
763
+ $out = array();
764
+ $debug = debug_backtrace();
765
+ //Remove current & calling functions from trace
766
+ $offset = ( intval($offset) ) ? intval($offset) : 1;
767
+ $debug = array_slice($debug, $offset);
768
+ if ( ($debug_levels = count($debug)) ) {
769
+ //Setup levels
770
+ $levels = intval($levels);
771
+ if ( empty($levels) || $levels > $debug_levels ) {
772
+ $levels = $debug_levels;
773
+ }
774
+
775
+ //Setup properties
776
+ if ( is_string($properties) )
777
+ $properties = explode(',', $properties);
778
+ if ( is_array($properties) )
779
+ $properties = array_map('trim', $properties);
780
+
781
+ //Build output
782
+ for ( $x = 0; $x < $levels; $x++ ) {
783
+ $level_out = array();
784
+ if ( !is_array($properties) ) {
785
+ $level_out = $debug[$x];
786
+ } else {
787
+ foreach ( $properties as $prop ) {
788
+ if ( isset($debug[$x][$prop]) )
789
+ $level_out[$prop] = $debug[$x][$prop];
790
+ }
791
+ }
792
+ if ( !empty($level_out) )
793
+ $out[] = $level_out;
794
+ }
795
+ }
796
+ //Extract value if single level is in output
797
+ if ( count($out) == 1 && count($out[0]) == 1 && $out = array_values($out[0]) )
798
+ $out = $out[0];
799
+ return $out;
800
+ }
801
  }
js/admin.js CHANGED
@@ -26,6 +26,7 @@ if ( typeof(fvrt) == 'undefined' || typeof(fvrt) != 'object' )
26
  };
27
 
28
  fvrt['sel'] = {
 
29
  list: '#fv_list',
30
  item: '.fv_item',
31
  image: '.icon',
@@ -71,7 +72,12 @@ if ( typeof(fvrt) == 'undefined' || typeof(fvrt) != 'object' )
71
  * @return array Icon IDs
72
  */
73
  fvrt['getIds'] = function() {
74
- return $(this.getField()).val().split(',');
 
 
 
 
 
75
  };
76
 
77
  /**
@@ -148,6 +154,8 @@ if ( typeof(fvrt) == 'undefined' || typeof(fvrt) != 'object' )
148
 
149
  //Add element ID to list
150
  this.addId(args.id);
 
 
151
  }
152
  };
153
 
@@ -162,6 +170,16 @@ if ( typeof(fvrt) == 'undefined' || typeof(fvrt) != 'object' )
162
  $(el).parents('.fv_item').remove();
163
  //Remove ID from field
164
  this.removeId(id);
 
 
 
 
 
 
 
 
 
 
165
  };
166
 
167
  //Initialize on document load
26
  };
27
 
28
  fvrt['sel'] = {
29
+ no_icons: '#fv_no_icons',
30
  list: '#fv_list',
31
  item: '.fv_item',
32
  image: '.icon',
72
  * @return array Icon IDs
73
  */
74
  fvrt['getIds'] = function() {
75
+ var ids = [];
76
+ var idVal = $(this.getField()).val();
77
+ if ( idVal.toString().length > 0 ) {
78
+ ids = idVal.split(',');
79
+ }
80
+ return ids;
81
  };
82
 
83
  /**
154
 
155
  //Add element ID to list
156
  this.addId(args.id);
157
+
158
+ this.setMessageVisibility();
159
  }
160
  };
161
 
170
  $(el).parents('.fv_item').remove();
171
  //Remove ID from field
172
  this.removeId(id);
173
+
174
+ this.setMessageVisibility();
175
+ };
176
+
177
+ fvrt['setMessageVisibility'] = function() {
178
+ if (this.getIds().length)
179
+ $(this.sel.no_icons).hide();
180
+ else {
181
+ $(this.sel.no_icons).show();
182
+ }
183
  };
184
 
185
  //Initialize on document load
js/media.js CHANGED
@@ -17,7 +17,7 @@ if ( typeof(fvrt) == 'undefined' || typeof(fvrt) != 'object' )
17
  * url: Attachment URL
18
  */
19
  setIcon : function (a) {
20
- if ( typeof(a) == 'object' ) {
21
  fvrt.addItem(a);
22
  }
23
  //Close popup
17
  * url: Attachment URL
18
  */
19
  setIcon : function (a) {
20
+ if ( typeof(a) == 'object' && fvrt.addItem ) {
21
  fvrt.addItem(a);
22
  }
23
  //Close popup
main.php CHANGED
@@ -3,10 +3,10 @@
3
  Plugin Name: Favicon Rotator
4
  Plugin URI: http://archetyped.com/tools/favicon-rotator/
5
  Description: Easily set site favicon and even rotate through multiple icons
6
- Version: 1.0
7
  Author: Archetyped
8
  Author URI: http://archetyped.com
9
  */
10
 
11
  require_once 'model.php';
12
- $fvrt = new FaviconRotator();
3
  Plugin Name: Favicon Rotator
4
  Plugin URI: http://archetyped.com/tools/favicon-rotator/
5
  Description: Easily set site favicon and even rotate through multiple icons
6
+ Version: 1.1.2
7
  Author: Archetyped
8
  Author URI: http://archetyped.com
9
  */
10
 
11
  require_once 'model.php';
12
+ $fvrt = new FaviconRotator();
model.php CHANGED
@@ -4,9 +4,8 @@ require_once 'includes/class.base.php';
4
  require_once 'includes/class.media.php';
5
 
6
  /**
7
- * Redactor class
8
  * @author Archetyped
9
- *
10
  */
11
  class FaviconRotator extends FVRT_Base {
12
 
@@ -75,7 +74,7 @@ class FaviconRotator extends FVRT_Base {
75
  add_action('admin_menu', $this->m('admin_menu'));
76
  //Plugins page
77
  add_filter('plugin_action_links_' . $this->util->get_plugin_base_name(), $this->m('admin_plugin_action_links'), 10, 4);
78
-
79
  /*-** Main **-*/
80
 
81
  //Template
@@ -144,11 +143,22 @@ class FaviconRotator extends FVRT_Base {
144
  if ( !empty($ids) ) {
145
  $icons = get_posts(array('post_type' => 'attachment', 'include' => $ids));
146
  }
147
- return $icons;
 
 
 
 
 
 
 
 
 
 
148
  }
149
 
150
  /**
151
  * Save list of selected icons to DB
 
152
  */
153
  function save_icons($ids = null) {
154
  //Check if valid icon IDs are passed to function
@@ -159,12 +169,23 @@ class FaviconRotator extends FVRT_Base {
159
  }
160
 
161
  //Get icon IDs from form submission
162
- if ( is_null($ids) && isset($_POST['fv_ids']) && check_admin_referer($this->action_save) )
163
  $ids = explode(',', $_POST['fv_ids']);
164
-
165
  //Save to DB
166
- if ( is_array($ids) )
 
 
 
 
 
 
 
 
 
 
167
  $this->set_option($this->opt_icons, $ids);
 
168
  }
169
 
170
  /**
@@ -179,14 +200,17 @@ class FaviconRotator extends FVRT_Base {
179
  //Select one from random
180
  $idx = ( count($icons) > 1 ) ? array_rand($icons) : 0;
181
  $icon_id = $icons[$idx];
182
- $icon = wp_get_attachment_url($icon_id);
183
- if ( !$icon || ( !wp_attachment_is_image($icon_id) && 'ico' != substr($icon, strrpos($icon, '.') + 1) ) ) {
184
  //Reset variable to NULL
185
  $icon = null;
186
  //Remove icon from list (no longer valid)
187
  unset($icons[$idx]);
188
  array_values($icons);
189
  }
 
 
 
190
  }
191
 
192
  //Display icon
@@ -257,17 +281,17 @@ class FaviconRotator extends FVRT_Base {
257
  <?php screen_icon(); ?>
258
  <h2><?php _e('Favicon Rotator'); ?> <a href="<?php echo $this->media->get_upload_iframe_src('image'); ?>" class="button add-new-h2 thickbox" title="<?php esc_attr_e('Add Icon'); ?>"><?php echo esc_html_x('Add new', 'file')?></a></h2>
259
  <div id="fv_list_container">
260
- <?php if ( !$icons ) : ?>
261
- <p>No favicons set</p>
262
- <?php endif; //No icons message ?>
263
  <ul id="fv_list">
264
  <?php foreach ( $icons as $icon ) : //List icons
 
 
265
  $src = wp_get_attachment_image_src($icon->ID, 'full');
266
  $src = $src[0];
267
  ?>
268
  <li class="fv_item">
269
  <div>
270
- <img class="icon" src="<?php echo $src; ?>" />
271
  <div class="details">
272
  <div class="name"><?php echo basename($src); ?></div>
273
  <div class="options">
4
  require_once 'includes/class.media.php';
5
 
6
  /**
7
+ * @package Favicon Rotator
8
  * @author Archetyped
 
9
  */
10
  class FaviconRotator extends FVRT_Base {
11
 
74
  add_action('admin_menu', $this->m('admin_menu'));
75
  //Plugins page
76
  add_filter('plugin_action_links_' . $this->util->get_plugin_base_name(), $this->m('admin_plugin_action_links'), 10, 4);
77
+
78
  /*-** Main **-*/
79
 
80
  //Template
143
  if ( !empty($ids) ) {
144
  $icons = get_posts(array('post_type' => 'attachment', 'include' => $ids));
145
  }
146
+
147
+ //Fix icon option if invalid icons were passed
148
+ if ( count($icons) != count($ids) ) {
149
+ $ids = array();
150
+ foreach ( $icons as $icon ) {
151
+ $ids[] = $icon->ID;
152
+ }
153
+ //Save to DB
154
+ $this->save_icons($ids);
155
+ }
156
+ return $icons;
157
  }
158
 
159
  /**
160
  * Save list of selected icons to DB
161
+ * @param array $ids (optional) Array of icon IDs
162
  */
163
  function save_icons($ids = null) {
164
  //Check if valid icon IDs are passed to function
169
  }
170
 
171
  //Get icon IDs from form submission
172
+ if ( is_null($ids) && isset($_POST['fv_ids']) && check_admin_referer($this->action_save) ) {
173
  $ids = explode(',', $_POST['fv_ids']);
174
+ }
175
  //Save to DB
176
+ if ( is_array($ids) ) {
177
+ //Validate values
178
+ $changed = false;
179
+ foreach ( $ids as $key => $id ) {
180
+ if ( !intval($id) ) {
181
+ unset($ids[$key]);
182
+ $changed = true;
183
+ }
184
+ }
185
+ if ( $changed )
186
+ $ids = array_values($ids);
187
  $this->set_option($this->opt_icons, $ids);
188
+ }
189
  }
190
 
191
  /**
200
  //Select one from random
201
  $idx = ( count($icons) > 1 ) ? array_rand($icons) : 0;
202
  $icon_id = $icons[$idx];
203
+ $icon = $this->media->get_icon_src($icon_id);
204
+ if ( !$icon || ( is_string($icon) && 'ico' != substr($icon, strrpos($icon, '.') + 1) ) ) {
205
  //Reset variable to NULL
206
  $icon = null;
207
  //Remove icon from list (no longer valid)
208
  unset($icons[$idx]);
209
  array_values($icons);
210
  }
211
+ //Load image src (for image attachments)
212
+ if ( is_array($icon) )
213
+ $icon = $icon[0];
214
  }
215
 
216
  //Display icon
281
  <?php screen_icon(); ?>
282
  <h2><?php _e('Favicon Rotator'); ?> <a href="<?php echo $this->media->get_upload_iframe_src('image'); ?>" class="button add-new-h2 thickbox" title="<?php esc_attr_e('Add Icon'); ?>"><?php echo esc_html_x('Add new', 'file')?></a></h2>
283
  <div id="fv_list_container">
284
+ <p id="fv_no_icons"<?php if ( $icons ) echo ' style="display: none;"'?>>No favicons set</p>
 
 
285
  <ul id="fv_list">
286
  <?php foreach ( $icons as $icon ) : //List icons
287
+ $icon_src = wp_get_attachment_image_src($icon->ID, $this->icon_size);
288
+ $icon_src = $icon_src[0];
289
  $src = wp_get_attachment_image_src($icon->ID, 'full');
290
  $src = $src[0];
291
  ?>
292
  <li class="fv_item">
293
  <div>
294
+ <img class="icon" src="<?php echo $icon_src; ?>" />
295
  <div class="details">
296
  <div class="name"><?php echo basename($src); ?></div>
297
  <div class="options">
readme.txt CHANGED
@@ -1,4 +1,4 @@
1
- === Plugin Name ===
2
  Contributors: archetyped
3
  Tags: favicon,icon,template,theme,customization,simple,media
4
  Requires at least: 3.0
@@ -9,9 +9,13 @@ Easily set site favicon and even rotate through multiple icons
9
 
10
  == Description ==
11
 
12
- Favicon Rotator makes it easy to customize the favicon for your site. Just add a favicon below and it will be displayed whenever someone visits your site.
 
 
 
 
 
13
 
14
- Favicon Rotator supports **multiple icons**, from which a **randomly selected** favicon from the rotation will be displayed.
15
 
16
  [More Information on Favicons](http://wikipedia.org/wiki/Favicon)
17
 
@@ -36,5 +40,13 @@ Go to http://archetyped.com/tools/favicon-rotator/ for any questions or comments
36
  1. Favicon submenu in Appearance menu
37
 
38
  == Changelog ==
 
 
 
 
 
 
 
 
39
  = 1.0 =
40
  * Initial release
1
+ === Favicon Rotator ===
2
  Contributors: archetyped
3
  Tags: favicon,icon,template,theme,customization,simple,media
4
  Requires at least: 3.0
9
 
10
  == Description ==
11
 
12
+ Favicon Rotator makes it easy to customize the favicon for your site. Just add a favicon via the administration page and it will be displayed whenever someone visits your site.
13
+
14
+ #### Highlights
15
+ * Simply point and click to add a favicon to your site
16
+ * Support for **multiple icons**, from which a **randomly selected** favicon from the rotation will be displayed.
17
+ * Automatic icon generation for large images (smaller files and faster loading)
18
 
 
19
 
20
  [More Information on Favicons](http://wikipedia.org/wiki/Favicon)
21
 
40
  1. Favicon submenu in Appearance menu
41
 
42
  == Changelog ==
43
+ = 1.1.2 =
44
+ * Updated: Utilities code (internal)
45
+ = 1.1 =
46
+ * Added: Generate icon file from uploaded images
47
+ * Added: Settings link from plugins page
48
+ * Optimized: File path resolution
49
+ = 1.0.1 =
50
+ * Fix: Various bugs
51
  = 1.0 =
52
  * Initial release
screenshot-1.png DELETED
Binary file
screenshot-2.png DELETED
Binary file