WordPress Button Plugin MaxButtons - Version 6.27

Version Description

  • Tested for 4.9.2
  • Security - Added rel='noopener' for links opening in new window
  • Fixed missing values on a template
Download this release

Release Info

Developer basszje
Plugin Icon 128x128 WordPress Button Plugin MaxButtons
Version 6.27
Comparing to
See all releases

Code changes from version 6.26.1 to 6.27

blocks/basic.php CHANGED
@@ -146,17 +146,33 @@ class basicBlock extends maxBlock
146
 
147
  $data = $this->data[$this->blockname];
148
  $button_id = $this->data["id"];
 
149
 
150
  $anchor = $domObj->find("a",0);
151
 
152
  if (isset($data["nofollow"]) && $data["nofollow"] == 1)
153
- $anchor->rel = "nofollow";
 
 
 
 
154
  // $buttonAttrs[] = "rel=nofollow";
 
155
  if (isset($data["new_window"]) && $data["new_window"] == 1)
 
156
  $anchor->target = "_blank";
 
 
 
157
  if (isset($data['link_title']) && strlen($data['link_title']) > 0)
158
  $anchor->title = $data['link_title'];
159
 
 
 
 
 
 
 
160
 
161
  if (isset($data["url"]) && $data["url"] != '')
162
  {
146
 
147
  $data = $this->data[$this->blockname];
148
  $button_id = $this->data["id"];
149
+ $rels = array();
150
 
151
  $anchor = $domObj->find("a",0);
152
 
153
  if (isset($data["nofollow"]) && $data["nofollow"] == 1)
154
+ {
155
+ $rels[] = 'nofollow';
156
+ $rels[] = 'noopener';
157
+ }
158
+ // $anchor->rel = "nofollow";
159
  // $buttonAttrs[] = "rel=nofollow";
160
+
161
  if (isset($data["new_window"]) && $data["new_window"] == 1)
162
+ {
163
  $anchor->target = "_blank";
164
+ if (! in_array('noopener', $rels))
165
+ $rels[] = 'noopener';
166
+ }
167
  if (isset($data['link_title']) && strlen($data['link_title']) > 0)
168
  $anchor->title = $data['link_title'];
169
 
170
+ $rels = apply_filters('mb/button/rel', $rels);
171
+
172
+ if (count($rels) > 0)
173
+ {
174
+ $anchor->rel = implode(' ', $rels);
175
+ }
176
 
177
  if (isset($data["url"]) && $data["url"] != '')
178
  {
blocks/container.php CHANGED
@@ -166,7 +166,6 @@ class containerBlock extends maxBlock
166
 
167
  $admin->addField($container_width, 'start', 'end');
168
 
169
-
170
  // Margin - trouble
171
  $ptop = new maxField('number');
172
  $ptop->label = __('Margin', 'maxbuttons');
@@ -221,11 +220,11 @@ class containerBlock extends maxBlock
221
  $align->value= maxBlocks::getValue('container_alignment');
222
  //$align->setDefault(maxBlocks::getDefault('container_alignment'));
223
  $align->content = maxUtils::selectify($align->name, $maxbuttons_container_alignments, $align->value);
224
- $align->output('start', 'end');
225
 
226
  $admin->addField($align, 'start', 'end');
227
 
228
- $admin->display_fields();
229
  ?>
230
 
231
  </div>
166
 
167
  $admin->addField($container_width, 'start', 'end');
168
 
 
169
  // Margin - trouble
170
  $ptop = new maxField('number');
171
  $ptop->label = __('Margin', 'maxbuttons');
220
  $align->value= maxBlocks::getValue('container_alignment');
221
  //$align->setDefault(maxBlocks::getDefault('container_alignment'));
222
  $align->content = maxUtils::selectify($align->name, $maxbuttons_container_alignments, $align->value);
223
+ //$align->output('start', 'end');
224
 
225
  $admin->addField($align, 'start', 'end');
226
 
227
+ $admin->display_fields();
228
  ?>
229
 
230
  </div>
blocks/icon.php CHANGED
@@ -95,7 +95,6 @@ class iconBlock extends maxBlock
95
  */
96
  $css = $this->parse_rule_textalign($css, 'mb-icon', 'normal');
97
 
98
-
99
  return $css;
100
  }
101
 
@@ -123,7 +122,7 @@ class iconBlock extends maxBlock
123
  }
124
  }
125
 
126
- return $css;
127
  }
128
 
129
  public function parse_button($domObj, $mode = 'normal')
95
  */
96
  $css = $this->parse_rule_textalign($css, 'mb-icon', 'normal');
97
 
 
98
  return $css;
99
  }
100
 
122
  }
123
  }
124
 
125
+ return $css;
126
  }
127
 
128
  public function parse_button($domObj, $mode = 'normal')
blocks/tpl/radio.tpl CHANGED
@@ -11,6 +11,6 @@
11
  {if:icon} <i class='dashicons %%icon%%' tabindex='0'></i> {/if:icon}
12
  {if:custom_icon} <i class='%%custom_icon%%'></i>{/if:custom_icon}
13
  {if:image} <img src='%%image%%' /> {/if:image}
14
- {if:label} %%label {/if:label}
15
  </label>
16
  </div>
11
  {if:icon} <i class='dashicons %%icon%%' tabindex='0'></i> {/if:icon}
12
  {if:custom_icon} <i class='%%custom_icon%%'></i>{/if:custom_icon}
13
  {if:image} <img src='%%image%%' /> {/if:image}
14
+ {if:label} %%label%% {/if:label}
15
  </label>
16
  </div>
classes/button.php CHANGED
@@ -1,41 +1,41 @@
1
  <?php
2
- namespace MaxButtons;
3
  defined('ABSPATH') or die('No direct access permitted');
4
 
5
- /* Datamodel and base functionality for a button
6
 
7
  */
8
 
9
  use \simple_html_dom as simple_html_dom;
10
-
11
  class maxButton
12
  {
13
- protected $id = 0;
14
  protected $document_id = 0; // an id that's not duplicated when there are multiple buttons on the same page. Preferably reliable as well.
15
- protected $name = '';
16
- protected $status = '';
17
- protected $description = '';
18
- protected $cache = '';
19
-
20
  protected $button_loaded = false;
21
 
22
- protected $data = array();
23
  protected $blocks; // Block Classes
24
  protected $templates = array(); // .tpl files
25
 
26
- protected $button_css = array();
27
- protected $button_js = array();
28
-
29
  // output conditions
30
- protected $load_css = 'footer'; // [ footer, inline, external, element ]
31
- protected $load_js = 'footer';
32
-
33
- protected $cssParser = false;
34
- protected $parsed_css = '';
35
-
36
-
37
- /* Class constructor
38
-
39
  Get als loads the various blocks of which a button is built up. Blocks can be added and removed using the mb-init-blocks filter
40
  */
41
  function __construct()
@@ -43,31 +43,31 @@ class maxButton
43
  maxUtils::addTime("Button construct");
44
 
45
  // the parser
46
-
47
- // get all files from blocks map
48
-
49
- // get all blocks via apply filters, do init. Init should not load anything big.
50
- $this->loadBlockClasses();
51
-
52
- }
53
-
54
  /* Makes overriding block features possible by subclass
55
-
56
  */
57
  private function loadBlockClasses()
58
  {
59
 
60
- // set blocks to the 'block name' that survived.
61
- maxUtils::addTime("Load Block classes");
62
-
63
  //$classes = apply_filters("mb_blockclassesload", $classes);
64
- $class_array = maxBlocks::getBlockClasses();
65
- $classes = array_map(maxUtils::namespaceit('maxUtils::array_namespace'), $class_array );
66
-
67
  foreach($classes as $block => $class)
68
  {
69
- $block = new $class();
70
-
71
  $this->blocks[] = $block;
72
  if (is_admin())
73
  {
@@ -75,18 +75,18 @@ class maxButton
75
  }
76
  }
77
 
78
-
79
  $this->clear(); // init
80
- do_action("mb\blockclasses", $class_array);
81
 
82
  }
83
-
84
- /** Simple function to retrieve loaded blocks - * Used by install class */
85
- public function getBlocks()
86
  {
87
  return $this->blocks;
88
- }
89
-
90
  /** Get Data from Database and set variables
91
  *
92
  * You can pass either id or name to this function
@@ -102,52 +102,52 @@ class maxButton
102
  $status = sanitize_text_field($status);
103
 
104
  global $wpdb;
105
- $this->clear(); // clear the internals of any previous work
106
-
107
  // check to see if the value passed is NOT numeric. If it is, use title, else assume numeric
108
  if($id == 0 && $name != '') {
109
  $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE name = '%s' and status ='%s'", trim($name), $status ), ARRAY_A);
110
-
111
  } else {
112
  $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE id = %d and status ='%s'", $id, $status), ARRAY_A);
113
  }
114
-
115
- if (count($row) == 0)
116
  {
117
- return false;
118
- }
119
 
120
- /* Take the id from the query, otherwise ( when button shortcode called by name ) id might not be present properly' */
121
- $button_id = $row["id"];
122
  maxButtons::buttonLoad(array("button_id" => $button_id)); // central registration
123
-
124
  return $this->setupData($row);
125
-
126
  }
127
  /** Clear button settings
128
  *
129
  * This function prevent that generated values from previous set actions will still be present.
130
- */
131
- function clear()
132
  {
133
  unset($this->data);
134
  unset($this->button_css);
135
  $this->id = 0; // clear id
136
  $this->button_css = array();
137
- $this->button_js = array();
138
  $this->data = array('id' => 0);
139
  $this->data = $this->save(array(),false);
140
 
141
- $this->cache = '';
142
  $this->button_loaded = false;
143
 
144
  foreach($this->blocks as $block)
145
  {
146
- $block->set($this->data); // reset blocks
147
  }
148
 
149
  }
150
-
151
  function setupData($data)
152
  {
153
 
@@ -159,54 +159,54 @@ class maxButton
159
  if (array_key_exists($block_name, $data)) // strangely isset doesn't work
160
  {
161
  $this->data[$block_name] = maybe_unserialize($data[$block_name]); // allow to feed unserialized stuff not from dbase
162
- if (! is_array($this->data[$block_name]))
163
  {
164
  $this->data[$block_name] = json_decode($data[$block_name], true);
165
  }
166
-
167
  }
168
  }
169
-
170
  $this->id = $data["id"];
171
 
172
- // Because PHP 5.3
173
  $class = maxUtils::namespaceit('maxButtons');
174
  $this->document_id = $class::getDocumentID(array("button_id" => $this->id));
175
  $this->cache = isset($data["cache"]) ? trim($data["cache"]) : ''; // not set at button packs / non-dbase buttons!
176
- $this->data["id"] = $this->id; // needed for certain blocks, to be button aware.
177
- $this->data["document_id"] = $this->document_id; // bound to JS and others.
178
- $this->name = $data["name"];
179
  $this->status = $data["status"];
180
- $this->description = $this->data["basic"]["description"];
181
 
182
  //do_action('mb-data-load', $this->data);
183
  foreach($this->blocks as $block)
184
  {
185
  $block->set($this->data);
186
  }
187
-
188
  maxBlocks::setData($this->data);
189
 
190
 
191
  return true;
192
-
193
  }
194
-
195
- function get( )
196
  {
197
  return $this->data;
198
-
199
  }
200
-
201
- function getID()
202
  {
203
- return $this->id;
204
  }
205
- function getDocumentID()
206
  {
207
- return $this->document_id;
208
  }
209
- function getName()
210
  {
211
  return $this->name;
212
  }
@@ -214,240 +214,240 @@ class maxButton
214
  {
215
  return $this->description;
216
  }
217
-
218
  function getStatus()
219
  {
220
- return $this->status;
221
  }
222
-
223
- function getParsedCSS()
224
  {
225
- return $this->parsed_css;
226
  }
227
-
228
  function getCSSArray()
229
  {
230
 
231
  return $this->button_css;
232
  }
233
-
234
  function getCSSParser()
235
  {
236
  if (! $this->cssParser)
237
- $this->cssParser = new maxCSSParser();
238
-
239
  return $this->cssParser;
240
  }
241
  // get the cache
242
- function getCache()
243
  {
244
  return $this->cache;
245
  }
246
-
247
- // modify the cache at own risk
248
  function setCache($cache)
249
  {
250
- $this->cache = $cache;
251
- }
252
 
253
  /* Used by collections and import. Use sparingly. Button data is reput to blocks on display */
254
- function setData($blockname, $data )
255
  {
256
  foreach($data as $key => $value)
257
  {
258
- $this->data[$blockname][$key] = $value;
259
-
260
  }
261
  }
262
 
263
-
264
  /* Tell all blocks to reload the data
265
-
266
- This function will tell all loaded blocks to reload it's data. This is needed when data is changed after the initial button load.
267
-
268
- */
269
  function reloadData()
270
  {
271
  exit('reload Data - do not use');
272
  //do_action('mb-data-load', $this->data);
273
-
274
- }
275
 
276
  /* Parse CSS from the elements
277
-
278
  @param string $mode [normal,preview,editor] - The view needed.
279
- @param string $forceCompile Recompile the CSS in any case
280
  */
281
  function parse_css($mode = "normal", $forceCompile = false )
282
  {
283
- $css = $this->button_css;
284
-
285
  if (isset($this->cache) && $this->cache != '' && ! $forceCompile)
286
- {
287
-
288
  $css = $this->cache;
289
  // kill media queries from cache
290
  if ($mode != 'normal')
291
  {
292
- $pattern = "/@media.*}/is";
293
  preg_match($pattern, $css, $matches);
294
- $css = preg_replace($pattern, '', $css);
295
  }
296
 
297
  maxUtils::addTime("Button: Cache loaded");
298
  }
299
  else
300
- {
301
- /* Internal filter, please don't use */
302
  foreach($this->blocks as $block)
303
  {
304
- $css = $block->parse_css($css, $mode);
305
  }
306
  //$css = apply_filters('mb-css-blocks', $css, $mode);
307
-
308
  /* Filter the raw CSS array before compile
309
-
310
- This filters passes an array with all CSS element before compile time. This should be CSS elements that can be understood by the CSS parser.
311
- @since 4.20
312
- @param $css CSS Array - split by element and pseudo (normal/hover)
313
-
314
  */
315
-
316
- $css = apply_filters('mb/button/rawcss', $css, $mode);
317
 
318
- $this->button_css = $css;
319
 
 
320
 
321
  $css = $this->getCSSParser()->parse($this->button_css);
322
- $css = apply_filters('mb/button/compiledcss', $css, $mode); // the final result.
323
-
324
  if ($mode == 'normal') // only in general mode, otherwise things go amiss.
325
  $this->update_cache($css);
326
 
327
  }
328
-
329
- $this->parsed_css = $css;
330
-
331
-
332
- return $css;
333
- }
334
-
335
- /* Call blocks for javascript
336
-
337
- Function will call for all block element to crunch the required javascript for output ( if any )
338
- @param string $mode [normal, preview, editor]
339
-
340
  */
341
- function parse_js($mode = "normal")
342
  {
343
  maxUtils::addTime("Button :: parse JS");
344
- $js = $this->button_js;
345
  foreach($this->blocks as $block)
346
  {
347
- $js = $block->parse_js($js,$mode);
348
-
349
  }
350
 
351
- $this->button_js = $js;
352
  }
353
-
354
  /* Parse the actual button
355
-
356
- Function adds the basic button components, creates the DOM object for the button and asks all block elements to parse their additions.
357
-
358
- @param string $mode [normal, preview, editor]
359
  @return Object DomObj presentation of the button
360
  */
361
  function parse_button($mode = 'normal')
362
  {
363
- $name = $this->name;
364
  // non-latin breaks CSS / ID's - so move to latin.
365
  $name = maxUtils::translit($name);
366
  $name = sanitize_title($name);
367
 
368
  $classes = array("maxbutton-" . $this->id,
369
  "maxbutton");
370
- if ($name != '')
 
 
371
  $classes[] = "maxbutton-" . $name;
372
-
373
- $classes = apply_filters('mb-mainclasses', $classes);
374
- $classes = implode(' ', $classes);
375
-
376
  $domObj = new simple_html_dom();
377
- $domObj->load('<a class="' . $classes . '"></a>');
378
-
379
 
380
  foreach($this->blocks as $block)
381
  {
382
  $domObj = $block->parse_button($domObj, $mode);
383
- }
384
-
385
-
386
  $domObj->load($domObj->save());
387
-
388
  $cssParser = $this->getCSSParser();
389
  $cssParser->loadDom($domObj);
390
 
391
- return $domObj;
392
  }
