PluginProbe
WP Ultimate Post Grid / 4.0.1
WP Ultimate Post Grid v4.0.1
4.1.1 trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.8 1.9 2.0 2.1 2.2 2.3 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.2 3.0.0 3.3.0 3.4.0 3.5.0 3.6.0 3.7.0 All 32 releases
wp-ultimate-post-grid / includes / public / class-wpupg-grid.php

class-wpupg-grid.php in WP Ultimate Post Grid 4.0.1, at includes/public/class-wpupg-grid.php

1,167 lines 32.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Represents a grid.
4 *
5 * @link https://bootstrapped.ventures
6 * @since 3.0.0
7 *
8 * @package WP_Ultimate_Post_Grid
9 * @subpackage WP_Ultimate_Post_Grid/includes/public
10 */
11
12 /**
13 * Represents a grid.
14 *
15 * @since 3.0.0
16 * @package WP_Ultimate_Post_Grid
17 * @subpackage WP_Ultimate_Post_Grid/includes/public
18 * @author Brecht Vandersmissen <[email protected]>
19 */
20 class WPUPG_Grid {
21
22 /**
23 * WP_Post object associated with this grid post type.
24 *
25 * @since 3.0.0
26 * @access private
27 * @var object $post WP_Post object of this grid post type.
28 */
29 private $post;
30
31 /**
32 * Cached IDs to display in this grid.
33 *
34 * @since 3.0.0
35 * @access private
36 * @var array $ids Grid item IDs.
37 */
38 private $ids = false;
39
40 /**
41 * Cached total IDs to display in this grid.
42 *
43 * @since 3.3.0
44 * @access private
45 * @var array $total_ids Total number of grid ids.
46 */
47 private $total_ids = false;
48
49 /**
50 * Cached terms to display in this grid.
51 *
52 * @since 3.0.0
53 * @access private
54 * @var array $ids Terms for this grid.
55 */
56 private $terms = false;
57
58 /**
59 * Metadata associated with this grid post type.
60 *
61 * @since 3.0.0
62 * @access private
63 * @var array $meta Grid metadata.
64 */
65 private $meta = false;
66
67 /**
68 * Get new grid object from associated post.
69 *
70 * @since 3.0.0
71 * @param mixed $post Meta or WP_Post object for this grid post type.
72 */
73 public function __construct( $post_or_meta ) {
74 $post = is_object( $post_or_meta ) && $post_or_meta instanceof WP_Post ? $post_or_meta : false;
75 $this->post = $post;
76
77 // Not a WP_Post object, so just manually set the meta values.
78 if ( ! $post ) {
79 $this->meta = $post_or_meta;
80 }
81 }
82
83 /**
84 * Get grid data.
85 *
86 * @since 3.0.0
87 */
88 public function get_data() {
89 $grid = array();
90
91 // Technical Fields.
92 $grid['id'] = $this->id();
93 $grid['version'] = $this->version();
94
95 // Grid General.
96 $grid['name'] = $this->name();
97 $grid['slug'] = $this->slug();
98
99 // Grid Data Source.
100 $grid['type'] = $this->type();
101 $grid['post_types'] = $this->post_types();
102 $grid['post_status'] = $this->post_status();
103 $grid['post_status_require_permission'] = $this->post_status_require_permission();
104 $grid['taxonomies'] = $this->taxonomies();
105 $grid['password_protected'] = $this->password_protected();
106 $grid['language'] = $this->language();
107 $grid['order_by'] = $this->order_by();
108 $grid['order'] = $this->order();
109 $grid['order_custom_key'] = $this->order_custom_key();
110 $grid['order_custom_key_numeric'] = $this->order_custom_key_numeric();
111 $grid['terms_order_by'] = $this->terms_order_by();
112 $grid['terms_order'] = $this->terms_order();
113
114 // Grid Limit Items.
115 $grid['limit_posts_offset'] = $this->limit_posts_offset();
116 $grid['limit_posts_number'] = $this->limit_posts_number();
117 $grid['images_only'] = $this->images_only();
118 $grid['terms_images_only'] = $this->terms_images_only();
119 $grid['terms_hide_empty'] = $this->terms_hide_empty();
120 $grid['limit_terms'] = $this->limit_terms();
121 $grid['limit_terms_terms'] = $this->limit_terms_terms();
122 $grid['limit_terms_type'] = $this->limit_terms_type();
123 $grid['limit_posts'] = $this->limit_posts();
124 $grid['limit_rules'] = $this->limit_rules();
125
126 // Grid Filters.
127 $grid['filters'] = $this->filters();
128 $grid['filters_enabled'] = $this->filters_enabled();
129 $grid['filters_style'] = $this->filters_style();
130 $grid['filters_relation'] = $this->filters_relation();
131 $grid['filters_no_selection'] = $this->filters_no_selection();
132 $grid['responsive_toggle_style'] = $this->responsive_toggle_style();
133 $grid['responsive_toggle_style_closed'] = $this->responsive_toggle_style_closed();
134 $grid['responsive_toggle_style_open'] = $this->responsive_toggle_style_open();
135
136 // Grid Layout.
137 $grid['layout_mode'] = $this->layout_mode();
138 $grid['centered'] = $this->centered();
139 $grid['rtl_mode'] = $this->rtl_mode();
140 $grid['layout_desktop_sizing'] = $this->layout_desktop_sizing();
141 $grid['layout_desktop_sizing_fixed'] = $this->layout_desktop_sizing_fixed();
142 $grid['layout_desktop_sizing_columns'] = $this->layout_desktop_sizing_columns();
143 $grid['layout_desktop_sizing_margin'] = $this->layout_desktop_sizing_margin();
144 $grid['layout_tablet_different'] = $this->layout_tablet_different();
145 $grid['layout_tablet_sizing'] = $this->layout_tablet_sizing();
146 $grid['layout_tablet_sizing_fixed'] = $this->layout_tablet_sizing_fixed();
147 $grid['layout_tablet_sizing_columns'] = $this->layout_tablet_sizing_columns();
148 $grid['layout_tablet_sizing_margin'] = $this->layout_tablet_sizing_margin();
149 $grid['layout_mobile_different'] = $this->layout_mobile_different();
150 $grid['layout_mobile_sizing'] = $this->layout_mobile_sizing();
151 $grid['layout_mobile_sizing_fixed'] = $this->layout_mobile_sizing_fixed();
152 $grid['layout_mobile_sizing_columns'] = $this->layout_mobile_sizing_columns();
153 $grid['layout_mobile_sizing_margin'] = $this->layout_mobile_sizing_margin();
154
155 // Grid Item.
156 $grid['template'] = $this->template();
157 $grid['use_image'] = $this->use_image();
158 $grid['link'] = $this->link();
159 $grid['link_type'] = $this->link_type();
160 $grid['link_target'] = $this->link_target();
161
162 // Grid Pagination.
163 $grid['pagination_type'] = $this->pagination_type();
164 $grid['pagination'] = $this->pagination();
165
166 // Grid Other.
167 $grid['metadata'] = $this->metadata();
168 $grid['metadata_name'] = $this->metadata_name();
169 $grid['metadata_description'] = $this->metadata_description();
170 $grid['deeplinking'] = $this->deeplinking();
171 $grid['deeplinking_jump'] = $this->deeplinking_jump();
172 $grid['empty_message'] = $this->empty_message();
173
174 return $grid;
175 }
176
177 /**
178 * Get grid data for the manage page.
179 *
180 * @since 3.0.0
181 */
182 public function get_data_manage() {
183 $grid = $this->get_data();
184
185 $grid['date'] = $this->date();
186
187 return $grid;
188 }
189
190 /**
191 * Get isotope args for this grid.
192 *
193 * @since 3.0.0
194 */
195 public function get_javascript_args() {
196 $args = array();
197
198 // Arguments for grid.
199 $args['item_ids'] = $this->ids( array( 'type' => 'initial' ) );
200 $args['total_ids'] = $this->total_ids();
201 $args['order'] = array(
202 array(
203 'by' => $this->grid_order_by(),
204 'type' => $this->grid_order(),
205 ),
206 );
207 $args['link'] = $this->link() ? $this->link_target() : false;
208 $args['deeplinking'] = $this->deeplinking();
209 $args['deeplinking_jump'] = $this->deeplinking_jump();
210
211 // Arguments for Isotope JS.
212 $args['isotope'] = array(
213 'itemSelector' => '.wpupg-item',
214 'layoutMode' => $this->layout_mode(),
215 'transitionDuration' => intval( WPUPG_Settings::get( 'grid_animation_speed' ) ),
216 'stagger' => intval( WPUPG_Settings::get( 'grid_animation_stagger' ) ),
217 'hiddenStyle' => self::get_css_array( WPUPG_Settings::get( 'grid_animation_hide' ) ),
218 'visibleStyle' => self::get_css_array( WPUPG_Settings::get( 'grid_animation_show' ) ),
219 );
220
221 // RTL Mode.
222 if ( $this->rtl_mode() ) {
223 $args['isotope']['originLeft'] = false;
224 }
225
226 // Force height layout mode.
227 if ( 'fitRowsHeight' === $this->layout_mode() ) {
228 $args['isotope']['layoutMode'] = 'fitRows';
229 $args['force_height'] = true;
230 }
231
232 // CSS
233 if ( $this->can_use_centered() && $this->centered() ) {
234 $args['isotope']['masonry'] = array(
235 'isFitWidth' => true,
236 );
237 }
238
239 // Arguments for filters.
240 $args['filters_relation'] = $this->filters_relation();
241 $args['filters_no_selection'] = $this->filters_no_selection();
242 $args['filters'] = array();
243 if ( $this->filters_enabled() ) {
244 $filters = $this->filters();
245
246 foreach ( $filters as $index => $filter ) {
247 // Make sure filter ID is set.
248 if ( ! $filter['id'] ) {
249 $filter['id'] = $index + 1;
250 }
251
252 $filter_args = array(
253 'id' => $filter['id'],
254 'type' => $filter['type'],
255 );
256
257 $args['filters'][ $filter['id'] ] = apply_filters( 'wpupg_javascript_args_filter', $filter_args, $this, $filter );
258 }
259 }
260
261 // Arguments for pagination.
262 $args['pagination_type'] = $this->pagination_type();
263 $args['pagination'] = apply_filters( 'wpupg_javascript_args_pagination', false, $this );
264
265 return apply_filters( 'wpupg_javascript_args', $args, $this );
266 }
267
268 /**
269 * Get CSS array from string.
270 *
271 * @since 3.0.0
272 * @param mixed $string String to get the CSS from.
273 */
274 public function get_css_array( $string ) {
275 $css = array();
276
277 if ( $string ) {
278 $properties = explode( ';', $string );
279
280 foreach( $properties as $property ) {
281 $parts = explode( ':', $property );
282
283 if ( 2 === count( $parts ) ) {
284 $key = trim( $parts[0] );
285
286 if ( $key ) {
287 $css[ $key ] = trim( $parts[1] );
288 }
289 }
290 }
291 }
292
293 return $css;
294 }
295
296 /**
297 * Get metadata value.
298 *
299 * @since 3.0.0
300 * @param mixed $field Metadata field to retrieve.
301 * @param mixed $default Default to return if metadata is not set.
302 */
303 public function meta( $field, $default = '' ) {
304 $value = $default;
305
306 if ( false === $this->post ) {
307 if ( isset( $this->meta[ $field ] ) ) {
308 $value = $this->meta[ $field ];
309 }
310 } else {
311 // Use prefix when stored in actual meta.
312 $stored_field = 'wpupg_' . $field;
313
314 if ( ! $this->meta ) {
315 $this->meta = get_post_custom( $this->id() );
316 }
317
318 if ( isset( $this->meta[ $stored_field ] ) && null !== $this->meta[ $stored_field ][0] ) {
319 $value = $this->meta[ $stored_field ][0];
320 }
321 }
322
323 // Allow filtering of the value.
324 $value = apply_filters( 'wpupg_grid_meta_field_' . sanitize_key( $field ), $value, $this );
325
326 return $value;
327 }
328
329 /**
330 * Try to unserialize as best as possible.
331 *
332 * @since 3.0.0
333 * @param mixed $maybe_serialized Potentially serialized data.
334 */
335 public function unserialize( $maybe_serialized ) {
336 $unserialized = @maybe_unserialize( $maybe_serialized );
337
338 if ( false === $unserialized ) {
339 $maybe_serialized = preg_replace('/\s+/', ' ', $maybe_serialized );
340 $unserialized = unserialize( preg_replace_callback( '!s:(\d+):"(.*?)";!', array( $this, 'regex_replace_serialize' ), $maybe_serialized ) );
341 }
342
343 return $unserialized;
344 }
345
346 /**
347 * Callback for regex to fix serialize issues.
348 *
349 * @since 3.0.0
350 * @param mixed $match Regex match.
351 */
352 public function regex_replace_serialize( $match ) {
353 return ( $match[1] == strlen( $match[2] ) ) ? $match[0] : 's:' . strlen( $match[2] ) . ':"' . $match[2] . '";';
354 }
355
356 /**
357 * Grid Technical Fields.
358 */
359 public function id() {
360 return $this->post ? $this->post->ID : $this->meta( 'id' );
361 }
362 public function slug_or_id() {
363 $slug = $this->slug();
364
365 if ( ! $slug ) {
366 $slug = $this->id();
367 }
368
369 return $slug;
370 }
371 public function date() {
372 return $this->post ? $this->post->post_date : $this->meta( 'date' );
373 }
374 public function version() {
375 return $this->meta( 'version', '0.0.0' );
376 }
377
378 /**
379 * Grid General Fields.
380 */
381 public function name() {
382 return $this->post ? $this->post->post_title : $this->meta( 'name' );
383 }
384 public function slug() {
385 return $this->post ? $this->post->post_name : $this->meta( 'slug' );
386 }
387 /**
388 * Grid Data Source Fields.
389 */
390 public function type() {
391 return $this->meta( 'type', 'posts' );
392 }
393 public function post_types() {
394 return $this->unserialize( $this->meta( 'post_types', array( 'post' ) ) );
395 }
396 public function post_status() {
397 $post_status = $this->unserialize( $this->meta( 'post_status', array( 'publish' ) ) );
398
399 if ( in_array( 'attachment', $this->post_types() ) ) {
400 $post_status[] = 'inherit';
401 }
402
403 return $post_status;
404 }
405 public function post_status_require_permission() {
406 $bool = $this->meta( 'post_status_require_permission', true );
407 return (bool) $bool;
408 }
409 public function taxonomies() {
410 return $this->unserialize( $this->meta( 'taxonomies', array( 'category' ) ) );
411 }
412 public function password_protected() {
413 return $this->meta( 'password_protected', 'all' );
414 }
415 public function language() {
416 return $this->meta( 'language', false );
417 }
418 public function order_by() {
419 return $this->meta( 'order_by', 'date' );
420 }
421 public function order() {
422 $order = $this->meta( 'order', 'desc' );
423
424 if ( 'rand' === $this->order_by() ) {
425 // Adaptive pages break if order is not set to ASC when order_by is set to random.
426 $order = 'asc';
427 }
428
429 return $order;
430 }
431 public function order_custom_key() {
432 return $this->meta( 'order_custom_key', '' );
433 }
434 public function order_custom_key_numeric() {
435 $bool = $this->meta( 'order_custom_key_numeric', false );
436 return (bool) $bool;
437 }
438 public function terms_order_by() {
439 return $this->meta( 'terms_order_by', 'name' );
440 }
441 public function terms_order() {
442 return $this->meta( 'terms_order', 'asc' );
443 }
444 public function grid_order_by() {
445 if ( 'posts' === $this->type() ) {
446 return $this->order_by();
447 } else {
448 return $this->terms_order_by();
449 }
450 }
451 public function grid_order() {
452 if ( 'posts' === $this->type() ) {
453 return $this->order();
454 } else {
455 return $this->terms_order();
456 }
457 }
458 /**
459 * Grid Limit Items Fields.
460 */
461 public function limit_posts_offset() {
462 return $this->meta( 'limit_posts_offset', 0 );
463 }
464 public function limit_posts_number() {
465 return $this->meta( 'limit_posts_number', 0 );
466 }
467 public function images_only() {
468 $bool = $this->meta( 'images_only', false );
469 return (bool) $bool;
470 }
471 public function terms_images_only() {
472 $bool = $this->meta( 'terms_images_only', false );
473 return (bool) $bool;
474 }
475 public function terms_hide_empty() {
476 $bool = $this->meta( 'terms_hide_empty', false );
477 return (bool) $bool;
478 }
479 public function limit_terms() {
480 $bool = $this->meta( 'limit_terms', false );
481 return (bool) $bool;
482 }
483 public function limit_terms_terms() {
484 return $this->unserialize( $this->meta( 'limit_terms_terms', array() ) );
485 }
486 public function limit_terms_type() {
487 return $this->meta( 'limit_terms_type', 'restrict' );
488 }
489 public function limit_posts() {
490 $bool = $this->meta( 'limit_posts', false );
491 return (bool) $bool;
492 }
493 public function limit_rules() {
494 return $this->unserialize( $this->meta( 'limit_rules', array() ) );
495 }
496
497 /**
498 * Grid Filters Fields.
499 */
500 public function filter( $id ) {
501 if ( ! $this->filters_enabled() || ! $id ) {
502 return false;
503 }
504
505 $filters = $this->filters();
506
507 // If identifier was found, return filter.
508 $index = array_search( $id, array_column( $filters, 'id' ) );
509 if ( false !== $index ) {
510 return WPUPG_Filter::filter_with_defaults( $filters[ $index ] );
511 }
512
513 // Check if index + 1 was used as the ID if not found by identifier.
514 $index = intval( $id ) - 1;
515 if ( isset( $filters[ $index ] ) ) {
516 $filter = $filters[ $index ];
517 $filter['id'] = $id;
518 return WPUPG_Filter::filter_with_defaults( $filter );
519 }
520
521 return false;
522 }
523 public function filters() {
524 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
525 return WPUPG_Migrations::single_filter_to_multiple( $this );
526 }
527
528 $filters_with_defaults = array();
529 $filters = $this->unserialize( $this->meta( 'filters', array() ) );
530
531 foreach ( $filters as $index => $filter ) {
532 $filters_with_defaults[ $index ] = WPUPG_Filter::filter_with_defaults( $filter );
533 }
534
535 return $filters_with_defaults;
536 }
537 public function filters_enabled() {
538 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
539 return 0 < count( $this->filters() );
540 }
541
542 // No filters for a term grid.
543 if ( 'terms' === $this->type() ) {
544 return false;
545 }
546
547 $bool = $this->meta( 'filters_enabled', false );
548 return (bool) $bool;
549 }
550 public function filters_style( $field = false ) {
551 $defaults = WPUPG_Filter::get_general_style_defaults();
552 $filters_style = $this->unserialize( $this->meta( 'filters_style', array() ) );
553 $filters_style_with_defaults = array_replace_recursive( $defaults, $filters_style );
554
555 if ( $field === false ) {
556 return $filters_style_with_defaults;
557 } else {
558 return isset( $filters_style_with_defaults[ $field ] ) ? $filters_style_with_defaults[ $field ] : false;
559 }
560 }
561 public function filters_relation() {
562 return $this->meta( 'filters_relation', 'AND' );
563 }
564 public function filters_no_selection() {
565 return $this->meta( 'filters_no_selection', 'all' );
566 }
567 public function responsive_toggle_style() {
568 return $this->meta( 'responsive_toggle_style', 'custom' );
569 }
570 public function responsive_toggle_style_closed() {
571 return $this->meta( 'responsive_toggle_style_closed', '+' );
572 }
573 public function responsive_toggle_style_open() {
574 return $this->meta( 'responsive_toggle_style_open', '-' );
575 }
576
577 /**
578 * Grid Layout Fields.
579 */
580 public function layout_mode() {
581 return $this->meta( 'layout_mode', 'masonry' );
582 }
583 public function centered() {
584 $bool = $this->meta( 'centered', false );
585 return (bool) $bool;
586 }
587 public function rtl_mode() {
588 $bool = $this->meta( 'rtl_mode', false );
589 return (bool) $bool;
590 }
591 public function can_use_centered() {
592 $can_use_centered = false;
593
594 if ( 'masonry' === $this->layout_mode() ) {
595 if ( ! $this->layout_tablet_different() && ! $this->layout_mobile_different() ) {
596 $can_use_centered = true;
597 }
598 }
599
600 return $can_use_centered;
601 }
602 public function layout_desktop_sizing() {
603 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
604 return 'ignore';
605 }
606 return $this->meta( 'layout_desktop_sizing', 'fixed' );
607 }
608 public function layout_desktop_sizing_fixed() {
609 return $this->meta( 'layout_desktop_sizing_fixed', 300 );
610 }
611 public function layout_desktop_sizing_columns() {
612 return $this->meta( 'layout_desktop_sizing_columns', 3 );
613 }
614 public function layout_desktop_sizing_margin() {
615 return $this->meta( 'layout_desktop_sizing_margin', 10 );
616 }
617 public function layout_tablet_different() {
618 $bool = $this->meta( 'layout_tablet_different', false );
619 return (bool) $bool;
620 }
621 public function layout_tablet_sizing() {
622 return $this->meta( 'layout_tablet_sizing', 'fixed' );
623 }
624 public function layout_tablet_sizing_fixed() {
625 return $this->meta( 'layout_tablet_sizing_fixed', 300 );
626 }
627 public function layout_tablet_sizing_columns() {
628 return $this->meta( 'layout_tablet_sizing_columns', 2 );
629 }
630 public function layout_tablet_sizing_margin() {
631 return $this->meta( 'layout_tablet_sizing_margin', 10 );
632 }
633 public function layout_mobile_different() {
634 $bool = $this->meta( 'layout_mobile_different', false );
635 return (bool) $bool;
636 }
637 public function layout_mobile_sizing() {
638 return $this->meta( 'layout_mobile_sizing', 'columns' );
639 }
640 public function layout_mobile_sizing_fixed() {
641 return $this->meta( 'layout_mobile_sizing_fixed', 300 );
642 }
643 public function layout_mobile_sizing_columns() {
644 return $this->meta( 'layout_mobile_sizing_columns', 1 );
645 }
646 public function layout_mobile_sizing_margin() {
647 return $this->meta( 'layout_mobile_sizing_margin', 10 );
648 }
649 /**
650 * Grid Item Fields.
651 */
652 public function template() {
653 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
654 return WPUPG_Migrations::template_mapping( $this );
655 }
656 return $this->meta( 'template', 'simple' );
657 }
658 public function use_image() {
659 return $this->meta( 'use_image', 'default' );
660 }
661 public function link() {
662 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
663 return 'none' !== $this->meta( 'link_type' );
664 }
665 $bool = $this->meta( 'link', true );
666 return (bool) $bool;
667 }
668 public function link_type() {
669 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
670 return $this->meta( 'link_target', 'post' );
671 }
672 return $this->meta( 'link_type', 'post' );
673 }
674 public function link_target() {
675 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
676 $target = $this->meta( 'link_type', '_self' );
677 return 'none' === $target ? '_self' : $target;
678 }
679 return $this->meta( 'link_target', '_self' );
680 }
681 /**
682 * Grid Pagination Fields.
683 */
684 public function pagination_type() {
685 // No pagination for term grid at the moment.
686 if ( 'terms' === $this->type() ) {
687 return 'none';
688 }
689
690 $pagination_type = $this->meta( 'pagination_type', 'none' );
691
692 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
693 $pagination_type = str_replace( 'load_more_filter', 'load_more', $pagination_type );
694 }
695
696 return $pagination_type;
697 }
698 public function pagination( $type = false ) {
699 if ( version_compare( $this->version(), '3.0.0', '<' ) ) {
700 $pagination = WPUPG_Migrations::get_pagination_with_style( $this );
701 } else {
702 $pagination = $this->unserialize( $this->meta( 'pagination', array() ) );
703 }
704
705 $pagination_defaults = WPUPG_Pagination::get_defaults();
706 $pagination = array_replace_recursive( $pagination_defaults, $pagination );
707
708 if ( false === $type ) {
709 return $pagination;
710 } else {
711 if ( isset( $pagination[ $type ] ) ) {
712 return $pagination[ $type ];
713 } else {
714 return array();
715 }
716 }
717 }
718 /**
719 * Grid Other Fields.
720 */
721 public function metadata() {
722 $bool = $this->meta( 'metadata', false );
723 return (bool) $bool;
724 }
725 public function metadata_name() {
726 return $this->meta( 'metadata_name', '' );
727 }
728 public function metadata_description() {
729 return $this->meta( 'metadata_description', '' );
730 }
731 public function deeplinking() {
732 $bool = $this->meta( 'deeplinking', true );
733 return (bool) $bool;
734 }
735 public function deeplinking_jump() {
736 $bool = $this->meta( 'deeplinking_jump', false );
737 return (bool) $bool;
738 }
739 public function empty_message() {
740 return $this->meta( 'empty_message', '' );
741 }
742
743 /**
744 * Get the IDs that are displayed in this grid for the current page.
745 *
746 * @since 3.0.0
747 * @param mixed $grid_args Optional arguments.
748 */
749 public function ids( $grid_args = array() ) {
750 $all_ids = $this->all_ids( $grid_args );
751 $ids = apply_filters( 'wpupg_grid_ids', $all_ids, $this, $grid_args );
752
753 // Prevent already loaded IDs from loading again.
754 $already_loaded_ids = isset( $grid_args['loaded_ids'] ) ? $grid_args['loaded_ids'] : array();
755 return array_filter( $ids, function( $id ) use ( $already_loaded_ids ) { return ! in_array( $id, $already_loaded_ids ); } );
756 }
757
758 /**
759 * Get the total number of IDs for this grid.
760 *
761 * @since 3.4.0
762 */
763 public function total_ids() {
764 $total_ids = $this->total_ids;
765 return false !== $total_ids ? intval( $total_ids ) : false;
766 }
767
768 /**
769 * Get the query post arguments for getting all IDs.
770 *
771 * @since 3.0.0
772 * @param mixed $grid_args Optional arguments.
773 */
774 public function all_ids_query_post_args( $grid_args = array() ) {
775 $post_types = $this->post_types();
776
777 $args = array(
778 'post_type' => $post_types,
779 'post_status' => $this->post_status(),
780 'order' => $this->order(),
781 'orderby' => $this->order_by(),
782 'posts_per_page' => -1,
783 'fields' => 'ids',
784 );
785
786 // Read permission for private posts.
787 if ( in_array( 'private', $this->post_status() ) && $this->post_status_require_permission() ) {
788 $args['perm'] = 'readable';
789 }
790
791 // Password protected.
792 switch ( $this->password_protected() ) {
793 case 'exclude':
794 $args['has_password'] = false;
795 break;
796 case 'only':
797 $args['has_password'] = true;
798 break;
799 default:
800 $args['has_password'] = null;
801 }
802
803 // Images Only
804 if ( $this->images_only() ) {
805 if ( in_array( 'attachment', $post_types ) ) {
806 $args['post_mime_type'] = 'image/jpeg,image/gif,image/jpg,image/png';
807 } else {
808 $args['meta_query'] = array(
809 array(
810 'relation' => 'OR',
811 array(
812 'key' => '_thumbnail_id',
813 'value' => '0',
814 'compare' => '>'
815 ),
816 array(
817 'key' => 'wpupg_custom_image_id',
818 'value' => '0',
819 'compare' => '>'
820 ),
821 )
822 );
823 }
824 }
825
826 // Exclude specific ids.
827 if ( isset( $grid_args['loaded_ids'] ) ) {
828 $args['post__not_in'] = $grid_args['loaded_ids'];
829 }
830
831 // Apply filters.
832 $tax_query = array(
833 'relation' => 'AND',
834 );
835
836 $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
837 $meta_query['relation'] = 'AND';
838
839 $filters = isset( $grid_args['filters'] ) ? $grid_args['filters'] : array();
840 foreach ( $filters as $filter ) {
841 switch ( $filter['type'] ) {
842 case 'search':
843 $args['s'] = $filter['text'];
844 break;
845 case 'terms':
846 foreach ( $filter['terms'] as $taxonomy => $terms ) {
847 if ( $terms ) {
848 $tax_query[] = array(
849 'taxonomy' => $taxonomy,
850 'field' => 'slug',
851 'terms' => $terms,
852 'operator' => $filter['terms_inverse'] ? 'NOT IN' : 'IN',
853 );
854 }
855 }
856
857 if ( 'AND' !== $filter['terms_relation'] ) {
858 $tax_query['relation'] = $filter['terms_relation'];
859 }
860 break;
861 case 'custom_field':
862 foreach ( $filter['values'] as $value ) {
863 if ( $value ) {
864 switch ( $value['type'] ) {
865 case 'string':
866 $meta_query[] = array(
867 'key' => $filter['custom_field'],
868 'value' => $value['value'],
869 'compare' => $filter['values_inverse'] ? '!=' : '=',
870 );
871 break;
872 case 'fuzzy':
873 $meta_query[] = array(
874 'key' => $filter['custom_field'],
875 'value' => $value['value'],
876 'compare' => $filter['values_inverse'] ? 'NOT LIKE' : 'LIKE',
877 );
878 break;
879 case 'number':
880 $meta_query[] = array(
881 'key' => $filter['custom_field'],
882 'value' => $value['value'],
883 'type' => 'NUMERIC',
884 'compare' => $filter['values_inverse'] ? '!=' : '=',
885 );
886 break;
887 case 'range':
888 $meta_query[] = array(
889 'key' => $filter['custom_field'],
890 'value' => $value['value'],
891 'type' => 'NUMERIC',
892 'compare' => $filter['values_inverse'] ? 'NOT BETWEEN' : 'BETWEEN',
893 );
894 break;
895 }
896 }
897 }
898
899 if ( 'AND' !== $filter['values_relation'] ) {
900 $meta_query['relation'] = $filter['values_relation'];
901 }
902 break;
903 }
904 }
905
906 if ( 1 < count( $tax_query ) ) {
907 $args['tax_query'] = $tax_query;
908 }
909 if ( 1 < count( $meta_query ) ) {
910 $args['meta_query'] = $meta_query;
911 }
912
913 return apply_filters( 'wpupg_query_post_args', $args, $this, $grid_args );
914 }
915
916 /**
917 * Get all the IDs that are displayed in this grid.
918 *
919 * @since 3.0.0
920 * @param mixed $grid_args Optional arguments.
921 */
922 public function all_ids( $grid_args = array() ) {
923 if ( false === $this->ids ) {
924 $ids = array();
925 $total_ids = false;
926
927 if ( 'posts' === $this->type() ) {
928 $args = $this->all_ids_query_post_args( $grid_args );
929
930 // Optionally set specific language.
931 WPUPG_Multilingual::set_language( $this->language() );
932
933 // Query IDs.
934 $query = new WP_Query( $args );
935 $posts = $query->have_posts() ? $query->posts : array();
936 $ids = array_map( 'intval', $posts );
937 $total_ids = $query->found_posts;
938
939 // Unset language.
940 WPUPG_Multilingual::unset_language();
941
942 // Offset posts
943 if ( $this->limit_posts_offset() ) {
944 $ids = array_slice( $ids, $this->limit_posts_offset() );
945 }
946
947 // Limit Total # Posts
948 if ( $this->limit_posts_number() ) {
949 $ids = array_slice( $ids, 0, $this->limit_posts_number() );
950 }
951 }
952
953 $this->ids = apply_filters( 'wpupg_grid_all_ids', $ids, $this, $grid_args );
954 $this->total_ids = $total_ids;
955 }
956
957 return $this->ids;
958 }
959
960 /**
961 * Get the terms to display in this grid.
962 *
963 * @since 3.0.0
964 * @param mixed $grid_args Optional arguments.
965 */
966 public function terms( $grid_args = array() ) {
967 if ( false === $this->terms ) {
968 $terms = array(
969 'per_item' => array(),
970 'per_taxonomy' => array(),
971 );
972 $taxonomies = $this->filters_taxonomies();
973
974 // Only need to get terms if there actually are taxonomies.
975 if ( count( $taxonomies ) ) {
976 $post_ids = $this->all_ids( $grid_args );
977
978 // Build sanitized query.
979 global $wpdb;
980
981 $where_taxonomies = implode( '","', array_map( 'sanitize_key', $taxonomies ) );
982 $where_post_ids = implode( ',', array_map( 'intval', $post_ids ) );
983
984 $query = 'SELECT tr.object_id, tt.taxonomy, tt.parent, t.term_id, t.slug, t.name FROM ' . $wpdb->prefix . 'term_relationships tr JOIN ' . $wpdb->prefix . 'term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN ' . $wpdb->prefix . 'terms t on tt.term_id = t.term_id WHERE tt.taxonomy IN ("' . $where_taxonomies . '")';
985
986 if ( $where_post_ids ) {
987 $query .= ' AND tr.object_id IN (' . $where_post_ids . ')';
988 }
989
990 $results = $wpdb->get_results( $query, ARRAY_A );
991
992 // Loop over all results.
993 $terms = $this->handle_terms( $terms, $results );
994 }
995
996 $this->terms = $terms;
997 }
998
999 return $this->terms;
1000 }
1001
1002 /**
1003 * Get terms from query reults.
1004 *
1005 * @since 3.5.0
1006 */
1007 public function handle_terms( $terms, $results, $depth = 0 ) {
1008 $parents = array();
1009
1010 foreach ( $results as $result ) {
1011 $item_id = intval( $result['object_id'] );
1012 $taxonomy = $result['taxonomy'];
1013 $term_id = intval( $result['term_id'] );
1014 $parent = intval( $result['parent'] );
1015 $slug = rawurldecode( $result['slug'] );
1016 $name = apply_filters( 'wpupg_term_name', $result['name'], $term_id, $taxonomy );
1017
1018 // Make sure arrays exist.
1019 if ( ! isset( $terms['per_taxonomy'][ $taxonomy ] ) ) { $terms['per_taxonomy'][ $taxonomy ] = array(); }
1020 if ( ! isset( $terms['per_item'][ $item_id ] ) ) { $terms['per_item'][ $item_id ] = array(); }
1021 if ( ! isset( $terms['per_item'][ $item_id ][ $taxonomy ] ) ) {
1022 $terms['per_item'][ $item_id ][ $taxonomy ] = array(
1023 'terms' => array(),
1024 'parent_terms' => array(),
1025 );
1026 }
1027 if ( !isset( $terms['per_taxonomy'][ $taxonomy ][ $slug ] ) ) {
1028 $terms['per_taxonomy'][ $taxonomy ][ $slug ] = array(
1029 'id' => $term_id,
1030 'parent' => $parent,
1031 'name' => $name,
1032 'posts' => array(),
1033 'child_posts' => array(),
1034 );
1035 }
1036
1037 // Add in correct category.
1038 if ( 0 === $depth ) {
1039 $terms['per_item'][ $item_id ][ $taxonomy ]['terms'][] = $slug;
1040 $terms['per_taxonomy'][ $taxonomy ][ $slug ]['posts'][] = $item_id;
1041 } else {
1042 $terms['per_item'][ $item_id ][ $taxonomy ]['parent_terms'][] = $slug;
1043 $terms['per_taxonomy'][ $taxonomy ][ $slug ]['child_posts'][] = $item_id;
1044 }
1045
1046 // Check if there are further parents we need to get.
1047 if ( $parent ) {
1048 $parents[] = array(
1049 'object_id' => $item_id,
1050 'taxonomy' => $taxonomy,
1051 'term_id' => $parent,
1052 );
1053 }
1054 }
1055
1056 // Check if there are any parents we need to associate as well.
1057 if ( count( $parents ) ) {
1058 $parent_results = array();
1059
1060 $parent_ids = wp_list_pluck( $parents, 'term_id' );
1061 $parent_terms = get_terms( array(
1062 'include' => $parent_ids,
1063 ) );
1064
1065 if ( $parent_terms && ! is_wp_error( $parent_terms ) ) {
1066 // Set term_id as key.
1067 $keyed_parent_terms = array();
1068 foreach ( $parent_terms as $parent_term ) {
1069 $keyed_parent_terms[ $parent_term->term_id ] = $parent_term;
1070 }
1071
1072 foreach( $parents as $index => $parent ) {
1073 if ( isset( $keyed_parent_terms[ $parent['term_id'] ] ) ) {
1074 $parent_term = $keyed_parent_terms[ $parent['term_id'] ];
1075
1076 $parent_results[] = array(
1077 'object_id' => $parent['object_id'],
1078 'taxonomy' => $parent['taxonomy'],
1079 'term_id' => $parent['term_id'],
1080 'parent' => $parent_term->parent,
1081 'slug' => $parent_term->slug,
1082 'name' => $parent_term->name,
1083 );
1084 }
1085 }
1086 }
1087
1088 // Recursive loop.
1089 if ( count( $parent_results ) ) {
1090 $terms = $this->handle_terms( $terms, $parent_results, $depth + 1 );
1091 }
1092 }
1093
1094 return $terms;
1095 }
1096
1097 /**
1098 * Get the terms for a specific item.
1099 *
1100 * @since 3.0.0
1101 * @param int $item_id Item to get the terms for.
1102 */
1103 public function get_terms_for_item( $item_id ) {
1104 $terms = $this->terms();
1105
1106 return isset( $terms['per_item'][ $item_id ] ) ? $terms['per_item'][ $item_id ] : array();
1107 }
1108
1109 /**
1110 * Get the terms for a specific taxonomy.
1111 *
1112 * @since 3.0.0
1113 * @param string $taxonomy Taxonomy to get the terms for.
1114 */
1115 public function get_terms_for_taxonomy( $taxonomy ) {
1116 $terms = $this->terms();
1117
1118 return isset( $terms['per_taxonomy'][ $taxonomy ] ) ? $terms['per_taxonomy'][ $taxonomy ] : array();
1119 }
1120
1121 /**
1122 * Get the taxonomies filtered by in this grid.
1123 *
1124 * @since 3.0.0
1125 */
1126 public function filters_taxonomies() {
1127 $taxonomies = array();
1128
1129 if ( $this->filters_enabled() ) {
1130 $filters = $this->filters();
1131
1132 foreach ( $filters as $filter ) {
1133 if ( ! isset( $filter['options']['source'] ) || 'taxonomies' === $filter['options']['source'] ) {
1134 if ( isset( $filter['options']['taxonomies'] ) ) {
1135 $taxonomies = array_merge( $taxonomies, $filter['options']['taxonomies'] );
1136 }
1137 }
1138 }
1139 }
1140
1141 return array_unique( $taxonomies );
1142 }
1143
1144 /**
1145 * Get the custom fields filtered by in this grid.
1146 *
1147 * @since 3.3.0
1148 */
1149 public function filters_custom_fields() {
1150 $custom_fields = array();
1151
1152 if ( $this->filters_enabled() ) {
1153 $filters = $this->filters();
1154
1155 foreach ( $filters as $filter ) {
1156 if ( ! isset( $filter['options']['source'] ) || 'custom_field' === $filter['options']['source'] ) {
1157 if ( isset( $filter['options']['custom_field'] ) ) {
1158 $custom_fields[] = $filter['options']['custom_field'];
1159 }
1160 }
1161 }
1162 }
1163
1164 return array_unique( $custom_fields );
1165 }
1166 }
1167