PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.3.2
Pods – Custom Content Types and Fields v3.3.2
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 years ago element-pod_reference-content.php 1 year ago element-pod_reference.php 2 years ago element-view_template.php 1 year ago functions-pod_reference.php 2 years ago functions-view_template.php 11 months ago
functions-view_template.php
983 lines
1 <?php
2 /**
3 * Utility function for processesing frontier 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 = $attributes['value'] ? substr( (string) $attributes['value'], 0, 1 ) : null;
174
175 // check if + or - are present
176 if ( '+' === $first_character ) {
177 // is greater
178 $attributes['value'] = (float) substr( (string) $attributes['value'], 1 ) + 1;
179 $attributes['compare'] = '>';
180 } elseif ( '-' === $first_character ) {
181 // is smaller
182 $attributes['value'] = (float) substr( (string) $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 if ( ! is_object( $entry ) ) {
551 continue;
552 }
553
554 $subatts = array(
555 'id' => $entry->id,
556 'pod' => $entry->pod,
557 'index' => $key,
558 );
559
560 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
561
562 $template = str_replace( '{_key}', $key, $template );
563 $template = str_replace( '{@_key}', $key, $template );
564 $template = str_replace( '{_index}', $key, $template );
565 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
566
567 $out .= pods_do_shortcode( $entry->do_magic_tags( $template ), frontier_get_shortcodes() );
568 }
569 } else {
570 $template = frontier_decode_template( $content, $atts );
571
572 // Relationship to something other than a Pod (ie: user)
573 foreach ( $entries as $key => $entry ) {
574 $template = frontier_decode_template( $content, $atts );
575
576 $template = str_replace( '{_key}', '{@_index}', $template );
577 $template = str_replace( '{@_key}', '{@_index}', $template );
578 $template = str_replace( '{_index}', '{@_index}', $template );
579
580 if ( ! is_array( $entry ) ) {
581 $entry = array(
582 '_index' => $key,
583 '_value' => $entry,
584 );
585 }
586
587 $out .= pods_do_shortcode( frontier_pseudo_magic_tags( $template, $entry, $pod ), frontier_get_shortcodes() );
588 }
589 }//end if
590 }//end if
591
592 return pods_do_shortcode( $out, frontier_get_shortcodes() );
593 }
594
595 /**
596 * Search and replace like Pods magic tags but with an array of data instead of a Pod
597 *
598 * @param Pod $pod
599 * @param string $template
600 * @param array $data
601 * @param boolean $skip_unknown If true then values not in $data will not be touched
602 *
603 * @return string
604 * @since 2.7.0
605 */
606 function frontier_pseudo_magic_tags( $template, $data, $pod = null, $skip_unknown = false ) {
607 return preg_replace_callback(
608 '/({@(.*?)})/m', function ( $tag ) use ( $pod, $data, $skip_unknown ) {
609
610 // This is essentially Pods->process_magic_tags() but with the Pods specific code ripped out
611 if ( is_array( $tag ) ) {
612 if ( ! isset( $tag[2] ) && strlen( trim( $tag[2] ) ) < 1 ) {
613 return '';
614 }
615
616 $original_tag = $tag[0];
617 $tag = $tag[2];
618 }
619
620 $tag = trim( $tag, ' {@}' );
621 $tag = explode( ',', $tag );
622
623 if ( empty( $tag ) || ! isset( $tag[0] ) || strlen( trim( $tag[0] ) ) < 1 ) {
624 return '';
625 }
626
627 foreach ( $tag as $k => $v ) {
628 $tag[ $k ] = trim( $v );
629 }
630
631 $field_name = $tag[0];
632
633 $helper_name = '';
634 $before = '';
635 $after = '';
636
637 if ( isset( $data[ $field_name ] ) ) {
638 $value = $data[ $field_name ];
639 if ( isset( $tag[1] ) && ! empty( $tag[1] ) ) {
640 $helper_name = $tag[1];
641
642 if ( isset( $pod ) ) {
643 $value = $pod->helper( $helper_name, $value, $field_name );
644 }
645 }
646 } else {
647 if ( $skip_unknown ) {
648 return $original_tag;
649 }
650 $value = '';
651 }
652
653 if ( isset( $tag[2] ) && ! empty( $tag[2] ) ) {
654 $before = $tag[2];
655 }
656
657 if ( isset( $tag[3] ) && ! empty( $tag[3] ) ) {
658 $after = $tag[3];
659 }
660
661 $value = apply_filters( 'pods_do_magic_tags', $value, $field_name, $helper_name, $before, $after );
662
663 if ( is_array( $value ) ) {
664 $value = pods_serial_comma(
665 $value, array(
666 'field' => $field_name,
667 'fields' => $pod->fields,
668 )
669 );
670 }
671
672 if ( null !== $value && false !== $value ) {
673 return $before . $value . $after;
674 }
675
676 return '';
677 }, $template
678 );
679 }
680
681 /**
682 * processes template code within an each command from the base template
683 *
684 * @param string|null $code The code to filter.
685 * @param string $template The template to be processed.
686 * @param Pods $pod The Pods object.
687 *
688 * @return null
689 * @since 2.4.0
690 */
691 function frontier_prefilter_template( $code, $template, $pod ) {
692 $code = (string) $code;
693
694 global $frontier_once_tags;
695
696 $commands = array(
697 'each' => 'pod_sub_template',
698 'once' => 'pod_once_template',
699 'before' => 'pod_before_template',
700 'after' => 'pod_after_template',
701 'if' => 'pod_if_field',
702 );
703
704 if ( ! shortcode_exists( 'pod_sub_template' ) ) {
705 add_shortcode( 'pod_sub_template', 'frontier_do_subtemplate' );
706 }
707
708 $commands = array_merge( $commands, get_option( 'pods_frontier_extra_commands', array() ) );
709
710 /**
711 * Add additional control blocks to Pods templates
712 *
713 * Can also be use to remove each/once/before/after/if functionality from Pods Templates
714 *
715 * @param array $commands The control blocks in the form of 'tag' => 'shortcode'
716 *
717 * @return array An array of control blocks, and shortcodes used to power them.
718 *
719 * @since 1.0.0
720 */
721 $commands = apply_filters( 'pods_frontier_template_commands', $commands );
722
723 $aliases = array();
724 foreach ( $commands as $command => $shortcode ) {
725 //preg_match_all( '/(\[' . $command . '(?<attributes>.*?)]|\[\/' . $command . '\])/m', $code, $matches );
726 preg_match_all( '/('
727 . '\[' . preg_quote( $command, '/' ) . '\s*'
728 . '(?<field_attr>field="(?<field>[^"]*)")*' . '\s*'
729 . '(?<value_attr>value="(?<value>[^"]*)")*' . '\s*'
730 . '(?<compare_attr>compare="(?<compare>[^"]*)")*' . '\s*'
731 . '(?<other_attributes>[^\]]*)'
732 . ']|\[\/' . preg_quote( $command, '/' ) . '\]'
733 . ')/m', $code, $matches );
734
735 if ( ! empty( $matches[0] ) ) {
736 // holder for found tags.
737 $tags = array();
738 $indexCount = 0;
739 foreach ( $matches[0] as $key => $tag ) {
740 if ( false !== strpos( $tag, '[/' ) ) {
741 // close tag
742 $indexCount --;
743 $newclose = $tags[ $indexCount ];
744 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[/' . $newclose . ']', $code, 1 );
745
746 continue;
747 }//end if
748
749 // Handle open tags.
750
751 $field = null;
752 $value = null;
753 $compare = null;
754
755 $pod_name = '{@pod}';
756 $ID = '{@EntryID}';
757
758 if ( '' !== $matches['field_attr'][ $key ] ) {
759 $field = $matches['field'][ $key ];
760
761 if ( '' !== $matches['value_attr'][ $key ] ) {
762 $value = $matches['value'][ $key ];
763 }
764
765 if ( '' !== $matches['compare_attr'][ $key ] ) {
766 $compare = $matches['compare'][ $key ];
767 }
768 } elseif ( '' !== $matches['other_attributes'][ $key ] ) {
769 // get atts if any
770 // $atts = shortcode_parse_atts(str_replace('.', '____', $matches[2][$key]));
771 $pattern = '/(?<field>[\w\.\_\-]+)\s*=\s*"(?<value>[^"]*)"(?:\s|$)/';
772 $field = trim( $matches['other_attributes'][ $key ] );
773 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $field );
774
775 if ( preg_match_all( $pattern, $text, $field_value_match, PREG_SET_ORDER ) ) {
776 $field = $field_value_match[0]['field'];
777 $value = $field_value_match[0]['value'];
778 }
779 }//end if
780
781 if ( $field && false !== strpos( $field, '.' ) ) {
782 // Take the last element off of the array and use the ID.
783 $field_path = explode( '.', $field );
784 $last_field = array_pop( $field_path );
785 $field_path = implode( '.', $field_path );
786
787 $related_field = $pod->pod_data->get_field( $field_path );
788
789 if ( $related_field instanceof Field && 1 === $related_field->get_limit() ) {
790 $related_pod = $related_field->get_related_object();
791
792 if ( $related_pod instanceof Pod ) {
793 $table_field_id = $related_pod->get_arg( 'field_id' );
794
795 if ( $table_field_id ) {
796 // Use the other pod.
797 $pod_name = $related_pod->get_name();
798
799 // Rebuild the ID used for the lookup.
800 $ID = '{@' . $field_path . '.' . $table_field_id . '}';
801
802 // Override the field to use.
803 $field = $last_field;
804 }
805 }
806 }
807 }
808
809 $atts = ' pod="' . esc_attr( $pod_name ) . '"';
810 $atts .= ' id="' . esc_attr( $ID ) . '"';
811
812 if ( $field ) {
813 $atts .= ' field="' . esc_attr( $field ) . '"';
814 }
815
816 if ( null !== $value ) {
817 $atts .= ' value="' . esc_attr( $value ) . '"';
818 }
819
820 if ( null !== $compare ) {
821 $atts .= ' compare="' . esc_attr( $compare ) . '"';
822 }
823
824 $newtag = $shortcode . '__' . $key;
825 $tags[ $indexCount ] = $newtag;
826 $aliases[] = $newtag;
827
828 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[' . $newtag . $atts . ' index="{_index}"]', $code, 1 );
829
830 $indexCount ++;
831 }//end foreach
832 }//end if
833 }//end foreach
834 // get new aliased shortcodes
835 if ( ! empty( $aliases ) ) {
836 $code = frontier_backtrack_template( $code, $aliases );
837 }
838 $code = str_replace( '{@pod}', $pod->pod, $code );
839 $code = str_replace( '{@EntryID}', '{@' . $pod->pod_data['field_id'] . '}', $code );
840
841 return $code;
842 }
843
844 /**
845 * @param $code
846 * @param $aliases
847 *
848 * @return mixed
849 */
850 function frontier_backtrack_template( $code, $aliases ) {
851
852 $regex = frontier_get_regex( $aliases );
853 preg_match_all( '/' . $regex . '/s', $code, $used );
854
855 if ( ! empty( $used[2] ) ) {
856 foreach ( $used[2] as $key => $alias ) {
857 $shortcodes = explode( '__', $alias );
858 $content = $used[5][ $key ];
859 $atts = shortcode_parse_atts( $used[3][ $key ] );
860
861 $new_shortcode_name = $shortcodes[0];
862
863 $new_shortcode_atts_data = [
864 'seq' => $shortcodes[1],
865 ];
866
867 if ( ! empty( $atts ) ) {
868 if ( ! empty( $atts['field'] ) && false !== strpos( $atts['field'], '.' ) ) {
869 $content = str_replace( $atts['field'] . '.', '', $content );
870 }
871
872 preg_match_all( '/' . $regex . '/s', $content, $subused );
873
874 if ( ! empty( $subused[2] ) ) {
875 $content = frontier_backtrack_template( $content, $aliases );
876 }
877
878 $new_shortcode_atts_data[] = trim( $used[3][ $key ] );
879 }
880
881 $new_shortcode_atts = '';
882
883 foreach ( $new_shortcode_atts_data as $new_shortcode_att_key => $new_shortcode_att_data ) {
884 if ( is_int( $new_shortcode_att_key ) ) {
885 $new_shortcode_atts .= ' ' . $new_shortcode_att_data;
886 } else {
887 $new_shortcode_atts .= ' ' . $new_shortcode_att_key . '="' . esc_attr( $new_shortcode_att_data ) . '"';
888 }
889 }
890
891 // Build the new shortcode.
892 $new_shortcode = sprintf(
893 '[%1$s %2$s]%3$s[/%1$s]',
894 $new_shortcode_name,
895 $new_shortcode_atts,
896 base64_encode( $content )
897 );
898
899 $code = str_replace( $used[0][ $key ], $new_shortcode, $code );
900 }
901 }//end if
902
903 return $code;
904 }
905
906 /**
907 * @param $codes
908 *
909 * @return string
910 */
911 function frontier_get_regex( $codes ) {
912
913 // A custom version of the shortcode regex as to only use podsfrontier codes.
914 // this makes it easier to cycle through and get the used codes for inclusion
915 $validcodes = join( '|', array_map( 'preg_quote', $codes ) );
916
917 $regex_pieces = array(
918 // Opening bracket
919 '\\[',
920 // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
921 '(\\[?)',
922 // 2: selected codes only
923 "($validcodes)",
924 // Word boundary
925 '\\b',
926 // 3: Unroll the loop: Inside the opening shortcode tag
927 '(',
928 // Not a closing bracket or forward slash
929 '[^\\]\\/]*',
930 // A forward slash not followed by a closing bracket
931 '(?:' . '\\/(?!\\])',
932 // Not a closing bracket or forward slash
933 '[^\\]\\/]*',
934 // 4: Self closing tag ...
935 ')*?' . ')' . '(?:' . '(\\/)',
936 // ... and closing bracket
937 '\\]',
938 // Closing bracket
939 '|' . '\\]',
940 // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
941 '(?:' . '(',
942 // Not an opening bracket
943 '[^\\[]*+',
944 // An opening bracket not followed by the closing shortcode tag
945 '(?:' . '\\[(?!\\/\\2\\])',
946 // Not an opening bracket
947 '[^\\[]*+',
948 // Closing shortcode tag
949 ')*+' . ')' . '\\[\\/\\2\\]',
950 // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
951 ')?' . ')' . '(\\]?)',
952 );
953
954 return implode( '', $regex_pieces );
955 }
956
957 /**
958 * @param $code
959 * @param $base
960 * @param $template
961 * @param $pod
962 *
963 * @return string
964 */
965 function frontier_end_template( $code, $base, $template, $pod ) {
966
967 global $template_post_blocks;
968
969 if ( ! empty( $template_post_blocks['before'][ $pod->pod ] ) ) {
970 $code = $template_post_blocks['before'][ $pod->pod ] . $code;
971
972 unset( $template_post_blocks['before'][ $pod->pod ] );
973 }
974
975 if ( ! empty( $template_post_blocks['after'][ $pod->pod ] ) ) {
976 $code .= $template_post_blocks['after'][ $pod->pod ];
977
978 unset( $template_post_blocks['after'][ $pod->pod ] );
979 }
980
981 return pods_do_shortcode( $code, frontier_get_shortcodes() );
982 }
983