393
 
394
- /* Display all data and html to allow users to edit button settings */
395
- public function admin_fields()
396
  {
397
  foreach($this->blocks as $block)
398
  {
399
- $block->admin_fields();
400
-
401
  }
402
- //do_action('mb-admin-fields' );
403
-
404
  }
405
-
406
  /* Display the button */
407
  public function display($args = array() )
408
- {
409
  maxUtils::startTime('button-display-'. $this->id);
410
  $defaults = array(
411
  "mode" => 'normal',
412
  "preview_part" => "full",
413
- "echo" => true,
414
- "load_css" => "footer", // control how css is loaded.
415
- "compile" => false, // possibility to force recompile if needed.
416
  );
417
- $output = ''; // init output;
418
-
419
- $args = wp_parse_args($args, $defaults);
420
 
421
  $cssParser = $this->getCSSParser(); // init parser
422
-
423
- $this->load_css = $args["load_css"];
424
-
425
  if ($this->id == 0) // if button doesn't exists don't display unless in editor
426
  {
427
- if (! $args["mode"] == 'editor' )
428
  return;
429
-
430
- $this->clear();
431
-
432
  $this->data["id"] = 0;
433
  //do_action('mb-data-load', $data);
434
  }
435
-
436
- $mode = (isset($args["mode"])) ? $args["mode"] : "normal";
437
  switch($mode)
438
  {
439
- case "preview":
440
  $preview = true;
441
  $compile = false;
442
- break;
443
- case "editor":
444
- $preview = true;
445
- $compile = true;
446
- // editor is both compile and preview.
447
  break;
448
  break;
449
- case "normal":
450
- $preview = false;
451
  $compile = false;
452
  break;
453
  }
@@ -455,15 +455,15 @@ class maxButton
455
 
456
  // Apply filters for general data override
457
 
458
- $this->data = apply_filters('mb/button/data_before_display', $this->data, $mode, array('preview' => $preview, 'compile' => $compile) ); // hooks
 
 
459
 
460
-
461
-
462
  if ( $this->load_css == "element" || $args["preview_part"] != "full" || $args["compile"] == true) { // if css output is on element, for to compile - otherwise inline styles will not be loaded.
463
  $compile = true;
464
 
465
  }
466
- else
467
  $compile = false;
468
 
469
  // reload the data into the blocks, might have been altered by shortcode, filters etc.
@@ -473,232 +473,232 @@ class maxButton
473
  $block->set($this->data);
474
  }
475
 
476
- $domObj = $this->parse_button($mode);
477
-
478
  maxUtils::startTime('button-parse-css-'. $this->id);
479
- $this->parse_css($mode, $compile);
480
  maxUtils::endTime('button-parse-css-'. $this->id);
481
-
482
- if (! $preview) // no js on previews
483
- $this->parse_js($mode);
484
-
485
  if ($preview) // mark it preview
486
  {
487
 
488
  $domObj->find('a',0)->class .= ' maxbutton-preview';
489
  }
490
-
491
  if ($preview && $args["preview_part"] != 'full')
492
  {
493
-
494
  if ($args["preview_part"] != 'normal')
495
  {
496
- $domObj->find('a',0)->class .= ' hover';
497
  $domObj = $cssParser->outputInline($domObj,'hover');
498
 
499
  }
500
  else
501
  {
502
- $domObj->find('a',0)->class .= ' normal';
503
  $domObj = $cssParser->outputInline($domObj);
504
  }
505
 
506
  }
507
- elseif ($this->load_css == 'footer')
508
  {
509
- $css = $this->display_css(false, false);
510
- do_action('mb-footer',$this->id, $css);
511
-
512
  if (! $preview)
513
  {
514
  $js = $this->display_js(false, true);
515
  do_action('mb-footer', $this->document_id, $js, 'js');
516
  }
517
- } elseif ($this->load_css == 'inline')
518
  {
519
- if ($args["echo"])
520
  $this->display_css();
521
  else
522
  $output .= $this->display_css(false);
523
  }
524
- elseif ($this->load_css == 'element') // not possible to load both normal and hover to an element.
525
  {
526
- $domObj->find('a',0)->class .= ' normal';
527
- $domObj = $this->cssParser->outputInline($domObj);
528
- //$this->get_element_css($domObj, 'normal');
529
  }
530
-
531
 
532
  $output .= $domObj->save();
533
-
534
- $output = apply_filters('mb-before-button-output', $output);
535
- maxButtons::buttonDone(array("button_id" => $this->id, "document_id" => $this->document_id) );
536
-
537
  maxUtils::endTime('button-display-'. $this->id);
538
-
539
  if ($args["echo"])
540
- echo $output;
541
  else
542
- return $output;
543
 
544
- }
545
  /* Function used to map field id's to display for Frontend Javascript
546
-
547
- This function bundles all defined fields into a json encoded variable. This is used for the frontend javascript functions in the
548
  administrator area like colorpickers and real-time updating of the button preview
549
  */
550
  public function display_field_map()
551
  {
552
- $map = array();
553
  foreach($this->blocks as $block)
554
  {
555
- $map = $block->map_fields($map);
556
  }
557
- //$map = apply_filters("mb-field-map",$map);
558
-
559
 
560
- echo "<script language='javascript'>";
561
  echo "var buttonFieldMap = '" . json_encode($map) . "';" ;
562
  echo "</script>";
563
-
564
  }
565
-
566
- /* Write parsed CSS to output.
567
- @param echo Default true. When true, outputs directly, otherwise returns output string
568
  @param style_tag Default true. When true, outputs a html <style> tags around the output.
569
  */
570
  public function display_css($echo = true, $style_tag = true)
571
  {
572
- $output = '';
573
-
574
  if ($style_tag)
575
  $output .= "<style type='text/css'>";
576
-
577
  $output .= $this->parsed_css;
578
-
579
  if ($style_tag)
580
  $output .= "</style>";
581
-
582
-
583
- if ($echo) echo $output;
584
- else return $output;
585
-
586
  }
587
-
588
  /* Output Parsed Javascripting */
589
  public function display_js($echo = true, $tag = true)
590
  {
591
  $output = '';
592
 
593
- if (count($this->button_js) == 0)
594
  return; // no output, holiday
595
-
596
- if ($tag)
597
  {
598
- $output .= "<script type='text/javascript'> ";
599
  $output .= " if (typeof maxButton" . $this->document_id . " == 'undefined') { ";
600
  $output .= " function maxButton" . $this->document_id . "() { ";
601
  }
602
-
603
- foreach($this->button_js as $index => $code)
604
  {
605
- $output .= $code;
606
-
607
  }
608
-
609
- if ($tag)
610
  {
611
- $output .= " }
612
- }
613
- window.onload = maxButton" . $this->document_id . "();
614
- </script> ";
615
  }
616
 
617
- if ($echo) echo $output;
618
- else return $output;
619
  }
620
 
621
 
622
- /* Makes a copy of the current buttons.
623
-
624
- The button to be copied -must- be loaded and set
625
  */
626
- function copy()
627
- {
628
- $this->id = 0;
629
  $data = $this->data;
630
  $data["name"] = $this->name;
631
-
632
- return $this->update($data);
633
  }
634
  /* Change the publication status of the button.
635
-
636
  */
637
- function setStatus($status = "publish")
638
  {
639
- $data = $this->data;
640
- $data["status"] = sanitize_text_field($status);
 
 
641
 
642
- return $this->update($data);
643
-
644
- }
645
- /* Remove the button from database */
646
- public function delete($id)
647
  {
648
  global $wpdb;
649
  $wpdb->query($wpdb->prepare("DELETE FROM " . maxUtils::get_table_name() . " WHERE id = %d", $id));
650
  }
651
-
652
- /* Save changes to the button
653
-
654
- Updates or saves the button. Existing buttons must load their data and be set -first- or lose all not-passed data.
655
-
656
  @param post Post data in field - value format (flat $_POST array)
657
- @param boolean savedb if false do not save to database
658
  */
659
  public function save($post, $savedb = true)
660
  {
661
  $post = stripslashes_deep($post); // don't multiply slashes please.
662
- //$data = apply_filters('mb-save-fields',$this->data, $post);
663
  $data = $this->data;
664
-
665
- foreach($this->blocks as $block)
666
  {
667
- $data = $block->save_fields($data, $post);
668
  }
669
-
670
- if (! $savedb ) return $data;
671
- return $this->update($data); // save to db.
672
-
673
  }
674
-
675
  /* Updates the button data to the database. Adds a button if it doesn't exist */
676
- public function update($data)
677
- {
678
- global $wpdb;
679
- $return = false;
680
-
681
- $fields = array();
682
  foreach($this->blocks as $block)
683
  {
684
- $block_name = $block->get_name();
685
-
686
- if (isset($data[$block_name]))
687
  {
688
- $blockData = $data[$block_name];
689
  $fields[$block_name] = json_encode($blockData);
690
  }
691
- }
692
- if (isset($data["name"])) { // other fields.
693
- $fields["name"] = $data["name"];
694
  }
695
  if (isset($data["status"])) {
696
- $fields["status"] = $data["status"];
697
  }
698
-
699
-
700
  $where = array('id' => $this->id );
701
- if ($this->id > 0)
702
  {
703
  $where = array('id' => $this->id);
704
  $where_format = array('%d');
@@ -707,114 +707,114 @@ class maxButton
707
  }
708
  else
709
  {
710
- $fields['created'] = current_time('mysql',1);
711
 
712
  $result = $wpdb->insert(maxUtils::get_table_name(), $fields);
713
  $id = $wpdb->insert_id;
714
 
715
  $this->id = $id;
716
- $return = $id;
717
-
718
  }
719
-
720
-
721
  if ($result === false)
722
  {
723
  $error = "Database error " . $wpdb->last_error;
724
- MB()->add_notice('error', $error);
725
- $install = MB()->getClass("install");
726
  $install::create_database_table(); // run dbdelta to try and fix.
727
-
728
  }
729
-
730
- // update the cache
731
- $this->cache = ''; // empty cache
732
  $result = $this->set($this->id); // set the newest values
733
-
734
- if (! $result ) return false;
735
-
736
  $this->display(array("echo" => false, "load_css" => "element")); // do display routing to compile.
737
- $css = $this->parsed_css;
738
- $this->update_cache($css);
739
 
740
  return $return;
741
  }
742
-
743
  /* Updates the CSS cache. */
744
  public function update_cache($css)
745
  {
746
  $return = false;
747
- global $wpdb;
748
-
749
- if ($this->id > 0)
750
  {
751
- $fields = array("cache" => $css);
752
  $where = array('id' => $this->id);
753
  $where_format = array('%d');
754
  $wpdb->update(maxUtils::get_table_name(), $fields, $where, null, $where_format);
755
  $return = true;
756
-
757
  }
758
- return $return;
759
  }
760
-
761
  // Resets all of the button caches.
762
  public function reset_cache()
763
  {
764
  global $wpdb;
765
- $fields = array("cache" => null);
766
  $where = array(1 => 1);
767
  //$where_format = array('%d');
768
- $sql = "UPDATE " . maxUtils::get_table_name() . " SET cache = NULL ";
769
  $wpdb->query($sql);
770
-
771
  }
772
 
773
-
774
  /* Display button via shortcode
775
-
776
  Function that accepts WP shortcode arguments and displays or returns a button
777
-
778
- @param $atts array Shortcode Atts
779
  @return string HTML presentation of button
780
-
781
  */
782
  public function shortcode($atts)
783
- {
784
  extract(shortcode_atts(array(
785
  'id' => '',
786
  'name' => '',
787
  'text' => '',
788
  'url' => '',
789
- 'linktitle' => '',
790
  'window' => '',
791
  'nofollow' => '',
792
- 'nocache' => false,
793
- 'style' => 'footer',
794
  'exclude' => ''
795
 
796
- ), $atts));
797
 
798
- $button_id = $id;
799
  $button_name = $name;
800
-
801
- if ($button_id > 0)
802
- $result = $this->set($button_id);
803
- elseif ($button_name != '')
804
- $result = $this->set(0, $button_name);
805
  else return; // no button id / name
806
-
807
  /* Shortcode cache control
808
-
809
  If true the button CSS will be recompiled again. If false the plugin will check the cache for CSS declarations. Set to true if anything is interrupting the caching mechanism. Please note, recompiling causes some load times!
810
-
811
- @param boolean $nocache True / False
812
- */
813
- $compile = apply_filters("mb/shortcode/nocache", $nocache);
814
 
815
- if (! $result)
 
 
 
 
816
  return; // shortcode doesn't exist
817
-
818
  // If we're not in the admin and the button is in the trash, just return nothing
819
  if (!is_admin() && $this->status == 'trash') {
820
  return '';
@@ -822,95 +822,94 @@ class maxButton
822
  // Check to handle excludes
823
  if ("{$exclude}" != '') {
824
  global $post;
825
-
826
  // Don't render the button if excluded from the current post/page
827
  $exclude = explode(',', "{$exclude}");
828
  if (in_array($post->ID, $exclude)) {
829
  return '';
830
  }
831
  }
832
-
833
  // Override shortcode options comparing to default button data.
834
- $overrides = false;
835
- if ($text != '')
836
- {
837
- $this->data["text"]["text"] = $text;
838
  $overrides = true;
839
- }
840
- if ($url != '')
841
  {
842
 
843
- $this->data["basic"]["url"] = $url;
844
  //$compile = true; // css change forces recompile
845
  $overrides = true;
846
  }
847
- if ($window != '' && $window =='new')
848
  {
849
- $this->data["basic"]["new_window"] = 1;
850
  $overrides = true;
851
  }
852
- elseif ($window != '' && $window == 'same')
853
  {
854
- $this->data["basic"]["new_window"] = 0;
855
- $overrides = true;
856
  }
857
-
858
- if ($nofollow != '' && $nofollow == 'true')
859
  {
860
- $this->data["basic"]["nofollow"] = 1;
861
  $overrides = true;
862
  }
863
-
864
- if ($linktitle != '')
865
  {
866
- $this->data['basic']['link_title'] = $linktitle;
867
  $overrides = true;
868
  }
869
 
870
  switch($style)
871
  {
872
- case "inline":
873
- $load_css = 'inline';
874
  break;
875
  default:
876
- $load_css = 'footer';
877
  break;
878
- }
879
 
880
  // allow for more flexible changes and data manipulation.
881
  $data = $this->data;
882
- $this->data = $this->shortcode_overrides($this->data, $atts);
883
- $this->data = apply_filters('mb/shortcode/data', $this->data, $atts);
884
-
885
- /* if ($data !== $this->data)
886
  {
887
- $overrides = true;
888
  }
889
- */
890
  /* if ($overrides)
891
  {
892
  do_action('mb-data-load', $this->data);
893
  }
894
- */
895
  // if there are no reasons not to display; display
896
- $args = array("echo" => false,
897
- "load_css" => $load_css,
898
- "compile" => $compile,
899
  );
900
- $args = apply_filters('mb_shortcode_display_args', $args);
901
-
902
-
903
  $output = $this->display($args);
904
-
905
  return $output;
906
-
907
  }
908
-
909
-
910
  public function shortcode_overrides($data, $atts)
911
  {
912
  return $data;
913
  }
914
-
915
- } // class
916
 
 
1
  <?php
2
+ namespace MaxButtons;
3
  defined('ABSPATH') or die('No direct access permitted');
4
 
5
+ /* Datamodel and base functionality for a button
6
 
7
  */
8
 
9
  use \simple_html_dom as simple_html_dom;
10
+
11
  class maxButton
