PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.9.19.4
Pods – Custom Content Types and Fields v2.9.19.4
2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / components / Templates / includes / functions-view_template.php
pods / components / Templates / includes Last commit date
auto-template 2 weeks ago element-pod_reference.php 2 weeks ago element-view_template.php 2 weeks ago functions-pod_reference.php 2 weeks ago functions-view_template.php 2 weeks ago
functions-view_template.php
978 lines
1 <?php
2 /**
3 * Utility function for processesing fromtier based templates
4 *
5 * @package Pods_Frontier_Template_Editor\view_template
6 */
7
8 use Pods\Whatsit\Pod;
9 use Pods\Whatsit\Field;
10
11 // add filters
12 add_filter( 'pods_templates_post_template', 'frontier_end_template', 25, 4 );
13 add_filter( 'pods_templates_do_template', 'frontier_do_shortcode', 25, 1 );
14
15 // template shortcode handlers
16 add_shortcode( 'pod_once_template', 'frontier_template_once_blocks' );
17 add_shortcode( 'pod_after_template', 'frontier_template_blocks' );
18 add_shortcode( 'pod_before_template', 'frontier_template_blocks' );
19 add_shortcode( 'pod_if_field', 'frontier_if_block' );
20
21 /**
22 * Return array of valid frontier type shortcode tags
23 *
24 * @return array
25 */
26 function frontier_get_shortcodes() {
27
28 $shortcodes = array(
29 'each',
30 'pod_sub_template',
31 'once',
32 'pod_once_template',
33 'before',
34 'pod_before_template',
35 'after',
36 'pod_after_template',
37 'if',
38 'pod_if_field',
39 );
40
41 return $shortcodes;
42 }
43
44 /**
45 * @param $content
46 *
47 * @return string
48 * @since 2.4.3
49 */
50 function frontier_do_shortcode( $content ) {
51 // Run only Pods template shortcodes (each, once, before, after, if, and else).
52 return pods_do_shortcode( $content, frontier_get_shortcodes() );
53 }
54
55 /**
56 * @param $content
57 *
58 * @return string
59 * @since 2.8.6
60 */
61 function frontier_do_other_shortcodes( $content ) {
62 // Run all other shortcodes but ignore the Pods template shortcodes (each, once, before, after, if, and else).
63 return pods_do_shortcode( $content, [], frontier_get_shortcodes() );
64 }
65
66 /**
67 * decodes a like nested shortcode based template
68 *
69 * @param string encoded template to be decoded
70 * @param array attributed provided from parent
71 *
72 * @return string
73 * @since 2.4.0
74 */
75 function frontier_decode_template( $code, $atts ) {
76 $code = base64_decode( $code );
77
78 if ( isset( $atts['pod'] ) ) {
79 $code = str_replace( '{@pod}', $atts['pod'], $code );
80 }
81 if ( isset( $atts['id'] ) ) {
82 $code = str_replace( '{@EntryID}', $atts['id'], $code );
83 }
84 if ( isset( $atts['index'] ) ) {
85 $code = str_replace( '{_index}', $atts['index'], $code );
86 }
87
88 return $code;
89 }
90
91 /**
92 * processes if condition within a template
93 *
94 * @param array $attributes attributes from template
95 * @param string $code encoded template to be decoded
96 *
97 * @return string
98 * @since 2.4.0
99 */
100 function frontier_if_block( $attributes, $code ) {
101 $attributes = array_merge( [
102 'pod' => null,
103 'id' => null,
104 'field' => null,
105 'value' => null,
106 'compare' => null,
107 'index' => null,
108 ], $attributes );
109
110 $pod = Pods_Templates::get_obj( $attributes['pod'], $attributes['id'] );
111
112 if ( ! $pod || ! $pod->exists() ) {
113 return '';
114 }
115
116 $code = explode( '[else]', frontier_decode_template( $code, $attributes ) );
117
118 // field data
119 $field_data = null;
120 $field_type = 'text';
121
122 if ( ! empty( $attributes['field'] ) ) {
123 $supported_calculations = [
124 '_zebra' => 'number',
125 '_position' => 'number',
126 '_total' => 'number',
127 '_total_found' => 'number',
128 '_total_all_rows' => 'number',
129 '_total_pages' => 'number',
130 '_current_page' => 'number',
131 ];
132
133 if ( isset( $supported_calculations[ $attributes['field'] ] ) ) {
134 // Support [if field="_position" value="2"] and other calculation value handlers.
135 $field_data = $pod->field( $attributes['field'] );
136 $field_type = $supported_calculations[ $attributes['field'] ];
137 } elseif ( '_index' === $attributes['field'] ) {
138 $field_data = pods_v( 'index', $attributes );
139 } else {
140 $field_data = $pod->field( $attributes['field'] );
141 $field_type = $pod->fields( $attributes['field'], 'type' );
142 }
143 }
144
145 $is_empty = true;
146
147 if ( null !== $field_data ) {
148 if ( empty( $field_type ) ) {
149 $field_type = 'text';
150 }
151
152 $is_empty = PodsForm::field_method( $field_type, 'values_are_empty', $field_data );
153 }
154
155 $has_value_compare_attribute = null !== $attributes['value'] || null !== $attributes['compare'];
156
157 if ( ! $is_empty || $has_value_compare_attribute ) {
158 // Check if we do not have a value to compare with.
159 if ( ! $has_value_compare_attribute ) {
160 $template = $code[0];
161
162 // Maybe run any shortcode.
163 if ( defined( 'PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES' ) && PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES ) {
164 $template = frontier_do_other_shortcodes( $template );
165 }
166
167 // Field exists and is not empty, use [IF] content
168 $template = $pod->do_magic_tags( $template );
169
170 return frontier_do_shortcode( $template );
171 }
172
173 $first_character = substr( $attributes['value'], 0, 1 );
174
175 // check if + or - are present
176 if ( '+' === $first_character ) {
177 // is greater
178 $attributes['value'] = (float) substr( $attributes['value'], 1 ) + 1;
179 $attributes['compare'] = '>';
180 } elseif ( '-' === $first_character ) {
181 // is smaller
182 $attributes['value'] = (float) substr( $attributes['value'], 1 ) - 1;
183 $attributes['compare'] = '<';
184 }
185
186 if ( empty( $attributes['compare'] ) ) {
187 $attributes['compare'] = '=';
188 }
189
190 $attributes['compare'] = html_entity_decode( $attributes['compare'] );
191 $attributes['compare'] = strtoupper( $attributes['compare'] );
192
193 // Normalize the compare.
194 $comparisons = [
195 '=',
196 '!=',
197 'IN',
198 'NOT IN',
199 'EXISTS',
200 'NOT EXISTS',
201 '>',
202 '>=',
203 '<',
204 '<=',
205 'LIKE',
206 'NOT LIKE',
207 'EMPTY',
208 'NOT EMPTY',
209 ];
210
211 // Comparison not supported, assume it does not match.
212 if ( ! in_array( $attributes['compare'], $comparisons, true ) ) {
213 return '';
214 }
215
216 $pass = false;
217
218 $maybe_array = is_array( $field_data ) || is_array( $attributes['value'] );
219
220 // Handle comparison.
221 if ( '=' === $attributes['compare'] ) {
222 if ( $maybe_array ) {
223 $pass = in_array( (string) $attributes['value'], (array) $field_data, false );
224 } else {
225 $pass = (string) $field_data === (string) $attributes['value'];
226 }
227 } elseif ( '!=' === $attributes['compare'] ) {
228 if ( $maybe_array ) {
229 $pass = ! in_array( (string) $attributes['value'], (array) $field_data, false );
230 } else {
231 $pass = (string) $field_data !== (string) $attributes['value'];
232 }
233 } elseif ( 'EXISTS' === $attributes['compare'] ) {
234 $pass = null !== $field_data && [] !== $field_data;
235 } elseif ( 'NOT EXISTS' === $attributes['compare'] ) {
236 $pass = null === $field_data || [] === $field_data;
237 } elseif ( $maybe_array ) {
238 // We do not support comparisons for array values beyond equals.
239 $pass = false;
240 } elseif ( 'IN' === $attributes['compare'] ) {
241 $pass = in_array( (string) $field_data, explode( ',', $attributes['value'] ), false );
242 } elseif ( 'NOT IN' === $attributes['compare'] ) {
243 $pass = ! in_array( (string) $field_data, explode( ',', $attributes['value'] ), false );
244 } elseif ( '>' === $attributes['compare'] ) {
245 $pass = (float) $field_data > (float) $attributes['value'];
246 } elseif ( '>=' === $attributes['compare'] ) {
247 $pass = (float) $field_data >= (float) $attributes['value'];
248 } elseif ( '<' === $attributes['compare'] ) {
249 $pass = (float) $field_data < (float) $attributes['value'];
250 } elseif ( '<=' === $attributes['compare'] ) {
251 $pass = (float) $field_data <= (float) $attributes['value'];
252 } elseif ( 'LIKE' === $attributes['compare'] || 'NOT LIKE' === $attributes['compare'] ) {
253 $field_data = (string) $field_data;
254
255 $attributes['value'] = (string) $attributes['value'];
256
257 if ( false !== strpos( $attributes['value'], '%' ) ) {
258 // Handle % LIKE values.
259 $attributes['value'] = str_replace( '%', '.*', preg_quote( $attributes['value'], '/' ) );
260
261 $found = preg_match( '/^' . $attributes['value'] . '$/Uim', $field_data );
262
263 if ( 0 === $found ) {
264 $found = false;
265 }
266 } else {
267 $found = stripos( $field_data, $attributes['value'] );
268 }
269
270 if ( 'LIKE' === $attributes['compare'] ) {
271 // Check if the string contains the match.
272 $pass = false !== $found;
273 } elseif ( 'NOT LIKE' === $attributes['compare'] ) {
274 // Check if the string does not contain the match.
275 $pass = false === $found;
276 }
277 } elseif ( 'EMPTY' === $attributes['compare'] ) {
278 $pass = $is_empty;
279 } elseif ( 'NOT EMPTY' === $attributes['compare'] ) {
280 $pass = ! $is_empty;
281 }
282
283 if ( $pass ) {
284 $template = $code[0];
285
286 // Maybe run any shortcode.
287 if ( defined( 'PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES' ) && PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES ) {
288 $template = frontier_do_other_shortcodes( $template );
289 }
290
291 // IF statement true, use [IF] content as template.
292 $template = $pod->do_magic_tags( $template );
293
294 return frontier_do_shortcode( $template );
295 }
296
297 if ( isset( $code[1] ) ) {
298 $template = $code[1];
299
300 // Maybe run any shortcode.
301 if ( defined( 'PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES' ) && PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES ) {
302 $template = frontier_do_other_shortcodes( $template );
303 }
304
305 // There is an [ELSE] tag
306 $template = $pod->do_magic_tags( $template );
307
308 return frontier_do_shortcode( $template );
309 }
310
311 // Value did not match (and no [ELSE]), nothing should be displayed.
312 return '';
313 }
314
315 if ( isset( $code[1] ) ) {
316 $template = $code[1];
317
318 // Maybe run any shortcode.
319 if ( defined( 'PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES' ) && PODS_TEMPLATES_ALLOW_OTHER_SHORTCODES ) {
320 $template = frontier_do_other_shortcodes( $template );
321 }
322
323 // No value or field is empty and there is an [ELSE] tag. Use [ELSE].
324 $template = $pod->do_magic_tags( $template );
325
326 return frontier_do_shortcode( $template );
327 }
328
329 // No match at all for the format we support.
330 return '';
331 }
332
333 /**
334 * processes before and after template blocks
335 *
336 * @param array attributes from template
337 * @param string encoded template to be decoded
338 * @param string shortcode slug used to process
339 *
340 * @return null
341 * @since 2.4.0
342 */
343 function frontier_template_blocks( $atts, $code, $slug ) {
344
345 global $template_post_blocks;
346 if ( ! isset( $template_post_blocks ) ) {
347 $template_post_blocks = array(
348 'before' => null,
349 'after' => null,
350 );
351 }
352 if ( $slug === 'pod_before_template' ) {
353 if ( ! isset( $template_post_blocks['before'][ $atts['pod'] ] ) ) {
354 $template_post_blocks['before'][ $atts['pod'] ] = pods_do_shortcode(
355 frontier_decode_template( $code, $atts ), array(
356 'if',
357 'else',
358 )
359 );
360 }
361 } elseif ( $slug === 'pod_after_template' ) {
362 if ( ! isset( $template_post_blocks['after'][ $atts['pod'] ] ) ) {
363 $template_post_blocks['after'][ $atts['pod'] ] = pods_do_shortcode(
364 frontier_decode_template( $code, $atts ), array(
365 'if',
366 'else',
367 )
368 );
369 }
370 }
371
372 return null;
373 }
374
375 /**
376 * processes once blocks
377 *
378 * @param array attributes from template
379 * @param string encoded template to be decoded
380 *
381 * @return string template code
382 * @since 2.4.0
383 */
384 function frontier_template_once_blocks( $atts, $code ) {
385
386 global $frontier_once_hashes;
387
388 if ( ! isset( $frontier_once_hashes ) ) {
389 $frontier_once_hashes = array();
390 }
391
392 $blockhash = md5( $code . $atts['id'] );
393 if ( in_array( $blockhash, $frontier_once_hashes, true ) ) {
394 return '';
395 }
396 $frontier_once_hashes[] = $blockhash;
397
398 return pods_do_shortcode( frontier_decode_template( $code, $atts ), frontier_get_shortcodes() );
399 }
400
401 /**
402 * processes template code within an each command from the base template
403 *
404 * @param array attributes from template
405 * @param string template to be processed
406 *
407 * @return null
408 * @since 2.4.0
409 */
410 function frontier_do_subtemplate( $atts, $content ) {
411 $out = '';
412 $field_name = $atts['field'];
413
414 $pod = Pods_Templates::get_obj( $atts['pod'], $atts['id'] );
415
416 if ( ! $pod || ! $pod->exists() ) {
417 return '';
418 }
419
420 $field = $pod->fields( $field_name );
421
422 $is_repeatable_field = $field && $field->is_repeatable();
423
424 $entries = $pod->field( [
425 'name' => $field_name,
426 'display' => $is_repeatable_field,
427 'display_process_individually' => $is_repeatable_field,
428 ] );
429
430 if ( $field && ! empty( $entries ) ) {
431 $entries = (array) $entries;
432
433 // Force array even for single items since the logic below is using loops.
434 if (
435 (
436 $is_repeatable_field
437 || 'single' === $field->get_single_multi()
438 )
439 && ! isset( $entries[0] )
440 ) {
441 $entries = array( $entries );
442 }
443
444 // Object types that could be Pods
445 $object_types = array( 'post_type', 'pod' );
446
447 if ( $is_repeatable_field ) {
448 foreach ( $entries as $key => $entry ) {
449 $template = frontier_decode_template( $content, $atts );
450
451 $template = str_replace( '{_key}', '{@_index}', $template );
452 $template = str_replace( '{@_key}', '{@_index}', $template );
453 $template = str_replace( '{_index}', '{@_index}', $template );
454
455 $entry = array(
456 '_index' => $key,
457 '_value' => $entry,
458 );
459
460 $out .= frontier_pseudo_magic_tags( $template, $entry, $pod, true );
461 }
462 }
463 /**
464 * Note on the change below for issue #3018:
465 * ... || 'taxonomy' == $pod->fields[ $atts[ 'field' ] ][ 'type' ]
466 *
467 * calling field() above for a taxonomy object field will populate
468 * $pod->fields[ $field_name ] for the object field's data, in this
469 * case a taxonomy object field. Without calling
470 * $pod->field( $field_name ), it would not normally be available in
471 * the $pod->fields array and is something to not expect to be there in
472 * 3.0 as this was unintentional.
473 */
474 elseif ( 'taxonomy' === $field['type'] || in_array( $field['pick_object'], $object_types, true ) ) {
475 // Match any Pod object or taxonomy
476 foreach ( $entries as $key => $entry ) {
477 $subpod = pods_get_instance( $field['pick_val'] );
478
479 if ( ! $subpod || ! $subpod->valid() ) {
480 continue;
481 }
482
483 $subatts = array(
484 'id' => $entry[ $subpod->pod_data['field_id'] ],
485 'pod' => $field['pick_val'],
486 );
487
488 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
489 $template = str_replace( '{_key}', $key, $template );
490 $template = str_replace( '{@_key}', $key, $template );
491 $template = str_replace( '{_index}', $key, $template );
492 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
493
494 // Kludge to work with taxonomies, pending a better solution: see issue #3018
495 $target_id = null;
496 if ( isset( $entry['ID'] ) ) {
497 $target_id = $entry['ID'];
498 } elseif ( isset( $entry['id'] ) ) {
499 // Advanced Content Types have lowercase 'id'
500 $target_id = $entry['id'];
501 } elseif ( isset( $entry['term_id'] ) ) {
502 $target_id = $entry['term_id'];
503 }
504
505 $out .= pods_shortcode_run_safely(
506 array(
507 'name' => $field['pick_val'],
508 'slug' => $target_id,
509 'index' => $key,
510 ),
511 $template,
512 false
513 );
514
515 }//end foreach
516 } elseif ( 'file' === $field['type'] ) {
517 $template = frontier_decode_template( $content, $atts );
518 $media_pod = pods( 'media' );
519
520 foreach ( $entries as $key => $entry ) {
521 $template = str_replace( '{_key}', $key, $template );
522 $template = str_replace( '{@_key}', $key, $template );
523 $template = str_replace( '{_index}', $key, $template );
524
525 if ( $media_pod && $media_pod->valid() && $media_pod->fetch( $entry['ID'] ) ) {
526 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
527
528 $entry_pod = $media_pod;
529 } else {
530 $template = str_replace( '{@_img', '{@image_attachment.' . $entry['ID'], $template );
531 $template = str_replace( '{@_src', '{@image_attachment_url.' . $entry['ID'], $template );
532 $template = str_replace( '{@' . $field_name . '}', '{@image_attachment.' . $entry['ID'] . '}', $template );
533
534 // Fix for lowercase ID's.
535 $entry['id'] = $entry['ID'];
536
537 // Allow array-like tags.
538 $template = frontier_pseudo_magic_tags( $template, $entry, $pod, true );
539
540 // Fallback to parent Pod so above tags still work.
541 $entry_pod = $pod;
542 }
543
544 $out .= pods_do_shortcode( $entry_pod->do_magic_tags( $template ), frontier_get_shortcodes() );
545 }
546 } elseif ( isset( $field['table_info'], $field['table_info']['pod'] ) ) {
547 // Relationship to something that is extended by Pods
548 $entries = $pod->field( array( 'name' => $field_name, 'output' => 'pod' ) );
549 foreach ( $entries as $key => $entry ) {
550 $subatts = array(
551 'id' => $entry->id,
552 'pod' => $entry->pod,
553 'index' => $key,
554 );
555
556 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
557
558 $template = str_replace( '{_key}', $key, $template );
559 $template = str_replace( '{@_key}', $key, $template );
560 $template = str_replace( '{_index}', $key, $template );
561 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
562
563 $out .= pods_do_shortcode( $entry->do_magic_tags( $template ), frontier_get_shortcodes() );
564 }
565 } else {
566 $template = frontier_decode_template( $content, $atts );
567
568 // Relationship to something other than a Pod (ie: user)
569 foreach ( $entries as $key => $entry ) {
570 $template = frontier_decode_template( $content, $atts );
571
572 $template = str_replace( '{_key}', '{@_index}', $template );
573 $template = str_replace( '{@_key}', '{@_index}', $template );
574 $template = str_replace( '{_index}', '{@_index}', $template );
575
576 if ( ! is_array( $entry ) ) {
577 $entry = array(
578 '_index' => $key,
579 '_value' => $entry,
580 );
581 }
582
583 $out .= pods_do_shortcode( frontier_pseudo_magic_tags( $template, $entry, $pod ), frontier_get_shortcodes() );
584 }
585 }//end if
586 }//end if
587
588 return pods_do_shortcode( $out, frontier_get_shortcodes() );
589 }
590
591 /**
592 * Search and replace like Pods magic tags but with an array of data instead of a Pod
593 *
594 * @param Pod $pod
595 * @param string $template
596 * @param array $data
597 * @param boolean $skip_unknown If true then values not in $data will not be touched
598 *
599 * @return string
600 * @since 2.7.0
601 */
602 function frontier_pseudo_magic_tags( $template, $data, $pod = null, $skip_unknown = false ) {
603 return preg_replace_callback(
604 '/({@(.*?)})/m', function ( $tag ) use ( $pod, $data, $skip_unknown ) {
605
606 // This is essentially Pods->process_magic_tags() but with the Pods specific code ripped out
607 if ( is_array( $tag ) ) {
608 if ( ! isset( $tag[2] ) && strlen( trim( $tag[2] ) ) < 1 ) {
609 return '';
610 }
611
612 $original_tag = $tag[0];
613 $tag = $tag[2];
614 }
615
616 $tag = trim( $tag, ' {@}' );
617 $tag = explode( ',', $tag );
618
619 if ( empty( $tag ) || ! isset( $tag[0] ) || strlen( trim( $tag[0] ) ) < 1 ) {
620 return '';
621 }
622
623 foreach ( $tag as $k => $v ) {
624 $tag[ $k ] = trim( $v );
625 }
626
627 $field_name = $tag[0];
628
629 $helper_name = '';
630 $before = '';
631 $after = '';
632
633 if ( isset( $data[ $field_name ] ) ) {
634 $value = $data[ $field_name ];
635 if ( isset( $tag[1] ) && ! empty( $tag[1] ) ) {
636 $helper_name = $tag[1];
637
638 if ( isset( $pod ) ) {
639 $value = $pod->helper( $helper_name, $value, $field_name );
640 }
641 }
642 } else {
643 if ( $skip_unknown ) {
644 return $original_tag;
645 }
646 $value = '';
647 }
648
649 if ( isset( $tag[2] ) && ! empty( $tag[2] ) ) {
650 $before = $tag[2];
651 }
652
653 if ( isset( $tag[3] ) && ! empty( $tag[3] ) ) {
654 $after = $tag[3];
655 }
656
657 $value = apply_filters( 'pods_do_magic_tags', $value, $field_name, $helper_name, $before, $after );
658
659 if ( is_array( $value ) ) {
660 $value = pods_serial_comma(
661 $value, array(
662 'field' => $field_name,
663 'fields' => $pod->fields,
664 )
665 );
666 }
667
668 if ( null !== $value && false !== $value ) {
669 return $before . $value . $after;
670 }
671
672 return '';
673 }, $template
674 );
675 }
676
677 /**
678 * processes template code within an each command from the base template
679 *
680 * @param array $code The code to filter.
681 * @param string $template The template to be processed.
682 * @param Pods $pod The Pods object.
683 *
684 * @return null
685 * @since 2.4.0
686 */
687 function frontier_prefilter_template( $code, $template, $pod ) {
688
689 global $frontier_once_tags;
690
691 $commands = array(
692 'each' => 'pod_sub_template',
693 'once' => 'pod_once_template',
694 'before' => 'pod_before_template',
695 'after' => 'pod_after_template',
696 'if' => 'pod_if_field',
697 );
698
699 if ( ! shortcode_exists( 'pod_sub_template' ) ) {
700 add_shortcode( 'pod_sub_template', 'frontier_do_subtemplate' );
701 }
702
703 $commands = array_merge( $commands, get_option( 'pods_frontier_extra_commands', array() ) );
704
705 /**
706 * Add additional control blocks to Pods templates
707 *
708 * Can also be use to remove each/once/before/after/if functionality from Pods Templates
709 *
710 * @param array $commands The control blocks in the form of 'tag' => 'shortcode'
711 *
712 * @return array An array of control blocks, and shortcodes used to power them.
713 *
714 * @since 1.0.0
715 */
716 $commands = apply_filters( 'pods_frontier_template_commands', $commands );
717
718 $aliases = array();
719 foreach ( $commands as $command => $shortcode ) {
720 //preg_match_all( '/(\[' . $command . '(?<attributes>.*?)]|\[\/' . $command . '\])/m', $code, $matches );
721 preg_match_all( '/('
722 . '\[' . preg_quote( $command, '/' ) . '\s*'
723 . '(?<field_attr>field="(?<field>[^"]*)")*' . '\s*'
724 . '(?<value_attr>value="(?<value>[^"]*)")*' . '\s*'
725 . '(?<compare_attr>compare="(?<compare>[^"]*)")*' . '\s*'
726 . '(?<other_attributes>[^\]]*)'
727 . ']|\[\/' . preg_quote( $command, '/' ) . '\]'
728 . ')/m', $code, $matches );
729
730 if ( ! empty( $matches[0] ) ) {
731 // holder for found tags.
732 $tags = array();
733 $indexCount = 0;
734 foreach ( $matches[0] as $key => $tag ) {
735 if ( false !== strpos( $tag, '[/' ) ) {
736 // close tag
737 $indexCount --;
738 $newclose = $tags[ $indexCount ];
739 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[/' . $newclose . ']', $code, 1 );
740
741 continue;
742 }//end if
743
744 // Handle open tags.
745
746 $field = null;
747 $value = null;
748 $compare = null;
749
750 $pod_name = '{@pod}';
751 $ID = '{@EntryID}';
752
753 if ( '' !== $matches['field_attr'][ $key ] ) {
754 $field = $matches['field'][ $key ];
755
756 if ( '' !== $matches['value_attr'][ $key ] ) {
757 $value = $matches['value'][ $key ];
758 }
759
760 if ( '' !== $matches['compare_attr'][ $key ] ) {
761 $compare = $matches['compare'][ $key ];
762 }
763 } elseif ( '' !== $matches['other_attributes'][ $key ] ) {
764 // get atts if any
765 // $atts = shortcode_parse_atts(str_replace('.', '____', $matches[2][$key]));
766 $pattern = '/(?<field>[\w\.\_\-]+)\s*=\s*"(?<value>[^"]*)"(?:\s|$)/';
767 $field = trim( $matches['other_attributes'][ $key ] );
768 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $field );
769
770 if ( preg_match_all( $pattern, $text, $field_value_match, PREG_SET_ORDER ) ) {
771 $field = $field_value_match[0]['field'];
772 $value = $field_value_match[0]['value'];
773 }
774 }//end if
775
776 if ( $field && false !== strpos( $field, '.' ) ) {
777 // Take the last element off of the array and use the ID.
778 $field_path = explode( '.', $field );
779 $last_field = array_pop( $field_path );
780 $field_path = implode( '.', $field_path );
781
782 $related_field = $pod->pod_data->get_field( $field_path );
783
784 if ( $related_field instanceof Field && 1 === $related_field->get_limit() ) {
785 $related_pod = $related_field->get_related_object();
786
787 if ( $related_pod instanceof Pod ) {
788 $table_field_id = $related_pod->get_arg( 'field_id' );
789
790 if ( $table_field_id ) {
791 // Use the other pod.
792 $pod_name = $related_pod->get_name();
793
794 // Rebuild the ID used for the lookup.
795 $ID = '{@' . $field_path . '.' . $table_field_id . '}';
796
797 // Override the field to use.
798 $field = $last_field;
799 }
800 }
801 }
802 }
803
804 $atts = ' pod="' . esc_attr( $pod_name ) . '"';
805 $atts .= ' id="' . esc_attr( $ID ) . '"';
806
807 if ( $field ) {
808 $atts .= ' field="' . esc_attr( $field ) . '"';
809 }
810
811 if ( null !== $value ) {
812 $atts .= ' value="' . esc_attr( $value ) . '"';
813 }
814
815 if ( null !== $compare ) {
816 $atts .= ' compare="' . esc_attr( $compare ) . '"';
817 }
818
819 $newtag = $shortcode . '__' . $key;
820 $tags[ $indexCount ] = $newtag;
821 $aliases[] = $newtag;
822
823 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[' . $newtag . $atts . ' index="{_index}"]', $code, 1 );
824
825 $indexCount ++;
826 }//end foreach
827 }//end if
828 }//end foreach
829 // get new aliased shortcodes
830 if ( ! empty( $aliases ) ) {
831 $code = frontier_backtrack_template( $code, $aliases );
832 }
833 $code = str_replace( '{@pod}', $pod->pod, $code );
834 $code = str_replace( '{@EntryID}', '{@' . $pod->pod_data['field_id'] . '}', $code );
835
836 return $code;
837 }
838
839 /**
840 * @param $code
841 * @param $aliases
842 *
843 * @return mixed
844 */
845 function frontier_backtrack_template( $code, $aliases ) {
846
847 $regex = frontier_get_regex( $aliases );
848 preg_match_all( '/' . $regex . '/s', $code, $used );
849
850 if ( ! empty( $used[2] ) ) {
851 foreach ( $used[2] as $key => $alias ) {
852 $shortcodes = explode( '__', $alias );
853 $content = $used[5][ $key ];
854 $atts = shortcode_parse_atts( $used[3][ $key ] );
855
856 $new_shortcode_name = $shortcodes[0];
857
858 $new_shortcode_atts_data = [
859 'seq' => $shortcodes[1],
860 ];
861
862 if ( ! empty( $atts ) ) {
863 if ( ! empty( $atts['field'] ) && false !== strpos( $atts['field'], '.' ) ) {
864 $content = str_replace( $atts['field'] . '.', '', $content );
865 }
866
867 preg_match_all( '/' . $regex . '/s', $content, $subused );
868
869 if ( ! empty( $subused[2] ) ) {
870 $content = frontier_backtrack_template( $content, $aliases );
871 }
872
873 $new_shortcode_atts_data[] = trim( $used[3][ $key ] );
874 }
875
876 $new_shortcode_atts = '';
877
878 foreach ( $new_shortcode_atts_data as $new_shortcode_att_key => $new_shortcode_att_data ) {
879 if ( is_int( $new_shortcode_att_key ) ) {
880 $new_shortcode_atts .= ' ' . $new_shortcode_att_data;
881 } else {
882 $new_shortcode_atts .= ' ' . $new_shortcode_att_key . '="' . esc_attr( $new_shortcode_att_data ) . '"';
883 }
884 }
885
886 // Build the new shortcode.
887 $new_shortcode = sprintf(
888 '[%1$s %2$s]%3$s[/%1$s]',
889 $new_shortcode_name,
890 $new_shortcode_atts,
891 base64_encode( $content )
892 );
893
894 $code = str_replace( $used[0][ $key ], $new_shortcode, $code );
895 }
896 }//end if
897
898 return $code;
899 }
900
901 /**
902 * @param $codes
903 *
904 * @return string
905 */
906 function frontier_get_regex( $codes ) {
907
908 // A custom version of the shortcode regex as to only use podsfrontier codes.
909 // this makes it easier to cycle through and get the used codes for inclusion
910 $validcodes = join( '|', array_map( 'preg_quote', $codes ) );
911
912 $regex_pieces = array(
913 // Opening bracket
914 '\\[',
915 // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
916 '(\\[?)',
917 // 2: selected codes only
918 "($validcodes)",
919 // Word boundary
920 '\\b',
921 // 3: Unroll the loop: Inside the opening shortcode tag
922 '(',
923 // Not a closing bracket or forward slash
924 '[^\\]\\/]*',
925 // A forward slash not followed by a closing bracket
926 '(?:' . '\\/(?!\\])',
927 // Not a closing bracket or forward slash
928 '[^\\]\\/]*',
929 // 4: Self closing tag ...
930 ')*?' . ')' . '(?:' . '(\\/)',
931 // ... and closing bracket
932 '\\]',
933 // Closing bracket
934 '|' . '\\]',
935 // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
936 '(?:' . '(',
937 // Not an opening bracket
938 '[^\\[]*+',
939 // An opening bracket not followed by the closing shortcode tag
940 '(?:' . '\\[(?!\\/\\2\\])',
941 // Not an opening bracket
942 '[^\\[]*+',
943 // Closing shortcode tag
944 ')*+' . ')' . '\\[\\/\\2\\]',
945 // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
946 ')?' . ')' . '(\\]?)',
947 );
948
949 return implode( '', $regex_pieces );
950 }
951
952 /**
953 * @param $code
954 * @param $base
955 * @param $template
956 * @param $pod
957 *
958 * @return string
959 */
960 function frontier_end_template( $code, $base, $template, $pod ) {
961
962 global $template_post_blocks;
963
964 if ( ! empty( $template_post_blocks['before'][ $pod->pod ] ) ) {
965 $code = $template_post_blocks['before'][ $pod->pod ] . $code;
966
967 unset( $template_post_blocks['before'][ $pod->pod ] );
968 }
969
970 if ( ! empty( $template_post_blocks['after'][ $pod->pod ] ) ) {
971 $code .= $template_post_blocks['after'][ $pod->pod ];
972
973 unset( $template_post_blocks['after'][ $pod->pod ] );
974 }
975
976 return pods_do_shortcode( $code, frontier_get_shortcodes() );
977 }
978