PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.5.3
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.5.3
4.5.4 4.2.1 4.2.2 4.2.3 4.5.0 4.5.2 4.5.3 4.2.0 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 All 146 releases
ultimate-post-kit / includes / controls / group-query / group-control-query.php

group-control-query.php in Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets 4.5.3, at includes/controls/group-query/group-control-query.php

795 lines 27.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace UltimatePostKit\Includes\Controls\GroupQuery;
4
5 use Elementor\Controls_Manager;
6 use UltimatePostKit\Includes\Controls\SelectInput\Dynamic_Select;
7 use UltimatePostKit\Base\Module_Base;
8
9 if (!defined('ABSPATH')) {
10 exit; // Exit if accessed directly.
11 }
12
13 abstract class Group_Control_Query extends Module_Base {
14
15 protected function register_query_builder_controls() {
16
17 $this->add_control(
18 'posts_source',
19 [
20 'label' => __('Source', 'ultimate-post-kit'),
21 'type' => Controls_Manager::SELECT,
22 'options' => $this->getGroupControlQueryPostTypes(),
23 'default' => 'post',
24 ]
25 );
26
27 $this->add_control(
28 'posts_source_description',
29 [
30 'label' => '',
31 'type' => Controls_Manager::RAW_HTML,
32 'raw' => __('This current query may not be display posts in the editor. Please save and refresh the page to see the posts.', 'ultimate-post-kit'),
33 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
34 'condition' => [
35 'posts_source' => 'current_query',
36 ],
37 ]
38 );
39
40 $this->add_control(
41 'posts_source_description_2',
42 [
43 'label' => '',
44 'type' => Controls_Manager::RAW_HTML,
45 'raw' => sprintf(
46 /* translators: 1: HTML link to options-reading.php */
47 __('Posts per page is global for current query. Set <strong>"Blog pages show at most"</strong> from settings page of WordPress. Go to <a href="%s" target="_blank" rel="noopener">Settings &gt; Reading</a>.', 'ultimate-post-kit'),
48 esc_url(admin_url('options-reading.php'))
49 ),
50 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
51 'condition' => [
52 'posts_source' => 'current_query',
53 ],
54 ]
55 );
56
57 $this->add_control(
58 'posts_selected_ids',
59 [
60 'label' => __('Search & Select', 'ultimate-post-kit'),
61 'type' => Dynamic_Select::TYPE,
62 'multiple' => true,
63 'label_block' => true,
64 'query_args' => [
65 'query' => 'posts',
66 ],
67 'condition' => [
68 'posts_source' => 'manual_selection',
69 ]
70 ]
71 );
72
73 $this->start_controls_tabs(
74 'tabs_posts_include_exclude',
75 [
76 'condition' => [
77 'posts_source!' => ['manual_selection', 'current_query'],
78 ]
79 ]
80 );
81
82 $this->start_controls_tab(
83 'tab_posts_include',
84 [
85 'label' => __('Include', 'ultimate-post-kit'),
86 'condition' => [
87 'posts_source!' => ['manual_selection', 'current_query'],
88 ]
89 ]
90 );
91
92 $this->add_control(
93 'posts_include_by',
94 [
95 'label' => __('Include By', 'ultimate-post-kit'),
96 'type' => Controls_Manager::SELECT2,
97 'multiple' => true,
98 'label_block' => true,
99 'options' => [
100 'authors' => __('Authors', 'ultimate-post-kit'),
101 'terms' => __('Terms', 'ultimate-post-kit'),
102 ],
103 'condition' => [
104 'posts_source!' => ['manual_selection', 'current_query'],
105 ]
106 ]
107 );
108
109 $this->add_control(
110 'posts_include_author_ids',
111 [
112 'label' => __('Authors', 'ultimate-post-kit'),
113 'type' => Dynamic_Select::TYPE,
114 'multiple' => true,
115 'label_block' => true,
116 'query_args' => [
117 'query' => 'authors',
118 ],
119 'condition' => [
120 'posts_include_by' => 'authors',
121 'posts_source!' => ['manual_selection', 'current_query'],
122 ]
123 ]
124 );
125
126 $this->add_control(
127 'posts_include_term_ids',
128 [
129 'label' => __('Terms', 'ultimate-post-kit'),
130 'description' => __('Terms are items in a taxonomy. The available taxonomies are: Categories, Tags, Formats and custom taxonomies.', 'ultimate-post-kit'),
131 'type' => Dynamic_Select::TYPE,
132 'multiple' => true,
133 'label_block' => true,
134 'placeholder' => __('Type and select terms', 'ultimate-post-kit'),
135 'query_args' => [
136 'query' => 'terms',
137 'widget_props' => [
138 'post_type' => 'posts_source'
139 ]
140 ],
141 'condition' => [
142 'posts_include_by' => 'terms',
143 'posts_source!' => ['manual_selection', 'current_query'],
144 ]
145 ]
146 );
147
148 $this->end_controls_tab();
149
150 $this->start_controls_tab(
151 'tab_posts_exclude',
152 [
153 'label' => __('Exclude', 'ultimate-post-kit'),
154 'condition' => [
155 'posts_source!' => ['manual_selection', 'current_query'],
156 ]
157 ]
158 );
159
160 $this->add_control(
161 'posts_exclude_by',
162 [
163 'label' => __('Exclude By', 'ultimate-post-kit'),
164 'type' => Controls_Manager::SELECT2,
165 'multiple' => true,
166 'label_block' => true,
167 'options' => [
168 'authors' => __('Authors', 'ultimate-post-kit'),
169 'current_post' => __('Current Post', 'ultimate-post-kit'),
170 'manual_selection' => __('Manual Selection', 'ultimate-post-kit'),
171 'terms' => __('Terms', 'ultimate-post-kit'),
172 ],
173 'condition' => [
174 'posts_source!' => ['manual_selection', 'current_query'],
175 ]
176 ]
177 );
178
179 $this->add_control(
180 'posts_exclude_ids',
181 [
182 'label' => __('Search & Select', 'ultimate-post-kit'),
183 'type' => Dynamic_Select::TYPE,
184 'multiple' => true,
185 'label_block' => true,
186 'query_args' => [
187 'query' => 'posts',
188 'widget_props' => [
189 'post_type' => 'posts_source'
190 ]
191 ],
192 'condition' => [
193 'posts_source!' => ['manual_selection', 'current_query'],
194 'posts_exclude_by' => 'manual_selection',
195 ]
196 ]
197 );
198
199 $this->add_control(
200 'posts_exclude_author_ids',
201 [
202 'label' => __('Authors', 'ultimate-post-kit'),
203 'type' => Dynamic_Select::TYPE,
204 'multiple' => true,
205 'label_block' => true,
206 'query_args' => [
207 'query' => 'authors',
208 ],
209 'condition' => [
210 'posts_exclude_by' => 'authors',
211 'posts_source!' => ['manual_selection', 'current_query'],
212 ]
213 ]
214 );
215
216 $this->add_control(
217 'posts_exclude_term_ids',
218 [
219 'label' => __('Terms', 'ultimate-post-kit'),
220 'description' => __('Terms are items in a taxonomy. The available taxonomies are: Categories, Tags, Formats and custom taxonomies.', 'ultimate-post-kit'),
221 'type' => Dynamic_Select::TYPE,
222 'multiple' => true,
223 'label_block' => true,
224 'placeholder' => __('Type and select terms', 'ultimate-post-kit'),
225 'query_args' => [
226 'query' => 'terms',
227 'widget_props' => [
228 'post_type' => 'posts_source'
229 ]
230 ],
231 'condition' => [
232 'posts_exclude_by' => 'terms',
233 'posts_source!' => ['manual_selection', 'current_query'],
234 ]
235 ]
236 );
237
238 $this->end_controls_tab();
239 $this->end_controls_tabs();
240
241 $this->add_control(
242 'posts_divider',
243 [
244 'type' => Controls_Manager::DIVIDER,
245 'condition' => [
246 'posts_source!' => 'current_query',
247 ]
248 ]
249 );
250
251 $this->add_control(
252 'posts_offset',
253 [
254 'label' => __('Offset', 'ultimate-post-kit'),
255 'type' => Controls_Manager::NUMBER,
256 'default' => 0,
257 ]
258 );
259
260 $this->add_control(
261 'posts_select_date',
262 [
263 'label' => __('Date', 'ultimate-post-kit'),
264 'type' => Controls_Manager::SELECT,
265 'default' => 'anytime',
266 'options' => [
267 'anytime' => __('All', 'ultimate-post-kit'),
268 'today' => __('Past Day', 'ultimate-post-kit'),
269 'week' => __('Past Week', 'ultimate-post-kit'),
270 'month' => __('Past Month', 'ultimate-post-kit'),
271 'quarter' => __('Past Quarter', 'ultimate-post-kit'),
272 'year' => __('Past Year', 'ultimate-post-kit'),
273 'exact' => __('Custom', 'ultimate-post-kit'),
274 ],
275 'condition' => [
276 'posts_source!' => 'current_query',
277 ]
278 ]
279 );
280
281 $this->add_control(
282 'posts_date_before',
283 [
284 'label' => __('Before', 'ultimate-post-kit'),
285 'type' => Controls_Manager::DATE_TIME,
286 'description' => __('Setting a ‘Before’ date will show all the posts published until the chosen date (inclusive).', 'ultimate-post-kit'),
287 'condition' => [
288 'posts_select_date' => 'exact',
289 'posts_source!' => 'current_query',
290 ]
291 ]
292 );
293
294 $this->add_control(
295 'posts_date_after',
296 [
297 'label' => __('After', 'ultimate-post-kit'),
298 'type' => Controls_Manager::DATE_TIME,
299 'description' => __('Setting an ‘After’ date will show all the posts published since the chosen date (inclusive).', 'ultimate-post-kit'),
300 'condition' => [
301 'posts_select_date' => 'exact',
302 'posts_source!' => 'current_query',
303 ]
304 ]
305 );
306
307 $this->add_control(
308 'posts_orderby',
309 [
310 'label' => __('Order By', 'ultimate-post-kit'),
311 'type' => Controls_Manager::SELECT,
312 'default' => 'date',
313 'options' => [
314 'title' => __('Title', 'ultimate-post-kit'),
315 'ID' => __('ID', 'ultimate-post-kit'),
316 'date' => __('Date', 'ultimate-post-kit'),
317 'author' => __('Author', 'ultimate-post-kit'),
318 'comment_count' => __('Comment Count', 'ultimate-post-kit'),
319 'menu_order' => __('Menu Order', 'ultimate-post-kit'),
320 'modified' => __( 'Last Modified', 'ultimate-post-kit' ),
321 'rand' => __('Random', 'ultimate-post-kit'),
322 ],
323 ]
324 );
325
326 $this->add_control(
327 'posts_order',
328 [
329 'label' => __('Order', 'ultimate-post-kit'),
330 'type' => Controls_Manager::SELECT,
331 'default' => 'desc',
332 'options' => [
333 'asc' => __('ASC', 'ultimate-post-kit'),
334 'desc' => __('DESC', 'ultimate-post-kit'),
335 ],
336 ]
337 );
338
339 $this->add_control(
340 'posts_ignore_sticky_posts',
341 [
342 'label' => __('Ignore Sticky Posts', 'ultimate-post-kit'),
343 'type' => Controls_Manager::SWITCHER,
344 'return_value' => 'yes',
345 'default' => 'yes',
346 'condition' => [
347 'posts_source' => ['post', 'current_query'],
348 ]
349 ]
350 );
351
352 $this->add_control(
353 'posts_only_with_featured_image',
354 [
355 'label' => __('Only Featured Image Post', 'ultimate-post-kit'),
356 'description' => __('Enable to display posts only when featured image is present.', 'ultimate-post-kit'),
357 'type' => Controls_Manager::SWITCHER,
358 'return_value' => 'yes',
359 'condition' => [
360 'posts_source!' => 'current_query',
361 ]
362 ]
363 );
364
365 $this->add_control(
366 'query_id',
367 [
368 'label' => __('Query ID', 'ultimate-post-kit'),
369 'description' => __('Give your Query a custom unique id to allow server side filtering', 'ultimate-post-kit'),
370 'type' => Controls_Manager::TEXT,
371 'separator' => 'before',
372 ]
373 );
374 }
375
376 private function setMetaQueryArgs() {
377
378 $args = [];
379
380 if ('current_query' === $this->getGroupControlQueryPostType()) {
381 return [];
382 }
383
384 $args['order'] = $this->get_settings_for_display('posts_order');
385 $args['orderby'] = $this->get_settings_for_display('posts_orderby');
386
387 /**
388 * Set Feature Images
389 */
390
391 if ($this->get_settings_for_display('posts_only_with_featured_image') === 'yes') {
392 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Elementor widget query built from user-configured controls; expected behaviour.
393 $args['meta_key'] = '_thumbnail_id';
394 }
395
396 /**
397 * Set Date
398 */
399
400 $selected_date = $this->get_settings_for_display('posts_select_date');
401
402 if (!empty($selected_date)) {
403 $date_query = [];
404
405 switch ($selected_date) {
406 case 'today':
407 $date_query['after'] = '-1 day';
408 break;
409
410 case 'week':
411 $date_query['after'] = '-1 week';
412 break;
413
414 case 'month':
415 $date_query['after'] = '-1 month';
416 break;
417
418 case 'quarter':
419 $date_query['after'] = '-3 month';
420 break;
421
422 case 'year':
423 $date_query['after'] = '-1 year';
424 break;
425
426 case 'exact':
427 $after_date = $this->get_settings_for_display('posts_date_after');
428
429 if (!empty($after_date)) {
430 $date_query['after'] = $after_date;
431 }
432
433 $before_date = $this->get_settings_for_display('posts_date_before');
434
435 if (!empty($before_date)) {
436 $date_query['before'] = $before_date;
437 }
438
439 $date_query['inclusive'] = true;
440 break;
441 }
442
443 if (!empty($date_query)) {
444 $args['date_query'] = $date_query;
445 }
446 }
447
448 return $args;
449 }
450
451 protected function getGroupControlQueryArgs() {
452
453 $settings = $this->get_settings_for_display();
454 $args = $this->setMetaQueryArgs();
455
456 $args['post_status'] = 'publish';
457 $args['suppress_filters'] = false;
458 $exclude_by = $this->getGroupControlQueryParamBy('exclude');
459
460 if (0 < $settings['posts_offset']) {
461 $args['offset_to_fix'] = $settings['posts_offset'];
462 }
463
464 /**
465 * Set Ignore Sticky
466 */
467 if (
468 $this->getGroupControlQueryPostType() === 'post'
469 && $this->get_settings_for_display('posts_ignore_sticky_posts') === 'yes'
470 ) {
471 $args['ignore_sticky_posts'] = true;
472
473 if (in_array('current_post', $exclude_by)) {
474 // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Elementor widget query built from user-configured controls; expected behaviour.
475 $args['post__not_in'] = [get_the_ID()];
476 }
477 }
478
479 if ($this->getGroupControlQueryPostType() === 'manual_selection') {
480 /**
481 * Set Including Manually
482 */
483 $selected_ids = $this->get_settings_for_display('posts_selected_ids');
484 $selected_ids = wp_parse_id_list($selected_ids);
485 $args['post_type'] = 'any';
486 if (!empty($selected_ids)) {
487 $args['post__in'] = $selected_ids;
488 }
489
490 $args['ignore_sticky_posts'] = 1;
491 } elseif ('current_query' === $this->getGroupControlQueryPostType()) {
492 /**
493 * Make Current Query
494 */
495 $args = $GLOBALS['wp_query']->query_vars;
496 $args = apply_filters('ultimate_post_kit/query/get_query_args/current_query', $args);
497 } elseif ('_ultimate_post_kit_pro_related_post_type' == $this->getGroupControlQueryPostType()) {
498 /**
499 * Set Related Query
500 */
501 $post_id = get_queried_object_id();
502 $related_post_id = is_singular() && (0 !== $post_id) ? $post_id : null;
503 $args['post_type'] = get_post_type($related_post_id);
504
505 $exclude_by = $this->getGroupControlQueryParamBy('exclude');
506 if (in_array('current_post', $exclude_by)) {
507 // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Elementor widget query built from user-configured controls; expected behaviour.
508 $args['post__not_in'] = [get_the_ID()];
509 }
510
511 /**
512 * Set Authors
513 */
514 $args = $this->getAuthorArgs($args, $settings, $related_post_id);
515
516 /**
517 * Set Taxonomy
518 */
519 $args = $this->getTermsArgs($args, $settings);
520
521 $args['ignore_sticky_posts'] = 1;
522 $args = apply_filters('ultimate_post_kit/query/get_query_args/related_query', $args);
523 } else {
524
525 /**
526 * Set Post Type
527 */
528 $args['post_type'] = $this->getGroupControlQueryPostType();
529
530 /**
531 * Set Exclude Post
532 */
533 $exclude_by = $this->getGroupControlQueryParamBy('exclude');
534 $current_post = [];
535
536 if (in_array('current_post', $exclude_by) && is_singular()) {
537 $current_post = [get_the_ID()];
538 }
539
540 if (in_array('manual_selection', $exclude_by)) {
541 $exclude_ids = $settings['posts_exclude_ids'];
542 // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Elementor widget query built from user-configured controls; expected behaviour.
543 $args['post__not_in'] = array_merge($current_post, wp_parse_id_list($exclude_ids));
544 }
545
546 /**
547 * Set Authors
548 */
549 $args = $this->getAuthorArgs($args, $settings);
550
551 /**
552 * Set Taxonomy
553 */
554 $args = $this->getTermsArgs($args, $settings);
555 }
556
557 if ($this->get_settings_for_display('query_id')) {
558 $args['upk_widget_query'] = true;
559 add_action('pre_get_posts', [$this, 'pre_get_posts_query_filter']);
560 }
561
562 // fixing custom offset
563 ## https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
564 // Only register the fixers when this widget actually uses an offset, and
565 // scope them to this widget's own query so they never affect other
566 // queries (e.g. another post widget rendered later on the same page).
567 if (!empty($args['offset_to_fix'])) {
568 add_action('pre_get_posts', [$this, 'fix_query'], 1);
569 add_filter('found_posts', [$this, 'prefix_adjust_offset_pagination'], 1, 2);
570 }
571
572 return $args;
573 }
574
575 private function getAuthorArgs($args, $settings, mixed $post = null) {
576
577 $include_by = $this->getGroupControlQueryParamBy('include');
578 $exclude_by = $this->getGroupControlQueryParamBy('exclude');
579 $include_users = [];
580 $exclude_users = [];
581
582 if (in_array('authors', $include_by)) {
583 $include_users = wp_parse_id_list($settings['posts_include_author_ids']);
584 } elseif ($post) {
585 $include_users = get_post_field('post_author', $post);
586 }
587
588 if (in_array('authors', $exclude_by)) {
589 $exclude_users = wp_parse_id_list($settings['posts_exclude_author_ids']);
590 $include_users = array_diff($include_users, $exclude_users);
591 }
592
593 if (!empty($include_users)) {
594 $args['author__in'] = $include_users;
595 }
596
597 if (!empty($exclude_users)) {
598 $args['author__not_in'] = $exclude_users;
599 }
600
601 return $args;
602 }
603
604 private function getTermsArgs($args, $settings) {
605
606 $include_by = $this->getGroupControlQueryParamBy('include');
607 $exclude_by = $this->getGroupControlQueryParamBy('exclude');
608 $include_terms = [];
609 $terms_query = [];
610
611 if (in_array('terms', $include_by)) {
612 $include_terms = wp_parse_id_list($settings['posts_include_term_ids']);
613 }
614
615 if (in_array('terms', $exclude_by)) {
616 $exclude_terms = wp_parse_id_list($settings['posts_exclude_term_ids']);
617 $include_terms = array_diff($include_terms, $exclude_terms);
618 }
619
620 if (!empty($include_terms)) {
621 $tax_terms_map = $this->mapGroupControlQuery($include_terms);
622
623 foreach ($tax_terms_map as $tax => $terms) {
624 $terms_query[] = [
625 'taxonomy' => $tax,
626 'field' => 'term_id',
627 'terms' => $terms,
628 'operator' => 'IN',
629 ];
630 }
631 }
632
633 if (!empty($exclude_terms)) {
634 $tax_terms_map = $this->mapGroupControlQuery($exclude_terms);
635
636 foreach ($tax_terms_map as $tax => $terms) {
637 $terms_query[] = [
638 'taxonomy' => $tax,
639 'field' => 'term_id',
640 'terms' => $terms,
641 'operator' => 'NOT IN',
642 ];
643 }
644 }
645
646 if (!empty($terms_query)) {
647 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Elementor widget query built from user-configured controls; expected behaviour.
648 $args['tax_query'] = $terms_query;
649 $args['tax_query']['relation'] = 'AND';
650 }
651
652 return $args;
653 }
654
655 /**
656 * @return mixed
657 */
658 private function getGroupControlQueryPostType() {
659 return $this->get_settings_for_display('posts_source');
660 }
661
662 /**
663 * Get Query Params by args
664 *
665 * @param string $by
666 *
667 * @return array|mixed
668 */
669 private function getGroupControlQueryParamBy($by = 'exclude') {
670 $mapBy = [
671 // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- Elementor widget query built from user-configured controls; expected behaviour.
672 'exclude' => 'posts_exclude_by',
673 'include' => 'posts_include_by',
674 ];
675
676 $setting = $this->get_settings_for_display($mapBy[$by]);
677
678 return (!empty($setting) ? $setting : []);
679 }
680
681 /**
682 * @param array $term_ids
683 *
684 * @return array
685 */
686 private function mapGroupControlQuery($term_ids = []) {
687 $terms = get_terms(
688 [
689 'term_taxonomy_id' => $term_ids,
690 'hide_empty' => false,
691 ]
692 );
693
694 $tax_terms_map = [];
695
696 foreach ($terms as $term) {
697 $taxonomy = $term->taxonomy;
698 $tax_terms_map[$taxonomy][] = $term->term_id;
699 }
700
701 return $tax_terms_map;
702 }
703
704
705 /**
706 * @return array|string[]|\WP_Post_Type[]
707 */
708 private function getGroupControlQueryPostTypes() {
709 $post_types = get_post_types(['public' => true], 'objects');
710 $post_types = array_column($post_types, 'label', 'name');
711
712 $ignorePostTypes = [
713 'elementor_library' => '',
714 'attachment' => '',
715 'bdt_template_manager' => '',
716 'bdt-custom-template' => '',
717 ];
718
719 $post_types = array_diff_key($post_types, $ignorePostTypes);
720
721 $extra_types = [
722 'manual_selection' => __('Manual Selection', 'ultimate-post-kit'),
723 'current_query' => __('Current Query', 'ultimate-post-kit'),
724 '_ultimate_post_kit_pro_related_post_type' => __('Related', 'ultimate-post-kit'),
725 ];
726
727 $post_types = array_merge($post_types, $extra_types);
728
729 return $post_types;
730 }
731
732 /**
733 * @param WP_Query $query fix the offset
734 */
735
736 function fix_query( &$query ) {
737
738 // Only touch this widget's own query. The flag travels with the query
739 // args, so unrelated queries (other widgets, the main loop, etc.) are
740 // left untouched even if this callback is still attached.
741 if ( ! isset( $query->query_vars['offset_to_fix'] ) ) {
742 return;
743 }
744
745 // Self-remove so this only applies to a single query and never leaks
746 // into subsequent queries on the same request.
747 remove_action( 'pre_get_posts', [ $this, 'fix_query' ], 1 );
748
749 $offset = (int) $query->query_vars['offset_to_fix'];
750
751 $posts_per_page = isset( $query->query_vars['posts_per_page'] )
752 ? (int) $query->query_vars['posts_per_page']
753 : (int) get_option( 'posts_per_page', 10 );
754
755 if ( $query->is_paged ) {
756 $page_offset = $offset + ( ( $query->query_vars['paged'] - 1 ) * $posts_per_page );
757 $query->set( 'offset', $page_offset );
758 } else {
759 $query->set( 'offset', $offset );
760 }
761 }
762
763 public function prefix_adjust_offset_pagination( $found_posts, $query ) {
764
765 if ( ! isset( $query->query_vars['offset_to_fix'] ) ) {
766 return $found_posts;
767 }
768
769 remove_filter( 'found_posts', [ $this, 'prefix_adjust_offset_pagination' ], 1 );
770
771 $offset_to_fix = intval( $query->query_vars['offset_to_fix'] );
772
773 if ( $offset_to_fix ) {
774 $found_posts -= $offset_to_fix;
775 }
776
777 return $found_posts;
778 }
779
780 public function pre_get_posts_query_filter( $wp_query ) {
781
782 if ( empty( $wp_query->get( 'upk_widget_query' ) ) ) {
783 return;
784 }
785
786 remove_action( 'pre_get_posts', [ $this, 'pre_get_posts_query_filter' ] );
787
788 $query_id = $this->get_settings_for_display( 'query_id' );
789
790 if ( $query_id ) {
791 do_action( "ultimate_post_kit_pro/query/{$query_id}", $wp_query, $this );
792 }
793 }
794 }
795