12
  {
13
+ protected $id = 0;
14
  protected $document_id = 0; // an id that's not duplicated when there are multiple buttons on the same page. Preferably reliable as well.
15
+ protected $name = '';
16
+ protected $status = '';
17
+ protected $description = '';
18
+ protected $cache = '';
19
+
20
  protected $button_loaded = false;
21
 
22
+ protected $data = array();
23
  protected $blocks; // Block Classes
24
  protected $templates = array(); // .tpl files
25
 
26
+ protected $button_css = array();
27
+ protected $button_js = array();
28
+
29
  // output conditions
30
+ protected $load_css = 'footer'; // [ footer, inline, external, element ]
31
+ protected $load_js = 'footer';
32
+
33
+ protected $cssParser = false;
34
+ protected $parsed_css = '';
35
+
36
+
37
+ /* Class constructor
38
+
39
  Get als loads the various blocks of which a button is built up. Blocks can be added and removed using the mb-init-blocks filter
40
  */
41
  function __construct()
43
  maxUtils::addTime("Button construct");
44
 
45
  // the parser
46
+
47
+ // get all files from blocks map
48
+
49
+ // get all blocks via apply filters, do init. Init should not load anything big.
50
+ $this->loadBlockClasses();
51
+
52
+ }
53
+
54
  /* Makes overriding block features possible by subclass
55
+
56
  */
57
  private function loadBlockClasses()
58
  {
59
 
60
+ // set blocks to the 'block name' that survived.
61
+ maxUtils::addTime("Load Block classes");
62
+
63
  //$classes = apply_filters("mb_blockclassesload", $classes);
64
+ $class_array = maxBlocks::getBlockClasses();
65
+ $classes = array_map(maxUtils::namespaceit('maxUtils::array_namespace'), $class_array );
66
+
67
  foreach($classes as $block => $class)
68
  {
69
+ $block = new $class();
70
+
71
  $this->blocks[] = $block;
72
  if (is_admin())
73
  {
75
  }
76
  }
77
 
78
+
79
  $this->clear(); // init
80
+ do_action("mb\blockclasses", $class_array);
81
 
82
  }
83
+
84
+ /** Simple function to retrieve loaded blocks - * Used by install class */
85
+ public function getBlocks()
86
  {
87
  return $this->blocks;
88
+ }
89
+
90
  /** Get Data from Database and set variables
91
  *
92
  * You can pass either id or name to this function
102
  $status = sanitize_text_field($status);
103
 
104
  global $wpdb;
105
+ $this->clear(); // clear the internals of any previous work
106
+
107
  // check to see if the value passed is NOT numeric. If it is, use title, else assume numeric
108
  if($id == 0 && $name != '') {
109
  $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE name = '%s' and status ='%s'", trim($name), $status ), ARRAY_A);
110
+
111
  } else {
112
  $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE id = %d and status ='%s'", $id, $status), ARRAY_A);
113
  }
114
+
115
+ if (count($row) == 0)
116
  {
117
+ return false;
118
+ }
119
 
120
+ /* Take the id from the query, otherwise ( when button shortcode called by name ) id might not be present properly' */
121
+ $button_id = $row["id"];
122
  maxButtons::buttonLoad(array("button_id" => $button_id)); // central registration
123
+
124
  return $this->setupData($row);
125
+
126
  }
127
  /** Clear button settings
128
  *
129
  * This function prevent that generated values from previous set actions will still be present.
130
+ */
131
+ function clear()
132
  {
133
  unset($this->data);
134
  unset($this->button_css);
135
  $this->id = 0; // clear id
136
  $this->button_css = array();
137
+ $this->button_js = array();
138
  $this->data = array('id' => 0);
139
  $this->data = $this->save(array(),false);
140
 
141
+ $this->cache = '';
142
  $this->button_loaded = false;
143
 
144
  foreach($this->blocks as $block)
145
  {
146
+ $block->set($this->data); // reset blocks
147
  }
148
 
149
  }
150
+
151
  function setupData($data)
152
  {
153
 
159
  if (array_key_exists($block_name, $data)) // strangely isset doesn't work
160
  {
161
  $this->data[$block_name] = maybe_unserialize($data[$block_name]); // allow to feed unserialized stuff not from dbase
162
+ if (! is_array($this->data[$block_name]))
163
  {
164
  $this->data[$block_name] = json_decode($data[$block_name], true);
165
  }
166
+
167
  }
168
  }
169
+
170
  $this->id = $data["id"];
171
 
172
+ // Because PHP 5.3
173
  $class = maxUtils::namespaceit('maxButtons');
174
  $this->document_id = $class::getDocumentID(array("button_id" => $this->id));
175
  $this->cache = isset($data["cache"]) ? trim($data["cache"]) : ''; // not set at button packs / non-dbase buttons!
176
+ $this->data["id"] = $this->id; // needed for certain blocks, to be button aware.
177
+ $this->data["document_id"] = $this->document_id; // bound to JS and others.
178
+ $this->name = $data["name"];
179
  $this->status = $data["status"];
180
+ $this->description = $this->data["basic"]["description"];
181
 
182
  //do_action('mb-data-load', $this->data);
183
  foreach($this->blocks as $block)
184
  {
185
  $block->set($this->data);
186
  }
187
+
188
  maxBlocks::setData($this->data);
189
 
190
 
191
  return true;
192
+
193
  }
194
+
195
+ function get( )
196
  {
197
  return $this->data;
198
+
199
  }
200
+
201
+ function getID()
202
  {
203
+ return $this->id;
204
  }
205
+ function getDocumentID()
206
  {
207
+ return $this->document_id;
208
  }
209
+ function getName()
210
  {
211
  return $this->name;
212
  }
214
  {
215
  return $this->description;
216
  }
217
+
218
  function getStatus()
219
  {
220
+ return $this->status;
221
  }
222
+
223
+ function getParsedCSS()
224
  {
225
+ return $this->parsed_css;
226
  }
227
+
228
  function getCSSArray()
229
  {
230
 
231
  return $this->button_css;
232
  }
233
+
234
  function getCSSParser()
235
  {
236
  if (! $this->cssParser)
237
+ $this->cssParser = new maxCSSParser();
238
+
239
  return $this->cssParser;
240
  }
241
  // get the cache
242
+ function getCache()
243
  {
244
  return $this->cache;
245
  }
246
+
247
+ // modify the cache at own risk
248
  function setCache($cache)
249
  {
250
+ $this->cache = $cache;
251
+ }
252
 
253
  /* Used by collections and import. Use sparingly. Button data is reput to blocks on display */
254
+ function setData($blockname, $data )
255
  {
256
  foreach($data as $key => $value)
257
  {
258
+ $this->data[$blockname][$key] = $value;
259
+
260
  }
261
  }
262
 
263
+
264
  /* Tell all blocks to reload the data
265
+
266
+ This function will tell all loaded blocks to reload it's data. This is needed when data is changed after the initial button load.
267
+
268
+ */
269
  function reloadData()
270
  {
271
  exit('reload Data - do not use');
272
  //do_action('mb-data-load', $this->data);
273
+
274
+ }
275
 
276
  /* Parse CSS from the elements
277
+
278
  @param string $mode [normal,preview,editor] - The view needed.
279
+ @param string $forceCompile Recompile the CSS in any case
280
  */
281
  function parse_css($mode = "normal", $forceCompile = false )
282
  {
283
+ $css = $this->button_css;
284
+
285
  if (isset($this->cache) && $this->cache != '' && ! $forceCompile)
286
+ {
287
+
288
  $css = $this->cache;
289
  // kill media queries from cache
290
  if ($mode != 'normal')
291
  {
292
+ $pattern = "/@media.*}/is";
293
  preg_match($pattern, $css, $matches);
294
+ $css = preg_replace($pattern, '', $css);
295
  }
296
 
297
  maxUtils::addTime("Button: Cache loaded");
298
  }
299
  else
300
+ {
301
+ /* Internal filter, please don't use */
302
  foreach($this->blocks as $block)
303
  {
304
+ $css = $block->parse_css($css, $mode);
305
  }
306
  //$css = apply_filters('mb-css-blocks', $css, $mode);
307
+
308
  /* Filter the raw CSS array before compile
309
+
310
+ This filters passes an array with all CSS element before compile time. This should be CSS elements that can be understood by the CSS parser.
311
+ @since 4.20
312
+ @param $css CSS Array - split by element and pseudo (normal/hover)
313
+
314
  */
 
 
315
 
316
+ $css = apply_filters('mb/button/rawcss', $css, $mode);
317
 
318
+ $this->button_css = $css;
319
 
320
  $css = $this->getCSSParser()->parse($this->button_css);
321
+ $css = apply_filters('mb/button/compiledcss', $css, $mode); // the final result.
322
+
323
  if ($mode == 'normal') // only in general mode, otherwise things go amiss.
324
  $this->update_cache($css);
325
 
326
  }
327
+
328
+ $this->parsed_css = $css;
329
+
330
+
331
+ return $css;
332
+ }
333
+
334
+ /* Call blocks for javascript
335
+
336
+ Function will call for all block element to crunch the required javascript for output ( if any )
337
+ @param string $mode [normal, preview, editor]
338
+
339
  */
340
+ function parse_js($mode = "normal")
341
  {
342
  maxUtils::addTime("Button :: parse JS");
343
+ $js = $this->button_js;
344
  foreach($this->blocks as $block)
345
  {
346
+ $js = $block->parse_js($js,$mode);
347
+
348
  }
349
 
350
+ $this->button_js = $js;
351
  }
352
+
353
  /* Parse the actual button
354
+
355
+ Function adds the basic button components, creates the DOM object for the button and asks all block elements to parse their additions.
356
+
357
+ @param string $mode [normal, preview, editor]
358
  @return Object DomObj presentation of the button
359
  */
360
  function parse_button($mode = 'normal')
361
  {
362
+ $name = $this->name;
363
  // non-latin breaks CSS / ID's - so move to latin.
364
  $name = maxUtils::translit($name);
365
  $name = sanitize_title($name);
366
 
367
  $classes = array("maxbutton-" . $this->id,
368
  "maxbutton");
369
+
370
+
371
+ if ($name != '')
372
  $classes[] = "maxbutton-" . $name;
373
+
374
+ $classes = apply_filters('mb-mainclasses', $classes);
375
+ $classes = implode(' ', $classes);
376
+
377
  $domObj = new simple_html_dom();
378
+ $domObj->load('<a class="' . $classes . '"></a>');
 
379
 
380
  foreach($this->blocks as $block)
381
  {
382
  $domObj = $block->parse_button($domObj, $mode);
383
+ }
384
+
385
+
386
  $domObj->load($domObj->save());
387
+
388
  $cssParser = $this->getCSSParser();
389
  $cssParser->loadDom($domObj);
390
 
391
+ return $domObj;
392
  }
393
 
394
+ /* Display all data and html to allow users to edit button settings */
395
+ public function admin_fields()
396
  {
397
  foreach($this->blocks as $block)
398
  {
399
+ $block->admin_fields();
400
+
401
  }
402
+ //do_action('mb-admin-fields' );
403
+
404
  }
405
+
406
  /* Display the button */
407
  public function display($args = array() )
408
+ {
409
  maxUtils::startTime('button-display-'. $this->id);
410
  $defaults = array(
411
  "mode" => 'normal',
412
  "preview_part" => "full",
413
+ "echo" => true,
414
+ "load_css" => "footer", // control how css is loaded.
415
+ "compile" => false, // possibility to force recompile if needed.
416
  );
417
+ $output = ''; // init output;
418
+
419
+ $args = wp_parse_args($args, $defaults);
420
 
421
  $cssParser = $this->getCSSParser(); // init parser
422
+
423
+ $this->load_css = $args["load_css"];
424
+
425
  if ($this->id == 0) // if button doesn't exists don't display unless in editor
426
  {
427
+ if (! $args["mode"] == 'editor' )
428
  return;
429
+
430
+ $this->clear();
431
+
432
  $this->data["id"] = 0;
433
  //do_action('mb-data-load', $data);
434
  }
435
+
436
+ $mode = (isset($args["mode"])) ? $args["mode"] : "normal";
437
  switch($mode)
438
  {
439
+ case "preview":
440
  $preview = true;
441
  $compile = false;
442
+ break;
443
+ case "editor":
444
+ $preview = true;
445
+ $compile = true;
446
+ // editor is both compile and preview.
447
  break;
448
  break;
449
+ case "normal":
450
+ $preview = false;
451
  $compile = false;
452
  break;
453
  }
455
 
456
  // Apply filters for general data override
457
 
458
+ $this->data = apply_filters('mb/button/data_before_display', $this->data, $mode, array('preview' => $preview, 'compile' => $compile) ); // hooks
459
+
460
+
461
 
 
 
462
  if ( $this->load_css == "element" || $args["preview_part"] != "full" || $args["compile"] == true) { // if css output is on element, for to compile - otherwise inline styles will not be loaded.
463
  $compile = true;
464
 
465
  }
466
+ else
467
  $compile = false;
468
 
469
  // reload the data into the blocks, might have been altered by shortcode, filters etc.
473
  $block->set($this->data);
474
  }
475
 
476
+ $domObj = $this->parse_button($mode);
477
+
478
  maxUtils::startTime('button-parse-css-'. $this->id);
479
+ $this->parse_css($mode, $compile);
480
  maxUtils::endTime('button-parse-css-'. $this->id);
481
+
482
+ if (! $preview) // no js on previews
483
+ $this->parse_js($mode);
484
+
485
  if ($preview) // mark it preview
486
  {
487
 
488
  $domObj->find('a',0)->class .= ' maxbutton-preview';
489
  }
490
+
491
  if ($preview && $args["preview_part"] != 'full')
492
  {
493
+
494
  if ($args["preview_part"] != 'normal')
495
  {
496
+ $domObj->find('a',0)->class .= ' hover';
497
  $domObj = $cssParser->outputInline($domObj,'hover');
498
 
499
  }
500
  else
501
  {
502
+ $domObj->find('a',0)->class .= ' normal';
503
  $domObj = $cssParser->outputInline($domObj);
504
  }
505
 
506
  }
507
+ elseif ($this->load_css == 'footer')
508
  {
509
+ $css = $this->display_css(false, false);
510
+ do_action('mb-footer',$this->id, $css);
511
+
512
  if (! $preview)
513
  {
514
  $js = $this->display_js(false, true);
515
  do_action('mb-footer', $this->document_id, $js, 'js');
516
  }
517
+ } elseif ($this->load_css == 'inline')
518
  {
519
+ if ($args["echo"])
520
  $this->display_css();
521
  else
522
  $output .= $this->display_css(false);
523
  }
524
+ elseif ($this->load_css == 'element') // not possible to load both normal and hover to an element.
525
  {
526
+ $domObj->find('a',0)->class .= ' normal';
527
+ $domObj = $this->cssParser->outputInline($domObj);
528
+ //$this->get_element_css($domObj, 'normal');
529
  }
530
+
531
 
532
  $output .= $domObj->save();
533
+
534
+ $output = apply_filters('mb-before-button-output', $output);
535
+ maxButtons::buttonDone(array("button_id" => $this->id, "document_id" => $this->document_id) );
536
+
537
  maxUtils::endTime('button-display-'. $this->id);
538
+
539
  if ($args["echo"])
540
+ echo $output;
541
  else
542
+ return $output;
543
 
544
+ }
545
  /* Function used to map field id's to display for Frontend Javascript
546
+
547
+ This function bundles all defined fields into a json encoded variable. This is used for the frontend javascript functions in the
548
  administrator area like colorpickers and real-time updating of the button preview
549
  */
550
  public function display_field_map()
551
  {
552
+ $map = array();
553
  foreach($this->blocks as $block)
554
  {
555
+ $map = $block->map_fields($map);
556
  }
557
+ //$map = apply_filters("mb-field-map",$map);
558
+
559
 
560
+ echo "<script language='javascript'>";
561
  echo "var buttonFieldMap = '" . json_encode($map) . "';" ;
562
  echo "</script>";
563
+
564
  }
565
+
566
+ /* Write parsed CSS to output.
567
+ @param echo Default true. When true, outputs directly, otherwise returns output string
568
  @param style_tag Default true. When true, outputs a html <style> tags around the output.
569
  */
570
  public function display_css($echo = true, $style_tag = true)
571
  {
572
+ $output = '';
573
+
574
  if ($style_tag)
575
  $output .= "<style type='text/css'>";
576
+
577
  $output .= $this->parsed_css;
578
+
579
  if ($style_tag)
580
  $output .= "</style>";
581
+
582
+
583
+ if ($echo) echo $output;
584
+ else return $output;
585
+
586
  }
