PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.8.23.4
Pods – Custom Content Types and Fields v2.8.23.4
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 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 3 weeks ago element-pod_reference.php 3 weeks ago element-view_template.php 3 weeks ago functions-pod_reference.php 3 weeks ago functions-view_template.php 3 weeks ago
functions-view_template.php
910 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
412 $out = null;
413 $field_name = $atts['field'];
414
415 $pod = Pods_Templates::get_obj( $atts['pod'], $atts['id'] );
416
417 if ( ! $pod || ! $pod->exists() ) {
418 return '';
419 }
420
421 $entries = $pod->field( $field_name );
422
423 $field = $pod->fields( $field_name );
424
425 if ( ! empty( $entries ) && $field ) {
426 $entries = (array) $entries;
427
428 // Force array even for single items since the logic below is using loops.
429 if ( 'single' === pods_v( $field['type'] . '_format_type', $field, 'single' ) && ! isset( $entries[0] ) ) {
430 $entries = array( $entries );
431 }
432
433 // Object types that could be Pods
434 $object_types = array( 'post_type', 'pod' );
435
436 /**
437 * Note on the change below for issue #3018:
438 * ... || 'taxonomy' == $pod->fields[ $atts[ 'field' ] ][ 'type' ]
439 *
440 * calling field() above for a taxonomy object field will populate
441 * $pod->fields[ $field_name ] for the object field's data, in this
442 * case a taxonomy object field. Without calling
443 * $pod->field( $field_name ), it would not normally be available in
444 * the $pod->fields array and is something to not expect to be there in
445 * 3.0 as this was unintentional.
446 */
447 if ( 'taxonomy' === $field['type'] || in_array( $field['pick_object'], $object_types, true ) ) {
448 // Match any Pod object or taxonomy
449 foreach ( $entries as $key => $entry ) {
450 $subpod = pods( $field['pick_val'] );
451
452 if ( ! $subpod || ! $subpod->valid() ) {
453 continue;
454 }
455
456 $subatts = array(
457 'id' => $entry[ $subpod->pod_data['field_id'] ],
458 'pod' => $field['pick_val'],
459 );
460
461 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
462 $template = str_replace( '{_index}', $key, $template );
463 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
464
465 // Kludge to work with taxonomies, pending a better solution: see issue #3018
466 $target_id = null;
467 if ( isset( $entry['ID'] ) ) {
468 $target_id = $entry['ID'];
469 } elseif ( isset( $entry['id'] ) ) {
470 // Advanced Content Types have lowercase 'id'
471 $target_id = $entry['id'];
472 } elseif ( isset( $entry['term_id'] ) ) {
473 $target_id = $entry['term_id'];
474 }
475
476 $out .= pods_shortcode_run_safely(
477 array(
478 'name' => $field['pick_val'],
479 'slug' => $target_id,
480 'index' => $key,
481 ),
482 $template,
483 false
484 );
485
486 }//end foreach
487 } elseif ( 'file' === $field['type'] ) {
488 $template = frontier_decode_template( $content, $atts );
489 $media_pod = pods( 'media' );
490
491 foreach ( $entries as $key => $entry ) {
492 $content = str_replace( '{_index}', $key, $template );
493
494 if ( $media_pod && $media_pod->valid() && $media_pod->fetch( $entry['ID'] ) ) {
495 $content = str_replace( '{@' . $field_name . '.', '{@', $content );
496
497 $entry_pod = $media_pod;
498 } else {
499 $content = str_replace( '{@_img', '{@image_attachment.' . $entry['ID'], $content );
500 $content = str_replace( '{@_src', '{@image_attachment_url.' . $entry['ID'], $content );
501 $content = str_replace( '{@' . $field_name . '}', '{@image_attachment.' . $entry['ID'] . '}', $content );
502
503 // Fix for lowercase ID's.
504 $entry['id'] = $entry['ID'];
505
506 // Allow array-like tags.
507 $content = frontier_pseudo_magic_tags( $content, $entry, $pod, true );
508
509 // Fallback to parent Pod so above tags still work.
510 $entry_pod = $pod;
511 }
512
513 $out .= pods_do_shortcode( $entry_pod->do_magic_tags( $content ), frontier_get_shortcodes() );
514 }
515 } elseif ( isset( $field['table_info'], $field['table_info']['pod'] ) ) {
516 // Relationship to something that is extended by Pods
517 $entries = $pod->field( array( 'name' => $field_name, 'output' => 'pod' ) );
518 foreach ( $entries as $key => $entry ) {
519 $subatts = array(
520 'id' => $entry->id,
521 'pod' => $entry->pod,
522 );
523
524 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
525 $template = str_replace( '{_index}', $key, $template );
526 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
527
528 $out .= pods_do_shortcode( $entry->do_magic_tags( $template ), frontier_get_shortcodes() );
529 }
530 } else {
531 // Relationship to something other than a Pod (ie: user)
532 foreach ( $entries as $key => $entry ) {
533 $template = frontier_decode_template( $content, $atts );
534 $template = str_replace( '{_index}', $key, $template );
535 if ( ! is_array( $entry ) ) {
536 $entry = array(
537 '_key' => $key,
538 '_value' => $entry,
539 );
540 }
541 $out .= pods_do_shortcode( frontier_pseudo_magic_tags( $template, $entry, $pod ), frontier_get_shortcodes() );
542 }
543 }//end if
544 }//end if
545
546 return pods_do_shortcode( $out, frontier_get_shortcodes() );
547 }
548
549 /**
550 * Search and replace like Pods magic tags but with an array of data instead of a Pod
551 *
552 * @param Pod $pod
553 * @param string $template
554 * @param array $data
555 * @param boolean $skip_unknown If true then values not in $data will not be touched
556 *
557 * @return string
558 * @since 2.7.0
559 */
560 function frontier_pseudo_magic_tags( $template, $data, $pod = null, $skip_unknown = false ) {
561
562 return preg_replace_callback(
563 '/({@(.*?)})/m', function ( $tag ) use ( $pod, $data, $skip_unknown ) {
564
565 // This is essentially Pods->process_magic_tags() but with the Pods specific code ripped out
566 if ( is_array( $tag ) ) {
567 if ( ! isset( $tag[2] ) && strlen( trim( $tag[2] ) ) < 1 ) {
568 return '';
569 }
570
571 $original_tag = $tag[0];
572 $tag = $tag[2];
573 }
574
575 $tag = trim( $tag, ' {@}' );
576 $tag = explode( ',', $tag );
577
578 if ( empty( $tag ) || ! isset( $tag[0] ) || strlen( trim( $tag[0] ) ) < 1 ) {
579 return '';
580 }
581
582 foreach ( $tag as $k => $v ) {
583 $tag[ $k ] = trim( $v );
584 }
585
586 $field_name = $tag[0];
587
588 $helper_name = '';
589 $before = '';
590 $after = '';
591
592 if ( isset( $data[ $field_name ] ) ) {
593 $value = $data[ $field_name ];
594 if ( isset( $tag[1] ) && ! empty( $tag[1] ) ) {
595 $helper_name = $tag[1];
596
597 if ( isset( $pod ) ) {
598 $value = $pod->helper( $helper_name, $value, $field_name );
599 }
600 }
601 } else {
602 if ( $skip_unknown ) {
603 return $original_tag;
604 }
605 $value = '';
606 }
607
608 if ( isset( $tag[2] ) && ! empty( $tag[2] ) ) {
609 $before = $tag[2];
610 }
611
612 if ( isset( $tag[3] ) && ! empty( $tag[3] ) ) {
613 $after = $tag[3];
614 }
615
616 $value = apply_filters( 'pods_do_magic_tags', $value, $field_name, $helper_name, $before, $after );
617
618 if ( is_array( $value ) ) {
619 $value = pods_serial_comma(
620 $value, array(
621 'field' => $field_name,
622 'fields' => $this->fields,
623 )
624 );
625 }
626
627 if ( null !== $value && false !== $value ) {
628 return $before . $value . $after;
629 }
630
631 return '';
632 }, $template
633 );
634 }
635
636 /**
637 * processes template code within an each command from the base template
638 *
639 * @param array $code The code to filter.
640 * @param string $template The template to be processed.
641 * @param Pods $pod The Pods object.
642 *
643 * @return null
644 * @since 2.4.0
645 */
646 function frontier_prefilter_template( $code, $template, $pod ) {
647
648 global $frontier_once_tags;
649
650 $commands = array(
651 'each' => 'pod_sub_template',
652 'once' => 'pod_once_template',
653 'before' => 'pod_before_template',
654 'after' => 'pod_after_template',
655 'if' => 'pod_if_field',
656 );
657
658 if ( ! shortcode_exists( 'pod_sub_template' ) ) {
659 add_shortcode( 'pod_sub_template', 'frontier_do_subtemplate' );
660 }
661
662 $commands = array_merge( $commands, get_option( 'pods_frontier_extra_commands', array() ) );
663
664 /**
665 * Add additional control blocks to Pods templates
666 *
667 * Can also be use to remove each/once/before/after/if functionality from Pods Templates
668 *
669 * @param array $commands The control blocks in the form of 'tag' => 'shortcode'
670 *
671 * @return array An array of control blocks, and shortcodes used to power them.
672 *
673 * @since 1.0.0
674 */
675 $commands = apply_filters( 'pods_frontier_template_commands', $commands );
676
677 $aliases = array();
678 foreach ( $commands as $command => $shortcode ) {
679 //preg_match_all( '/(\[' . $command . '(?<attributes>.*?)]|\[\/' . $command . '\])/m', $code, $matches );
680 preg_match_all( '/('
681 . '\[' . preg_quote( $command, '/' ) . '\s*'
682 . '(?<field_attr>field="(?<field>[^"]*)")*' . '\s*'
683 . '(?<value_attr>value="(?<value>[^"]*)")*' . '\s*'
684 . '(?<compare_attr>compare="(?<compare>[^"]*)")*' . '\s*'
685 . '(?<other_attributes>[^\]]*)'
686 . ']|\[\/' . preg_quote( $command, '/' ) . '\]'
687 . ')/m', $code, $matches );
688
689 if ( ! empty( $matches[0] ) ) {
690 // holder for found tags.
691 $tags = array();
692 $indexCount = 0;
693 foreach ( $matches[0] as $key => $tag ) {
694 if ( false !== strpos( $tag, '[/' ) ) {
695 // close tag
696 $indexCount --;
697 $newclose = $tags[ $indexCount ];
698 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[/' . $newclose . ']', $code, 1 );
699
700 continue;
701 }//end if
702
703 // Handle open tags.
704
705 $field = null;
706 $value = null;
707 $compare = null;
708
709 $pod_name = '{@pod}';
710 $ID = '{@EntryID}';
711
712 if ( '' !== $matches['field_attr'][ $key ] ) {
713 $field = $matches['field'][ $key ];
714
715 if ( '' !== $matches['value_attr'][ $key ] ) {
716 $value = $matches['value'][ $key ];
717 }
718
719 if ( '' !== $matches['compare_attr'][ $key ] ) {
720 $compare = $matches['compare'][ $key ];
721 }
722 } elseif ( '' !== $matches['other_attributes'][ $key ] ) {
723 // get atts if any
724 // $atts = shortcode_parse_atts(str_replace('.', '____', $matches[2][$key]));
725 $pattern = '/(?<field>[\w\.\_\-]+)\s*=\s*"(?<value>[^"]*)"(?:\s|$)/';
726 $field = trim( $matches['other_attributes'][ $key ] );
727 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $field );
728
729 if ( preg_match_all( $pattern, $text, $field_value_match, PREG_SET_ORDER ) ) {
730 $field = $field_value_match[0]['field'];
731 $value = $field_value_match[0]['value'];
732 }
733 }//end if
734
735 if ( $field && false !== strpos( $field, '.' ) ) {
736 // Take the last element off of the array and use the ID.
737 $field_path = explode( '.', $field );
738 $last_field = array_pop( $field_path );
739 $field_path = implode( '.', $field_path );
740
741 $related_field = $pod->pod_data->get_field( $field_path );
742
743 if ( $related_field instanceof Field && 1 === $related_field->get_limit() ) {
744 $related_pod = $related_field->get_related_object();
745
746 if ( $related_pod instanceof Pod ) {
747 $table_field_id = $related_pod->get_arg( 'field_id' );
748
749 if ( $table_field_id ) {
750 // Use the other pod.
751 $pod_name = $related_pod->get_name();
752
753 // Rebuild the ID used for the lookup.
754 $ID = '{@' . $field_path . '.' . $table_field_id . '}';
755
756 // Override the field to use.
757 $field = $last_field;
758 }
759 }
760 }
761 }
762
763 $atts = ' pod="' . esc_attr( $pod_name ) . '"';
764 $atts .= ' id="' . esc_attr( $ID ) . '"';
765
766 if ( $field ) {
767 $atts .= ' field="' . esc_attr( $field ) . '"';
768 }
769
770 if ( null !== $value ) {
771 $atts .= ' value="' . esc_attr( $value ) . '"';
772 }
773
774 if ( null !== $compare ) {
775 $atts .= ' compare="' . esc_attr( $compare ) . '"';
776 }
777
778 $newtag = $shortcode . '__' . $key;
779 $tags[ $indexCount ] = $newtag;
780 $aliases[] = $newtag;
781
782 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[' . $newtag . $atts . ' index="{_index}"]', $code, 1 );
783
784 $indexCount ++;
785 }//end foreach
786 }//end if
787 }//end foreach
788 // get new aliased shortcodes
789 if ( ! empty( $aliases ) ) {
790 $code = frontier_backtrack_template( $code, $aliases );
791 }
792 $code = str_replace( '{@pod}', $pod->pod, $code );
793 $code = str_replace( '{@EntryID}', '{@' . $pod->pod_data['field_id'] . '}', $code );
794
795 return $code;
796 }
797
798 /**
799 * @param $code
800 * @param $aliases
801 *
802 * @return mixed
803 */
804 function frontier_backtrack_template( $code, $aliases ) {
805
806 $regex = frontier_get_regex( $aliases );
807 preg_match_all( '/' . $regex . '/s', $code, $used );
808
809 if ( ! empty( $used[2] ) ) {
810 foreach ( $used[2] as $key => $alias ) {
811 $shortcodes = explode( '__', $alias );
812 $content = $used[5][ $key ];
813 $atts = shortcode_parse_atts( $used[3][ $key ] );
814 if ( ! empty( $atts ) ) {
815 if ( ! empty( $atts['field'] ) && false !== strpos( $atts['field'], '.' ) ) {
816 $content = str_replace( $atts['field'] . '.', '', $content );
817 }
818 preg_match_all( '/' . $regex . '/s', $content, $subused );
819 if ( ! empty( $subused[2] ) ) {
820 $content = frontier_backtrack_template( $content, $aliases );
821 }
822 $codecontent = '[' . $shortcodes[0] . ' ' . trim( $used[3][ $key ] ) . ' seq="' . $shortcodes[1] . '"]' . base64_encode( $content ) . '[/' . $shortcodes[0] . ']';
823 } else {
824 $codecontent = '[' . $shortcodes[0] . ' seq="' . $shortcodes[1] . '"]' . base64_encode( $content ) . '[/' . $shortcodes[0] . ']';
825 }
826 $code = str_replace( $used[0][ $key ], $codecontent, $code );
827 }
828 }//end if
829
830 return $code;
831 }
832
833 /**
834 * @param $codes
835 *
836 * @return string
837 */
838 function frontier_get_regex( $codes ) {
839
840 // A custom version of the shortcode regex as to only use podsfrontier codes.
841 // this makes it easier to cycle through and get the used codes for inclusion
842 $validcodes = join( '|', array_map( 'preg_quote', $codes ) );
843
844 $regex_pieces = array(
845 // Opening bracket
846 '\\[',
847 // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
848 '(\\[?)',
849 // 2: selected codes only
850 "($validcodes)",
851 // Word boundary
852 '\\b',
853 // 3: Unroll the loop: Inside the opening shortcode tag
854 '(',
855 // Not a closing bracket or forward slash
856 '[^\\]\\/]*',
857 // A forward slash not followed by a closing bracket
858 '(?:' . '\\/(?!\\])',
859 // Not a closing bracket or forward slash
860 '[^\\]\\/]*',
861 // 4: Self closing tag ...
862 ')*?' . ')' . '(?:' . '(\\/)',
863 // ... and closing bracket
864 '\\]',
865 // Closing bracket
866 '|' . '\\]',
867 // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
868 '(?:' . '(',
869 // Not an opening bracket
870 '[^\\[]*+',
871 // An opening bracket not followed by the closing shortcode tag
872 '(?:' . '\\[(?!\\/\\2\\])',
873 // Not an opening bracket
874 '[^\\[]*+',
875 // Closing shortcode tag
876 ')*+' . ')' . '\\[\\/\\2\\]',
877 // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
878 ')?' . ')' . '(\\]?)',
879 );
880
881 return implode( '', $regex_pieces );
882 }
883
884 /**
885 * @param $code
886 * @param $base
887 * @param $template
888 * @param $pod
889 *
890 * @return string
891 */
892 function frontier_end_template( $code, $base, $template, $pod ) {
893
894 global $template_post_blocks;
895
896 if ( ! empty( $template_post_blocks['before'][ $pod->pod ] ) ) {
897 $code = $template_post_blocks['before'][ $pod->pod ] . $code;
898
899 unset( $template_post_blocks['before'][ $pod->pod ] );
900 }
901
902 if ( ! empty( $template_post_blocks['after'][ $pod->pod ] ) ) {
903 $code .= $template_post_blocks['after'][ $pod->pod ];
904
905 unset( $template_post_blocks['after'][ $pod->pod ] );
906 }
907
908 return pods_do_shortcode( $code, frontier_get_shortcodes() );
909 }
910