PluginProbe
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP / 1.2.75
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP v1.2.75
1.2.76 1.2.75 1.2.74 1.2.73 1.2.72 1.2.71 1.2.70 1.2.69 1.2.68 1.2.67 1.2.66 1.2.65 1.2.64 1.2.63 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 All 176 releases
userswp / vendor / ayecode / wp-super-duper / includes / class-super-duper-bricks-element.php

class-super-duper-bricks-element.php in UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP 1.2.75, at vendor/ayecode/wp-super-duper/includes/class-super-duper-bricks-element.php

501 lines 16.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3
4 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
5
6
7 class Super_Duper_Bricks_Element extends \Bricks\Element {
8
9 public $widget;
10
11 public function __construct( $element = null ) {
12
13
14 $block_icon = !empty($this->widget->options['block-icon']) ? $this->widget->options['block-icon'] : '';
15
16
17 $this->category = !empty($this->widget->options['textdomain']) ? esc_attr( $this->widget->options['textdomain'] ) : 'Super Duper';
18 $this->name = $this->widget->id_base;
19 $this->icon = (strpos($block_icon, 'fa') === 0) ? esc_attr($this->widget->options['block-icon']) : 'fas fa-globe-americas';
20
21 parent::__construct($element);
22 }
23
24 /**
25 * Set the element name.
26 *
27 * @return array|string|string[]|null
28 */
29 public function get_label() {
30 $escaped_text = esc_attr( $this->widget->name );
31 return str_replace( ' &gt; ', ' > ', $escaped_text ); // keep our > but have it safe
32 }
33
34 /**
35 * Bricks function to set the controls
36 *
37 * @return void
38 */
39 public function set_controls() {
40 $args = $this->sd_convert_arguments($this->widget);
41
42 if (!empty($args)) {
43 $this->controls = $this->controls + $args;
44 }
45
46 }
47
48 /**
49 * Set the bricks control groups from the GD ones.
50 *
51 * @return void
52 */
53 public function set_control_groups() {
54 $args = $this->sd_get_arguments();
55
56 $groups = array();
57 if(!empty($args)) {
58 foreach ($args as $k => $v) {
59 $g_slug = !empty($v['group']) ? sanitize_title( $v['group'] ) : '';
60 if($g_slug && empty($groups[$g_slug])) {
61 $groups[$g_slug] = array(
62 'title' => esc_html( $v['group'] ),
63 'tab' => 'content',
64 );
65 }
66 }
67 }
68
69 if(!empty($groups)) {
70 $this->control_groups = $this->control_groups + $groups;
71 }
72
73 }
74
75 /**
76 * Get the setting input arguments.
77 *
78 * @return mixed
79 */
80 public function sd_get_arguments() {
81 $args = $this->widget->set_arguments();
82
83 $widget_options = ! empty( $this->widget->options ) ? $this->widget->options : array();
84 $widget_instance = ! empty( $this->widget->instance ) ? $this->widget->instance : array();
85
86 $args = apply_filters( 'wp_super_duper_arguments', $args, $widget_options, $widget_instance );
87
88 $arg_keys_subtract = $this->sd_remove_arguments();
89
90 if ( ! empty( $arg_keys_subtract ) ) {
91 foreach($arg_keys_subtract as $key ){
92 unset($args[$key]);
93 }
94 }
95
96 return $args;
97 }
98
99
100 /**
101 * Simply use our own render function for the output.
102 *
103 * @return void
104 */
105 public function render() {
106 $settings = $this->sd_maybe_convert_values( $this->settings );
107
108 // Set the AyeCode UI calss on the wrapper
109 $this->set_attribute( '_root', 'class', 'bsui' );
110
111 // We might need to add a placeholder here for previews.
112
113 do_action( 'super_duper_before_render_bricks_element', $settings, $this->widget, $this );
114
115 // Add the bricks attributes to wrapper
116 echo "<div {$this->render_attributes( '_root' )}>";
117 echo $this->widget->output( $settings );
118 echo '</div>';
119 }
120
121 /**
122 * Values can never be arrays so convert if bricks setting make it an array.
123 *
124 * @param $settings
125 * @return mixed
126 */
127 public function sd_maybe_convert_values( $settings ) {
128
129
130 if (!empty($settings)) {
131 foreach( $settings as $k => $v ) {
132 if(is_array($v)) {
133 $value = '';
134 // is color
135 if (isset($v['hex'])) {
136 $value = $v['hex'];
137 } elseif (isset($v['icon'])) {
138 $value = $v['icon'];
139 }
140
141
142 // set the value
143 $settings[$k] = $value;
144 }
145
146 }
147 }
148
149 return $settings;
150 }
151
152 /**
153 * Convert SD arguments to Bricks arguments.
154 *
155 * @param $widget
156 *
157 * @return array
158 */
159 public function sd_convert_arguments() {
160 $bricks_args = array();
161
162 $args = $this->sd_get_arguments();
163
164 if ( ! empty( $args ) ) {
165 foreach ( $args as $key => $arg ) {
166 // convert title
167 if ( ! empty( $arg['title'] ) ) {
168 $arg['label'] = $arg['title'];
169 unset( $arg['title'] );
170 }
171
172 // set fields not to use dynamic data
173 $arg['hasDynamicData'] = false;
174
175 if ( ! empty( $arg['group'] ) ) {
176 $arg['group'] = sanitize_title( $arg['group'] );
177 }
178
179 $arg['rerender'] = true;
180
181 // Convert checkbox to select, because Bricks settings don't save un-checked checkbox value.
182 if ( isset( $arg['type'] ) && $arg['type'] == 'checkbox' && empty( $arg['multiple'] ) ) {
183 $arg['type'] = 'select';
184
185 if ( ! empty( $arg['value'] ) && is_scalar( $arg['value'] ) && $arg['value'] !== '0' ) {
186 $checked_value = $arg['value'];
187 } else {
188 $checked_value = '1';
189 }
190
191 $arg['options'] = array(
192 $checked_value => _x( 'Yes', 'Widget option: Yes', 'geodirectory' ),
193 '0' => _x( 'No', 'Widget option: No', 'geodirectory' )
194 );
195 }
196
197 // required
198 if( ! empty( $arg['element_require'] ) ) {
199 $arg['required'] = $this->sd_convert_required( $arg['element_require'] );
200 unset( $arg['element_require'] );
201 }
202
203 // icons
204 if ( 'icon' === $key ) {
205 $arg['type'] = 'icon';
206 }
207
208 // Bricks don't render dropdown when first option key is 0.
209 if ( in_array( $key, array( 'zoom', 'mapzoom' ) ) && ! empty( $arg['options'] ) && is_array( $arg['options'] ) && ( $option_keys = array_keys( $arg['options'] ) ) ) {
210 // Move first element to last.
211 if ( $option_keys[0] === 0 || $option_keys[0] === '0' ) {
212 $options = $arg['options'];
213 unset( $arg['options'][0] );
214 $arg['options'][0] = $options[0];
215 }
216 }
217
218 $bricks_args[$key] = $arg;
219 }
220 }
221
222 return $bricks_args;
223 }
224
225 /**
226 * Convert the SD element_required to the Bricks required syntax.
227 *
228 * @param $element_require
229 * @return array
230 */
231 public function sd_convert_required($element_require) {
232 $bricks_required = [];
233
234 // Handle logical OR (||) for multiple values
235 if (strpos($element_require, '||') !== false) {
236 preg_match('/\[%(.+?)%\] *== *"(.*?)"/', $element_require, $matches);
237 if ($matches) {
238 $control_id = $matches[1];
239 preg_match_all('/\[%.*?%\] *== *"(.*?)"/', $element_require, $value_matches);
240 $values = $value_matches[1];
241 $bricks_required[] = [$control_id, '=', $values];
242 }
243 return $bricks_required;
244 }
245
246 // Match individual conditions
247 preg_match_all('/(!)?\[%(.*?)%\](?:\s*([!=<>]=?)\s*(".*?"|\'.*?\'|\d+))?/', $element_require, $matches, PREG_SET_ORDER);
248
249 foreach ($matches as $match) {
250 $is_negation = isset($match[1]) && $match[1] === '!';
251 $control_id = $match[2];
252 $operator = isset($match[3]) ? str_replace('==', '=', $match[3]) : ($is_negation ? '=' : '!=');
253 $value = isset($match[4]) ? trim($match[4], '"\'') : ($is_negation ? '' : '');
254
255 // Adjust for negation without explicit operator
256 if ($is_negation && !isset($match[3])) {
257 $operator = '=';
258 $value = '';
259 }
260
261 $bricks_required[] = [$control_id, $operator, $value];
262 }
263
264 return $bricks_required;
265 }
266
267
268 /**
269 * A way to remove some settings by keys.
270 *
271 * @return array
272 */
273 public function sd_remove_arguments()
274 {
275 return array();
276 }
277
278 }
279
280
281 /**
282 * This implements the desktop, tablet and mobile breakpoints views with our fields that are hidden on these types and adda the icon after the label to show which it applies to.
283 */
284 add_action( 'wp_enqueue_scripts', function() {
285
286 // Check if we're in the Bricks Editor
287 if ( isset( $_GET['bricks'] ) && $_GET['bricks'] && bricks_is_builder_main() ) {
288 // Add inline script to the 'bricks-builder' script
289 wp_add_inline_script(
290 'bricks-builder',
291 "
292
293 (function () {
294 // Function to get the current breakpoint from the #bricks-preview class
295 function getCurrentBreakpoint() {
296 const bricksPreview = document.getElementById('bricks-preview');
297 if (!bricksPreview) return null;
298
299 // Check which breakpoint class is active
300 if (bricksPreview.classList.contains('desktop')) {
301 return 'desktop';
302 } else if (bricksPreview.classList.contains('tablet_portrait')) {
303 return 'tablet';
304 } else if (bricksPreview.classList.contains('mobile_landscape') || bricksPreview.classList.contains('mobile_portrait')) {
305 return 'phone';
306 }
307 return null;
308 }
309
310 // Function to group fields by base key
311 function groupFields() {
312 const controls = document.querySelectorAll('[data-controlkey]');
313 const grouped = {};
314
315 controls.forEach((control) => {
316 const controlKey = control.getAttribute('data-controlkey');
317 const baseKey = controlKey.replace(/(_sm|_md|_lg)$/, ''); // Remove _sm, _md, or _lg suffix
318
319 if (!grouped[baseKey]) {
320 grouped[baseKey] = { base: null, md: null, lg: null };
321 }
322
323 if (controlKey.endsWith('_lg')) {
324 grouped[baseKey].lg = control;
325 } else if (controlKey.endsWith('_md')) {
326 grouped[baseKey].md = control;
327 } else {
328 grouped[baseKey].base = control; // No suffix is treated as base (sm)
329 }
330 });
331
332 return grouped;
333 }
334
335 // Function to update visibility of controls
336 function updateControlVisibility() {
337 const breakpoint = getCurrentBreakpoint();
338 const groupedFields = groupFields();
339
340 Object.keys(groupedFields).forEach((baseKey) => {
341 const { base, md, lg } = groupedFields[baseKey];
342
343 // Skip fields that have no `_md` or `_lg` counterparts
344 if (!md && !lg) {
345 if (base) base.style.display = ''; // Ensure base field is always visible
346 return;
347 }
348
349 // Apply hide/show logic based on the breakpoint
350 if (breakpoint === 'desktop') {
351 if (base) base.style.display = 'none';
352 if (md) md.style.display = 'none';
353 if (lg) lg.style.display = ''; // Show _lg
354 } else if (breakpoint === 'tablet') {
355 if (base) base.style.display = 'none';
356 if (md) md.style.display = ''; // Show _md
357 if (lg) lg.style.display = 'none';
358 } else if (breakpoint === 'phone') {
359 if (base) base.style.display = ''; // Show base (sm)
360 if (md) md.style.display = 'none';
361 if (lg) lg.style.display = 'none';
362 }
363 });
364 }
365
366 // Observe changes in the #bricks-panel-element content
367 const panelElementObserver = new MutationObserver(() => {
368 updateControlVisibility();
369 });
370
371 const bricksPanelElement = document.getElementById('bricks-panel-element');
372 if (bricksPanelElement) {
373 panelElementObserver.observe(bricksPanelElement, { childList: true, subtree: true });
374 }
375
376 // Also observe changes to the #bricks-preview element for breakpoint changes
377 const bricksPreviewObserver = new MutationObserver(() => {
378 updateControlVisibility();
379 });
380
381 const bricksPreview = document.getElementById('bricks-preview');
382 if (bricksPreview) {
383 bricksPreviewObserver.observe(bricksPreview, { attributes: true, attributeFilter: ['class'] });
384 }
385
386 // Run on initial load
387 updateControlVisibility();
388 })();
389
390
391 (function () {
392 // Function to get the current breakpoint from the #bricks-preview class
393 function getCurrentBreakpoint() {
394 const bricksPreview = document.getElementById('bricks-preview');
395 if (!bricksPreview) return null;
396
397 if (bricksPreview.classList.contains('desktop')) {
398 return 'desktop';
399 } else if (bricksPreview.classList.contains('tablet_portrait')) {
400 return 'tablet';
401 } else if (bricksPreview.classList.contains('mobile_landscape') || bricksPreview.classList.contains('mobile_portrait')) {
402 return 'phone';
403 }
404 return null;
405 }
406
407 // SVG icons
408 const icons = {
409 lg: `
410 <span class=\"bricks-svg-wrapper\" data-name=\"laptop\" style=\"padding-top:3px;\" title=\"Desktop\">
411 <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 14 14\" class=\"bricks-svg\">
412 <g id=\"laptop--device-laptop-electronics-computer-notebook\">
413 <path id=\"Vector\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.08 1.61H10.9136C11.4549 1.61 11.8936 2.0488 11.8936 2.59V7.98H2.1V2.59C2.1 2.002 2.492 1.61 3.08 1.61Z\" stroke-width=\"1\"></path>
414 <path id=\"Vector 3945\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M0.6957 11.2566L2.1 7.98H11.9L13.3042 11.2566C13.3477 11.3578 13.37 11.4667 13.37 11.5769C13.37 12.0259 13.0059 12.39 12.5569 12.39H1.4431C0.994 12.39 0.63 12.0259 0.63 11.5769C0.63 11.4667 0.6524 11.3578 0.6957 11.2566Z\" stroke-width=\"1\"></path>
415 </g>
416 </svg>
417 </span>
418 `,
419 md: `
420 <span class=\"bricks-svg-wrapper\" data-name=\"tablet-portrait\" style=\"padding-top:3px;\" title=\"Tablet\"><svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 14 14\" class=\"bricks-svg\"><g id=\"one-handed-holding-tablet-handheld\"><path id=\"Rectangle 2038\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9.64593 1.23658C9.47168 1.089 9.24623 1 9 1H2c-0.55228 0 -1 0.44771 -1 1v9.0938c0 0.5522 0.44772 1 1 1h3.75\" stroke-width=\"1\"></path><path id=\"vector 296\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m12.3106 13 0.6383 -3.15223c0.0742 -0.36672 0.0675 -0.7452 -0.0197 -1.10906l-0.9088 -3.79119c-0.1682 -0.70134 -0.7013 -1.25797 -1.3954 -1.45681l-0.6221 -0.17821 -0.0002 5.23879c0 0.35407 -0.35839 0.59595 -0.68734 0.46392l-1.6994 -0.68209c-0.3105 -0.12463 -0.66467 -0.06608 -0.91839 0.15183 -0.3824 0.32842 -0.41818 0.90721 -0.07914 1.28012l1.24302 1.36723L8.89958 13\" stroke-width=\"1\"></path></g></svg></span>
421 `,
422 sm: `
423 <span class=\"bricks-svg-wrapper\" data-name=\"phone-portrait\" style=\"padding-top:3px;\" title=\"Mobile\">
424 <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 14 14\" class=\"bricks-svg\">
425 <g id=\"phone-mobile-phone--android-phone-mobile-device-smartphone-iphone\">
426 <path id=\"Vector\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M10.5 0.5h-7c-0.55228 0 -1 0.447715 -1 1v11c0 0.5523 0.44772 1 1 1h7c0.5523 0 1 -0.4477 1 -1v-11c0 -0.552285 -0.4477 -1 -1 -1Z\" stroke-width=\"1\"></path>
427 <path id=\"Vector_2\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6.5 11h1\" stroke-width=\"1\"></path>
428 </g>
429 </svg>
430 </span>
431 `,
432 };
433
434
435 // Function to group fields by base key
436 function groupFields() {
437 const controls = document.querySelectorAll('[data-controlkey]');
438 const grouped = {};
439
440 controls.forEach((control) => {
441 const controlKey = control.getAttribute('data-controlkey');
442 const baseKey = controlKey.replace(/(_sm|_md|_lg)$/, ''); // Remove _sm, _md, or _lg suffix
443
444 if (!grouped[baseKey]) {
445 grouped[baseKey] = { base: null, md: null, lg: null };
446 }
447
448 if (controlKey.endsWith('_lg')) {
449 grouped[baseKey].lg = control;
450 } else if (controlKey.endsWith('_md')) {
451 grouped[baseKey].md = control;
452 } else {
453 grouped[baseKey].base = control; // No suffix is treated as base (sm)
454 }
455 });
456
457 return grouped;
458 }
459
460 // Function to add icons to labels
461 function addIconsToLabels() {
462 const groupedFields = groupFields();
463
464 Object.keys(groupedFields).forEach((baseKey) => {
465 const { base, md, lg } = groupedFields[baseKey];
466
467 // Skip fields that do not have `_md` or `_lg` counterparts
468 if (!md && !lg) return;
469
470 if (base) appendIcon(base, 'sm');
471 if (md) appendIcon(md, 'md');
472 if (lg) appendIcon(lg, 'lg');
473 });
474 }
475
476 // Append an icon to the label of a control
477 function appendIcon(control, type) {
478 const label = control.querySelector('label');
479 if (label && !label.querySelector('.bricks-svg-wrapper')) {
480 label.insertAdjacentHTML('beforeend', icons[type]);
481 }
482 }
483
484 // Observe changes in the #bricks-panel-element content
485 const panelElementObserver = new MutationObserver(() => {
486 addIconsToLabels(); // Ensure icons are added when the panel updates
487 });
488
489 const bricksPanelElement = document.getElementById('bricks-panel-element');
490 if (bricksPanelElement) {
491 panelElementObserver.observe(bricksPanelElement, { childList: true, subtree: true });
492 }
493
494 // Initial run to add icons
495 addIconsToLabels();
496 })();
497 "
498 );
499 }
500 });
501