587
+
588
  /* Output Parsed Javascripting */
589
  public function display_js($echo = true, $tag = true)
590
  {
591
  $output = '';
592
 
593
+ if (count($this->button_js) == 0)
594
  return; // no output, holiday
595
+
596
+ if ($tag)
597
  {
598
+ $output .= "<script type='text/javascript'> ";
599
  $output .= " if (typeof maxButton" . $this->document_id . " == 'undefined') { ";
600
  $output .= " function maxButton" . $this->document_id . "() { ";
601
  }
602
+
603
+ foreach($this->button_js as $index => $code)
604
  {
605
+ $output .= $code;
606
+
607
  }
608
+
609
+ if ($tag)
610
  {
611
+ $output .= " }
612
+ }
613
+ window.onload = maxButton" . $this->document_id . "();
614
+ </script> ";
615
  }
616
 
617
+ if ($echo) echo $output;
618
+ else return $output;
619
  }
620
 
621
 
622
+ /* Makes a copy of the current buttons.
623
+
624
+ The button to be copied -must- be loaded and set
625
  */
626
+ function copy()
627
+ {
628
+ $this->id = 0;
629
  $data = $this->data;
630
  $data["name"] = $this->name;
631
+
632
+ return $this->update($data);
633
  }
634
  /* Change the publication status of the button.
635
+
636
  */
637
+ function setStatus($status = "publish")
638
  {
639
+ $data = $this->data;
640
+ $data["status"] = sanitize_text_field($status);
641
+
642
+ return $this->update($data);
643
 
644
+ }
645
+ /* Remove the button from database */
646
+ public function delete($id)
 
 
647
  {
648
  global $wpdb;
649
  $wpdb->query($wpdb->prepare("DELETE FROM " . maxUtils::get_table_name() . " WHERE id = %d", $id));
650
  }
651
+
652
+ /* Save changes to the button
653
+
654
+ Updates or saves the button. Existing buttons must load their data and be set -first- or lose all not-passed data.
655
+
656
  @param post Post data in field - value format (flat $_POST array)
657
+ @param boolean savedb if false do not save to database
658
  */
659
  public function save($post, $savedb = true)
660
  {
661
  $post = stripslashes_deep($post); // don't multiply slashes please.
662
+ //$data = apply_filters('mb-save-fields',$this->data, $post);
663
  $data = $this->data;
664
+
665
+ foreach($this->blocks as $block)
666
  {
667
+ $data = $block->save_fields($data, $post);
668
  }
669
+
670
+ if (! $savedb ) return $data;
671
+ return $this->update($data); // save to db.
672
+
673
  }
674
+
675
  /* Updates the button data to the database. Adds a button if it doesn't exist */
676
+ public function update($data)
677
+ {
678
+ global $wpdb;
679
+ $return = false;
680
+
681
+ $fields = array();
682
  foreach($this->blocks as $block)
683
  {
684
+ $block_name = $block->get_name();
685
+
686
+ if (isset($data[$block_name]))
687
  {
688
+ $blockData = $data[$block_name];
689
  $fields[$block_name] = json_encode($blockData);
690
  }
691
+ }
692
+ if (isset($data["name"])) { // other fields.
693
+ $fields["name"] = $data["name"];
694
  }
695
  if (isset($data["status"])) {
696
+ $fields["status"] = $data["status"];
697
  }
698
+
699
+
700
  $where = array('id' => $this->id );
701
+ if ($this->id > 0)
702
  {
703
  $where = array('id' => $this->id);
704
  $where_format = array('%d');
707
  }
708
  else
709
  {
710
+ $fields['created'] = current_time('mysql',1);
711
 
712
  $result = $wpdb->insert(maxUtils::get_table_name(), $fields);
713
  $id = $wpdb->insert_id;
714
 
715
  $this->id = $id;
716
+ $return = $id;
717
+
718
  }
719
+
720
+
721
  if ($result === false)
722
  {
723
  $error = "Database error " . $wpdb->last_error;
724
+ MB()->add_notice('error', $error);
725
+ $install = MB()->getClass("install");
726
  $install::create_database_table(); // run dbdelta to try and fix.
727
+
728
  }
729
+
730
+ // update the cache
731
+ $this->cache = ''; // empty cache
732
  $result = $this->set($this->id); // set the newest values
733
+
734
+ if (! $result ) return false;
735
+
736
  $this->display(array("echo" => false, "load_css" => "element")); // do display routing to compile.
737
+ $css = $this->parsed_css;
738
+ $this->update_cache($css);
739
 
740
  return $return;
741
  }
742
+
743
  /* Updates the CSS cache. */
744
  public function update_cache($css)
745
  {
746
  $return = false;
747
+ global $wpdb;
748
+
749
+ if ($this->id > 0)
750
  {
751
+ $fields = array("cache" => $css);
752
  $where = array('id' => $this->id);
753
  $where_format = array('%d');
754
  $wpdb->update(maxUtils::get_table_name(), $fields, $where, null, $where_format);
755
  $return = true;
756
+
757
  }
758
+ return $return;
759
  }
760
+
761
  // Resets all of the button caches.
762
  public function reset_cache()
763
  {
764
  global $wpdb;
765
+ $fields = array("cache" => null);
766
  $where = array(1 => 1);
767
  //$where_format = array('%d');
768
+ $sql = "UPDATE " . maxUtils::get_table_name() . " SET cache = NULL ";
769
  $wpdb->query($sql);
770
+
771
  }
772
 
773
+
774
  /* Display button via shortcode
775
+
776
  Function that accepts WP shortcode arguments and displays or returns a button
777
+
778
+ @param $atts array Shortcode Atts
779
  @return string HTML presentation of button
780
+
781
  */
782
  public function shortcode($atts)
783
+ {
784
  extract(shortcode_atts(array(
785
  'id' => '',
786
  'name' => '',
787
  'text' => '',
788
  'url' => '',
789
+ 'linktitle' => '',
790
  'window' => '',
791
  'nofollow' => '',
792
+ 'nocache' => false,
793
+ 'style' => 'footer',
794
  'exclude' => ''
795
 
796
+ ), $atts));
797
 
798
+ $button_id = $id;
799
  $button_name = $name;
800
+
801
+ if ($button_id > 0)
802
+ $result = $this->set($button_id);
803
+ elseif ($button_name != '')
804
+ $result = $this->set(0, $button_name);
805
  else return; // no button id / name
806
+
807
  /* Shortcode cache control
808
+
809
  If true the button CSS will be recompiled again. If false the plugin will check the cache for CSS declarations. Set to true if anything is interrupting the caching mechanism. Please note, recompiling causes some load times!
 
 
 
 
810
 
811
+ @param boolean $nocache True / False
812
+ */
813
+ $compile = apply_filters("mb/shortcode/nocache", $nocache);
814
+
815
+ if (! $result)
816
  return; // shortcode doesn't exist
817
+
818
  // If we're not in the admin and the button is in the trash, just return nothing
819
  if (!is_admin() && $this->status == 'trash') {
820
  return '';
822
  // Check to handle excludes
823
  if ("{$exclude}" != '') {
824
  global $post;
825
+
826
  // Don't render the button if excluded from the current post/page
827
  $exclude = explode(',', "{$exclude}");
828
  if (in_array($post->ID, $exclude)) {
829
  return '';
830
  }
831
  }
832
+
833
  // Override shortcode options comparing to default button data.
834
+ $overrides = false;
835
+ if ($text != '')
836
+ {
837
+ $this->data["text"]["text"] = $text;
838
  $overrides = true;
839
+ }
840
+ if ($url != '')
841
  {
842
 
843
+ $this->data["basic"]["url"] = $url;
844
  //$compile = true; // css change forces recompile
845
  $overrides = true;
846
  }
847
+ if ($window != '' && $window =='new')
848
  {
849
+ $this->data["basic"]["new_window"] = 1;
850
  $overrides = true;
851
  }
852
+ elseif ($window != '' && $window == 'same')
853
  {
854
+ $this->data["basic"]["new_window"] = 0;
855
+ $overrides = true;
856
  }
857
+
858
+ if ($nofollow != '' && $nofollow == 'true')
859
  {
860
+ $this->data["basic"]["nofollow"] = 1;
861
  $overrides = true;
862
  }
863
+
864
+ if ($linktitle != '')
865
  {
866
+ $this->data['basic']['link_title'] = $linktitle;
867
  $overrides = true;
868
  }
869
 
870
  switch($style)
871
  {
872
+ case "inline":
873
+ $load_css = 'inline';
874
  break;
875
  default:
876
+ $load_css = 'footer';
877
  break;
878
+ }
879
 
880
  // allow for more flexible changes and data manipulation.
881
  $data = $this->data;
882
+ $this->data = $this->shortcode_overrides($this->data, $atts);
883
+ $this->data = apply_filters('mb/shortcode/data', $this->data, $atts);
884
+
885
+ /* if ($data !== $this->data)
886
  {
887
+ $overrides = true;
888
  }
889
+ */
890
  /* if ($overrides)
891
  {
892
  do_action('mb-data-load', $this->data);
893
  }
894
+ */
895
  // if there are no reasons not to display; display
896
+ $args = array("echo" => false,
897
+ "load_css" => $load_css,
898
+ "compile" => $compile,
899
  );
900
+ $args = apply_filters('mb_shortcode_display_args', $args);
901
+
902
+
903
  $output = $this->display($args);
904
+
905
  return $output;
906
+
907
  }
908
+
909
+
910
  public function shortcode_overrides($data, $atts)
911
  {
912
  return $data;
913
  }
 
 
914
 
915
+ } // class
classes/max-utils.php CHANGED
@@ -2,77 +2,78 @@
2
  namespace MaxButtons;
3
  defined('ABSPATH') or die('No direct access permitted');
4
 
5
- // new class for the future.
6
  class maxUtils
7
  {
8
-
9
  protected static $timings = array();
10
- protected static $time_operations = array();
11
  protected static $timer = 0;
12
-
13
-
14
- /** Callback for array filter to prepend namepaces. **/
15
- public static function array_namespace($var)
16
  {
17
- $namespace = __NAMESPACE__ . '\\'; // PHP 5.3
18
- return ($namespace . $var);
19
- }
20
-
21
  public static function namespaceit($var)
22
  {
23
- $namespace = __NAMESPACE__ . '\\'; // PHP 5.3
24
  return $namespace . $var;
25
  }
26
-
27
- // central ajax action handler
28
  public static function ajax_action()
29
  {
30
- $status = 'error';
 
 
 
 
31
 
32
- $plugin_action = isset($_POST['plugin_action']) ? sanitize_text_field($_POST['plugin_action']) : '';
33
- $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : false;
34
- $message = __( sprintf("No Handler found for action %s ", $plugin_action), 'maxbuttons');
35
-
36
  if (! wp_verify_nonce($nonce, 'maxajax') )
37
  {
38
  $message = __('Nonce not verified', 'maxbuttons');
39
  }
40
  else
41
  {
42
- do_action('maxbuttons/ajax/' . $plugin_action, $_POST);
43
  }
44
-
45
- echo json_encode( array( 'status' => $status,
46
- 'message' => $message,
47
  )
48
- );
49
- wp_die();
50
  }
51
-
52
- public static function translit($string)
53
  {
54
- require_once(MB()->get_plugin_path() . "assets/libraries/url_slug.php");
55
- $string = mb_url_slug($string, array("transliterate" => true));
 
56
  return $string;
57
  }
58
 
59
  public static function selectify($name, $array, $selected, $target = '', $class = '')
60
  {
61
  // optional target for js updating
62
- if ($target != '' )
63
- $target = " data-target='$target' ";
64
- if ($class != '')
65
- $class = " class='$class' ";
66
  $output = "<select name='$name' id='$name' $target $class>";
67
-
68
- foreach($array as $key => $value)
69
  {
70
- $output .= "<option value='$key' " . selected($key, $selected, false) . ">$value</option>";
71
  }
72
- $output .= "</select>";
73
-
74
  return $output;
75
-
76
  }
77
 
78
 
@@ -92,10 +93,10 @@ class maxUtils
92
  $g = hexdec(substr($hex, 2, 2));
93
  $b = hexdec(substr($hex, 4, 2));
94
  }
95
-
96
  // The array of rgb values
97
  $rgb_array = array($r, $g, $b);
98
-
99
  // Catch for opacity when the button has not been saved
100
  if($opacity == '') {
101
  $alpha = 1;
@@ -106,255 +107,255 @@ class maxUtils
106
 
107
  // The rgb values separated by commas
108
  $rgb = implode(", ", $rgb_array);
109
-
110
  // Spits out rgba(0, 0, 0, 0.5) format
111
  return 'rgba(' . $rgb . ', ' . $alpha . ')';
112
  }
113
-
114
  static function strip_px($value) {
115
  return rtrim( intval($value), 'px');
116
  }
117
 
118
- static function generate_font_sizes($start, $end, $step = 1)
119
  {
120
- $sizes = array();
121
-
122
  for ($i = $start; $i <= $end; $i += $step)
123
  {
124
- $sizes[$i] = $i;
125
-
126
  }
127
- return $sizes;
128
-
129
  }
130
 
131
 
132
  static function get_media_query($get_option = 1)
133
  {
134
-
135
  $queries = array("phone" => "only screen and (max-width : 480px)",
136
- "phone_land" => "only screen and (min-width : 321px) and (max-width : 480px)",
137
- "phone_portrait" => " only screen and (max-width : 320px)",
138
  "ipad" => "only screen and (min-width : 768px) and (max-width : 1024px)",
139
  "medium_phone" => "only screen and (min-width: 480px) and (max-width: 768px)",
140
- "ipad_land" => "only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape)",
141
  "ipad_portrait" => "only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait)",
142
  "desktop" => "only screen and (min-width : 1224px)",
143
- "large_desktop" => "only screen and (min-width : 1824px)",
144
  );
145
-
146
  $query_names = array(
147
- "phone" => __("Small phones","maxbuttons"),
148
- "phone_land" => __("Small phones (landscape)","maxbuttons"),
149
- "phone_portrait" => __("Small phones (portrait)","maxbuttons"),
150
  "medium_phone" => __("Medium-size (smart)phone","maxbuttons"),
151
  "ipad" => __("Ipad (all) / Large phones","maxbuttons"),
152
- "ipad_land" => __("Ipad landscape","maxbuttons"),
153
  "ipad_portrait" => __("Ipad portrait","maxbuttons"),
154
  "desktop" => __("Desktop","maxbuttons"),
155
- "large_desktop" => __("Large desktops","maxbuttons"),
156
- "custom" => __("Custom size","maxbuttons"),
157
- );
158
-
159
  $query_descriptions = array(
160
  "phone" => __("Optimized for small smartphones ( screen sizes under 480px )","maxbuttons"),
161
- "phone_land" => __("Optimzed for small smartphones in landscape and higher ( screen sizes 321px - 480px)","maxbuttons"),
162
- "phone_portrait" => __("Optimized for small phones ( screen size max 320px )","maxbuttons"),
163
- "ipad" => __("Optimized for devices between 768px and 1024px","maxbuttons"),
164
- "medium_phone" => __("Optimized for medium sizes devices between 480px and 768px","maxbuttons"),
165
- "ipad_land" => __("Optimized for devices between 768px and 1024px in landscape","maxbuttons"),
166
- "ipad_portrait" => __("Optimized for deviced between 768px and 1024 in portrait","maxbuttons"),
167
  "desktop" => __("Desktop screens from 1224px","maxbuttons"),
168
  "large_desktop" => __("Large desktop screens, from 1824px","maxbuttons"),
169
- "custom" => __("Set your own breakpoints","maxbuttons"),
170
- );
171
-
172
-
173
  switch($get_option)
174
  {
175
- case 1:
176
  return $query_names;
177
  break;
178
- case 2:
179
- return $queries;
180
  break;
181
- case 3:
182
  return $query_descriptions;
183
  break;
184
  }
185
-
186
  }
187
-
188
- static function get_buttons_table_name($old = false)
189
  {
190
- self::addTime('Legacy Function call : get_buttons_table_name');
191
  return self::get_table_name($old);
192
  }
