PluginProbe
MaxButtons – Create buttons / 6.5
MaxButtons – Create buttons v6.5
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 / collection.php

collection.php in MaxButtons – Create buttons 6.5, at classes/collection.php

769 lines 18.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined('ABSPATH') or die('No direct access permitted');
3
4 class maxCollection
5 {
6 protected $collection_type = 'none';
7 protected $uses_blocks = array();
8 protected $blocks = array(); // array of objects
9
10 protected $collection_id = 0;
11
12 // layout functions
13 protected $cssParser;
14 protected $collection_js;
15
16 // derived from button class, prepare for maxcss parser
17 //protected $collection_css = array('normal' => array() ,':hover' => array() ,':visited' => array(), "responsive" => array());
18 protected $buttons = array(); // array of buttons, ready for display - pre parse
19
20
21 /* Constructor
22 Sets the blocks used in this collection. These are mostly derived from subclasses of the specific collection types.
23 */
24 public function __construct()
25 {
26 maxCollections::checkExpireTrans();
27
28 foreach($this->uses_blocks as $block_name )
29 {
30 $block = maxCollections::getBlock($block_name);
31 if ($block)
32 {
33 $block->setCollection($this);
34 $block->set(array()); // defaults
35 $this->blocks[$block_name] = $block;
36 }
37 }
38
39
40 }
41 /* Get all buttons that are currently loaded */
42 public function getLoadedButtons()
43 {
44 return $this->buttons;
45 }
46
47
48
49 /* Get a certain block class by name */
50 public function getBlock($blockname)
51 {
52
53 if (isset($this->blocks[$blockname]))
54 return $this->blocks[$blockname];
55 else
56 return false;
57 }
58
59 /* Get the type of the collection */
60 public function getType()
61 {
62 return $this->collection_type;
63 }
64
65 /* Get the ID of the collection */
66 public function getID()
67 {
68 return $this->collection_id;
69 }
70
71 /** Get the MaxCSSParser classes which handles SCSS. This function is derived from the one in Button class */
72 public function getCSSParser()
73 {
74 if (! $this->cssParser)
75 $this->cssParser = new maxCSSParser();
76
77 return $this->cssParser;
78 }
79
80 /** Set the collection by ID
81 @param $collection_id ID of the collection stored in database
82 */
83 public function set($collection_id)
84 {
85 $this->collection_id = $collection_id;
86
87 // make every block set it's stuff.
88 $values = $this->get_meta($collection_id);
89
90 foreach($this->blocks as $block)
91 {
92
93 $block->set($values);
94 // run every blocks setter
95
96 }
97 }
98
99
100 /** Interface for handling AJAX requests to communicate with the seperate blocks.
101 @param $result The initial (default) result to JSON back
102 @param $block_name The name of the block in question
103 @param $action The name of the block function to call
104 @param $data Data specified by JS to use for this function
105 @return $result - Standardized result block including error, body
106 */
107 public function doBlockAJAX($result, $block_name, $action, $data)
108 {
109 // core class is being called.
110 if ($block_name == 'collection')
111 {
112 $result = $this->$action($result, $data);
113 return $result;
114 }
115
116 if (isset($this->blocks[$block_name]))
117 {
118 $block= $this->blocks[$block_name];
119 $result = $block->$action($result, $data);
120 return $result;
121
122 }
123
124 $result["error"] = true;
125 $result["title"] = __("Error : Block was not there","maxbuttons");
126 return $result;
127 }
128
129 /** Save the collection data to the database. This will invoke the save functions of the blocks itself to gather, verify and manipulate data */
130 public function save($post)
131 {
132 $data = array();
133
134 // Collection id needed to save meta data and others.
135 if ($this->collection_id == 0) // assume new
136 {
137 $collection_id = $this->getNewCollectionID();
138
139 $this->collection_id = $collection_id;
140 }
141
142 // run this by each block and collect data
143 foreach($this->blocks as $block)
144 {
145 $data = $block->save_fields($data, $post);
146 }
147
148 $data = apply_filters("mb_col_save_collection_data", $data, $post);
149
150 // clean what was not set
151 $this->clean_meta($data);
152
153 // write data as a per block per key value into the database
154 foreach($data as $blockname => $blockdata)
155 {
156 // seems dangerous
157 $meta_id = $this->update_meta($this->collection_id, $blockname, $blockdata);
158
159 }
160
161 return $this->collection_id;
162
163 }
164
165 // remove post meta not in data post.
166 public function clean_meta($data)
167 {
168 $data_blocks = array_keys($data);
169
170
171 $meta = $this->get_meta($this->collection_id);
172
173
174 foreach($meta as $meta_key => $values)
175 {
176 if (! in_array($meta_key, $data_blocks))
177 {
178 $this->delete_meta($this->collection_id, $meta_key);
179 }
180
181 }
182
183 }
184
185 protected function update_meta($collection_id, $collection_key, $collection_value)
186 {
187 global $wpdb;
188 $table = maxUtils::get_collection_table_name();
189
190 if ($collection_value == '') return; // no data no database entry
191 if (is_array($collection_value) && count($collection_value) == 0) return; // same for empty arrays
192
193 if (is_array($collection_value))
194 $collection_value = json_encode($collection_value);
195
196 if ($collection_id == 0) // assume new
197 {
198 $collection_id = $this->getNewCollectionID();
199
200 $this->collection_id = $collection_id;
201 }
202
203 $sql = "SELECT meta_id from $table where collection_id = %d and collection_key = %s ";
204 $sql = $wpdb->prepare($sql, $collection_id, $collection_key);
205
206 $results = $wpdb->get_results($sql, ARRAY_A);
207
208 if (count($results) == 1)
209 {
210 $meta_id = $results[0]["meta_id"];
211 $data = array("collection_value" => $collection_value); // what's being updated
212 $where = array("meta_id" => $meta_id);
213
214 $wpdb->update($table, $data, $where);
215 return $meta_id;
216 }
217 if (count($results) == 0)
218 {
219 $data = array("collection_value" => $collection_value,
220 "collection_key" => $collection_key,
221 "collection_id" => $collection_id,
222 );
223
224 $meta_id = $wpdb->insert($table, $data);
225
226 return $meta_id;
227 }
228 else
229 {
230 MB()->add_notice("error", __("Update Collection meta has multiple rows, this should not be possible.","maxbuttons"));
231
232 }
233 }
234
235
236 /** Determine the next ID for collection */
237 protected function getNewCollectionID()
238 {
239 global $wpdb;
240 $table = maxUtils::get_collection_table_name();
241
242 $sql = "SELECT max(collection_id) as max from $table";
243
244 $max = intval($wpdb->get_var($sql));
245
246 $max = $max + 1;
247 return $max;
248 }
249
250 protected function delete_meta($collection_id, $collection_key)
251 {
252 if (intval($collection_id) > 0 && $collection_key != "")
253 {
254 global $wpdb;
255 // delete_post_meta($collection_id, $collection_key);
256 $table = maxUtils::get_collection_table_name();
257 $where = array("collection_id" => $collection_id,
258 "collection_key" => $collection_key
259 );
260 $where_format = array("%d", "%s");
261 $wpdb->delete($table, $where, $format);
262
263 }
264 }
265
266
267 /** Delete the collection. This is done via AJAX request */
268 public function delete($result, $data)
269 {
270 global $wpdb;
271 if(! $this->collection_id > 0)
272 return false;
273
274 $picker = $this->getBlock("picker");
275 $picker_data = $picker->get();
276 $buttons = $picker_data["selection"];
277 $button = MB()->getClass("button");
278
279 $buttons_removed = 0;
280
281 foreach($buttons as $button_id)
282 {
283 $deleted = $this->maybe_delete_button($button_id);
284 if ($deleted)
285 $buttons_removed++;
286
287 }
288
289 $table = maxUtils::get_collection_table_name();
290 $where = array("collection_id" => $this->collection_id);
291 $where_format = array("%d");
292 $wpdb->delete($table, $where, $where_format);
293
294 $result["data"]["body"] = __("The collection is removed","maxbuttons");
295 $result["data"]["title"] = __("Removed","maxbuttons");
296 $result["data"]["buttons_removed"] = $buttons_removed;
297 $result["data"]["collection_id"] = $this->collection_id;
298 return $result;
299
300
301 }
302
303 /** On deletion of a collection check for each button if this is an auto-generated button just made for this collection and if
304 no changes where made to this button. If both conditions are true, remove the button */
305 function maybe_delete_button($button_id)
306 {
307 $button = MB()->getClass("button");
308
309 $button->set($button_id);
310 $button_data = $button->get();
311
312 $collection_id= $this->collection_id;
313
314 // remove unedited buttons created for this collection - use with care.
315 if (isset($button_data["meta"]["user_edited"]))
316 {
317 $created_source = (isset($button_data["meta"]["created_source"])) ? $button_data["meta"]["created_source"] : '';
318 if ($button_data["meta"]["user_edited"] === false && $created_source == 'collection')
319 {
320 $in_collections = $button_data["meta"]["in_collections"];
321
322 $key = array_search($collection_id, $in_collections);
323
324 if ($key !== false)
325 {
326 unset($button_data["meta"]["in_collections"][$key]);
327
328 if (count($button_data["meta"]["in_collections"]) == 0)
329 { $button->delete($button_id);
330 return true;
331 }
332 else
333 {
334 if ($button_id > 0) // safety.
335 $button->update($button_data);
336 }
337 }
338 }
339
340
341 }
342 return false;
343 }
344
345 function get_meta ($collection_id, $collection_key = '')
346 {
347 global $wpdb;
348 $table = maxUtils::get_collection_table_name();
349
350 $prepare = array($collection_id);
351
352 $sql = "SELECT * from $table where collection_id = %d ";
353 if ($collection_key != '')
354 {
355 $sql .= " and collection_key = %s ";
356 array_push($prepare, $collection_key);
357
358 }
359
360 $sql = $wpdb->prepare($sql, $prepare);
361
362 $results = $wpdb->get_results($sql, ARRAY_A);
363
364 $result_array = array(); // format array by field name = values to feed blocks and others.
365 if (! is_null($results))
366 {
367 $nr = array();
368 foreach($results as $row)
369 {
370 $key = $row["collection_key"];
371 /* A field can be either plain text or JSON */
372 if(json_decode($row["collection_value"]))
373 $value = json_decode($row["collection_value"], true);
374 else
375 $value = $row["collection_value"];
376 $result_array[$key] = $value;
377
378 //$row["collection_value"] = unserialize($row["collection_value"]);
379 }
380
381 return $result_array;
382 }
383 else
384 {
385 return false;
386 }
387 }
388
389 function display($args = array())
390 {
391 maxUtils::startTime('collection-display');
392 $defaults = array(
393 "preview" => false,
394 "echo" => true,
395 "style_tag" => false,
396 "compile" => false,
397 "js_tag" => true,
398 "load_type" => "footer",
399 );
400
401 $args = wp_parse_args($args, $defaults);
402
403 $cache = MaxCollections::checkCachedCollection($this->collection_id);
404
405 if (! $cache)
406 {
407 $cssParser = $this->getCSSParser();
408 $domObj = $this->parse($args);
409 $css = $this->parseCSS($args);
410
411 $js = $this->parseJS($args);
412
413 $output = $domObj->save();
414 unset($domObj);
415
416
417 // CSS & JS output control
418 $output .= $this->displayCSS($css, $args);
419 $output .= $this->displayJS($js, $args);
420 }
421 else
422 $output = $cache;
423
424 MaxCollections::addCachedCollection($this->collection_id, $output);
425
426 maxUtils::endTime('collection-display');
427
428 if ($args["echo"])
429 {
430 echo $output;
431 }
432 else
433 {
434 return $output;
435 }
436
437 }
438
439 public function displayCSS($css, $args = array() ) // $echo = true, $style_tag = true)
440 {
441
442 $default = array(
443 "echo" => true,
444 "style_tag" => true,
445 "load_type" => "footer",
446 );
447 $args = wp_parse_args($args, $default);
448 if ($args['load_type'] == 'inline')
449 $args['style_tag'] =true;
450
451 $output = '';
452
453 if ($args["style_tag"])
454 $output .= "<style type='text/css'>";
455
456 $output .= $css;
457
458 if ($args["style_tag"])
459 $output .= "</style>";
460
461
462 if ($args["load_type"] == 'footer')
463 {
464
465 do_action('mb-footer','collection-' . $this->collection_id, $output);
466 }
467 elseif ($args["load_type"] == 'inline')
468 {
469 if ($args["echo"]) echo $output;
470 else return $output;
471
472 }
473
474 }
475
476 public function displayJS($js, $args = array() ) // $echo = true, $style_tag = true)
477 {
478 $default = array(
479 "echo" => true,
480 "js_tag" => true,
481 "load_type" => "footer",
482 "preview" => false,
483 );
484
485
486 $args = wp_parse_args($args, $default);
487
488 if ($args["preview"])
489 return; // no js on previews.
490
491 $output = '';
492
493 if (count($js) == 0)
494 return; // no output, holiday
495
496 if ($args["js_tag"])
497 {
498 $output .= "<script type='text/javascript'> ";
499 // $output .= " if (typeof MBcollection" . $this->collection_id . " == 'undefined') { ";
500 // $output .= " function MBcollection" . $this->collection_id . "() { ";
501
502
503 }
504
505 foreach($js as $index => $code)
506 {
507 $output .= $code;
508 }
509
510 if ($args["js_tag"])
511 {
512 $output .= " // }
513 // }
514 // window.onload = MBcollection" . $this->collection_id . "();
515 </script> ";
516 }
517
518
519 if ($args["load_type"] == 'footer')
520 {
521
522 do_action('mb-footer','collection-' . $this->collection_id, $output, "js");
523 }
524 elseif ($args["load_type"] == 'inline')
525 {
526 if ($args["echo"]) echo $output;
527 else return $output;
528
529 }
530 }
531
532 public function display_field_map()
533 {
534 $map = array();
535 foreach ($this->blocks as $block)
536 {
537 $map = $block->map_fields($map);
538 }
539 echo "<script language='javascript'>";
540 echo "var collectionFieldMap = '" . json_encode($map) . "';" ;
541 echo "</script>";
542 }
543
544 /* Parses the collection, via the blocks */
545 function parse($args)
546 {
547 $preview = isset($args["preview"]) ? $args["preview"] : false;
548
549 $domObj = new simple_html_dom();
550 $collection_id = $this->collection_id;
551
552 $node = "<div class='maxcollection maxcollection-" . $collection_id . "' data-collection='" . $collection_id . "'>
553 </div>";
554 $node = apply_filters("mb-col-basic-container",$node);
555 $domObj->load($node);
556
557 // use picker to get button classes in array
558 $picker = $this->getBlock("picker");
559 $this->buttons = $picker->getButtons();
560
561 // changes to buttons in this function
562 maxUtils::startTime('collection-parse-parsebuttons');
563 foreach($this->blocks as $block)
564 {
565 $block->setPreview($preview);
566 $this->buttons = $block->parseButtons($this->buttons);
567
568
569 }
570 maxUtils::endTime('collection-parse-parsebuttons');
571
572 maxUtils::startTime('collection-parse-blockparse');
573 // general parsing
574
575 foreach($this->blocks as $block)
576 {
577 $domObj = $block->parse($domObj, $args);
578 }
579 maxUtils::endTime('collection-parse-blockparse');
580
581 $this->buttons = array();
582
583 $cssParser = $this->getCSSParser();
584 $domObj->load($domObj->save() );
585 $cssParser->loadDom($domObj);
586
587 return $domObj;
588 }
589 function parseCSS($args)
590 {
591 $css = array();
592
593 foreach($this->blocks as $block)
594 {
595 $css = $block->parseCSS($css, $args);
596 }
597
598 $css = $this->getCSSParser()->parse($css);
599
600 return $css;
601 }
602
603 function parseJS($args)
604 {
605 $js = array();
606
607 $defaults = array("preview" => false,
608 );
609
610 $args = wp_parse_args($args, $defaults);
611
612 if ($args["preview"])
613 return false; // no js on previews
614
615 foreach($this->blocks as $block)
616 {
617 $js = $block->parseJS($js, $args);
618
619 }
620
621 return $js;
622 }
623
624
625 function shortcode($atts, $content = null)
626 {
627
628 // ugly -need to rework logic here.
629 //$collection = maxCollections::getCollection('social');
630 $display_args = shortcode_atts(array(
631 "echo" => false,
632 "mode" => "normal",
633 "nocache" => false,
634 "style" => 'footer',
635 ),
636
637 $atts);
638
639 $collection_id = $this->collection_id;
640
641 //$this->set($collection_id);
642 $display_args["compile"] = $display_args["nocache"];
643 $display_args['load_type'] = $display_args['style'];
644 unset($display_args['style']);
645 unset($display_args["nocache"]);
646
647 $output = $this->display($display_args);
648
649 return $output;
650 }
651
652
653 // Get the pack definition that are present in the system.
654 function editor_getPacks()
655 {
656 //$pack_paths = apply_filters('mb-col-pack-paths', array(MB()->get_plugin_path() . "/") );
657 $packs["maxbuttons"]["func"] = array($this, 'editor_getButtons');
658 $packs["maxbuttons"]["tab"] = __("Your MaxButtons","maxbuttons");
659 return $packs;
660
661 }
662
663 public function ajax_getButtons($result, $data)
664 {
665 $packs = $this->editor_getPacks();
666 $req_pack= $data["pack"];
667
668 foreach($packs as $index => $pack_data)
669 {
670 if ($req_pack == $index)
671 {
672 $buttons = call_user_func($pack_data["func"], $index, $data);
673
674 }
675 }
676 $output = '';
677
678
679 $page_args = array();
680 if (isset($data["paged"]))
681 {
682 $page_args["paged"] = $data["paged"];
683 }
684
685 if ($req_pack == 'maxbuttons')
686 {
687 $page_args["limit"] = 18;
688 ob_start();
689 do_action("mb-display-meta");
690 do_action("mb-display-pagination", $page_args);
691 $pagination = "<div class='tablenav top'>" .ob_get_contents() . "</div>";
692 ob_end_clean();
693
694 $output .= $pagination;
695 }
696
697 foreach($buttons as $button)
698 {
699 $button_data = $button->get();
700
701 $button_id = $button->getID();
702 $name = $button->getName();
703
704 $meta = isset($button_data["meta"]) ? $button_data["meta"] : array();
705 do_action('mb-data-load',$button_data); // weakness of the bubbling filter model
706
707 $output .= "<div class='item shortcode-container' data-id='$button_id'> ";
708 $output .= $button->display(array("mode" => "preview", 'echo' => false, 'load_css' => 'inline') ); //"mode" => "preview", "compile" => true,
709 $output .= "<span class='button_data'>" . base64_encode(json_encode($button_data)) . "</span>";
710 $output .= "<span class='button_name'>" . $name . "</span>";
711 $output .= "</div>";
712
713 }
714
715 if ($req_pack == 'maxbuttons')
716 {
717 $output .= $pagination;
718 }
719
720 $result["body"] = $output;
721 return $result;
722
723 }
724
725 // show the available buttons
726 function editor_getButtons($pack, $data)
727 {
728 $button_array = array();
729
730 $admin = MB()->getClass("admin");
731 $button = MB()->getClass("button");
732
733 $paged = (isset($data["paged"])) ? $data["paged"] : 1;
734
735 $buttons = $admin->getButtons(array(
736 "orderby" => "id",
737 "order" => "DESC",
738 "paged" => $paged,
739 "limit" => 18,
740 ));
741
742
743 foreach($buttons as $btn)
744 {
745 $id = $btn["id"];
746 $b = MB()->getClass('button');
747 $b->clear();
748 $b->set($id);
749 $button_data = $b->get();
750 // exclude auto-generated non-user edited buttons.
751 if ( ! isset($button_data["meta"]["user_edited"]) || ($button_data["meta"]["user_edited"] == true || $button_data["meta"]["created_source"] != "collection"))
752 $button_array[] = $b; // the object
753 }
754 return $button_array;
755 }
756
757 function showBlocks()
758 {
759
760 foreach($this->blocks as $block)
761 {
762 echo $block->admin_fields();
763
764 }
765
766 }
767 } //class
768
769