PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.7.31.4
Pods – Custom Content Types and Fields v2.7.31.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 5 days ago element-pod_reference.php 5 days ago element-view_template.php 5 days ago functions-pod_reference.php 5 days ago functions-view_template.php 5 days ago
functions-view_template.php
692 lines
1 <?php
2 /**
3 * Utility function for processesing fromtier based templates
4 *
5 * @package Pods_Frontier_Template_Editor\view_template
6 */
7
8 // add filters
9 add_filter( 'pods_templates_post_template', 'frontier_end_template', 25, 4 );
10 add_filter( 'pods_templates_do_template', 'frontier_do_shortcode', 25, 1 );
11
12 // template shortcode handlers
13 add_shortcode( 'pod_once_template', 'frontier_template_once_blocks' );
14 add_shortcode( 'pod_after_template', 'frontier_template_blocks' );
15 add_shortcode( 'pod_before_template', 'frontier_template_blocks' );
16 add_shortcode( 'pod_if_field', 'frontier_if_block' );
17
18 /**
19 * Return array of valid frontier type shortcode tags
20 *
21 * @return array
22 */
23 function frontier_get_shortcodes() {
24
25 $shortcodes = array(
26 'each',
27 'pod_sub_template',
28 'once',
29 'pod_once_template',
30 'before',
31 'pod_before_template',
32 'after',
33 'pod_after_template',
34 'if',
35 'pod_if_field',
36 );
37
38 return $shortcodes;
39 }
40
41 /**
42 * @param $content
43 *
44 * @return string
45 * @since 2.4.3
46 */
47 function frontier_do_shortcode( $content ) {
48
49 $content = pods_do_shortcode( $content, frontier_get_shortcodes() );
50
51 return $content;
52
53 }
54
55 /**
56 * decodes a like nested shortcode based template
57 *
58 * @param string encoded template to be decoded
59 * @param array attributed provided from parent
60 *
61 * @return string
62 * @since 2.4.0
63 */
64 function frontier_decode_template( $code, $atts ) {
65
66 $code = base64_decode( $code );
67 $pod = pods( $atts['pod'] );
68
69 if ( isset( $atts['pod'] ) ) {
70 $code = str_replace( '@pod', $atts['pod'], $code );
71 }
72 if ( isset( $atts['id'] ) ) {
73 $code = str_replace( '{@EntryID}', $atts['id'], $code );
74 }
75 if ( isset( $atts['index'] ) ) {
76 $code = str_replace( '{_index}', $atts['index'], $code );
77 }
78
79 return $code;
80 }
81
82 /**
83 * processes if condition within a template
84 *
85 * @param array $atts attributes from template
86 * @param string $code encoded template to be decoded
87 *
88 * @return string
89 * @since 2.4.0
90 */
91 function frontier_if_block( $atts, $code ) {
92
93 $pod = pods( $atts['pod'], $atts['id'] );
94
95 if ( ! $pod || ! $pod->valid() || ! $pod->exists() ) {
96 return '';
97 }
98
99 $code = explode( '[else]', frontier_decode_template( $code, $atts ) );
100
101 // sysvals
102 $system_values = array(
103 '_index',
104 );
105
106 // field data
107 $field_data = null;
108 $field_type = null;
109
110 if ( in_array( $atts['field'], $system_values, true ) ) {
111 switch ( $atts['field'] ) {
112 case '_index':
113 $field_data = $atts['index'];
114
115 break;
116 }
117 } else {
118 $field_data = $pod->field( $atts['field'] );
119
120 $field_type = $pod->fields( $atts['field'], 'type' );
121 }
122
123 $is_empty = true;
124
125 if ( null !== $field_data ) {
126 if ( empty( $field_type ) ) {
127 $field_type = 'text';
128 }
129
130 $is_empty = PodsForm::field_method( $field_type, 'values_are_empty', $field_data );
131 }
132
133 $output = '';
134
135 if ( ! $is_empty || isset( $atts['value'] ) ) {
136 // theres a field - let go deeper
137 if ( isset( $atts['value'] ) ) {
138
139 // check if + or - are present
140 if ( '+' === substr( $atts['value'], 0, 1 ) ) {
141 // is greater
142 $atts['value'] = (float) substr( $atts['value'], 1 ) + 1;
143
144 if ( (float) $field_data > $atts['value'] ) {
145 // is greater - set it the same to allow
146 $atts['value'] = $field_data;
147 }
148 } elseif ( substr( $atts['value'], 0, 1 ) === '-' ) {
149 // is smaller
150 $atts['value'] = (float) substr( $atts['value'], 1 ) - 1;
151
152 if ( (float) $field_data < $atts['value'] ) {
153 // is greater - set it the same to allow
154 $atts['value'] = $field_data;
155 }
156 }
157
158 if ( (string) $field_data === (string) $atts['value'] ) {
159 // IF statement true, use [IF] content as template
160 $template = $pod->do_magic_tags( $code[0] );
161 } else {
162 // No 'field' value (or value false), switch to [else] content
163 if ( isset( $code[1] ) ) {
164 // There is an [ELSE] tag
165 $template = $pod->do_magic_tags( $code[1] );
166 } else {
167 // Value did not match (and no [ELSE]), nothing should be displayed
168 $template = '';
169 }
170 }
171 } else {
172 // Field exists and is not empty, use [IF] content
173 $template = $pod->do_magic_tags( $code[0] );
174 }//end if
175 } elseif ( isset( $code[1] ) ) {
176 // No value or field is empty and there is an [ELSE] tag. Use [ELSE]
177 $template = $pod->do_magic_tags( $code[1] );
178 } else {
179 $template = '';
180 }//end if
181
182 return do_shortcode( $template );
183 }
184
185 /**
186 * processes before and after template blocks
187 *
188 * @param array attributes from template
189 * @param string encoded template to be decoded
190 * @param string shortcode slug used to process
191 *
192 * @return null
193 * @since 2.4.0
194 */
195 function frontier_template_blocks( $atts, $code, $slug ) {
196
197 global $template_post_blocks;
198 if ( ! isset( $template_post_blocks ) ) {
199 $template_post_blocks = array(
200 'before' => null,
201 'after' => null,
202 );
203 }
204 if ( $slug === 'pod_before_template' ) {
205 if ( ! isset( $template_post_blocks['before'][ $atts['pod'] ] ) ) {
206 $template_post_blocks['before'][ $atts['pod'] ] = pods_do_shortcode(
207 frontier_decode_template( $code, $atts ), array(
208 'if',
209 'else',
210 )
211 );
212 }
213 } elseif ( $slug === 'pod_after_template' ) {
214 if ( ! isset( $template_post_blocks['after'][ $atts['pod'] ] ) ) {
215 $template_post_blocks['after'][ $atts['pod'] ] = pods_do_shortcode(
216 frontier_decode_template( $code, $atts ), array(
217 'if',
218 'else',
219 )
220 );
221 }
222 }
223
224 return null;
225 }
226
227 /**
228 * processes once blocks
229 *
230 * @param array attributes from template
231 * @param string encoded template to be decoded
232 *
233 * @return string template code
234 * @since 2.4.0
235 */
236 function frontier_template_once_blocks( $atts, $code ) {
237
238 global $frontier_once_hashes;
239
240 if ( ! isset( $frontier_once_hashes ) ) {
241 $frontier_once_hashes = array();
242 }
243
244 $blockhash = md5( $code . $atts['id'] );
245 if ( in_array( $blockhash, $frontier_once_hashes, true ) ) {
246 return '';
247 }
248 $frontier_once_hashes[] = $blockhash;
249
250 return pods_do_shortcode( frontier_decode_template( $code, $atts ), frontier_get_shortcodes() );
251 }
252
253 /**
254 * processes template code within an each command from the base template
255 *
256 * @param array attributes from template
257 * @param string template to be processed
258 *
259 * @return null
260 * @since 2.4.0
261 */
262 function frontier_do_subtemplate( $atts, $content ) {
263
264 $out = null;
265 $pod = pods( $atts['pod'], $atts['id'] );
266 $field_name = $atts['field'];
267
268 $entries = $pod->field( $field_name );
269
270 if ( ! empty( $entries ) ) {
271 $entries = (array) $entries;
272
273 $field = $pod->fields[ $field_name ];
274
275 // Force array even for single items since the logic below is using loops.
276 if ( 'single' === pods_v( $field['type'] . '_format_type', $field['options'], 'single' ) && ! isset( $entries[0] ) ) {
277 $entries = array( $entries );
278 }
279
280 // Object types that could be Pods
281 $object_types = array( 'post_type', 'pod' );
282
283 /**
284 * Note on the change below for issue #3018:
285 * ... || 'taxonomy' == $pod->fields[ $atts[ 'field' ] ][ 'type' ]
286 *
287 * calling field() above for a taxonomy object field will populate
288 * $pod->fields[ $field_name ] for the object field's data, in this
289 * case a taxonomy object field. Without calling
290 * $pod->field( $field_name ), it would not normally be available in
291 * the $pod->fields array and is something to not expect to be there in
292 * 3.0 as this was unintentional.
293 */
294 if ( in_array( $field['pick_object'], $object_types, true ) || 'taxonomy' == $field['type'] ) {
295 // Match any Pod object or taxonomy
296 foreach ( $entries as $key => $entry ) {
297 $subpod = pods( $field['pick_val'] );
298
299 $subatts = array(
300 'id' => $entry[ $subpod->api->pod_data['field_id'] ],
301 'pod' => $field['pick_val'],
302 );
303
304 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
305 $template = str_replace( '{_index}', $key, $template );
306 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
307
308 // Kludge to work with taxonomies, pending a better solution: see issue #3018
309 $target_id = null;
310 if ( isset( $entry['ID'] ) ) {
311 $target_id = $entry['ID'];
312 } elseif ( isset( $entry['id'] ) ) {
313 // Advanced Content Types have lowercase 'id'
314 $target_id = $entry['id'];
315 } elseif ( isset( $entry['term_id'] ) ) {
316 $target_id = $entry['term_id'];
317 }
318
319 $out .= pods_shortcode_run_safely(
320 array(
321 'name' => $field['pick_val'],
322 'slug' => $target_id,
323 'index' => $key,
324 ),
325 $template,
326 false
327 );
328
329 }//end foreach
330 } elseif ( 'file' == $field['type'] && 'attachment' == $field['options']['file_uploader'] ) {
331 $template = frontier_decode_template( $content, $atts );
332 $media_pod = pods( 'media' );
333
334 foreach ( $entries as $key => $entry ) {
335 $content = str_replace( '{_index}', $key, $template );
336 $content = str_replace( '{@_img', '{@image_attachment.' . $entry['ID'], $content );
337 $content = str_replace( '{@_src', '{@image_attachment_url.' . $entry['ID'], $content );
338 $content = str_replace( '{@' . $field_name . '}', '{@image_attachment.' . $entry['ID'] . '}', $content );
339
340 if ( $media_pod && $media_pod->valid() && $media_pod->fetch( $entry['ID'] ) ) {
341 $content = str_replace( '{@' . $field_name . '.', '{@', $content );
342 $entry_pod = $media_pod;
343 } else {
344 // Fix for lowercase ID's.
345 $entry['id'] = $entry['ID'];
346 // Allow array-like tags.
347 $content = frontier_pseudo_magic_tags( $content, $entry, $pod, true );
348 // Fallback to parent Pod so above tags still work.
349 $entry_pod = $pod;
350 }
351
352 $out .= pods_do_shortcode( $entry_pod->do_magic_tags( $content ), frontier_get_shortcodes() );
353 }
354 } elseif ( isset( $field['table_info'], $field['table_info']['pod'] ) ) {
355 // Relationship to something that is extended by Pods
356 $entries = $pod->field( array( 'name' => $field_name, 'output' => 'pod' ) );
357 foreach ( $entries as $key => $entry ) {
358 $subatts = array(
359 'id' => $entry->id,
360 'pod' => $entry->pod,
361 );
362
363 $template = frontier_decode_template( $content, array_merge( $atts, $subatts ) );
364 $template = str_replace( '{_index}', $key, $template );
365 $template = str_replace( '{@' . $field_name . '.', '{@', $template );
366
367 $out .= pods_do_shortcode( $entry->do_magic_tags( $template ), frontier_get_shortcodes() );
368 }
369 } else {
370 // Relationship to something other than a Pod (ie: user)
371 foreach ( $entries as $key => $entry ) {
372 $template = frontier_decode_template( $content, $atts );
373 $template = str_replace( '{_index}', $key, $template );
374 if ( ! is_array( $entry ) ) {
375 $entry = array(
376 '_key' => $key,
377 '_value' => $entry,
378 );
379 }
380 $out .= pods_do_shortcode( frontier_pseudo_magic_tags( $template, $entry, $pod ), frontier_get_shortcodes() );
381 }
382 }//end if
383 }//end if
384
385 return pods_do_shortcode( $out, frontier_get_shortcodes() );
386 }
387
388 /**
389 * Search and replace like Pods magic tags but with an array of data instead of a Pod
390 *
391 * @param Pod $pod
392 * @param string $template
393 * @param array $data
394 * @param boolean $skip_unknown If true then values not in $data will not be touched
395 *
396 * @return string
397 * @since 2.7.0
398 */
399 function frontier_pseudo_magic_tags( $template, $data, $pod = null, $skip_unknown = false ) {
400
401 return preg_replace_callback(
402 '/({@(.*?)})/m', function ( $tag ) use ( $pod, $data, $skip_unknown ) {
403
404 // This is essentially Pods->process_magic_tags() but with the Pods specific code ripped out
405 if ( is_array( $tag ) ) {
406 if ( ! isset( $tag[2] ) && strlen( trim( $tag[2] ) ) < 1 ) {
407 return '';
408 }
409
410 $original_tag = $tag[0];
411 $tag = $tag[2];
412 }
413
414 $tag = trim( $tag, ' {@}' );
415 $tag = explode( ',', $tag );
416
417 if ( empty( $tag ) || ! isset( $tag[0] ) || strlen( trim( $tag[0] ) ) < 1 ) {
418 return '';
419 }
420
421 foreach ( $tag as $k => $v ) {
422 $tag[ $k ] = trim( $v );
423 }
424
425 $field_name = $tag[0];
426
427 $helper_name = '';
428 $before = '';
429 $after = '';
430
431 if ( isset( $data[ $field_name ] ) ) {
432 $value = $data[ $field_name ];
433 if ( isset( $tag[1] ) && ! empty( $tag[1] ) ) {
434 $helper_name = $tag[1];
435
436 if ( isset( $pod ) ) {
437 $value = $pod->helper( $helper_name, $value, $field_name );
438 }
439 }
440 } else {
441 if ( $skip_unknown ) {
442 return $original_tag;
443 }
444 $value = '';
445 }
446
447 if ( isset( $tag[2] ) && ! empty( $tag[2] ) ) {
448 $before = $tag[2];
449 }
450
451 if ( isset( $tag[3] ) && ! empty( $tag[3] ) ) {
452 $after = $tag[3];
453 }
454
455 $value = apply_filters( 'pods_do_magic_tags', $value, $field_name, $helper_name, $before, $after );
456
457 if ( is_array( $value ) ) {
458 $value = pods_serial_comma(
459 $value, array(
460 'field' => $field_name,
461 'fields' => $this->fields,
462 )
463 );
464 }
465
466 if ( null !== $value && false !== $value ) {
467 return $before . $value . $after;
468 }
469
470 return '';
471 }, $template
472 );
473 }
474
475 /**
476 * processes template code within an each command from the base template
477 *
478 * @param array attributes from template
479 * @param string template to be processed
480 *
481 * @return null
482 * @since 2.4.0
483 */
484 function frontier_prefilter_template( $code, $template, $pod ) {
485
486 global $frontier_once_tags;
487
488 $commands = array(
489 'each' => 'pod_sub_template',
490 'once' => 'pod_once_template',
491 'before' => 'pod_before_template',
492 'after' => 'pod_after_template',
493 'if' => 'pod_if_field',
494 );
495
496 if ( ! shortcode_exists( 'pod_sub_template' ) ) {
497 add_shortcode( 'pod_sub_template', 'frontier_do_subtemplate' );
498 }
499
500 $commands = array_merge( $commands, get_option( 'pods_frontier_extra_commands', array() ) );
501
502 /**
503 * Add additional control blocks to Pods templates
504 *
505 * Can also be use to remove each/once/before/after/if functionality from Pods Templates
506 *
507 * @param array $commands The control blocks in the form of 'tag' => 'shortcode'
508 *
509 * @return array An array of control blocks, and shortcodes used to power them.
510 *
511 * @since 1.0.0
512 */
513 $commands = apply_filters( 'pods_frontier_template_commands', $commands );
514
515 $aliases = array();
516 foreach ( $commands as $command => $shortcode ) {
517 preg_match_all( '/(\[' . $command . '(.*?)]|\[\/' . $command . '\])/m', $code, $matches );
518 if ( ! empty( $matches[0] ) ) {
519 // holder for found blocks.
520 $blocks = array();
521 $indexCount = 0;
522 foreach ( $matches[0] as $key => $tag ) {
523 if ( false === strpos( $tag, '[/' ) ) {
524 // open tag
525 $field = null;
526 $value = null;
527 $ID = '{@EntryID}';
528 $atts = ' pod="@pod" id="' . $ID . '"';
529 if ( ! empty( $matches[2][ $key ] ) ) {
530 // get atts if any
531 // $atts = shortcode_parse_atts(str_replace('.', '____', $matches[2][$key]));
532 $atts = array();
533 $pattern = '/(\w.+)\s*=\s*"([^"]*)"(?:\s|$)/';
534 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $matches[2][ $key ] );
535 if ( preg_match_all( $pattern, $text, $match, PREG_SET_ORDER ) ) {
536 $field = $match[0][1];
537 $value = $match[0][2];
538 } else {
539 $field = trim( $matches[2][ $key ] );
540 }
541 if ( false !== strpos( $field, '.' ) ) {
542 $path = explode( '.', $field );
543 $field = array_pop( $path );
544 $ID = '{@' . implode( '.', $path ) . '.' . $pod->api->pod_data['field_id'] . '}';
545 }
546 $atts = ' id="' . $ID . '" pod="@pod" field="' . $field . '"';
547 if ( ! empty( $value ) ) {
548 $atts .= ' value="' . $value . '"';
549 }
550 }//end if
551
552 $newtag = $shortcode . '__' . $key;
553 $tags[ $indexCount ] = $newtag;
554 $aliases[] = $newtag;
555 $code = preg_replace( '/(' . preg_quote( $tag ) . ')/m', '[' . $newtag . $atts . ' index="{_index}"]', $code, 1 );
556 $indexCount ++;
557 } else {
558 // close tag
559 $indexCount --;
560 $newclose = $tags[ $indexCount ];
561 $code = preg_replace( '/(' . preg_quote( $tag, '/' ) . ')/m', '[/' . $newclose . ']', $code, 1 );
562
563 }//end if
564 }//end foreach
565 if ( $command == 'if' ) {
566 // dump($pod);
567 }
568 }//end if
569 }//end foreach
570 // get new aliased shotcodes
571 if ( ! empty( $aliases ) ) {
572 $code = frontier_backtrack_template( $code, $aliases );
573 }
574 $code = str_replace( '@pod', $pod->pod, $code );
575 $code = str_replace( '@EntryID', '@' . $pod->api->pod_data['field_id'], $code );
576
577 return $code;
578 }
579
580 /**
581 * @param $code
582 * @param $aliases
583 *
584 * @return mixed
585 */
586 function frontier_backtrack_template( $code, $aliases ) {
587
588 $regex = frontier_get_regex( $aliases );
589 preg_match_all( '/' . $regex . '/s', $code, $used );
590
591 if ( ! empty( $used[2] ) ) {
592 foreach ( $used[2] as $key => $alias ) {
593 $shortcodes = explode( '__', $alias );
594 $content = $used[5][ $key ];
595 $atts = shortcode_parse_atts( $used[3][ $key ] );
596 if ( ! empty( $atts ) ) {
597 if ( ! empty( $atts['field'] ) && false !== strpos( $atts['field'], '.' ) ) {
598 $content = str_replace( $atts['field'] . '.', '', $content );
599 }
600 preg_match_all( '/' . $regex . '/s', $content, $subused );
601 if ( ! empty( $subused[2] ) ) {
602 $content = frontier_backtrack_template( $content, $aliases );
603 }
604 $codecontent = '[' . $shortcodes[0] . ' ' . trim( $used[3][ $key ] ) . ' seq="' . $shortcodes[1] . '"]' . base64_encode( $content ) . '[/' . $shortcodes[0] . ']';
605 } else {
606 $codecontent = '[' . $shortcodes[0] . ' seq="' . $shortcodes[1] . '"]' . base64_encode( $content ) . '[/' . $shortcodes[0] . ']';
607 }
608 $code = str_replace( $used[0][ $key ], $codecontent, $code );
609 }
610 }//end if
611
612 return $code;
613 }
614
615 /**
616 * @param $codes
617 *
618 * @return string
619 */
620 function frontier_get_regex( $codes ) {
621
622 // A custom version of the shortcode regex as to only use podsfrontier codes.
623 // this makes it easier to cycle through and get the used codes for inclusion
624 $validcodes = join( '|', array_map( 'preg_quote', $codes ) );
625
626 $regex_pieces = array(
627 // Opening bracket
628 '\\[',
629 // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
630 '(\\[?)',
631 // 2: selected codes only
632 "($validcodes)",
633 // Word boundary
634 '\\b',
635 // 3: Unroll the loop: Inside the opening shortcode tag
636 '(',
637 // Not a closing bracket or forward slash
638 '[^\\]\\/]*',
639 // A forward slash not followed by a closing bracket
640 '(?:' . '\\/(?!\\])',
641 // Not a closing bracket or forward slash
642 '[^\\]\\/]*',
643 // 4: Self closing tag ...
644 ')*?' . ')' . '(?:' . '(\\/)',
645 // ... and closing bracket
646 '\\]',
647 // Closing bracket
648 '|' . '\\]',
649 // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
650 '(?:' . '(',
651 // Not an opening bracket
652 '[^\\[]*+',
653 // An opening bracket not followed by the closing shortcode tag
654 '(?:' . '\\[(?!\\/\\2\\])',
655 // Not an opening bracket
656 '[^\\[]*+',
657 // Closing shortcode tag
658 ')*+' . ')' . '\\[\\/\\2\\]',
659 // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
660 ')?' . ')' . '(\\]?)',
661 );
662
663 return implode( '', $regex_pieces );
664 }
665
666 /**
667 * @param $code
668 * @param $base
669 * @param $template
670 * @param $pod
671 *
672 * @return string
673 */
674 function frontier_end_template( $code, $base, $template, $pod ) {
675
676 global $template_post_blocks;
677
678 if ( ! empty( $template_post_blocks['before'][ $pod->pod ] ) ) {
679 $code = $template_post_blocks['before'][ $pod->pod ] . $code;
680
681 unset( $template_post_blocks['before'][ $pod->pod ] );
682 }
683
684 if ( ! empty( $template_post_blocks['after'][ $pod->pod ] ) ) {
685 $code .= $template_post_blocks['after'][ $pod->pod ];
686
687 unset( $template_post_blocks['after'][ $pod->pod ] );
688 }
689
690 return pods_do_shortcode( $code, frontier_get_shortcodes() );
691 }
692