193
-
194
  static function get_table_name($old = false) {
195
  global $wpdb;
196
  if ($old)
197
  return $wpdb->prefix . 'maxbuttons_buttons';
198
  else
199
- return $wpdb->prefix . 'maxbuttonsv3';
200
  }
201
 
202
- static function get_collection_table_name() {
203
- global $wpdb;
204
- return $wpdb->prefix . 'maxbuttons_collections';
205
-
206
  }
207
 
208
- static function get_coltrans_table_name() {
209
- global $wpdb;
210
- return $wpdb->prefix . 'maxbuttons_collections_trans';
211
-
212
  }
213
-
214
  /* Replacement function for Wordpress' transients and problematic name length. */
215
- static function get_transient($name)
216
  {
217
- global $wpdb;
218
- // self::removeExpiredTrans();
219
-
220
- if ($name == '')
221
  return false;
222
-
223
  $table = self::get_coltrans_table_name();
224
-
225
- $sql = "SELECT value FROM $table where name= '%s' ";
226
- $sql = $wpdb->prepare($sql, $name);
227
-
228
- $var = $wpdb->get_var($sql);
229
-
230
- if (is_null($var))
231
  $var = false;
232
-
233
- return $var;
234
-
235
  }
236
-
237
-
238
  static function set_transient($name, $value , $expire = -1 )
239
  {
240
- global $wpdb;
241
-
242
-
243
  if ($expire == -1 )
244
- $expire = HOUR_IN_SECONDS * 4;
245
-
246
- if ($name == '')
247
- return false;
248
-
249
- $expire_time = time() + $expire;
250
-
251
  $table = self::get_coltrans_table_name();
252
-
253
  // prevent doubles, remove any present by this name
254
- self::delete_transient($name);
255
-
256
- $wpdb->insert($table,
257
- array("name" => $name,
258
- "value" => $value,
259
  "expire" => $expire_time
260
- ),
261
- array("%s","%s","%d"));
262
-
263
-
264
- }
265
-
266
- static function delete_transient($name)
267
  {
268
- global $wpdb;
269
-
270
-
271
  $table = self::get_coltrans_table_name();
272
- $wpdb->delete($table, array("name" => $name), array('%s') );
273
 
274
  }
275
-
276
- static function removeExpiredTrans()
277
  {
278
- global $wpdb;
279
-
280
  $table = self::get_coltrans_table_name();
281
- $sql = "DELETE FROM $table WHERE expire < UNIX_TIMESTAMP(NOW())";
282
  $return = $wpdb->query($sql);
283
-
284
  if($return === false)
285
  {
286
  $error = "Database error " . $wpdb->last_error;
287
- MB()->add_notice('error', $error);
288
  $install = MB()->getClass('install');
289
- $install->create_database_table();
290
  }
291
-
292
  }
293
-
294
- /** Function will try to unload any FA scripts other than MB from WP. In case of conflict */
295
- static function fixFAConflict()
296
  {
297
- $forcefa = get_option('maxbuttons_forcefa');
298
-
299
- if ($forcefa != '1')
300
  return;
301
-
302
  global $wp_styles;
303
 
304
- $our_fa_there = false;
305
-
306
- foreach($wp_styles->registered as $script => $details)
307
  {
308
- if ($script == 'mbpro-font-awesome')
309
  {
310
- $our_fa_there = true;
311
  break;
312
- }
313
  }
314
-
315
  // fix nothing on pages where we are not loading.
316
- if (! $our_fa_there)
317
- return;
318
-
319
 
320
  // Loop through all registered styles and remove any that appear to be Font Awesome.
321
  foreach ( $wp_styles->registered as $script => $details ) {
322
  $src = isset($details->src) ? $details->src : false;
323
 
324
- if ($script == 'mbpro-font-awesome')
325
  {
326
  $mbpro_src = $src;
327
  continue; // exclude us
328
  }
329
-
330
  if ( false !== strpos( $script, 'fontawesome' ) || false !== strpos( $script, 'font-awesome' ) ) {
331
  wp_dequeue_style( $script );
332
  }
333
  if ($src && ( false !== strpos($src, 'font-awesome') || false !== strpos($src, 'fontawesome') ) )
334
  {
335
- wp_dequeue_style( $script );
336
  }
337
 
338
  }
339
-
340
- // This is a fix specific for NGGallery since they load their scripts weirdly / wrongly, but do check for the presence of a style named 'fontawesome' .
341
  wp_register_style('fontawesome', $src);
342
 
343
  }
344
-
345
 
346
  static function timeInit()
347
  {
348
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
349
  return;
350
-
351
  self::$timer = microtime(true);
352
 
353
- if (is_admin())
354
- add_filter("admin_footer",array(self::namespaceit('maxUtils'), "showTime"), 100);
355
  else
356
- add_action("wp_footer",array(self::namespaceit('maxUtils'), "showTime"));
357
-
358
  }
359
 
360
  static function addTime($msg)
@@ -362,28 +363,28 @@ class maxUtils
362
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
363
  return;
364
 
365
-
366
- self::$timings[] = array("msg" => $msg,"time" => microtime(true));
367
  }
368
-
369
  static function startTime($operation)
370
  {
371
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
372
  return;
373
-
374
- self::$time_operations[$operation][] = array("start" => microtime(true),
375
- "end" => 0,
376
- );
377
-
378
  }
379
-
380
- static function endTime($operation)
381
  {
382
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
383
  return;
384
-
385
- $timedcount = count(self::$time_operations[$operation]);
386
- for ($i = 0; $i < $timedcount; $i++)
387
  {
388
  if (self::$time_operations[$operation][$i]["end"] == 0)
389
  {
@@ -391,79 +392,79 @@ class maxUtils
391
  break;
392
  }
393
  }
394
-
395
  }
396
-
397
  static function showTime()
398
  {
399
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
400
  return;
401
-
402
  $timer = self::$timer;
403
- $text = '';
404
- $text .= "<div id='mb-timer'>";
405
- $text .= "<p><strong>Timed Operations</strong></p>";
406
-
407
- foreach(self::$time_operations as $operation => $operations)
408
  {
409
  foreach($operations as $index => $data)
410
  {
411
- $start = $data["start"];
412
- $end = $data["end"];
413
- $duration = $end - $start;
414
-
415
-
416
  $text .= "<span class='first'>$duration</span>
417
- <span class='second'>$operation</span>
418
- <span class='third'>&nbsp; </span><br />
419
- ";
420
-
421
-
422
  }
423
  }
424
-
425
-
426
- $text .= "<p><strong>" . __("MaxButtons Loading Time:","maxbuttons") . "</strong></p>";
427
  $prev_time =0;
428
-
429
- $time_array = array();
430
-
431
  foreach(self::$timings as $timing)
432
  {
433
- $cum = ($timing["time"] - $prev_time);
434
- $text .= "<span class='first'>" . ($timing["time"] - $timer) . "</span><span class='second'> " . $timing["msg"] . "</span><span class='third'>$cum</span> <br /> ";
435
- //$time_array[$cum] = $timing["msg"];
436
  $prev_time = $timing["time"];
437
  }
438
 
439
  /*ksort($time_array);
440
-
441
- $text .= "<br><br><strong>By time taken:</strong><br>";
442
  foreach($time_array as $timeline)
443
  {
444
- $text .= "$timeline <br />";
445
  }
446
  */
447
  $text .= "</div> ";
448
- $text .= "<style>#mb-timer { margin-left: 180px; }
449
- #mb-timer span {
450
  display: inline-block;
451
  font-size: 12px;
452
  }
453
- #mb-timer span.first {
454
- width: 170px;
 
 
 
455
  }
456
- #mb-timer span.second {
457
- width: 300px;
458
  }
459
- #mb-timer span.third {
460
- width: 150px;
461
- }
462
- </style>";
463
-
464
  echo $text;
465
-
466
-
467
- //return $filter . $text;
468
  }
469
  }
2
  namespace MaxButtons;
3
  defined('ABSPATH') or die('No direct access permitted');
4
 
5
+ // new class for the future.
6
  class maxUtils
7
  {
8
+
9
  protected static $timings = array();
10
+ protected static $time_operations = array();
11
  protected static $timer = 0;
12
+
13
+
14
+ /** Callback for array filter to prepend namepaces. **/
15
+ public static function array_namespace($var)
16
  {
17
+ $namespace = __NAMESPACE__ . '\\'; // PHP 5.3
18
+ return ($namespace . $var);
19
+ }
20
+
21
  public static function namespaceit($var)
22
  {
23
+ $namespace = __NAMESPACE__ . '\\'; // PHP 5.3
24
  return $namespace . $var;
25
  }
26
+
27
+ // central ajax action handler
28
  public static function ajax_action()
29
  {
30
+ $status = 'error';
31
+
32
+ $plugin_action = isset($_POST['plugin_action']) ? sanitize_text_field($_POST['plugin_action']) : '';
33
+ $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : false;
34
+ $message = __( sprintf("No Handler found for action %s ", $plugin_action), 'maxbuttons');
35
 
 
 
 
 
36
  if (! wp_verify_nonce($nonce, 'maxajax') )
37
  {
38
  $message = __('Nonce not verified', 'maxbuttons');
39
  }
40
  else
41
  {
42
+ do_action('maxbuttons/ajax/' . $plugin_action, $_POST);
43
  }
44
+
45
+ echo json_encode( array( 'status' => $status,
46
+ 'message' => $message,
47
  )
48
+ );
49
+ wp_die();
50
  }
51
+
52
+ public static function translit($string)
53
  {
54
+ require_once(MB()->get_plugin_path() . "assets/libraries/url_slug.php");
55
+
56
+ $string = mb_url_slug($string, array("transliterate" => true));
57
  return $string;
58
  }
59
 
60
  public static function selectify($name, $array, $selected, $target = '', $class = '')
61
  {
62
  // optional target for js updating
63
+ if ($target != '' )
64
+ $target = " data-target='$target' ";
65
+ if ($class != '')
66
+ $class = " class='$class' ";
67
  $output = "<select name='$name' id='$name' $target $class>";
68
+
69
+ foreach($array as $key => $value)
70
  {
71
+ $output .= "<option value='$key' " . selected($key, $selected, false) . ">$value</option>";
72
  }
73
+ $output .= "</select>";
74
+
75
  return $output;
76
+
77
  }
78
 
79
 
93
  $g = hexdec(substr($hex, 2, 2));
94
  $b = hexdec(substr($hex, 4, 2));
95
  }
96
+
97
  // The array of rgb values
98
  $rgb_array = array($r, $g, $b);
99
+
100
  // Catch for opacity when the button has not been saved
101
  if($opacity == '') {
102
  $alpha = 1;
107
 
108
  // The rgb values separated by commas
109
  $rgb = implode(", ", $rgb_array);
110
+
111
  // Spits out rgba(0, 0, 0, 0.5) format
112
  return 'rgba(' . $rgb . ', ' . $alpha . ')';
113
  }
114
+
115
  static function strip_px($value) {
116
  return rtrim( intval($value), 'px');
117
  }
118
 
119
+ static function generate_font_sizes($start, $end, $step = 1)
120
  {
121
+ $sizes = array();
122
+
123
  for ($i = $start; $i <= $end; $i += $step)
124
  {
125
+ $sizes[$i] = $i;
126
+
127
  }
128
+ return $sizes;
129
+
130
  }
131
 
132
 
133
  static function get_media_query($get_option = 1)
134
  {
135
+
136
  $queries = array("phone" => "only screen and (max-width : 480px)",
137
+ "phone_land" => "only screen and (min-width : 321px) and (max-width : 480px)",
138
+ "phone_portrait" => " only screen and (max-width : 320px)",
139
  "ipad" => "only screen and (min-width : 768px) and (max-width : 1024px)",
140
  "medium_phone" => "only screen and (min-width: 480px) and (max-width: 768px)",
141
+ "ipad_land" => "only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape)",
142
  "ipad_portrait" => "only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait)",
143
  "desktop" => "only screen and (min-width : 1224px)",
144
+ "large_desktop" => "only screen and (min-width : 1824px)",
145
  );
146
+
147
  $query_names = array(
148
+ "phone" => __("Small phones","maxbuttons"),
149
+ "phone_land" => __("Small phones (landscape)","maxbuttons"),
150
+ "phone_portrait" => __("Small phones (portrait)","maxbuttons"),
151
  "medium_phone" => __("Medium-size (smart)phone","maxbuttons"),
152
  "ipad" => __("Ipad (all) / Large phones","maxbuttons"),
153
+ "ipad_land" => __("Ipad landscape","maxbuttons"),
154
  "ipad_portrait" => __("Ipad portrait","maxbuttons"),
155
  "desktop" => __("Desktop","maxbuttons"),
156
+ "large_desktop" => __("Large desktops","maxbuttons"),
157
+ "custom" => __("Custom size","maxbuttons"),
158
+ );
159
+
160
  $query_descriptions = array(
161
  "phone" => __("Optimized for small smartphones ( screen sizes under 480px )","maxbuttons"),
162
+ "phone_land" => __("Optimzed for small smartphones in landscape and higher ( screen sizes 321px - 480px)","maxbuttons"),
163
+ "phone_portrait" => __("Optimized for small phones ( screen size max 320px )","maxbuttons"),
164
+ "ipad" => __("Optimized for devices between 768px and 1024px","maxbuttons"),
165
+ "medium_phone" => __("Optimized for medium sizes devices between 480px and 768px","maxbuttons"),
166
+ "ipad_land" => __("Optimized for devices between 768px and 1024px in landscape","maxbuttons"),
167
+ "ipad_portrait" => __("Optimized for deviced between 768px and 1024 in portrait","maxbuttons"),
168
  "desktop" => __("Desktop screens from 1224px","maxbuttons"),
169
  "large_desktop" => __("Large desktop screens, from 1824px","maxbuttons"),
170
+ "custom" => __("Set your own breakpoints","maxbuttons"),
171
+ );
172
+
173
+
174
  switch($get_option)
175
  {
176
+ case 1:
177
  return $query_names;
178
  break;
179
+ case 2:
180
+ return $queries;
181
  break;
182
+ case 3:
183
  return $query_descriptions;
184
  break;
185
  }
186
+
187
  }
188
+
189
+ static function get_buttons_table_name($old = false)
190
  {
191
+ self::addTime('Legacy Function call : get_buttons_table_name');
192
  return self::get_table_name($old);
193
  }
194
+
195
  static function get_table_name($old = false) {
196
  global $wpdb;
197
  if ($old)
198
  return $wpdb->prefix . 'maxbuttons_buttons';
199
  else
200
+ return $wpdb->prefix . 'maxbuttonsv3';
201
  }
202
 
203
+ static function get_collection_table_name() {
204
+ global $wpdb;
205
+ return $wpdb->prefix . 'maxbuttons_collections';
206
+
207
  }
208
 
209
+ static function get_coltrans_table_name() {
210
+ global $wpdb;
211
+ return $wpdb->prefix . 'maxbuttons_collections_trans';
212
+
213
  }
214
+
215
  /* Replacement function for Wordpress' transients and problematic name length. */
216
+ static function get_transient($name)
217
  {
218
+ global $wpdb;
219
+ // self::removeExpiredTrans();
220
+
221
+ if ($name == '')
222
  return false;
223
+
224
  $table = self::get_coltrans_table_name();
225
+
226
+ $sql = "SELECT value FROM $table where name= '%s' ";
227
+ $sql = $wpdb->prepare($sql, $name);
228
+
229
+ $var = $wpdb->get_var($sql);
230
+
231
+ if (is_null($var))
232
  $var = false;
233
+
234
+ return $var;
235
+
236
  }
237
+
238
+
239
  static function set_transient($name, $value , $expire = -1 )
