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 / block.php

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

468 lines 12.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 /** A block is a combination of related settings.
7 *
8 * Blocks are grouped and put into the same Database table row. This way related data, it's executing, display and other decision
9 * making is seperate from other blocks improving realiability and readability of the code.
10 */
11 use MaxButtons\maxBlocks as maxBlocks;
12 use MaxButtons\maxField as maxField;
13
14 abstract class maxBlock
15 {
16 protected $data = array();
17 protected $is_default = true; // exclude / include a whole block in default screen
18 protected $is_responsive = true; // exclude / include a whole block in responsive screens.
19 protected $is_new = false; // only display when adding a screen.
20
21 /** Block constructor
22 *
23 * Constructor for a button block. Hooks up all needed filters and inits data for a block.
24 *
25 */
26 public function __construct($priority = 10)
27 {
28 $this->fields = apply_filters($this->blockname. "-block-fields",$this->fields);
29 $this->data[$this->blockname] = array(); //empty init
30 }
31
32 /** Save fields runs the POST variable through all blocks
33 *
34 * Taking the post variable from the form, the function will attach the submitted data to the block - field logic and
35 * return a data object to save to the Database. If no value is submitted, the default will be loaded.
36 *
37 * @param $data Array Data in blockname - field logic format
38 * @param $post Array $_POST style data
39 *
40 * @return $data Array
41 */
42 public function save_fields($data, $post, $screens)
43 {
44 $block = isset($data[$this->blockname]) ? $data[$this->blockname] : array();
45
46 foreach($this->fields as $field => $options)
47 {
48 $block[$field]= $this->getFieldSaveValue($field, $options, $post, false);
49
50 if (is_array($screens))
51 {
52 foreach($screens as $screenObj)
53 {
54 if ($screenObj->is_responsive())
55 {
56 $r_field_id = $screenObj->getFieldID($field);
57 $r_field_val = $this->getFieldSaveValue($r_field_id, $options, $post, true);
58
59 // if responsive value is different than the main field -> changes has been made, only save changes.
60 if ($r_field_val !== false && $r_field_val != $block[$field])
61 {
62 $block[$r_field_id] = $r_field_val;
63 }
64 elseif (isset($block[$r_field_id])) // if field is same as main, but exists (changing values), remove it.
65 {
66 unset($block[$r_field_id]);
67 }
68 }
69 }
70 }
71
72 }
73 $data[$this->blockname] = $block;
74 return $data;
75 }
76
77 /**
78 * @param $field ID of the field ( with screen prefix )
79 * @param $options Options contained in the field.
80 * @param $post Array of what was in the post
81 * @param $is_responsive This field is part of a responsive screen
82 */
83 private function getFieldSaveValue($field, $options, $post, $is_responsive = false)
84 {
85
86 $default = (isset($options["default"])) ? $options["default"] : '';
87
88 if ($is_responsive)
89 $default = false; // don't write defaults for responsive screens, omit.
90
91 $value = $default;
92
93
94 if (is_string($default) && strpos($default,"px") !== false)
95 $value = (isset($post[$field]) ) ? intval($post[$field]) : $default;
96 elseif( isset($post[$field]) && is_array($post[$field]))
97 {
98 $value = $post[$field];
99 }
100 elseif (isset($post[$field]))
101 {
102 $value = sanitize_text_field($post[$field]);
103 }
104 elseif (isset($options['unset_value'])) // option when field is unset in post, give it a value still ( checkboxes etc ) . Overrides default.
105 {
106 $value = $options['unset_value'];
107 }
108
109
110
111 return $value;
112 }
113
114 /** Return fields of current block
115 *
116 * Will return fields of current block only
117 * @return Array $fields
118 */
119 public function get_fields()
120 {
121 return $this->fields;
122 }
123
124 /** Returns Blockname of current block
125 *
126 *
127 * @return $string | boolean Name of the block, if set, otherwise false
128 */
129 public function get_name()
130 {
131 if (isset($this->blockname))
132 return $this->blockname;
133
134 return false;
135 }
136
137 public function is_responsive()
138 {
139 return $this->is_responsive;
140 }
141
142 public function is_default()
143 {
144 return $this->is_default;
145 }
146
147 public function is_new()
148 {
149 return $this->is_new;
150 }
151
152 /* Build the Block admin interface
153 *
154 * Builds admin interface via Admin class ( addfield ). After building, display fields should be called.
155 * @abstract
156 */
157 abstract public function admin_fields($screen);
158
159
160 /** Adding a sidebar **
161 *
162 * This function can be used to add a sidebar to the block. The sidebar should be called before display_fields is put out but after the last field
163 *
164 * */
165 public function sidebar($screen)
166 {
167 return;
168 }
169
170 /** Parse HTML portion of button
171 *
172 * This filter is passed through to modify the HTML parts of the button.
173 *
174 * Note: When changing parts of the DomObj writing new tags / DOM to elements, it's needed to regenerate the Object.
175 *
176 * @param $button DomObj SimpleDOMObject
177 * @param $mode String[normal|preview] Flag to check if loading in preview
178 *
179 * @return DomObj
180 */
181 public function parse_button($button, $mode) { return $button; }
182 public function post_parse_button($domObj, $mode) { return $domObj; }
183
184 /* Parse CSS of the button
185 *
186 * This function will go through the blocks, matching the $css definitions of a fields and putting them in the
187 * correct tags ( partly using csspart ) .
188 *
189 * @param $css Array [normal|hover|other][cssline] = css declaration
190 * @param $mode String [normal|preview]
191 *
192 * @return $css Array
193 */
194 public function parse_css($css, $screens, string $mode = 'normal') {
195
196 $data = $this->getBlockData();
197
198 // get all fields from this block
199 foreach($screens as $screenObj) // these are our screens.
200 {
201 $mixins = array();
202
203 foreach($this->fields as $field => $field_data)
204 {
205 $field_id = $screenObj->getFieldID($field);
206 if (isset($data[$field_id]) )
207 {
208
209 $css = $this->parseField($css, $field_id, $data[$field_id], $field_data, $screenObj);
210 if (isset($field_data['mixin']) && $screenObj->is_responsive()) // garantuee the whole mixin is present.
211 {
212 $mixin = $field_data['mixin'];
213 maxBlocks::addMixin($mixin, $field, $screenObj->id);
214 }
215 }
216
217 } // fields
218
219 // check the mixins. This checks the field, not field_id since for responsive it'll need to add from the default screen when completing the data.
220 } // screens
221
222 return $css;
223 }
224
225 public function parsefix_mixins($css, $screens)
226 {
227 // $mixins = MaxBLocks::getMixins();
228 $data = $this->getBlockData();
229
230 foreach($screens as $screenObj) // these are our screens.
231 {
232 if (! $screenObj->is_responsive())
233 continue;
234
235 foreach($this->fields as $field => $field_data)
236 {
237 $field_id = $screenObj->getFieldID($field);
238 if (isset($field_data['mixin']))
239 {
240 $mixarray = maxBlocks::getMixins($field_data['mixin'], $screenObj->id); //$mixins[$field_data['mixin']];
241
242 if (count($mixarray) == 0) // mixin not in use.
243 continue;
244
245 if (! in_array($field, $mixarray))
246 {
247 $mixvalue = isset($data[$field]) ? $data[$field] : ''; // get extra data from the default screen
248 $css = $this->parseField($css, $field, $mixvalue, $field_data, $screenObj);
249 }
250 }
251 }
252 // }
253 }
254 return $css;
255
256 }
257
258 /** Parses a field.
259 *
260 * @param $css The CSS collection Being parsed
261 * @param $field_id The name of the field, this can be with screen_id prefixed
262 * @param $value The value of the field.
263 * @param $field_data Data of the field
264 * @param $screenObj Object of the current screen.
265 * @return Array CSS after parsed field.
266 */
267 protected function parseField($css, $field_id, $value, $field_data, $screenObj)
268 {
269 // get cssparts, can be comma-seperated value
270 $csspart = (isset($field_data["csspart"])) ? explode(",",$field_data["csspart"]) : array('maxbutton');
271 $csspseudo = (isset($field_data["csspseudo"])) ? explode(",", $field_data["csspseudo"]) : 'normal';
272 $is_responsive = ($screenObj->is_responsive() ) ? true : false;
273 $screen_id = $screenObj->id;
274
275 // if this field has a css property
276 if (isset($field_data["css"]))
277 {
278
279 // value can be int or otherwise.
280 if (is_string($value))
281 {
282 $value = str_replace(array(";"), '', $value); //sanitize
283 }
284 else {
285 $value = strval($value); // cast to string for further checks
286 }
287
288 if (isset($field_data['unitfield']) && ! strpos($value,"px"))
289 {
290 if ($value == '') $value = '0'; // pixel values, no empty but 0
291 $unitfield = $screenObj->getFieldID($field_data['unitfield']);
292
293 if (isset($this->data[$this->blockname][$unitfield]))
294 {
295 $unit = $this->data[$this->blockname][$unitfield]; // unitfield found
296 }
297 elseif ($is_responsive && isset($this->data[$this->blockname][$field_data['unitfield']])) // Unitfield is not stored if same as main, but can be non-default (e.g. % )
298 {
299 $unit = $this->data[$this->blockname][$field_data['unitfield']];
300 }
301 else
302 $unit =false;
303
304 $value .= ($unit == 'percent') ? '%' : 'px';
305
306 }
307 elseif (isset($field_data["default"]) && strpos($field_data["default"],"px") && ! strpos($value,"px"))
308 {
309 if ($value == '')
310 {
311 $value = '0'; // pixel values, no empty but 0
312 }
313 $value .= "px";
314 }
315 elseif (isset($field_data["default"]) && strpos($field_data["default"],"%") && ! strpos($value,"%"))
316 {
317 if ($value == '') $value = '0'; // pixel values, no empty but 0
318 $value .= "%";
319 }
320
321 /** CSSvalidate is a function reference for further shaping the value based on specific wishes.
322 * Can return a new value, or false which indicates removal. This aims to replace block specific parse_css functions.
323 */
324 if (isset($field_data['cssvalidate']))
325 {
326 $value = $this->{$field_data['cssvalidate']}($value, $field_id, $field_data, $screenObj);
327 if ($value == false) // don't add this field anywhere.
328 return $css;
329 }
330
331 $value = $this->sanitizeCSS($value);
332
333 foreach($csspart as $part)
334 {
335 if (is_array($csspseudo))
336 {
337 foreach($csspseudo as $pseudo)
338 {
339 if ($is_responsive)
340 $css[$part]['responsive'][$screen_id][$pseudo][$field_data["css"]] = $value ;
341 else
342 $css[$part][$pseudo][$field_data["css"]] = $value ;
343 }
344 }
345 else
346 {
347 if ($is_responsive)
348 $css[$part]['responsive'][$screen_id][$csspseudo][$field_data["css"]] = $value ;
349 else
350 $css[$part][$csspseudo][$field_data["css"]] = $value ;
351 }
352 }
353 }
354
355 return $css;
356 }
357
358 // Sanitize to prevent any wrong characters in general CSS.
359
360 protected function sanitizeCSS($value)
361 {
362 if (! is_string($value) && ! is_array($value))
363 {
364 return $value;
365 }
366
367 $replace = [
368 '"',
369 '\\',
370 '/',
371 '+',
372 ];
373
374
375 $value = str_replace($replace, '', $value);
376
377 return $value;
378 }
379
380 /* Ability to output custom JS for each button */
381 public function parse_js($js, $mode = 'normal')
382 {
383 return $js;
384 }
385
386 protected function validate_not_empty($value, $field_id, $field_data, $screenObj)
387 {
388 if ($value == '' || is_null($value) || empty($value))
389 {
390 return false;
391 }
392 return true;
393 }
394
395
396 /** Map the Block fields
397 *
398 * This function will take the field name and link it to the defined CSS definition to use in providing the live preview in the
399 * button editor. I.e. a field with name x will be linked to CSS-property X . Or to a custom Javascript function.
400 *
401 * @param $map Array [$field_id][css|attr|func|] = property/function
402 *
403 * @return Array
404 */
405 public function map_fields($map)
406 {
407 foreach($this->fields as $field => $field_data)
408 {
409 if (isset($field_data["css"]))
410 {
411 $cssdef = $field_data["css"];
412 $multidef = explode('-',$cssdef);
413 if ( count($multidef) > 1)
414 {
415 $cssdef = "";
416 for($i = 0; $i < count($multidef); $i++)
417 {
418 if ($i == 0)
419 $cssdef .= $multidef[$i];
420 else
421 $cssdef .= ucfirst($multidef[$i]);
422 }
423 }
424 $map[$field]["css"] = $cssdef;
425 if ( isset($field_data["default"]) && strpos($field_data["default"],"px") != false )
426 $map[$field]["css_unit"] = 'px';
427 else if ( isset($field_data["default"]) && strpos($field_data["default"],"%") != false )
428 $map[$field]["css_unit"] = '%';
429
430 if (isset($field_data['unitfield']))
431 {
432 $map[$field]['unitfield'] = $field_data['unitfield'];
433 }
434 }
435 if (isset($field_data["csspart"]))
436 $map[$field]["csspart"] = $field_data["csspart"];
437 if (isset($field_data['csspseudo']))
438 $map[$field]['pseudo'] = $field_data['csspseudo'];
439
440
441 // Attempt to new relationship type.
442 if (isset($field_data['is_sub_of'] ))
443 {
444 $map[$field]['is_sub_of'] = $field_data['is_sub_of'];
445 }
446 }
447 return $map;
448 }
449
450 /** Sets the data
451 *
452 * This action is called from button class when data is pulled from the database and populates the dataArray to all blocks
453 *
454 */
455 public function set($dataArray)
456 {
457 $this->data = $dataArray;
458 }
459
460 // simple util function to get blockdata.
461 protected function getBlockData($blockName = null)
462 {
463 $blockName = (! is_null($blockName)) ? $blockName : $this->blockname;
464 return (isset($this->data[$blockName])) ? $this->data[$blockName] : array();
465 }
466
467 } // class
468