PluginProbe
MaxButtons – Create buttons / 9.8.2
MaxButtons – Create buttons v9.8.2
6.23 6.24 6.25 6.26 6.26.1 6.27 6.28 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.1.1 7.1.2 7.1.3 7.10 7.11 7.13 7.13.1 7.13.2 7.13.3 All 100 releases
maxbuttons / classes / button.php

button.php in MaxButtons – Create buttons 9.8.2, at classes/button.php

977 lines 23.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types=1);
3 namespace MaxButtons;
4 defined('ABSPATH') or die('No direct access permitted');
5
6 /* Datamodel and base functionality for a button
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 protected $updated = 0;
20
21 protected $button_loaded = false;
22
23 protected $data = array();
24 protected $blocks; // Block Classes
25 protected $templates = array(); // .tpl files
26
27 protected $button_css = array();
28 protected $button_js = array();
29
30 // output conditions
31 protected $load_css = 'footer'; // [ footer, inline, external, element ]
32 protected $load_js = 'footer';
33
34 protected $cssParser = false;
35 protected $parsed_css = '';
36
37
38 /* Class constructor
39
40 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
41 */
42 public function __construct()
43 {
44 maxUtils::addTime("Button construct");
45
46 // the parser
47
48 // get all files from blocks map
49
50 // get all blocks classes, do init on the blocks. Init should not load anything big.
51 $this->loadBlockClasses();
52
53 }
54
55 /* Makes overriding block features possible by subclass
56
57 */
58 private function loadBlockClasses()
59 {
60
61 // set blocks to the 'block name' that survived.
62 maxUtils::addTime("Load Block classes");
63
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 maxBlocks::add($block);
71 $this->blocks[] = $block;
72 }
73
74 $this->clear(); // init
75 }
76
77 /** Simple function to retrieve loaded blocks - * Used by install class and controllers */
78 public function getBlocks()
79 {
80 return $this->blocks;
81 }
82
83 /** Get Data from Database and set variables
84 *
85 * You can pass either id or name to this function
86 *
87 * @return Boolean Returns false when no data was found using either ID or name
88 */
89 public function set($id = 0, $name = '', $status = 'publish')
90 {
91 maxUtils::addTime("Button set $id");
92
93 $id = intval($id);
94 $name = sanitize_text_field($name);
95 $status = sanitize_text_field($status);
96
97 global $wpdb;
98 $this->clear(); // clear the internals of any previous work
99
100 // check to see if the value passed is NOT numeric. If it is, use title, else assume numeric
101 if($id == 0 && $name != '') {
102 $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE name = '%s' and status ='%s'", trim($name), $status ), ARRAY_A);
103
104 } else {
105 $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE id = %d and status ='%s'", $id, $status), ARRAY_A);
106 }
107
108 if (! is_array($row)) // no db row results in null / false
109 {
110 return false;
111 }
112 elseif (count($row) == 0)
113 {
114 return false;
115 }
116
117 /* Take the id from the query, otherwise ( when button shortcode called by name ) id might not be present properly' */
118 $button_id = $row["id"];
119 maxButtons::buttonLoad(array("button_id" => $button_id)); // central registration
120
121 return $this->setupData($row);
122
123 }
124 /** Clear button settings
125 *
126 * This function prevent that generated values from previous set actions will still be present.
127 */
128 public function clear()
129 {
130 unset($this->data);
131 unset($this->button_css);
132 $this->id = 0; // clear id
133 $this->button_css = array();
134 $this->button_js = array();
135 // reset data to defaults.
136 $this->data = array('id' => 0);
137 $this->data = $this->save(array(),array(), false);
138 $this->updated = '0';
139
140 $this->cache = '';
141 $this->button_loaded = false;
142
143 maxBlocks::clearFoundMixins();
144 Screen::setupScreens($this->data);
145
146 foreach($this->blocks as $block)
147 {
148 $block->set(array()); // reset blocks
149 }
150 }
151
152 public function setupData($data)
153 {
154 maxUtils::addTime("Button: Setup data");
155 foreach($this->blocks as $block)
156 {
157 $block_name = $block->get_name();
158
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]) && ! is_null($this->data[$block_name]))
163 {
164 $this->data[$block_name] = json_decode($data[$block_name], true);
165 }
166 }
167 }
168
169 $this->id = $data["id"];
170
171 // Because PHP 5.3
172 $class = maxUtils::namespaceit('maxButtons');
173 $this->document_id = $class::getDocumentID(array("button_id" => $this->id));
174 $this->cache = isset($data["cache"]) ? trim($data["cache"]) : ''; // not set at button packs / non-dbase buttons!
175 $this->data["id"] = $this->id; // needed for certain blocks, to be button aware.
176 $this->data["document_id"] = $this->document_id; // bound to JS and others.
177 $this->name = $data["name"];
178 $this->status = $data["status"];
179 // strval because this field does a lot of strtotime conversions
180 $this->updated = isset($data['updated']) ? strval($data['updated']) : '0';
181 $this->description = isset($this->data["basic"]["description"]) ? $this->data["basic"]["description"] : '';
182
183 foreach($this->blocks as $block)
184 {
185 $block->set($this->data);
186 }
187
188
189 Screen::setupScreens($this->data);
190 return true;
191 }
192
193 /* Used by collections and import. Use sparingly. Button data is reput to blocks on display */
194 public function setData($blockname, $data )
195 {
196 foreach($data as $key => $value)
197 {
198 $this->data[$blockname][$key] = $value;
199
200 }
201 }
202
203 public function get( )
204 {
205 return $this->data;
206 }
207
208 public function getID()
209 {
210 return $this->id;
211 }
212
213 public function getDocumentID()
214 {
215 return $this->document_id;
216 }
217 public function getName()
218 {
219 return $this->name;
220 }
221
222 public function getDescription()
223 {
224 return $this->description;
225 }
226
227 public function getStatus()
228 {
229 return $this->status;
230 }
231
232 public function getUpdated($forDisplay = true)
233 {
234 $updated = strval($this->updated);
235
236 if ($forDisplay)
237 return date_i18n( get_option( 'date_format' ), strtotime($updated) );
238 else
239 return strtotime($updated);
240 }
241
242 public function getParsedCSS()
243 {
244 return $this->parsed_css;
245 }
246
247 public function getCSSArray()
248 {
249
250 return $this->button_css;
251 }
252
253 protected function getCSSParser()
254 {
255 if (! $this->cssParser)
256 $this->cssParser = new maxCSSParser();
257
258 return $this->cssParser;
259 }
260
261 /** Get responsive declarations via screens
262 * Migration of old formats should be via installation class
263 */
264 public function getResponsiveScreens()
265 {
266 // Doesn't return setup screen, since that already happens on button load
267 return Screen::getScreens(); //Screen::setupScreens($this->data);
268 }
269
270 // get the cache
271 public function getCache()
272 {
273 return $this->cache;
274 }
275
276 // modify the cache at own risk
277 public function setCache($cache)
278 {
279 $this->cache = $cache;
280 }
281
282 /* Parse CSS from the elements
283
284 @param string $mode [normal,preview,editor] - The view needed.
285 @param string $forceCompile Recompile the CSS in any case
286 */
287 public function parse_css(string $mode = "normal", bool $forceCompile = false )
288 {
289 $css = array(); //$this->button_css;
290
291 if (isset($this->cache) && $this->cache != '' && ! $forceCompile)
292 {
293
294 $css = $this->cache;
295 // kill media queries from cache
296 if ($mode != 'normal')
297 {
298 $pattern = "/@media.*}/is";
299 preg_match($pattern, $css, $matches);
300 $css = preg_replace($pattern, '', $css);
301 }
302
303 maxUtils::addTime("Button: Cache loaded");
304 }
305 else
306 {
307
308 // Load responsive screens to pass. Only for normal mode. Withold in preview / editor.
309 $screens = array();
310 $screens = $this->getResponsiveScreens();
311
312 foreach($screens as $screen_name => $screenObj)
313 {
314 if ($mode !== 'normal' && $screenObj->is_responsive()) // skip when not normal, but responisve screen.
315 unset($screens[$screen_name]);
316 elseif ($screenObj->is_new() ) // don't parse the new screen.
317 unset($screens[$screen_name]);
318 }
319
320 /* Internal filter, please don't use */
321 foreach($this->blocks as $block)
322 {
323 $css = $block->parse_css($css, $screens, $mode);
324 }
325
326
327
328 // Nasty fix for mixins needed in responsive screens
329 foreach($this->blocks as $block)
330 {
331 $css = $block->parsefix_mixins($css, $screens);
332 }
333
334 /* Filter the raw CSS array before compile
335
336 This filters passes an array with all CSS elements before compile time. This should be CSS elements that can be understood by the CSS parser.
337 @since 4.20
338 @param $css CSS Array - split by element and pseudo (normal/hover)
339 */
340
341 $css = apply_filters('mb/button/rawcss', $css, $mode);
342
343 // Get Screens again from Class. Blocks parse might override this ( i.e. auto-responsive)
344 $screens = Screen::getScreens();
345
346 $this->button_css = $css;
347 $css = $this->getCSSParser()->setScreens($screens);
348 $css = $this->getCSSParser()->parse($this->button_css);
349
350 $css = apply_filters('mb/button/compiledcss', $css, $mode); // the final result.
351
352 if ($mode == 'normal') // only in general mode, otherwise things go amiss.
353 {
354 $this->update_cache($css);
355 }
356 }
357
358 $this->parsed_css = $css;
359
360 return $css;
361 }
362
363 /* Call blocks for javascript
364
365 Function will call for all block element to crunch the required javascript for output ( if any )
366 @param string $mode [normal, preview, editor]
367
368 */
369 protected function parse_js($mode = "normal")
370 {
371 maxUtils::addTime("Button :: parse JS");
372 $js = $this->button_js;
373 foreach($this->blocks as $block)
374 {
375 $js = $block->parse_js($js,$mode);
376
377 }
378
379 $this->button_js = $js;
380 }
381
382 /* Parse the actual button
383
384 Function adds the basic button components, creates the DOM object for the button and asks all block elements to parse their additions.
385
386 @param string $mode [normal, preview, editor]
387 @return Object DomObj presentation of the button
388 */
389 public function parse_button($mode = 'normal')
390 {
391 $name = $this->name;
392 // non-latin breaks CSS / ID's - so move to latin.
393 $name = maxUtils::translit($name);
394 $name = sanitize_title($name);
395 $name = str_replace('%', '', $name);
396
397 $classes = array("maxbutton-" . $this->id,
398 "maxbutton");
399
400
401 if ($name != '')
402 $classes[] = "maxbutton-" . $name;
403
404 $classes = implode(' ', $classes);
405
406
407
408 $domObj = new simple_html_dom();
409 $domObj->load('<a class="' . $classes . '"></a>');
410
411 foreach($this->blocks as $block)
412 {
413 $domObj = $block->parse_button($domObj, $mode);
414 }
415
416
417 $domObj->load($domObj->save());
418
419 $cssParser = $this->getCSSParser();
420 $cssParser->loadDom($domObj);
421
422 return $domObj;
423 }
424
425 protected function post_parse_button($domObj, $mode)
426 {
427 foreach($this->blocks as $block)
428 {
429 $domObj = $block->post_parse_button($domObj, $mode);
430 $domObj->load($domObj->save());
431 }
432
433 }
434
435 /* Display the button */
436 public function display($args = array() )
437 {
438 maxUtils::startTime('button-display-'. $this->id);
439 $defaults = array(
440 "mode" => 'normal',
441 "preview_part" => "full",
442 "echo" => true,
443 "load_css" => "footer", // control how css is loaded.
444 "compile" => false, // possibility to force recompile if needed.
445 );
446 $output = ''; // init output;
447
448 $args = wp_parse_args($args, $defaults);
449
450 $cssParser = $this->getCSSParser(); // init parser
451
452 $this->load_css = $args["load_css"];
453
454 if ($this->id == 0) // if button doesn't exists don't display unless in editor
455 {
456 if (! $args["mode"] == 'editor' )
457 return;
458
459 $this->clear();
460
461 $this->data["id"] = 0;
462 //do_action('mb-data-load', $data);
463 }
464
465 $mode = (isset($args["mode"])) ? $args["mode"] : "normal";
466 switch($mode)
467 {
468 case "preview":
469 $preview = true;
470 $compile = false;
471 break;
472 case "editor":
473 $preview = true;
474 $compile = true;
475 // editor is both compile and preview.
476 break;
477 break;
478 case "normal":
479 default:
480 $preview = false;
481 $compile = false;
482 break;
483 }
484
485
486 // Apply filters for general data override
487 $this->data = apply_filters('mb/button/data_before_display', $this->data, $mode, array('preview' => $preview, 'compile' => $compile) ); // hooks
488
489 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.
490 $compile = true;
491
492 }
493 else
494 $compile = false;
495
496 // reload the data into the blocks, might have been altered by shortcode, filters etc.
497
498 foreach($this->blocks as $block)
499 {
500 $block->set($this->data);
501 }
502
503 // create the button
504 $domObj = $this->parse_button($mode);
505
506 // create CSS
507 maxUtils::startTime('button-parse-css-'. $this->id);
508 $this->parse_css($mode, $compile);
509 maxUtils::endTime('button-parse-css-'. $this->id);
510
511
512 // operation after creating CSS model. Mainly adding extra classes
513 $this->post_parse_button($domObj, $mode);
514
515
516 if (! $preview) // no js on previews
517 $this->parse_js($mode);
518
519 if ($preview) // mark it preview
520 {
521
522 $domObj->find('a',0)->class .= ' maxbutton-preview';
523 }
524
525 if ($preview && $args["preview_part"] != 'full')
526 {
527
528 if ($args["preview_part"] != 'normal')
529 {
530 $domObj->find('a',0)->class .= ' hover';
531 $domObj->find('a', 0)->id = 'maxbuttons_preview_hover';
532 $domObj = $cssParser->outputInline($domObj,'hover');
533
534 }
535 else
536 {
537 $domObj->find('a',0)->class .= ' normal';
538 $domObj->find('a', 0)->id = 'maxbuttons_preview_normal';
539 $domObj = $cssParser->outputInline($domObj);
540 }
541
542 }
543 elseif ($this->load_css == 'footer')
544 {
545 $css = $this->display_css(false, false);
546 if ($preview)
547 do_action('mb-footer', 0, false, 'preview'); // code to warn no to usefile
548
549 do_action('mb-footer',$this->id, $css);
550
551 if (! $preview)
552 {
553 $js = $this->display_js(false, true);
554 do_action('mb-footer', $this->document_id, $js, 'js');
555 }
556 } elseif ($this->load_css == 'inline')
557 {
558 if ($args["echo"])
559 $this->display_css();
560 else
561 $output .= $this->display_css(false);
562 }
563 elseif ($this->load_css == 'element') // not possible to load both normal and hover to an element.
564 {
565 $domObj->find('a',0)->class .= ' normal';
566 $domObj = $this->getCSSParser()->outputInline($domObj);
567
568 $compile = $this->getCSSParser()->get_compile_errors();
569
570 }
571
572
573 $output .= $domObj->save();
574
575 $output = apply_filters('mb-before-button-output', $output);
576 maxButtons::buttonDone(array("button_id" => $this->id, "document_id" => $this->document_id) );
577
578 maxUtils::endTime('button-display-'. $this->id);
579
580 if ($args["echo"])
581 echo $output;
582 else
583 return $output;
584
585 }
586
587
588 /* Write parsed CSS to output.
589 @param echo Default true. When true, outputs directly, otherwise returns output string
590 @param style_tag Default true. When true, outputs a html <style> tags around the output.
591 */
592 public function display_css($echo = true, $style_tag = true)
593 {
594 $output = '';
595
596 if ($style_tag)
597 $output .= "<style type='text/css'>";
598
599 $output .= $this->parsed_css;
600
601 if ($style_tag)
602 $output .= "</style>";
603
604
605 if ($echo) echo $output;
606 else return $output;
607
608 }
609
610 /* Output Parsed Javascripting */
611 public function display_js($echo = true, $tag = true)
612 {
613 $output = '';
614
615 if (count($this->button_js) == 0)
616 return; // no output, holiday
617
618 if ($tag)
619 {
620 $output .= "<script type='text/javascript'> ";
621 $output .= " if (typeof maxButton" . $this->document_id . " == 'undefined') { ";
622 $output .= " function maxButton" . $this->document_id . "() { ";
623 }
624
625 foreach($this->button_js as $index => $code)
626 {
627 $output .= $code;
628
629 }
630
631 if ($tag)
632 {
633 $output .= " }
634 }
635 window.onload = maxButton" . $this->document_id . "();
636 </script> ";
637 }
638
639 if ($echo) echo $output;
640 else return $output;
641 }
642
643
644 /* Makes a copy of the current buttons.
645
646 The button to be copied -must- be loaded and set
647 */
648 public function copy()
649 {
650 $this->id = 0;
651 $data = $this->data;
652 $data["name"] = $this->name;
653
654 return $this->update($data);
655 }
656 /* Change the publication status of the button.
657
658 */
659 public function setStatus($status = "publish")
660 {
661 $data = $this->data;
662 $data["status"] = sanitize_text_field($status);
663
664 return $this->update($data);
665
666 }
667 /* Remove the button from database
668 *
669 */
670 public function delete(int $id)
671 {
672 global $wpdb;
673 $res = $wpdb->query($wpdb->prepare("DELETE FROM " . maxUtils::get_table_name() . " WHERE id = %d", $id));
674
675 return $res;
676 }
677
678 /* Save changes to the button
679
680 Updates or saves the button. Existing buttons must load their data and be set -first- or lose all not-passed data.
681
682 @param post Post data in field - value format (flat $_POST array)
683 @param Array $screens This will give the Responsive screens.
684 @param boolean savedb if false do not save to database
685 */
686 public function save($post, $screens, $savedb = true)
687 {
688 $post = stripslashes_deep($post); // don't multiply slashes please.
689 $data = $this->data;
690
691 $post_screens = isset($post['screens']) ? $post['screens'] : array();
692 // if screen is not passed in post, this means it's removed. Removed it from data ( not from post, since post should not deliver anything on that either )
693
694 foreach($screens as $screen) // screen, the object.
695 {
696 if (! in_array($screen->id, $post_screens))
697 {
698 $data = $screen->removeScreen($data);
699 }
700 }
701
702
703 foreach($this->blocks as $block)
704 {
705 $data = $block->save_fields($data, $post, $screens);
706 }
707
708 if (! $savedb ) return $data;
709 return $this->update($data); // save to db.
710
711 }
712
713 /* Updates the button data to the database. Adds a button if it doesn't exist */
714 public function update($data)
715 {
716 global $wpdb;
717 $return = false;
718
719 $fields = array();
720 foreach($this->blocks as $block)
721 {
722 $block_name = $block->get_name();
723
724 if (isset($data[$block_name]))
725 {
726 $blockData = $data[$block_name];
727
728 $fields[$block_name] = json_encode($blockData);
729 }
730 }
731 if (isset($data["name"])) { // other fields.
732 $fields["name"] = $data["name"];
733 }
734 if (isset($data["status"])) {
735 $fields["status"] = $data["status"];
736 }
737
738 $where = array('id' => $this->id );
739 if ($this->id > 0)
740 {
741 $where = array('id' => $this->id);
742 $where_format = array('%d');
743 $result = $wpdb->update(maxUtils::get_table_name(), $fields, $where, null, $where_format);
744 $return = true;
745 }
746 else
747 {
748 $fields['created'] = current_time('mysql',1);
749
750 $result = $wpdb->insert(maxUtils::get_table_name(), $fields);
751 $id = $wpdb->insert_id;
752
753 $this->id = $id;
754 $return = $id;
755
756 }
757
758 do_action('mb/button/save', $this->id);
759
760 if ($result === false)
761 {
762 $error = "Database error " . $wpdb->last_error;
763 MB()->add_notice('error', $error);
764 $install = MB()->getClass("install");
765 $install::create_database_table(); // run dbdelta to try and fix.
766
767 }
768
769 // update the cache
770 $this->cache = ''; // empty cache
771 $result = $this->set($this->id); // set the newest values
772
773 if (! $result ) return false;
774
775 $this->display(array("echo" => false, "load_css" => "element")); // do display routing to compile.
776 $css = $this->parsed_css;
777 $this->update_cache($css);
778
779 return $return;
780 }
781
782 /* Updates the CSS cache. */
783 public function update_cache($css)
784 {
785 $return = false;
786 global $wpdb;
787
788 if ($this->id > 0)
789 {
790 $fields = array("cache" => $css, 'updated' => $this->updated); // try not to update timestamp on recache.
791 $where = array('id' => $this->id);
792 $where_format = array('%d');
793 $wpdb->update(maxUtils::get_table_name(), $fields, $where, null, $where_format);
794 $return = true;
795
796 }
797 $this->cache = $css;
798 return $return;
799 }
800
801 // Resets all of the button caches.
802 public function reset_cache()
803 {
804 global $wpdb;
805 $fields = array("cache" => null, 'updated' => 'updated');
806 $where = array(1 => 1);
807 //$where_format = array('%d');
808 $sql = "UPDATE " . maxUtils::get_table_name() . " SET cache = NULL ";
809 $wpdb->query($sql);
810
811 }
812
813
814 /* Display button via shortcode
815
816 Function that accepts WP shortcode arguments and displays or returns a button
817
818 @param $atts array Shortcode Atts
819 @return string HTML presentation of button
820
821 */
822 public function shortcode($button_atts)
823 {
824
825 $atts = shortcode_atts(array(
826 'id' => null,
827 'name' => null,
828 'text' => null,
829 'url' => null,
830 'linktitle' => null,
831 'window' => null,
832 'nofollow' => null,
833 'nocache' => null,
834 'extraclass' => null,
835 'style' => 'footer',
836 'is_download' => null,
837
838 ), $button_atts, 'maxbutton');
839 $button_id = $atts['id'];
840 $button_name = $atts['name'];
841
842 if (! is_null($button_id) && $button_id > 0)
843 $result = $this->set($button_id);
844 elseif (! is_null($button_name))
845 $result = $this->set(0, $button_name);
846 else return; // no button id or name given
847
848 /* Shortcode cache control
849
850 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!
851
852 @param boolean $nocache True / False
853 */
854 $compile = apply_filters("mb/shortcode/nocache", $atts['nocache'] );
855
856 if (! $result)
857 return; // button doesn't exist
858
859 // If we're not in the admin and the button is in the trash, just return nothing
860 if (!is_admin() && $this->status == 'trash') {
861 return;
862 }
863
864 // Override shortcode options comparing to default button data.
865 if (! is_null($atts['text']) && $atts['text'] !== '')
866 {
867 $this->data["text"]["text"] = $atts['text'];
868 }
869
870 if (! is_null($atts['url']) && $atts['url'] !== '')
871 {
872 //
873 $protocols = maxUtils::getAllowedProcotols(['is_shortcode' => true]);
874
875 // Test the esc_url, only replace if it's longer than nothing. Otherwise use the main button one.
876 $url = esc_url($atts['url'], $protocols);
877 if (strlen($url) > 0)
878 {
879 $this->data["basic"]["url"] = $url ;
880 }
881 }
882
883 if (! is_null($atts['window']) )
884 {
885 if ($atts['window'] == 'new' )
886 $this->data["basic"]["new_window"] = 1;
887 elseif ($atts['window'] == 'same')
888 $this->data["basic"]["new_window"] = 0;
889 }
890
891 if (! is_null($atts['nofollow']) )
892 {
893 if ($atts['nofollow'] == 'true')
894 $this->data["basic"]["nofollow"] = 1;
895 elseif ($atts['nofollow'] == 'false')
896 $this->data["basic"]["nofollow"] = 0;
897 }
898
899 if (! is_null($atts['linktitle']) )
900 {
901 $this->data['basic']['link_title'] = esc_attr($atts['linktitle']);
902 }
903
904 if (! is_null($atts['extraclass']))
905 {
906
907 $this->data['advanced']['extra_classes'] .= ' ' . esc_attr($atts['extraclass']);
908 }
909
910 if (! is_null($atts['is_download']))
911 {
912 $this->data['basic']['is_download'] = ($atts['is_download'] == 'true') ? 1 : 0;
913 }
914
915 switch($atts['style'])
916 {
917 case "inline":
918 $load_css = 'inline';
919 break;
920 default:
921 $load_css = 'footer';
922 break;
923 }
924
925 // Button Atts ( unfiltered ) can be mistyped in a way that the key becomes an integer index and the whole value plus key moves to value ( like having in the shortcode "window"=new with wrong ""). This then causes issues when string comparing in strict.
926 $button_atts = array_filter($button_atts, 'is_string', ARRAY_FILTER_USE_KEY);
927
928 // allow for more flexible changes and data manipulation.
929 $this->data = $this->shortcode_overrides($this->data, $button_atts);
930 $this->data = $this->checkDataTags($this->data, $button_atts);
931 $this->data = apply_filters('mb/shortcode/data', $this->data, $atts);
932
933 // if there are no reasons not to display; display
934 $args = array("echo" => false,
935 "load_css" => $load_css,
936 "compile" => $compile,
937 );
938 $args = apply_filters('mb_shortcode_display_args', $args, $button_id, $this->data);
939
940 $output = $this->display($args);
941
942 return $output;
943 }
944
945
946 protected function shortcode_overrides($data, $atts)
947 {
948 return $data;
949 }
950
951 /** Check if HTML5 data-tags passed by shortcode to allow dynamic information being added to the button
952 * @param $data Array Maxbutton data
953 * @param $atts Array Shortcode atts
954 * @return Array Amended Maxbutton Data
955 */
956 protected function checkDataTags($data, $atts)
957 {
958
959 foreach($atts as $key => $value)
960 {
961 // Search for data-tags
962
963 if (strpos(strval($key),'data-') !== false)
964 {
965 if (! isset($data['advanced']['dataTags']))
966 {
967 $data['advanced']['dataTags'] = array();
968 }
969 $data['advanced']['dataTags'][sanitize_text_field($key)] = $value;
970 }
971 }
972 return $data;
973
974 }
975
976 } // class
977