240
  {
241
+ global $wpdb;
242
+
243
+
244
  if ($expire == -1 )
245
+ $expire = HOUR_IN_SECONDS * 4;
246
+
247
+ if ($name == '')
248
+ return false;
249
+
250
+ $expire_time = time() + $expire;
251
+
252
  $table = self::get_coltrans_table_name();
253
+
254
  // prevent doubles, remove any present by this name
255
+ self::delete_transient($name);
256
+
257
+ $wpdb->insert($table,
258
+ array("name" => $name,
259
+ "value" => $value,
260
  "expire" => $expire_time
261
+ ),
262
+ array("%s","%s","%d"));
263
+
264
+
265
+ }
266
+
267
+ static function delete_transient($name)
268
  {
269
+ global $wpdb;
270
+
271
+
272
  $table = self::get_coltrans_table_name();
273
+ $wpdb->delete($table, array("name" => $name), array('%s') );
274
 
275
  }
276
+
277
+ static function removeExpiredTrans()
278
  {
279
+ global $wpdb;
280
+
281
  $table = self::get_coltrans_table_name();
282
+ $sql = "DELETE FROM $table WHERE expire < UNIX_TIMESTAMP(NOW())";
283
  $return = $wpdb->query($sql);
284
+
285
  if($return === false)
286
  {
287
  $error = "Database error " . $wpdb->last_error;
288
+ MB()->add_notice('error', $error);
289
  $install = MB()->getClass('install');
290
+ $install->create_database_table();
291
  }
292
+
293
  }
294
+
295
+ /** Function will try to unload any FA scripts other than MB from WP. In case of conflict */
296
+ static function fixFAConflict()
297
  {
298
+ $forcefa = get_option('maxbuttons_forcefa');
299
+
300
+ if ($forcefa != '1')
301
  return;
302
+
303
  global $wp_styles;
304
 
305
+ $our_fa_there = false;
306
+
307
+ foreach($wp_styles->registered as $script => $details)
308
  {
309
+ if ($script == 'mbpro-font-awesome')
310
  {
311
+ $our_fa_there = true;
312
  break;
313
+ }
314
  }
315
+
316
  // fix nothing on pages where we are not loading.
317
+ if (! $our_fa_there)
318
+ return;
319
+
320
 
321
  // Loop through all registered styles and remove any that appear to be Font Awesome.
322
  foreach ( $wp_styles->registered as $script => $details ) {
323
  $src = isset($details->src) ? $details->src : false;
324
 
325
+ if ($script == 'mbpro-font-awesome')
326
  {
327
  $mbpro_src = $src;
328
  continue; // exclude us
329
  }
330
+
331
  if ( false !== strpos( $script, 'fontawesome' ) || false !== strpos( $script, 'font-awesome' ) ) {
332
  wp_dequeue_style( $script );
333
  }
334
  if ($src && ( false !== strpos($src, 'font-awesome') || false !== strpos($src, 'fontawesome') ) )
335
  {
336
+ wp_dequeue_style( $script );
337
  }
338
 
339
  }
340
+
341
+ // This is a fix specific for NGGallery since they load their scripts weirdly / wrongly, but do check for the presence of a style named 'fontawesome' .
342
  wp_register_style('fontawesome', $src);
343
 
344
  }
345
+
346
 
347
  static function timeInit()
348
  {
349
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
350
  return;
351
+
352
  self::$timer = microtime(true);
353
 
354
+ if (is_admin())
355
+ add_filter("admin_footer",array(self::namespaceit('maxUtils'), "showTime"), 100);
356
  else
357
+ add_action("wp_footer",array(self::namespaceit('maxUtils'), "showTime"));
358
+
359
  }
360
 
361
  static function addTime($msg)
363
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
364
  return;
365
 
366
+
367
+ self::$timings[] = array("msg" => $msg,"time" => microtime(true));
368
  }
369
+
370
  static function startTime($operation)
371
  {
372
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
373
  return;
374
+
375
+ self::$time_operations[$operation][] = array("start" => microtime(true),
376
+ "end" => 0,
377
+ );
378
+
379
  }
380
+
381
+ static function endTime($operation)
382
  {
383
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
384
  return;
385
+
386
+ $timedcount = count(self::$time_operations[$operation]);
387
+ for ($i = 0; $i < $timedcount; $i++)
388
  {
389
  if (self::$time_operations[$operation][$i]["end"] == 0)
390
  {
392
  break;
393
  }
394
  }
395
+
396
  }
397
+
398
  static function showTime()
399
  {
400
  if ( ! defined('MAXBUTTONS_BENCHMARK') || MAXBUTTONS_BENCHMARK !== true)
401
  return;
402
+
403
  $timer = self::$timer;
404
+ $text = '';
405
+ $text .= "<div id='mb-timer'>";
406
+ $text .= "<p><strong>Timed Operations</strong></p>";
407
+
408
+ foreach(self::$time_operations as $operation => $operations)
409
  {
410
  foreach($operations as $index => $data)
411
  {
412
+ $start = $data["start"];
413
+ $end = $data["end"];
414
+ $duration = $end - $start;
415
+
416
+
417
  $text .= "<span class='first'>$duration</span>
418
+ <span class='second'>$operation</span>
419
+ <span class='third'>&nbsp; </span><br />
420
+ ";
421
+
422
+
423
  }
424
  }
425
+
426
+
427
+ $text .= "<p><strong>" . __("MaxButtons Loading Time:","maxbuttons") . "</strong></p>";
428
  $prev_time =0;
429
+
430
+ $time_array = array();
431
+
432
  foreach(self::$timings as $timing)
433
  {
434
+ $cum = ($timing["time"] - $prev_time);
435
+ $text .= "<span class='first'>" . ($timing["time"] - $timer) . "</span><span class='second'> " . $timing["msg"] . "</span><span class='third'>$cum</span> <br /> ";
436
+ //$time_array[$cum] = $timing["msg"];
437
  $prev_time = $timing["time"];
438
  }
439
 
440
  /*ksort($time_array);
441
+
442
+ $text .= "<br><br><strong>By time taken:</strong><br>";
443
  foreach($time_array as $timeline)
444
  {
445
+ $text .= "$timeline <br />";
446
  }
447
  */
448
  $text .= "</div> ";
449
+ $text .= "<style>#mb-timer { margin-left: 180px; }
450
+ #mb-timer span {
451
  display: inline-block;
452
  font-size: 12px;
453
  }
454
+ #mb-timer span.first {
455
+ width: 170px;
456
+ }
457
+ #mb-timer span.second {
458
+ width: 300px;
459
  }
460
+ #mb-timer span.third {
461
+ width: 150px;
462
  }
463
+ </style>";
464
+
 
 
 
465
  echo $text;
466
+
467
+
468
+ //return $filter . $text;
469
  }
470
  }
classes/maxCSSParser.php CHANGED
@@ -2,292 +2,293 @@
2
  namespace MaxButtons;
3
  defined('ABSPATH') or die('No direct access permitted');
4
  /* Class to Parse CSS. Load as array with diffent pseudo-types,
5
- ability to add nested and new root blocks
6
  parses via scss
7
  ability to use complicated css stuff via scss mixins parsing like gradient
8
- auto-discovery for -unit field types to set units (like px, or %)
9
  auto-discovery of fields via domobj.
10
-
11
  */
12
 
13
  use \Exception as Exception;
14
 
15
  class maxCSSParser
16
  {
17
- protected $struct = array();
18
  protected $domObj = '';
19
- protected $pseudo = array("hover","active","responsive");
20
-
21
- protected $data;
22
  protected $output_css;
23
-
24
  protected $inline = array();
25
  protected $responsive = array();
26
-
27
- public $anchor_class = '.maxbutton'; // used for matching buttons in parse_part
28
-
29
  // settings
30
  protected $elements_ignore_zero = array(
31
  'text-shadow-left',
32
- 'text_shadow-top',
33
  'text-shadow-width',
34
  'box-shadow-offset-left',
35
- 'box-shadow-offset-top',
36
  'box-shadow-width',
37
- 'box-shadow-spread',
38
- ); // items to ignore if value is zero, otherwise they become unremovable ( where 0 is still something on display)
39
-
40
  protected $important = false;
41
-
42
  // log possible problems and incidents for debugging;
43
  protected $parse_log = array();
44
-
45
  function __construct()
46
  {
47
- //$root[] = array("a" => array("hover","active","responsive"));
48
 
49
  }
50
-
51
  function loadDom($domObj)
52
- {
53
  $this->domObj = $domObj;
54
 
55
  $root = $domObj->find(0,0);
56
- $struct[$root->tag] = array();
57
-
58
  $children = $root->children();
59
-
60
- if (count($children) > 0)
61
  $struct[$root->tag] = $this->loadRecursive(array(), $children);
62
-
63
 
64
  $this->struct = $struct;
65
 
66
 
67
  }
68
-
69
  function loadRecursive($struct, $children)
70
  {
71
  foreach($children as $domChild)
72
  {
73
 
74
- $class = $domChild->class;
75
- $class = str_replace(" ",".", $class); // combine seperate classes
76
-
77
- $struct[$class]["tag"] = $domChild->tag;
78
-
79
- $child_children = $domChild->children();
80
 
81
- if (count($child_children) > 0)
 
 
82
  {
83
-
84
  $struct[$class]["children"] = $this->loadRecursive(array(), $child_children);
85
  }
86
  }
87
-
88
  return $struct;
89
  }
90
-
91
-
92
  function parse($data)
93
- {
94
- $this->clear();
95
-
96
- $struct = $this->struct;
 
 
97
 
98
- $this->data = $data;
99
 
100
-
101
  if (isset($data["settings"])) // room for settings in parser
102
  {
103
  $settings = $data["settings"];
104
- $this->important = (isset($settings["important"])) ? $settings["important"] : false;
105
-
106
- unset($this->data["settings"]);
107
  }
108
 
109
- $elements = array_shift($struct); // first element is a 'stub' root.
110
 
111
  if ( is_null($elements) )
112
- return;
113
 
114
 
115
  foreach($elements as $el => $el_data)
116
  {
117
 
118
- $this->parse_part($el,$el_data);
119
  }
120
 
121
 
122
  $this->parse_responsive();
123
-
124
  maxUtils::startTime('compile CSS');
125
  $css = $this->compile($this->output_css);
 
126
  maxUtils::endTime('compile CSS');
127
 
128
 
129
  return $css;
130
-
131
  }
132
-
133
- // reset output values.
134
- protected function clear()
135
  {
136
- $this->data = '';
137
- $this->output_css = '';
138
  $this->inline = array();
139
  //$this->struct = array();
140
  $this->responsive = array();
141
-
142
  }
143
-
144
  protected function compile($css)
145
  {
146
  $scss = new \Leafo\ScssPhp\Compiler();
147
  $scss->setImportPaths(MB()->get_plugin_path() . "assets/scss");
148
-
149
- $minify = get_option("maxbuttons_minify", 1);
150
  if ($minify == 1)
151
  $scss->setFormatter('\Leafo\ScssPhp\Formatter\Compressed');
152
-
153
  $compile = " @import '_mixins.scss'; " . $css;
154
  //maxUtils::addTime("CSSParser: Compile start ");
155
-
156
  try
157
  {
158
  $css = $scss->compile($compile);
159
- } catch (Exception $e) {
160
-
161
- $css = $this->output_css;
162
- }
163
 
164
  //maxUtils::addTime("CSSParser: Compile end ");
165
 
166
  return $css;
167
  }
168
-
169
  function parse_part($element, $el_data, $el_add = '')
170
  {
171
  maxUtils::addTime("CSSParser: Parse $element ");
172
-
173
-
174
- $tag = $el_data["tag"];
175
  $element_data = $this->findData($this->data, $element);
176
-
177
- // not using scss selectors here since there is trouble w/ the :pseudo selector, which should be put on the maxbutton / a tag.
178
  if ($element != '')
179
  { $el_add .= " ." . $element;
180
-
181
  }
182
-
183
- if (isset($element_data["responsive"]))
184
  {
185
  $responsive = $element_data["responsive"]; // doing that at the end
186
- unset($element_data["responsive"]);
187
 
188
  $this->responsive[$el_add] = $responsive;
189
  }
190
-
191
  foreach($element_data as $pseudo => $values)
192
  {
193
-
194
- if ($pseudo != 'normal')
195
  {
196
- // select the maxbutton case, ending with either space or next class -dot.
197
  // Anchor class in default situation should be .maxbutton
198
- $anchor_class = $this->anchor_class;
199
-
200
- $count = 0;
201
-
202
  /* If PS Selector replacement doesn't match anchor class selector this probably means the parse is done in a higher level
203
- e.g. container level, so no proper will be set. In case 0 count replacement, just put it on current */
204
  $ps_selector = preg_replace('/' . $anchor_class . '$|' . $anchor_class . '([.| ])/i',"$anchor_class:$pseudo\$1",$el_add, -1, $count);
205
 
 
206
  if ($count === 0)
207
  {
208
- $ps_selector = $el_add . ":" . $pseudo;
209
  }
210
-
211
-
212
- $this->output_css .= " $ps_selector { ";
213
  }
214
  else {
215
  $this->output_css .= " $el_add { ";
216
  }
217
-
218
  $values = $this->doMixins($values);
219
 
220
  foreach($values as $cssTag => $cssVal)
221
  {
222
-
223
  $statement = $this->parse_cssline($values, $cssTag,$cssVal); ///"$cssTag $css_sep $cssVal$unit$css_end ";
224
 
225
  if ($statement)
226
  {
227
  $this->output_css .= $statement ;
228
-
229
  if (! isset($this->inline[$pseudo][$element])) $this->inline[$pseudo][$element] = '';
230
  $this->inline[$pseudo][$element] .= $statement;
231
- }
232
  }
233
 
234
- $this->output_css .= " } ";
235
  }
236
- if (isset($el_data["children"]))
237
  {
238
  foreach($el_data["children"] as $child_id => $child_data)
239
  {
240
-
241
  $this->parse_part($child_id, $child_data, $el_add);
242
  }
243
  }
244
 
245
  }
246
-
247
  function parse_cssline($values, $cssTag, $cssVal, $css_end = ';')
248
  {
249
 
250
  // unit check - two ways; either unitable items is first or unit declaration.
251
- if (isset($values[$cssTag . "_unit"]))
252
  {
253
- $unit = $values[$cssTag . "_unit"];
254
  }
255
  elseif(strpos($cssTag, "_unit") !== false)
256
  {
257
- return false; // no print, should be found under first def.
258
  }
259
  else $unit = '';
260
-
261
 
262
- $important = ($this->is_important()) ? " !important" : "";
263
- $important = ($cssTag == '@include') ? "" : $important; // mixin's problem, no checking here.
264
-
 
265
  $css_sep = ($cssTag == '@include') ? $css_sep = '' : ':';
266
-
267
  if ($cssVal == 0 && in_array($cssTag, $this->elements_ignore_zero))
268
- return false;
269
-
270
  if($cssVal !== '' && $cssTag !== '')
271
  {
272
  $statement = "$cssTag $css_sep $cssVal$unit$important$css_end ";
273
  return $statement;
274
  }
275
  return false;
276
-
277
  }
278
-
279
  function parse_responsive()
280
  {
281
 
282
- $responsive = $this->responsive;
283
- if (! is_array($responsive) || count($responsive) == 0)
284
- return;
285
 
286
  $media_queries = maxUtils::get_media_query(2); // query names
287
-
288
- $output = '';
289
-
290
- $query_array = array();
291
 
292
 
293
  foreach($responsive as $element => $queries)
@@ -295,95 +296,95 @@ class maxCSSParser
295
  foreach($queries as $query => $qdata)
296
  foreach($qdata as $index => $data)
297
  {{
298
- $query_array[$query][$index][$element] = $data;
299
-
300
  }}
301
  }
302
-
303
 
304
-
 
305
  foreach($query_array as $query => $vdata):
306
 
307
- if ($query == 'custom')
308
  {
309
 
310
- // first discover the custom size properties.
311
  foreach($vdata as $index => $data):
312
  foreach($data as $element => $values):
313
 
314
- if (isset($values["custom_maxwidth"]) || isset($values["custom_minwidth"]) )
315
  {
316
-
317
  $minwidth = (isset($values["custom_minwidth"])) ? intval($values["custom_minwidth"]) : -1;
318
- $maxwidth = (isset($values["custom_maxwidth"])) ? intval($values["custom_maxwidth"]) : -1;
319
-
320
-
321
- unset($vdata[$index][$element]["custom_minwidth"]);
322
  unset($vdata[$index][$element]["custom_maxwidth"]);
323
-
324
-
325
- // make it always an integer
326
- if ($minwidth == '') $minwidth = 0;
327
- if ($maxwidth == '') $maxwidth = 0;
328
-
329
- // if minwidth is not set and maxwidth zero or not set - ignore since it would result in an empty media line.
330
- //if ($minwidth <= 0 && $maxwidth <= 0)
331
  //{
332
  //continue;
333
  //}
334
-
335
- if ($minwidth > 0 && $maxwidth > 0)
336
- $qdef = "only screen and (min-width: $minwidth" . "px) and (max-width: $maxwidth" . "px)";
337
- if ($minwidth >= 0 && $maxwidth <= 0)
338
- $qdef = "only screen and (min-width: $minwidth" . "px) ";
339
- if ($minwidth <= 0 && $maxwidth > 0)
340
- $qdef = "only screen and (max-width: $maxwidth" . "px) ";
341
-
342
  //break;
343
 
344
- }
345
- endforeach; //foreach data
346
-
347
- // The problem is that every 'custom' query needs to run with a different qdef unlike other queries.
348
-
349
  $qdata = array($vdata[$index]);
350
-
351
- $output = $this->parse_responsive_definition($output, $qdef, $qdata);
352
- endforeach; // foreach vdata
353
  }
354
  else
355
  {
356
-
357
- $qdef = $media_queries[$query];
358
  $output = $this->parse_responsive_definition($output, $qdef, $vdata);
359
  }
360
 
361
  endforeach;
362
-
363
-
364
  $this->output_css .= $output;
365
  }
