PluginProbe
MaxButtons – Create buttons / 9.7.7
MaxButtons – Create buttons v9.7.7
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.7.7, 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
75 $this->clear(); // init
76 }
77
78 /** Simple function to retrieve loaded blocks - * Used by install class and controllers */
79 public function getBlocks()
80 {
81 return $this->blocks;
82 }
83
84 /** Get Data from Database and set variables
85 *
86 * You can pass either id or name to this function
87 *
88 * @return Boolean Returns false when no data was found using either ID or name
89 */
90 public function set($id = 0, $name = '', $status = 'publish')
91 {
92 maxUtils::addTime("Button set $id");
93
94 $id = intval($id);
95 $name = sanitize_text_field($name);
96 $status = sanitize_text_field($status);
97
98 global $wpdb;
99 $this->clear(); // clear the internals of any previous work
100
101 // check to see if the value passed is NOT numeric. If it is, use title, else assume numeric
102 if($id == 0 && $name != '') {
103 $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE name = '%s' and status ='%s'", trim($name), $status ), ARRAY_A);
104
105 } else {
106 $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . maxUtils::get_table_name() . " WHERE id = %d and status ='%s'", $id, $status), ARRAY_A);
107 }
108
109 if (! is_array($row)) // no db row results in null / false
110 {
111 return false;
112 }
113 elseif (count($row) == 0)
114 {
115 return false;
116 }
117
118 /* Take the id from the query, otherwise ( when button shortcode called by name ) id might not be present properly' */
119 $button_id = $row["id"];
120 maxButtons::buttonLoad(array("button_id" => $button_id)); // central registration
121
122 return $this->setupData($row);
123
124 }
125 /** Clear button settings
126 *
127 * This function prevent that generated values from previous set actions will still be present.
128 */
129 public function clear()
130 {
131 unset($this->data);
132 unset($this->button_css);
133 $this->id = 0; // clear id
134 $this->button_css = array();
135 $this->button_js = array();
136 // reset data to defaults.
137 $this->data = array('id' => 0);
138 $this->data = $this->save(array(),array(), false);
139 $this->updated = '0';
140
141 $this->cache = '';
142 $this->button_loaded = false;
143
144 maxBlocks::clearFoundMixins();
145 Screen::setupScreens($this->data);
146
147 foreach($this->blocks as $block)
148 {
149 $block->set(array()); // reset blocks
150 }
151 }
152
153 public function setupData($data)
154 {
155 maxUtils::addTime("Button: Setup data");
156 foreach($this->blocks as $block)
157 {
158 $block_name = $block->get_name();
159
160 if (array_key_exists($block_name, $data)) // strangely isset doesn't work
161 {
162 $this->data[$block_name] = maybe_unserialize($data[$block_name]); // allow to feed unserialized stuff not from dbase
163 if (! is_array($this->data[$block_name]) && ! is_null($this->data[$block_name]))
164 {
165 $this->data[$block_name] = json_decode($data[$block_name], true);
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 // strval because this field does a lot of strtotime conversions
181 $this->updated = isset($data['updated']) ? strval($data['updated']) : '0';
182 $this->description = isset($this->data["basic"]["description"]) ? $this->data["basic"]["description"] : '';
183
184 foreach($this->blocks as $block)
185 {
186 $block->set($this->data);
187 }
188
189
190 Screen::setupScreens($this->data);
191 return true;
192 }
193
194 /* Used by collections and import. Use sparingly. Button data is reput to blocks on display */
195 public function setData($blockname, $data )
196 {
197 foreach($data as $key => $value)
198 {
199 $this->data[$blockname][$key] = $value;
200
201 }
202 }
203
204 public function get( )
205 {
206 return $this->data;
207 }
208
209 public function getID()
210 {
211 return $this->id;
212 }
213
214 public function getDocumentID()
215 {
216 return $this->document_id;
217 }
218 public function getName()
219 {
220 return $this->name;
221 }
222
223 public function getDescription()
224 {
225 return $this->description;
226 }
227
228 public function getStatus()
229 {
230 return $this->status;
231 }
232
233 public function getUpdated($forDisplay = true)
234 {
235 $updated = strval($this->updated);
236
237 if ($forDisplay)
238 return date_i18n( get_option( 'date_format' ), strtotime($updated) );
239 else
240 return strtotime($updated);
241 }
242
243 public function getParsedCSS()
244 {
245 return $this->parsed_css;
246 }
247
248 public function getCSSArray()
249 {
250
251 return $this->button_css;
252 }
253
254 protected function getCSSParser()
255 {
256 if (! $this->cssParser)
257 $this->cssParser = new maxCSSParser();
258
259 return $this->cssParser;
260 }
261
262 /** Get responsive declarations via screens
263 * Migration of old formats should be via installation class
264 */
265 public function getResponsiveScreens()
266 {
267 // Doesn't return setup screen, since that already happens on button load
268 return Screen::getScreens(); //Screen::setupScreens($this->data);
269 }
270
271 // get the cache
272 public function getCache()
273 {
274 return $this->cache;
275 }
276
277 // modify the cache at own risk
278 public function setCache($cache)
279 {
280 $this->cache = $cache;
281 }
282
283 /* Parse CSS from the elements
284
285 @param string $mode [normal,preview,editor] - The view needed.
286 @param string $forceCompile Recompile the CSS in any case
287 */
288 public function parse_css(string $mode = "normal", bool $forceCompile = false )
289 {
290 $css = array(); //$this->button_css;
291
292 if (isset($this->cache) && $this->cache != '' && ! $forceCompile)
293 {
294
295 $css = $this->cache;
296 // kill media queries from cache
297 if ($mode != 'normal')
298 {
299 $pattern = "/@media.*}/is";
300 preg_match($pattern, $css, $matches);
301 $css = preg_replace($pattern, '', $css);
302 }
303
304 maxUtils::addTime("Button: Cache loaded");
305 }
306 else
307 {
308
309 // Load responsive screens to pass. Only for normal mode. Withold in preview / editor.
310 $screens = array();
311 $screens = $this->getResponsiveScreens();
312
313 foreach($screens as $screen_name => $screenObj)
314 {
315 if ($mode !== 'normal' && $screenObj->is_responsive()) // skip when not normal, but responisve screen.
316 unset($screens[$screen_name]);
317 elseif ($screenObj->is_new() ) // don't parse the new screen.
318 unset($screens[$screen_name]);
319 }
320
321 /* Internal filter, please don't use */
322 foreach($this->blocks as $block)
323 {
324 $css = $block->parse_css($css, $screens, $mode);
325 }
326
327
328
329 // Nasty fix for mixins needed in responsive screens
330 foreach($this->blocks as $block)
331 {
332 $css = $block->parsefix_mixins($css, $screens);
333 }
334
335 /* Filter the raw CSS array before compile
336
337 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.
338 @since 4.20
339 @param $css CSS Array - split by element and pseudo (normal/hover)
340 */
341
342 $css = apply_filters('mb/button/rawcss', $css, $mode);
343
344 // Get Screens again from Class. Blocks parse might override this ( i.e. auto-responsive)
345 $screens = Screen::getScreens();
346
347 $this->button_css = $css;
348 $css = $this->getCSSParser()->setScreens($screens);
349 $css = $this->getCSSParser()->parse($this->button_css);
350
351 $css = apply_filters('mb/button/compiledcss', $css, $mode); // the final result.
352
353 if ($mode == 'normal') // only in general mode, otherwise things go amiss.
354 {
355 $this->update_cache($css);
356 }
357 }
358
359 $this->parsed_css = $css;
360
361 return $css;
362 }
363
364 /* Call blocks for javascript
365
366 Function will call for all block element to crunch the required javascript for output ( if any )
367 @param string $mode [normal, preview, editor]
368
369 */
370 protected function parse_js($mode = "normal")
371 {
372 maxUtils::addTime("Button :: parse JS");
373 $js = $this->button_js;
374 foreach($this->blocks as $block)
375 {
376 $js = $block->parse_js($js,$mode);
377
378 }
379
380 $this->button_js = $js;
381 }
382
383 /* Parse the actual button
384
385 Function adds the basic button components, creates the DOM object for the button and asks all block elements to parse their additions.
386
387 @param string $mode [normal, preview, editor]
388 @return Object DomObj presentation of the button
389 */
390 public function parse_button($mode = 'normal')
391 {
392 $name = $this->name;
393 // non-latin breaks CSS / ID's - so move to latin.
394 $name = maxUtils::translit($name);
395 $name = sanitize_title($name);
396 $name = str_replace('%', '', $name);
397
398 $classes = array("maxbutton-" . $this->id,
399 "maxbutton");
400
401
402 if ($name != '')
403 $classes[] = "maxbutton-" . $name;
404
405 $classes = implode(' ', $classes);
406
407
408
409 $domObj = new simple_html_dom();
410 $domObj->load('<a class="' . $classes . '"></a>');
411
412 foreach($this->blocks as $block)
413 {
414 $domObj = $block->parse_button($domObj, $mode);
415 }
416
417
418 $domObj->load($domObj->save());
419
420 $cssParser = $this->getCSSParser();
421 $cssParser->loadDom($domObj);
422
423 return $domObj;
424 }
425
426 protected function post_parse_button($domObj, $mode)
427 {
428 foreach($this->blocks as $block)
429 {
430 $domObj = $block->post_parse_button($domObj, $mode);
431 $domObj->load($domObj->save());
432 }
433
434 }
435
436 /* Display the button */
437 public function display($args = array() )
438 {
439 maxUtils::startTime('button-display-'. $this->id);
440 $defaults = array(
441 "mode" => 'normal',
442 "preview_part" => "full",
443 "echo" => true,
444 "load_css" => "footer", // control how css is loaded.
445 "compile" => false, // possibility to force recompile if needed.
446 );
447 $output = ''; // init output;
448
449 $args = wp_parse_args($args, $defaults);
450
451 $cssParser = $this->getCSSParser(); // init parser
452
453 $this->load_css = $args["load_css"];
454
455 if ($this->id == 0) // if button doesn't exists don't display unless in editor
456 {
457 if (! $args["mode"] == 'editor' )
458 return;
459
460 $this->clear();
461
462 $this->data["id"] = 0;
463 //do_action('mb-data-load', $data);
464 }
465
466 $mode = (isset($args["mode"])) ? $args["mode"] : "normal";
467 switch($mode)
468 {
469 case "preview":
470 $preview = true;
471 $compile = false;
472 break;
473 case "editor":
474 $preview = true;
475 $compile = true;
476 // editor is both compile and preview.
477 break;
478 break;
479 case "normal":
480 default:
481 $preview = false;
482 $compile = false;
483 break;
484 }
485
486
487 // Apply filters for general data override
488 $this->data = apply_filters('mb/button/data_before_display', $this->data, $mode, array('preview' => $preview, 'compile' => $compile) ); // hooks
489
490 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.
491 $compile = true;
492
493 }
494 else
495 $compile = false;
496
497 // reload the data into the blocks, might have been altered by shortcode, filters etc.
498
499 foreach($this->blocks as $block)
500 {
501 $block->set($this->data);
502 }
503
504 // create the button
505 $domObj = $this->parse_button($mode);
506
507 // create CSS
508 maxUtils::startTime('button-parse-css-'. $this->id);
509 $this->parse_css($mode, $compile);
510 maxUtils::endTime('button-parse-css-'. $this->id);
511
512
513 // operation after creating CSS model. Mainly adding extra classes
514 $this->post_parse_button($domObj, $mode);
515
516
517 if (! $preview) // no js on previews
518 $this->parse_js($mode);
519
520 if ($preview) // mark it preview
521 {
522
523 $domObj->find('a',0)->class .= ' maxbutton-preview';
524 }
525
526 if ($preview && $args["preview_part"] != 'full')
527 {
528
529 if ($args["preview_part"] != 'normal')
530 {
531 $domObj->find('a',0)->class .= ' hover';
532 $domObj->find('a', 0)->id = 'maxbuttons_preview_hover';
533 $domObj = $cssParser->outputInline($domObj,'hover');
534
535 }
536 else
537 {
538 $domObj->find('a',0)->class .= ' normal';
539 $domObj->find('a', 0)->id = 'maxbuttons_preview_normal';
540 $domObj = $cssParser->outputInline($domObj);
541 }
542
543 }
544 elseif ($this->load_css == 'footer')
545 {
546 $css = $this->display_css(false, false);
547 if ($preview)
548 do_action('mb-footer', 0, false, 'preview'); // code to warn no to usefile
549
550 do_action('mb-footer',$this->id, $css);
551
552 if (! $preview)
553 {
554 $js = $this->display_js(false, true);
555 do_action('mb-footer', $this->document_id, $js, 'js');
556 }
557 } elseif ($this->load_css == 'inline')
558 {
559 if ($args["echo"])
560 $this->display_css();
561 else
562 $output .= $this->display_css(false);
563 }
564 elseif ($this->load_css == 'element') // not possible to load both normal and hover to an element.
565 {
566 $domObj->find('a',0)->class .= ' normal';
567 $domObj = $this->getCSSParser()->outputInline($domObj);
568
569 $compile = $this->getCSSParser()->get_compile_errors();
570
571 }
572
573
574 $output .= $domObj->save();
575
576 $output = apply_filters('mb-before-button-output', $output);
577 maxButtons::buttonDone(array("button_id" => $this->id, "document_id" => $this->document_id) );
578
579 maxUtils::endTime('button-display-'. $this->id);
580
581 if ($args["echo"])
582 echo $output;
583 else
584 return $output;
585
586 }
587
588
589 /* Write parsed CSS to output.
590 @param echo Default true. When true, outputs directly, otherwise returns output string
591 @param style_tag Default true. When true, outputs a html <style> tags around the output.
592 */
593 public function display_css($echo = true, $style_tag = true)
594 {
595 $output = '';
596
597 if ($style_tag)
598 $output .= "<style type='text/css'>";
599
600 $output .= $this->parsed_css;
601
602 if ($style_tag)
603 $output .= "</style>";
604
605
606 if ($echo) echo $output;
607 else return $output;
608
609 }
610
611 /* Output Parsed Javascripting */
612 public function display_js($echo = true, $tag = true)
613 {
614 $output = '';
615
616 if (count($this->button_js) == 0)
617 return; // no output, holiday
618
619 if ($tag)
620 {
621 $output .= "<script type='text/javascript'> ";
622 $output .= " if (typeof maxButton" . $this->document_id . " == 'undefined') { ";
623 $output .= " function maxButton" . $this->document_id . "() { ";
624 }
625
626 foreach($this->button_js as $index => $code)
627 {
628 $output .= $code;
629
630 }
631
632 if ($tag)
633 {
634 $output .= " }
635 }
636 window.onload = maxButton" . $this->document_id . "();
637 </script> ";
638 }
639
640 if ($echo) echo $output;
641 else return $output;
642 }
643
644
645 /* Makes a copy of the current buttons.
646
647 The button to be copied -must- be loaded and set
648 */
649 public function copy()
650 {
651 $this->id = 0;
652 $data = $this->data;
653 $data["name"] = $this->name;
654
655 return $this->update($data);
656 }
657 /* Change the publication status of the button.
658
659 */
660 public function setStatus($status = "publish")
661 {
662 $data = $this->data;
663 $data["status"] = sanitize_text_field($status);
664
665 return $this->update($data);
666
667 }
668 /* Remove the button from database
669 *
670 */
671 public function delete(int $id)
672 {
673 global $wpdb;
674 $res = $wpdb->query($wpdb->prepare("DELETE FROM " . maxUtils::get_table_name() . " WHERE id = %d", $id));
675
676 return $res;
677 }
678
679 /* Save changes to the button
680
681 Updates or saves the button. Existing buttons must load their data and be set -first- or lose all not-passed data.
682
683 @param post Post data in field - value format (flat $_POST array)
684 @param Array $screens This will give the Responsive screens.
685 @param boolean savedb if false do not save to database
686 */
687 public function save($post, $screens, $savedb = true)
688 {
689 $post = stripslashes_deep($post); // don't multiply slashes please.
690 $data = $this->data;
691
692 $post_screens = isset($post['screens']) ? $post['screens'] : array();
693 // 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 )
694
695 foreach($screens as $screen) // screen, the object.
696 {
697 if (! in_array($screen->id, $post_screens))
698 {
699 $data = $screen->removeScreen($data);
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 $atts = shortcode_atts(array(
825 'id' => null,
826 'name' => null,
827 'text' => null,
828 'url' => null,
829 'linktitle' => null,
830 'window' => null,
831 'nofollow' => null,
832 'nocache' => null,
833 'extraclass' => null,
834 'style' => 'footer',
835 'is_download' => null,
836
837 ), $button_atts, 'maxbutton');
838
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