366
-
367
  protected function parse_responsive_definition($output, $qdef, $vdata)
368
  {
369
-
370
  if (! isset($qdef) || $qdef == '') {
371
-
372
- return; // no definition.
373
  }
374
 
375
-
376
- $output .= "@media ". $qdef . " { ";
377
 
378
-
 
 
379
  foreach($vdata as $index => $data)
380
  {
381
-
382
  foreach($data as $element => $values) {
383
  //foreach($vdat as $index => $values):
384
- $output .= $element . " { ";
385
  $css_end = ';';
386
-
387
  // same as parse part, maybe merge in future
388
  foreach($values as $cssTag => $cssVal)
389
  {
@@ -391,213 +392,215 @@ class maxCSSParser
391
  $statement = $this->parse_cssline($values, $cssTag,$cssVal);
392
  if($statement)
393
  $output .= $statement;
394
-
395
  }
396
 
397
- $output .= " } ";
398
  // endforeach;
399
  }
400
 
401
-
402
  }
403
- $output .= " } ";
404
-
405
- //endforeach;
406
-
407
  return $output;
408
  }
409
-
410
  private function is_important()
411
  {
412
 
413
  if ($this->important == 1)
414
  return true;
415
- else
416
  return false;
417
  }
418
-
419
  function findData($data, $el)
420
  {
421
- $classes = explode(".", $el);
422
 
423
- foreach($data as $part => $values)
424
  {
425
  if (in_array($part, $classes))
 
426
  return $data[$part];
 
427
  }
428
  return array();
429
  }
430
-
431
  function doMixins($values)
432
  {
433
  $mixins = array("gradient", "box-shadow", "text-shadow");
434
-
435
- foreach($mixins as $mixin)
436
  {
437
 
438
  $results = preg_grep("/^$mixin/i",array_keys($values) );
439
- if (count($results) === 0)
440
- continue; // no mixins.
441
-
442
  $mixin_array = array();
443
  foreach($results as $result)
444
  {
445
- $mixin_array[$result] = $values[$result];
446
  }
447
 
448
  if (count($mixin_array) > 0)
449
  {
450
  switch($mixin)
451
  {
452
- case "gradient":
453
  $values = $this->mixin_gradient($mixin_array, $values);
454
-
455
  break;
456
- case "box-shadow":
457
  $values = $this->mixin_boxshadow($mixin_array, $values);
458
- break;
459
- case "text-shadow":
460
  $values = $this->mixin_textshadow($mixin_array, $values);
461
  break;
462
  }
463
  }
464
 
465
-
466
- }
467
  return $values;
468
  }
469
-
470
  function mixin_gradient($results, $values)
471
  {
472
 
473
  $start = isset($results["gradient-start-color"]) ? $results["gradient-start-color"] : '';
474
- $end = isset( $results["gradient-end-color"] ) ? $results["gradient-end-color"] : '';
475
- $start_opacity = isset( $results["gradient-start-opacity"] ) ? $results["gradient-start-opacity"] : '';
476
- $end_opacity = isset( $results["gradient-end-opacity"] ) ? $results["gradient-end-opacity"] : '';
477
- $stop = (isset( $results["gradient-stop"]) && $results["gradient-stop"] != '') ? $results["gradient-stop"] . "%" : '45%';
478
  // default to use ( old situation )
479
  $use_gradient = (isset($results['gradient-use-gradient']) && $results['gradient-use-gradient'] != '') ? $results['gradient-use-gradient'] : 1;
480
-
481
  $start = maxUtils::hex2rgba($start, $start_opacity);
482
- $end = maxUtils::hex2rgba($end, $end_opacity);
483
-
484
  $important = ($this->is_important()) ? "!important" : "";
485
- //$values = $this->add_include($values, "linear-gradient($start,$end,$stop,$important)");
486
 
487
  if ($use_gradient == 1)
488
  {
489
- $values = $this->add_include($values, "linear-gradient($start,$end,$stop,$important)");
490
  }
491
  else {
492
- $values['background-color'] = $start;
493
  }
494
 
495
- // remove the non-css keys from the value array ( field names )
496
  $values = array_diff_key($values, $results);
497
 
498
  return $values;
499
-
500
  }
501
-
502
  function mixin_boxshadow($results, $values)
503
  {
504
- $width = $results["box-shadow-width"];
505
- $left = $results["box-shadow-offset-left"];
506
- $top = $results["box-shadow-offset-top"];
507
- $spread = isset($results['box-shadow-spread']) ? $results['box-shadow-spread'] : 0;
508
- $color = isset($results["box-shadow-color"]) ? $results["box-shadow-color"] : '';
509
-
510
- $important = ($this->is_important()) ? "!important" : "";
511
-
512
- if ($width == 0 && $left == 0 && $top == 0)
513
- return $values;
514
-
515
- $values = $this->add_include($values, "box-shadow($left, $top, $width, $color,$spread, false, $important) ");
516
  $values = array_diff_key($values, $results);
517
 
518
- return $values;
519
  }
520
-
521
  function mixin_textshadow($results, $values)
522
  {
523
- $width = isset($results["text-shadow-width"]) ? $results["text-shadow-width"] : 0;
524
- $left = isset($results["text-shadow-left"]) ? $results["text-shadow-left"] : 0;
525
- $top = isset($results["text-shadow-top"]) ? $results["text-shadow-top"] : 0;
526
- $color = isset($results["text-shadow-color"]) ? $results["text-shadow-color"] : '';
527
- $important = ($this->is_important()) ? "!important" : "";
528
-
529
- if ($width == 0 && $left == 0 && $top == 0)
530
  {
531
  $values = array_diff_key($values, $results); // remove them from the values, prevent incorrect output.
532
- return $values;
533
  }
534
-
535
- $values = $this->add_include($values, "text-shadow ($left,$top,$width,$color $important)");
536
-
537
  $values = array_diff_key($values, $results);
538
-
539
  return $values;
540
  }
541
-
542
  private function add_include($values, $include)
543
  {
544
- if (isset($values["@include"]))
545
- $values["@include"] .= "; @include " . $include;
546
  else
547
- $values["@include"] = $include;
548
- return $values;
549
  }
550
-
551
  function outputInline($domObj, $pseudo = 'normal')
552
  {
553
  $domObj = $domObj->load($domObj->save());
554
-
555
  $inline = $this->inline;
556
-
557
- // ISSUE #43 Sometimes this breaks
558
- if (! isset($inline[$pseudo]))
559
  return $domObj;
560
 
561
  $elements = array_keys($inline[$pseudo]);
562
  if ($pseudo != 'normal') // gather all elements
563
  $elements = array_merge($elements, array_keys($inline["normal"]));
564
-
565
  foreach($elements as $element )
566
  {
567
- $styles = isset($inline[$pseudo][$element]) ? $inline[$pseudo][$element] : '';
568
-
569
  if ($pseudo != 'normal') // parse all possible missing styles from pseudo el.
570
- $normstyle = $this->compile($inline['normal'][$element]);
571
-
572
- $normstyle = '';
573
  if ($pseudo != 'normal') // parse all possible missing styles from pseudo el.
574
- $normstyle = $this->compile($inline['normal'][$element]);
575
-
576
  maxUtils::addTime("CSSParser: Parse inline done");
577
-
578
  $styles = $normstyle . $this->compile($styles);
579
-
580
- $element = trim(str_replace("."," ", $element)); // molten css class, seperator.
581
-
582
  $el = $domObj->find('[class*="' . $element . '"]', 0);
583
- if (is_null($el)) echo "NULL";
584
  $el->style = $styles;
585
-
586
  }
587
-
588
  return $domObj;
589
-
590
- }
591
-
592
- function output()
593
  {
594
-
595
-
596
  }
597
-
598
  }
599
 
600
- class compileException extends Exception {
601
  protected $code = -1;
602
 
603
  }
2
  namespace MaxButtons;
3
  defined('ABSPATH') or die('No direct access permitted');
4
  /* Class to Parse CSS. Load as array with diffent pseudo-types,
5
+ ability to add nested and new root blocks
6
  parses via scss
7
  ability to use complicated css stuff via scss mixins parsing like gradient
8
+ auto-discovery for -unit field types to set units (like px, or %)
9
  auto-discovery of fields via domobj.
10
+
11
  */
12
 
13
  use \Exception as Exception;
14
 
15
  class maxCSSParser
16
  {
17
+ protected $struct = array();
18
  protected $domObj = '';
19
+ protected $pseudo = array("hover","active","responsive");
20
+
21
+ protected $data;
22
  protected $output_css;
23
+
24
  protected $inline = array();
25
  protected $responsive = array();
26
+
27
+ public $anchor_class = '.maxbutton'; // used for matching buttons in parse_part
28
+
29
  // settings
30
  protected $elements_ignore_zero = array(
31
  'text-shadow-left',
32
+ 'text_shadow-top',
33
  'text-shadow-width',
34
  'box-shadow-offset-left',
35
+ 'box-shadow-offset-top',
36
  'box-shadow-width',
37
+ 'box-shadow-spread',
38
+ ); // items to ignore if value is zero, otherwise they become unremovable ( where 0 is still something on display)
39
+
40
  protected $important = false;
41
+
42
  // log possible problems and incidents for debugging;
43
  protected $parse_log = array();
44
+
45
  function __construct()
46
  {
47
+ //$root[] = array("a" => array("hover","active","responsive"));
48
 
49
  }
50
+
51
  function loadDom($domObj)
52
+ {
53
  $this->domObj = $domObj;
54
 
55
  $root = $domObj->find(0,0);
56
+ $struct[$root->tag] = array();
57
+
58
  $children = $root->children();
59
+
60
+ if (count($children) > 0)
61
  $struct[$root->tag] = $this->loadRecursive(array(), $children);
62
+
63
 
64
  $this->struct = $struct;
65
 
66
 
67
  }
68
+
69
  function loadRecursive($struct, $children)
70
  {
71
  foreach($children as $domChild)
72
  {
73
 
74
+ $class = $domChild->class;
75
+ $class = str_replace(" ",".", $class); // combine seperate classes
76
+ $struct[$class]["tag"] = $domChild->tag;
 
 
 
77
 
78
+ $child_children = $domChild->children();
79
+
80
+ if (count($child_children) > 0)
81
  {
82
+
83
  $struct[$class]["children"] = $this->loadRecursive(array(), $child_children);
84
  }
85
  }
86
+
87
  return $struct;
88
  }
89
+
90
+
91
  function parse($data)
92
+ {
93
+ $this->clear();
94
+
95
+ $struct = $this->struct;
96
+
97
+ $this->data = $data;
98
 
 
99
 
 
100
  if (isset($data["settings"])) // room for settings in parser
101
  {
102
  $settings = $data["settings"];
103
+ $this->important = (isset($settings["important"])) ? $settings["important"] : false;
104
+
105
+ unset($this->data["settings"]);
106
  }
107
 
108
+ $elements = array_shift($struct); // first element is a 'stub' root.
109
 
110
  if ( is_null($elements) )
111
+ return;
112
 
113
 
114
  foreach($elements as $el => $el_data)
115
  {
116
 
117
+ $this->parse_part($el,$el_data);
118
  }
119
 
120
 
121
  $this->parse_responsive();
122
+
123
  maxUtils::startTime('compile CSS');
124
  $css = $this->compile($this->output_css);
125
+
126
  maxUtils::endTime('compile CSS');
127
 
128
 
129
  return $css;
130
+
131
  }
132
+
133
+ // reset output values.
134
+ protected function clear()
135
  {
136
+ $this->data = '';
137
+ $this->output_css = '';
138
  $this->inline = array();
139
  //$this->struct = array();
140
  $this->responsive = array();
141
+
142
  }
143
+
144
  protected function compile($css)
145
  {
146
  $scss = new \Leafo\ScssPhp\Compiler();
147
  $scss->setImportPaths(MB()->get_plugin_path() . "assets/scss");
148
+
149
+ $minify = get_option("maxbuttons_minify", 1);
150
  if ($minify == 1)
151
  $scss->setFormatter('\Leafo\ScssPhp\Formatter\Compressed');
152
+
153
  $compile = " @import '_mixins.scss'; " . $css;
154
  //maxUtils::addTime("CSSParser: Compile start ");
155
+
156
  try
157
  {
158
  $css = $scss->compile($compile);
159
+ } catch (Exception $e) {
160
+
161
+ $css = $this->output_css;
162
+ }
163
 
164
  //maxUtils::addTime("CSSParser: Compile end ");
165
 
166
  return $css;
167
  }
168
+
169
  function parse_part($element, $el_data, $el_add = '')
170
  {
171
  maxUtils::addTime("CSSParser: Parse $element ");
172
+
173
+
174
+ $tag = $el_data["tag"];
175
  $element_data = $this->findData($this->data, $element);
176
+
177
+ // not using scss selectors here since there is trouble w/ the :pseudo selector, which should be put on the maxbutton / a tag.
178
  if ($element != '')
179
  { $el_add .= " ." . $element;
180
+
181
  }
182
+
183
+ if (isset($element_data["responsive"]))
184
  {
185
  $responsive = $element_data["responsive"]; // doing that at the end
186
+ unset($element_data["responsive"]);
187
 
188
  $this->responsive[$el_add] = $responsive;
189
  }
190
+
191
  foreach($element_data as $pseudo => $values)
192
  {
193
+
194
+ if ($pseudo != 'normal')
195
  {
196
+ // select the maxbutton case, ending with either space or next class -dot.
197
  // Anchor class in default situation should be .maxbutton
198
+ $anchor_class = $this->anchor_class;
199
+
200
+ $count = 0;
201
+
202
  /* If PS Selector replacement doesn't match anchor class selector this probably means the parse is done in a higher level
203
+ e.g. container level, so no proper will be set. In case 0 count replacement, just put it on current */
204
  $ps_selector = preg_replace('/' . $anchor_class . '$|' . $anchor_class . '([.| ])/i',"$anchor_class:$pseudo\$1",$el_add, -1, $count);
205
 
206
+
207
  if ($count === 0)
208
  {
209
+ $ps_selector = $el_add . ":" . $pseudo;
210
  }
211
+
212
+
213
+ $this->output_css .= " $ps_selector { ";
214
  }
215
  else {
216
  $this->output_css .= " $el_add { ";
217
  }
218
+
219
  $values = $this->doMixins($values);
220
 
221
  foreach($values as $cssTag => $cssVal)
222
  {
223
+
224
  $statement = $this->parse_cssline($values, $cssTag,$cssVal); ///"$cssTag $css_sep $cssVal$unit$css_end ";
225
 
226
  if ($statement)
227
  {
228
  $this->output_css .= $statement ;
229
+
230
  if (! isset($this->inline[$pseudo][$element])) $this->inline[$pseudo][$element] = '';
231
  $this->inline[$pseudo][$element] .= $statement;
232
+ }
233
  }
234
 
235
+ $this->output_css .= " } ";
236
  }
237
+ if (isset($el_data["children"]))
238
  {
239
  foreach($el_data["children"] as $child_id => $child_data)
240
  {
241
+
242
  $this->parse_part($child_id, $child_data, $el_add);
243
  }
244
  }
245
 
246
  }
247
+
248
  function parse_cssline($values, $cssTag, $cssVal, $css_end = ';')
249
  {
250
 
251
  // unit check - two ways; either unitable items is first or unit declaration.
252
+ if (isset($values[$cssTag . "_unit"]))
253
  {
254
+ $unit = $values[$cssTag . "_unit"];
255
  }
256
  elseif(strpos($cssTag, "_unit") !== false)
257
  {
258
+ return false; // no print, should be found under first def.
259
  }
260
  else $unit = '';
 
261
 
262
+
263
+ $important = ($this->is_important()) ? " !important" : "";
264
+ $important = ($cssTag == '@include') ? "" : $important; // mixin's problem, no checking here.
265
+
266
  $css_sep = ($cssTag == '@include') ? $css_sep = '' : ':';
267
+
268
  if ($cssVal == 0 && in_array($cssTag, $this->elements_ignore_zero))
269
+ return false;
270
+
271
  if($cssVal !== '' && $cssTag !== '')
272
  {
273
  $statement = "$cssTag $css_sep $cssVal$unit$important$css_end ";
274
  return $statement;
275
  }
276
  return false;
277
+
278
  }
279
+
280
  function parse_responsive()
281
  {
282
 
283
+ $responsive = $this->responsive;
284
+ if (! is_array($responsive) || count($responsive) == 0)
285
+ return;
286
 
287
  $media_queries = maxUtils::get_media_query(2); // query names
288
+
289
+ $output = '';
290
+
291
+ $query_array = array();
292
 
293
 
294
  foreach($responsive as $element => $queries)
296
  foreach($queries as $query => $qdata)
297
  foreach($qdata as $index => $data)
298
  {{
299
+ $query_array[$query][$index][$element] = $data;
300
+
301
  }}
302
  }
 
303
 
304
+
305
+
306
  foreach($query_array as $query => $vdata):
307
 
308
+ if ($query == 'custom')
309
  {
310
 
311
+ // first discover the custom size properties.
312
  foreach($vdata as $index => $data):
313
  foreach($data as $element => $values):
314
 
315
+ if (isset($values["custom_maxwidth"]) || isset($values["custom_minwidth"]) )
316
  {
317
+
318
  $minwidth = (isset($values["custom_minwidth"])) ? intval($values["custom_minwidth"]) : -1;
319
+ $maxwidth = (isset($values["custom_maxwidth"])) ? intval($values["custom_maxwidth"]) : -1;
320
+
321
+
322
+ unset($vdata[$index][$element]["custom_minwidth"]);
323
  unset($vdata[$index][$element]["custom_maxwidth"]);
324
+
325
+
326
+ // make it always an integer
327
+ if ($minwidth == '') $minwidth = 0;
328
+ if ($maxwidth == '') $maxwidth = 0;
329
+
330
+ // if minwidth is not set and maxwidth zero or not set - ignore since it would result in an empty media line.
331
+ //if ($minwidth <= 0 && $maxwidth <= 0)
332
  //{
333
  //continue;
334
  //}
335
+
336
+ if ($minwidth > 0 && $maxwidth > 0)
337
+ $qdef = "only screen and (min-width: $minwidth" . "px) and (max-width: $maxwidth" . "px)";
338
+ if ($minwidth >= 0 && $maxwidth <= 0)
339
+ $qdef = "only screen and (min-width: $minwidth" . "px) ";
340
+ if ($minwidth <= 0 && $maxwidth > 0)
341
+ $qdef = "only screen and (max-width: $maxwidth" . "px) ";
342
+
343
  //break;
344
 
345
+ }
346
+ endforeach; //foreach data
347
+
348
+ // The problem is that every 'custom' query needs to run with a different qdef unlike other queries.
349
+
350
  $qdata = array($vdata[$index]);
351
+
352
+ $output = $this->parse_responsive_definition($output, $qdef, $qdata);
353
+ endforeach; // foreach vdata
354
  }
355
  else
356
  {
357
+
358
+ $qdef = $media_queries[$query];
359
  $output = $this->parse_responsive_definition($output, $qdef, $vdata);
360
  }
361
 
362
  endforeach;
363
+
364
+
365
  $this->output_css .= $output;
366
  }
367
+
368
  protected function parse_responsive_definition($output, $qdef, $vdata)
369
  {
370
+
371
  if (! isset($qdef) || $qdef == '') {
372
+
373
+ return; // no definition.
374
  }
375
 
 
 
376
 
377
+ $output .= "@media ". $qdef . " { ";
378
+
379
+
380
  foreach($vdata as $index => $data)
381
  {
382
+
383
  foreach($data as $element => $values) {
384
  //foreach($vdat as $index => $values):
385
+ $output .= $element . " { ";
386
  $css_end = ';';
387
+
388
  // same as parse part, maybe merge in future
389
  foreach($values as $cssTag => $cssVal)
390
  {
392
  $statement = $this->parse_cssline($values, $cssTag,$cssVal);
393
  if($statement)
394
  $output .= $statement;
395
+
396
  }
397
 
398
+ $output .= " } ";
399
  // endforeach;
400
  }
401
 
402
+
403
  }
404
+ $output .= " } ";
405
+
406
+ //endforeach;
407
+
408
  return $output;
409
  }
410
+
411
  private function is_important()
412
  {
413
 
414
  if ($this->important == 1)
415
  return true;
416
+ else
417
  return false;
418
  }
419
+
420
  function findData($data, $el)
421
  {
422
+ $classes = explode(".", $el);
423
 
424
+ foreach($data as $part => $values)
425
  {
426
  if (in_array($part, $classes))
427
+ {
428
  return $data[$part];
429
+ }
430
  }
431
  return array();
432
  }
433
+
434
  function doMixins($values)
435
  {
436
  $mixins = array("gradient", "box-shadow", "text-shadow");
437
+
438
+ foreach($mixins as $mixin)
439
  {
440
 
441
  $results = preg_grep("/^$mixin/i",array_keys($values) );
442
+ if (count($results) === 0)
443
+ continue; // no mixins.
444
+
445
  $mixin_array = array();
446
  foreach($results as $result)
447
  {
448
+ $mixin_array[$result] = $values[$result];
449
  }
450
 
451
  if (count($mixin_array) > 0)
452
  {
453
  switch($mixin)
454
  {
455
+ case "gradient":
456
  $values = $this->mixin_gradient($mixin_array, $values);
457
+
458
  break;
459
+ case "box-shadow":
460
  $values = $this->mixin_boxshadow($mixin_array, $values);
461
+ break;
462
+ case "text-shadow":
463
  $values = $this->mixin_textshadow($mixin_array, $values);
464
  break;
465
  }
466
  }
467
 
468
+
469
+ }
470
  return $values;
471
  }
472
+
473
  function mixin_gradient($results, $values)
474
  {
475
 
476
  $start = isset($results["gradient-start-color"]) ? $results["gradient-start-color"] : '';
477
+ $end = isset( $results["gradient-end-color"] ) ? $results["gradient-end-color"] : '';
478
+ $start_opacity = isset( $results["gradient-start-opacity"] ) ? $results["gradient-start-opacity"] : '';
479
+ $end_opacity = isset( $results["gradient-end-opacity"] ) ? $results["gradient-end-opacity"] : '';
480
+ $stop = (isset( $results["gradient-stop"]) && $results["gradient-stop"] != '') ? $results["gradient-stop"] . "%" : '45%';
481
  // default to use ( old situation )
482
  $use_gradient = (isset($results['gradient-use-gradient']) && $results['gradient-use-gradient'] != '') ? $results['gradient-use-gradient'] : 1;
483
+
484
  $start = maxUtils::hex2rgba($start, $start_opacity);
485
+ $end = maxUtils::hex2rgba($end, $end_opacity);
486
+
487
  $important = ($this->is_important()) ? "!important" : "";
488
+ //$values = $this->add_include($values, "linear-gradient($start,$end,$stop,$important)");
489
 
490
  if ($use_gradient == 1)
491
  {
492
+ $values = $this->add_include($values, "linear-gradient($start,$end,$stop,$important)");
493
  }
494
  else {
495
+ $values['background-color'] = $start;
496
  }
497
 
498
+ // remove the non-css keys from the value array ( field names )
499
  $values = array_diff_key($values, $results);
500
 
501
  return $values;
502
+
503
  }
504
+
505
  function mixin_boxshadow($results, $values)
506
  {
507
+ $width = $results["box-shadow-width"];
508
+ $left = $results["box-shadow-offset-left"];
509
+ $top = $results["box-shadow-offset-top"];
510
+ $spread = isset($results['box-shadow-spread']) ? $results['box-shadow-spread'] : 0;
511
+ $color = isset($results["box-shadow-color"]) ? $results["box-shadow-color"] : '';
512
+
513
+ $important = ($this->is_important()) ? "!important" : "";
514
+
515
+ if ($width == 0 && $left == 0 && $top == 0)
516
+ return $values;
517
+
518
+ $values = $this->add_include($values, "box-shadow($left, $top, $width, $color,$spread, false, $important) ");
519
  $values = array_diff_key($values, $results);
520
 
521
+ return $values;
522
  }
523
+
524
  function mixin_textshadow($results, $values)
525
  {
526
+ $width = isset($results["text-shadow-width"]) ? $results["text-shadow-width"] : 0;
527
+ $left = isset($results["text-shadow-left"]) ? $results["text-shadow-left"] : 0;
528
+ $top = isset($results["text-shadow-top"]) ? $results["text-shadow-top"] : 0;
529
+ $color = isset($results["text-shadow-color"]) ? $results["text-shadow-color"] : '';
530
+ $important = ($this->is_important()) ? "!important" : "";
531
+
532
+ if ($width == 0 && $left == 0 && $top == 0)
533
  {
534
  $values = array_diff_key($values, $results); // remove them from the values, prevent incorrect output.
535
+ return $values;
536
  }
537
+
538
+ $values = $this->add_include($values, "text-shadow ($left,$top,$width,$color $important)");
539
+
540
  $values = array_diff_key($values, $results);
541
+
542
  return $values;
543
  }
544
+
545
  private function add_include($values, $include)
546
  {
547
+ if (isset($values["@include"]))
548
+ $values["@include"] .= "; @include " . $include;
549
  else
550
+ $values["@include"] = $include;
551
+ return $values;
552
  }
553
+
554
  function outputInline($domObj, $pseudo = 'normal')
555
  {
556
  $domObj = $domObj->load($domObj->save());
557
+
558
  $inline = $this->inline;
559
+
560
+ // ISSUE #43 Sometimes this breaks
561
+ if (! isset($inline[$pseudo]))
562
  return $domObj;
563
 
564
  $elements = array_keys($inline[$pseudo]);
565
  if ($pseudo != 'normal') // gather all elements
566
  $elements = array_merge($elements, array_keys($inline["normal"]));
567
+
568
  foreach($elements as $element )
569
  {
570
+ $styles = isset($inline[$pseudo][$element]) ? $inline[$pseudo][$element] : '';
571
+
572
  if ($pseudo != 'normal') // parse all possible missing styles from pseudo el.
573
+ $normstyle = $this->compile($inline['normal'][$element]);
574
+
575
+ $normstyle = '';
576
  if ($pseudo != 'normal') // parse all possible missing styles from pseudo el.
577
+ $normstyle = $this->compile($inline['normal'][$element]);
578
+
579
  maxUtils::addTime("CSSParser: Parse inline done");
580
+
581
  $styles = $normstyle . $this->compile($styles);
582
+
583
+ $element = trim(str_replace("."," ", $element)); // molten css class, seperator.
584
+
585
  $el = $domObj->find('[class*="' . $element . '"]', 0);
586
+
587
  $el->style = $styles;
588
+
589
  }
590
+
591
  return $domObj;
592
+
593
+ }
594
+
595
+ function output()
596
  {
597
+
598
+
599
  }
600
+
601
  }
602
 
603
+ class compileException extends Exception {
604
  protected $code = -1;
605
 
606
  }
maxbuttons.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: MaxButtons
4
  Plugin URI: http://maxbuttons.com
5
  Description: The best WordPress button generator. This is the free version; the Pro version <a href="http://maxbuttons.com/?ref=mbfree">can be found here</a>.
6
- Version: 6.26.1
7
  Author: Max Foundry
8
  Author URI: http://maxfoundry.com
9
  Text Domain: maxbuttons
@@ -16,9 +16,9 @@ namespace MaxButtons;
16
  if (! defined('MAXBUTTONS_ROOT_FILE'))
17
  define("MAXBUTTONS_ROOT_FILE", __FILE__);
18
  if (! defined('MAXBUTTONS_VERSION_NUM'))
19
- define('MAXBUTTONS_VERSION_NUM', '6.26.1');
20
 
21
- define('MAXBUTTONS_RELEASE',"08 Jan 2018");
22
 
23
 
24
  if (! function_exists('MaxButtons\maxbutton_double_load'))
3
  Plugin Name: MaxButtons
4
  Plugin URI: http://maxbuttons.com
5
  Description: The best WordPress button generator. This is the free version; the Pro version <a href="http://maxbuttons.com/?ref=mbfree">can be found here</a>.
6
+ Version: 6.27
7
  Author: Max Foundry
8
  Author URI: http://maxfoundry.com
9
  Text Domain: maxbuttons
16
  if (! defined('MAXBUTTONS_ROOT_FILE'))
17
  define("MAXBUTTONS_ROOT_FILE", __FILE__);
18
  if (! defined('MAXBUTTONS_VERSION_NUM'))
19
+ define('MAXBUTTONS_VERSION_NUM', '6.27');
20
 
21
+ define('MAXBUTTONS_RELEASE',"17 Jan 2018");
22
 
23
 
24
  if (! function_exists('MaxButtons\maxbutton_double_load'))
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: wordpress button plugin, share button, wordpress buttons, css3 button gene
4
  Requires at least: 4.0
5
  Tested up to: 4.9.1
6
  Requires PHP: 5.3
7
- Stable tag: 6.26.1
8
 
9
  WordPress button plugin so powerful and easy to use anyone can create beautiful buttons, share buttons and social icons.
10
 
@@ -243,11 +243,23 @@ By default WordPress can't display shortcodes in a menu. You can use this [plugi
243
 
244
  This depends on the slider plugin you are using. Most of the well-known ones are allowing the use of shortcodes within the slides. To find out if your plugin can handle that, please ask the slider vendor.
245
 
 
 
 
 
 
 
246
  == Changelog ==
247
 
 
 
 
 
 
 
248
  = 6.26.1 =
249
 
250
- * Fixed - Advanced options
251
 
252
  = 6.26 =
253
 
4
  Requires at least: 4.0
5
  Tested up to: 4.9.1
6
  Requires PHP: 5.3
7
+ Stable tag: 6.27
8
 
9
  WordPress button plugin so powerful and easy to use anyone can create beautiful buttons, share buttons and social icons.
10
 
243
 
244
  This depends on the slider plugin you are using. Most of the well-known ones are allowing the use of shortcodes within the slides. To find out if your plugin can handle that, please ask the slider vendor.
245
 
246
+ = Non-Latin language users =
247
+
248
+ The plugin works with users of non-lating languages with a few exceptions. First, the character set of the Database Table should be in UTF-8. If you see '????' characters in the plugin, go to Settings -> Advanced. There is a button to set the tabel to UTF-8
249
+
250
+ Secondly, please use latin only characters for button name ( Basic settings) and extra classes ( Advanced settings ). Not doing so might prevent the styling output from working correctly.
251
+
252
  == Changelog ==
253
 
254
+ = 6.27 =
255
+
256
+ * Tested for 4.9.2
257
+ * Security - Added rel='noopener' for links opening in new window
258
+ * Fixed missing values on a template
259
+
260
  = 6.26.1 =
261
 
262
+ * Fixed - Advanced options
263
 
264
  = 6.26 =
265