PluginProbe
SheetsPilot – AI Spreadsheet Bulk Edit for Posts, WooCommerce Products & SEO / trunk
SheetsPilot – AI Spreadsheet Bulk Edit for Posts, WooCommerce Products & SEO vtrunk
sheetspilot / inc_php / query_processing.class.php

query_processing.class.php in SheetsPilot – AI Spreadsheet Bulk Edit for Posts, WooCommerce Products & SEO trunk, at inc_php/query_processing.class.php

1,191 lines 37.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * @package SheetsPilot
5 * @author Unlimited Elements
6 * @copyright (C) 2026 Unlimited Elements, All Rights Reserved.
7 * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
8 **/
9 if (! defined('ABSPATH')) exit;
10 if (!defined("SHEETSPILOT_INC")) die("restricted access");
11
12 class SheetsPilotQueryProcessing
13 {
14 public $args = [];
15
16 public $postType = 'post';
17 public $is_new_row = false;
18 public $new_post_title = false;
19 public $duplicate_post_id = false;
20 public $offset = 0;
21 public $search_string = false;
22 public $single_post_id = false;
23 public $orderby = false;
24 public $order = false;
25 public $column_search = false;
26 public $column_name = false;
27 public $column_type = false;
28 public $filtering_values = [];
29 public $column_query = [];
30
31 /**
32 * echo ajax success response
33 */
34 //1 2 3 4 5 6 7
35 // $this->postType, $this->is_new_row = false, $this->duplicate_post_id = false, $this->offset = 0, $this->search_string = false, $this->single_post_id = false, $this->orderby = false,
36 // 8
37 //$this->order = false
38 public function getPostTypeArray()
39 {
40 global $wpdb;
41
42 $rowsPerPage = SheetsPilotHelper::getEditorPageSettings('rows_per_page');
43 if (!$rowsPerPage) {
44 $rowsPerPage = 10;
45 }
46
47 if (!$this->postType) {
48 $this->postType = 'post';
49 }
50
51 // get all editable fiedls
52 global $_wp_post_type_features;
53 $mandatory_fields = ['post_name', 'post_status', 'post_date'];
54 $supports_fiedls_relations = [
55 'title' => 'post_title',
56 "excerpt" => 'post_excerpt',
57 "editor" => 'post_content',
58 "thumbnail" => 'post_image',
59 "author" => 'post_author'
60 ];
61 $all_post_fields = isset($_wp_post_type_features[$this->postType]) ? $_wp_post_type_features[$this->postType] : [];
62
63
64 //media patch
65 if( $this->postType == 'attachment' ){
66 $all_post_fields['editor'] = true;
67 $all_post_fields['excerpt'] = true;
68 }
69
70
71 // get all post supported
72 $fields_to_use = [];
73 foreach ($all_post_fields as $key => $value) {
74 if (isset($supports_fiedls_relations[$key])) {
75 $fields_to_use[] = $supports_fiedls_relations[$key];
76 }
77 }
78
79 $fields_to_use = array_merge( array( 'bulk', 'id', '_sheetspilot_row_meta', 'elementor_active' ), $fields_to_use );
80 $fields_to_use = array_merge($fields_to_use, $mandatory_fields);
81
82
83
84
85 $post_type_taxonomies = get_object_taxonomies($this->postType, 'names');
86
87 // For products, remove WooCommerce attribute taxonomies from regular taxonomy columns.
88 if( $this->postType == 'product' ){
89 $tmp_tax = [];
90 foreach( $post_type_taxonomies as $s_tax ){
91 if( substr( $s_tax, 0, 3) != 'pa_' ){
92 $tmp_tax[] = $s_tax;
93 }
94 }
95 $post_type_taxonomies = $tmp_tax;
96 }
97
98
99 $fields_to_use = array_merge($fields_to_use, $post_type_taxonomies);
100
101
102
103 // acf fields addition
104 $acf_extra_fields = SheetsPilotCellEditor::get_acf_fields_for_post_type($this->postType);
105 foreach ($acf_extra_fields as $s_field_data) {
106 $fields_to_use[] = 'acf_' . $s_field_data['name'];
107 }
108
109 $offset_arg = 0;
110 if ($this->offset > 0) {
111 $offset_arg = $this->offset * $rowsPerPage;
112 }
113 $args = [
114 'post_type' => $this->postType,
115 'showposts' => $rowsPerPage,
116 'post_status' => 'any',
117 'offset' => $offset_arg,
118 'orderby' => 'ID',
119 ];
120
121
122
123 // ordering
124 if ($this->orderby && $this->order) {
125 if ($this->orderby === 'elementor_active') {
126 $args = $this->applyElementorActiveSortToArgs($args, $this->order);
127 } else {
128 // Map editor column names to WP_Query orderby values.
129 $orderby_map = array(
130 'id' => 'ID',
131 'ID' => 'ID',
132 'post_title' => 'title',
133 'post_date' => 'date',
134 'post_name' => 'name',
135 'post_author' => 'author',
136 'post_modified' => 'modified',
137 );
138 $args['orderby'] = isset( $orderby_map[ $this->orderby ] )
139 ? $orderby_map[ $this->orderby ]
140 : $this->orderby;
141 $args['order'] = $this->order;
142
143 if (substr_count($this->orderby, 'acf_') > 0 || substr_count($this->orderby, 'plugins_') > 0) {
144 $filtered_feild_name = str_replace('acf_', '', $this->orderby);
145 $filtered_feild_name = str_replace('plugins_', '', $filtered_feild_name);
146 $args['orderby'] = 'meta_value';
147
148 $args['meta_key'] = $filtered_feild_name;
149 }
150 }
151 }
152
153 // get existed post
154 if ($this->single_post_id) {
155 $args['post__in'] = [(int) $this->single_post_id];
156 $args['posts_per_page'] = 1;
157 $args['offset'] = 0;
158 }
159
160 if ($this->search_string) {
161 $args['s'] = $this->search_string;
162 }
163
164
165
166 // custom incolumn search
167 if ($this->column_search) {
168
169 unset($args['s']);
170
171 // getting type of search
172 if (substr($this->column_name, 0, 4) == 'acf_') {
173 // acf field
174 $inner_column_name = preg_replace('/[^a-zA-Z0-9_]/', '', substr($this->column_name, 4));
175 $inner_post_type = preg_replace('/[^a-zA-Z0-9_]/', '', $this->postType);
176
177 $wpdb_results = $wpdb->get_col(
178 $wpdb->prepare("SELECT p.ID
179 FROM {$wpdb->posts} p
180 JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
181 WHERE p.post_type = %s
182 AND pm.meta_key = %s
183 AND pm.meta_value LIKE %s",
184
185 $inner_post_type,
186 $inner_column_name,
187 '%' . $wpdb->esc_like( $this->search_string ) . '%'
188
189 )
190 );
191
192 $args['post__in'] = $wpdb_results;
193 } else
194 if (substr($this->column_name, 0, 8) == 'plugins_') {
195 // custom plugin
196 $inner_column_name = preg_replace('/[^a-zA-Z0-9_]/', '', substr($this->column_name, 8));
197 $inner_post_type = preg_replace('/[^a-zA-Z0-9_]/', '', $this->postType);
198
199 $wpdb_results = $wpdb->get_col(
200 $wpdb->prepare("SELECT p.ID
201 FROM {$wpdb->posts} p
202 JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
203 WHERE p.post_type = %s
204 AND pm.meta_key = %s
205 AND pm.meta_value LIKE %s
206 ",
207 $inner_post_type,
208 $inner_column_name,
209 '%' . $wpdb->esc_like( $this->search_string ) . '%'
210 )
211 );
212
213 $args['post__in'] = $wpdb_results;
214 } else {
215 // default fields
216 $column_name = preg_replace('/[^a-zA-Z0-9_]/', '', $this->column_name);
217 $wpdb_results = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->prefix}posts WHERE %i LIKE %s ", $column_name, '%' . $this->search_string . '%'));
218 $args['post__in'] = $wpdb_results;
219 }
220 }
221
222 // column filtering
223 // custom incolumn search
224 if ($this->column_name && $this->column_type && $this->filtering_values) {
225 unset($args['s']);
226
227 if ($this->column_type == 'acf_select') {
228 // filter by def
229 if (in_array($this->column_name, ['post_status'])) {
230 $args[$this->column_name] = $this->filtering_values;
231 } else
232 if (in_array($this->column_name, ['post_author'])) {
233 $args['author__in'] = $this->filtering_values;
234 } else {
235 // cusotm fields
236 $this->column_name = str_replace('acf_', '', $this->column_name);
237 $this->column_name = str_replace('plugins_', '', $this->column_name);
238 foreach ($this->filtering_values as $s_filter_value) {
239 $args['meta_query']['relation'] = 'OR';
240 $args['meta_query'][] = [
241 'key' => $this->column_name,
242 'value' => '"' . $s_filter_value . '"',
243 'compare' => 'LIKE'
244 ];
245 $args['meta_query'][] = [
246 'key' => $this->column_name,
247 'value' => $s_filter_value
248
249 ];
250 }
251 }
252 }
253
254 if ($this->column_type == 'tag' || $this->column_type == 'taxonomy') {
255 $args['tax_query'][] = [
256 'taxonomy' => $this->column_name,
257 'field' => 'term_id',
258 'terms' => $this->filtering_values,
259 ];
260 }
261
262 if ($this->column_name === 'elementor_active' && $this->column_type === 'switch') {
263 $args = $this->applyElementorActiveFilterToArgs($args, $this->filtering_values);
264 }
265 }
266
267
268 // column query filtering
269 if (count($this->column_query) > 0) {
270 $results_ids_list = [];
271 foreach ($this->column_query as $s_column_query) {
272
273 if ($s_column_query['type'] == 'text') {
274
275 $search_value = preg_replace('/[^a-zA-Z0-9_]/', '', $s_column_query['value']);
276
277 // getting type of search
278 if (substr($s_column_query['name'], 0, 4) == 'acf_') {
279 // acf field
280 $inner_column_name = preg_replace('/[^a-zA-Z0-9_]/', '', substr($s_column_query['name'], 4));
281 $inner_post_type = preg_replace('/[^a-zA-Z0-9_]/', '', $this->postType);
282
283 // phpcs:disable
284 $wpdb_results = $wpdb->get_col($wpdb->prepare("SELECT p.ID
285 FROM {$wpdb->posts} p
286 JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
287 WHERE p.post_type = %s
288 AND pm.meta_key = %s
289 AND pm.meta_value LIKE %s
290 ",
291 $inner_post_type,
292 $inner_column_name,
293 '%' . $wpdb->esc_like( $search_value ) . '%'
294
295 ));
296 // phpcs:enable
297 $results_ids_list[] = $wpdb_results;
298 } else
299 if (substr($s_column_query['name'], 0, 8) == 'plugins_') {
300 // custom plugin
301 $inner_column_name = preg_replace('/[^a-zA-Z0-9_]/', '', substr($s_column_query['name'], 8));
302 $inner_post_type = preg_replace('/[^a-zA-Z0-9_]/', '', $this->postType);
303
304 // phpcs:disable
305 $wpdb_results = $wpdb->get_col($wpdb->prepare("SELECT p.ID
306 FROM {$wpdb->posts} p
307 JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
308 WHERE p.post_type = %s
309 AND pm.meta_key = %s
310 AND pm.meta_value LIKE %s
311 ",
312
313 $inner_post_type,
314 $inner_column_name,
315 '%' . $wpdb->esc_like( $search_value ) . '%'
316
317 ));
318 // phpcs:enable
319 $results_ids_list[] = $wpdb_results;
320 } else {
321 // default fields
322 $column_name = preg_replace('/[^a-zA-Z0-9_]/', '', $s_column_query['name']);
323 $wpdb_results = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->prefix}posts WHERE %i LIKE %s ", $column_name, '%' . $search_value . '%'));
324 $results_ids_list[] = $wpdb_results;
325 }
326 }
327
328 if ($s_column_query['type'] == 'filter' && $s_column_query['value'] !== null) {
329
330 $inner_args = $args;
331
332 if ($s_column_query['column_type'] == 'acf_select') {
333 // filter by def
334 if (in_array($s_column_query['name'], ['post_status'])) {
335 $inner_args[$s_column_query['name']] = $s_column_query['value'];
336 } else
337 if (in_array($s_column_query['name'], ['post_author'])) {
338 $inner_args['author__in'] = $s_column_query['value'];
339 } else {
340 // cusotm fields
341 $s_column_query['name'] = str_replace('acf_', '', $s_column_query['name']);
342 $s_column_query['name'] = str_replace('plugins_', '', $s_column_query['name']);
343 foreach ($s_column_query['value'] as $s_filter_value) {
344 $inner_args['meta_query']['relation'] = 'OR';
345 $inner_args['meta_query'][] = [
346 'key' => $s_column_query['name'],
347 'value' => '"' . $s_filter_value . '"',
348 'compare' => 'LIKE'
349 ];
350 $inner_args['meta_query'][] = [
351 'key' => $s_column_query['name'],
352 'value' => $s_filter_value
353
354 ];
355 }
356 }
357 }
358
359 if ($s_column_query['column_type'] == 'tag' || $s_column_query['column_type'] == 'taxonomy') {
360 $inner_args['tax_query'][] = [
361 'taxonomy' => $s_column_query['name'],
362 'field' => 'term_id',
363 'terms' => $s_column_query['value'],
364 ];
365 }
366
367 if ($s_column_query['name'] === 'elementor_active' && $s_column_query['column_type'] === 'switch') {
368 $inner_args = $this->applyElementorActiveFilterToArgs($inner_args, $s_column_query['value']);
369 }
370 $inner_args['fields'] = 'ids';
371 $inner_args['showposts'] = -1;
372
373 $results_ids_list[] = get_posts($inner_args);
374 }
375
376 if ($s_column_query['type'] == 'calendar' && $s_column_query['value'] !== null) {
377
378 $inner_args = $args;
379
380
381 $inner_args['date_query'] = $this->getDateQueryByRange($s_column_query['value']);
382 $inner_args['fields'] = 'ids';
383 $inner_args['showposts'] = -1;
384
385 $results_ids_list[] = get_posts($inner_args);
386 }
387
388
389 // if all deselected
390 if ($s_column_query['type'] == 'filter' && $s_column_query['value'] === null) {
391 $results_ids_list[] = [];
392 }
393 }
394 $intersected_ids = call_user_func_array('array_intersect', $results_ids_list);
395 if (count($intersected_ids) == 0) {
396 $intersected_ids = [0];
397 }
398 $args['post__in'] = $intersected_ids;
399 }
400
401
402 $this->args = $args;
403 $all_posts = $this->runPostsQuery($args);
404
405 // add new row functionality
406 if ($this->is_new_row) {
407 if ($this->duplicate_post_id) {
408 $new_post_id = SheetsPilotCellEditor::duplicatePostProcessing($this->duplicate_post_id);
409 } else {
410 $post_type_obj = get_post_type_object($this->postType);
411 $new_post_title = SheetsPilotGlobals::$newPostTitle . ' ' . $post_type_obj->labels->singular_name;
412
413 $new_post_id = wp_insert_post([
414 'post_type' => $this->postType,
415 'post_title' => $new_post_title,
416 'post_status' => 'publish',
417 ]);
418 $new_post_slug = explode('-', get_post($new_post_id)->post_name);
419 $new_post_title = SheetsPilotGlobals::$newPostTitle . ' ' . $post_type_obj->labels->singular_name . ' ' . $new_post_slug[count($new_post_slug) - 1];
420
421 if( $this->new_post_title ){
422 $new_post_title = sanitize_text_field( $this->new_post_title );
423 }
424
425 wp_update_post([
426 'ID' => $new_post_id,
427 'post_status' => 'draft',
428 'post_title' => $new_post_title
429 ]);
430
431 if ($this->postType == 'product') {
432 update_post_meta($new_post_id, 'total_sales', 0);
433 update_post_meta($new_post_id, '_tax_status', 'taxable');
434 update_post_meta($new_post_id, '_tax_class', '');
435 update_post_meta($new_post_id, '_manage_stock', 'no');
436 update_post_meta($new_post_id, '_backorders', 'no');
437 update_post_meta($new_post_id, '_sold_individually', 'no');
438 update_post_meta($new_post_id, '_virtual', 'no');
439 update_post_meta($new_post_id, '_downloadable', 'no');
440 update_post_meta($new_post_id, '_download_limit', -1);
441 update_post_meta($new_post_id, '_download_expiry', -1);
442 update_post_meta($new_post_id, '_stock_status', 'instock');
443 wp_set_object_terms($new_post_id, 'simple', 'product_type');
444 }
445 }
446
447 $new_post = get_post($new_post_id);
448 $all_posts = [];
449 $all_posts[] = $new_post;
450 }
451
452 $postTypeOrder = SheetsPilotHelper::getEditorPageSettings($this->postType . '_columns_order');
453 if (!is_array($postTypeOrder)) {
454 $postTypeOrder = [];
455 }
456
457 $post_data_array = [];
458 foreach ($all_posts as $s_post) {
459 $thumbnail_id = get_post_thumbnail_id($s_post->ID);
460 $thumbnail = get_the_post_thumbnail_url($s_post->ID, SheetsPilotUniteFunctionsWP::THUMB_MEDIUM);
461 $thumbnailFull = get_the_post_thumbnail_url($s_post->ID, 'full');
462 $is_placeholder = false;
463 if (!$thumbnail) {
464 $thumbnail = SheetsPilotGlobals::$urlImagePlaceholder;
465 $is_placeholder = true;
466 }
467
468
469 $tmp_array_element = [
470 ['bulk' => $s_post->ID],
471 ['id' => $s_post->ID],
472 ['_sheetspilot_row_meta' => [
473 'is_elementor' => SheetsPilotHelperElementor::isPostBuiltWithElementor( $s_post->ID ),
474 ]],
475 ['post_title' => $s_post->post_title],
476 ['post_excerpt' => $s_post->post_excerpt],
477 ['post_content' => SheetsPilotHelperElementor::getPostContentDisplayForEditor( $s_post->ID )],
478
479 ...( SheetsPilotGlobals::$isElementorActive ?
480 [[
481 'elementor_active' => ( get_post_meta( $s_post->ID, '_elementor_edit_mode', true ) == 'builder' ? 'yes' : 'no' )
482 ]] : []
483 ),
484
485 ['post_name' => urldecode($s_post->post_name)],
486 ['post_author' => ['values' => [$s_post->post_author], 'multiple' => 0]],
487 ['post_status' => ['values' => [$s_post->post_status], 'multiple' => 0]],
488 ['post_date' => $s_post->post_date],
489 ['post_image' => '<img src="' . $thumbnail . '" data-full="' . $thumbnailFull . '" data-img="' . $thumbnail . '" data-id="' . $thumbnail_id . '"' . SheetsPilotHelper::getAttachmentImagePreviewDataAttrs( $thumbnail_id ) . ' class="ubai_featured_image_uploader sp_hover_preview' . ($is_placeholder ? 'is_placeholder' : '') . '" />'],
490 ];
491
492
493
494
495 // all registered taxonomies
496 foreach ($post_type_taxonomies as $s_reg_taxonomy) {
497 $this_taxonomy = get_taxonomy($s_reg_taxonomy);
498
499 /** fix for product to hide product type */
500 if (($this->postType == 'product' && $this_taxonomy->name == 'product_type') || ($this->postType == 'product' && $this_taxonomy->name == 'product_visibility') || ($this->postType == 'product' && $this_taxonomy->name == 'pos_product_visibility')) {
501 continue;
502 }
503
504 if (is_taxonomy_hierarchical($s_reg_taxonomy)) {
505 $tmp_array_element[] = [$this_taxonomy->name => SheetsPilotCellEditor::getCellCategoryContent($s_post->ID, $s_reg_taxonomy)];
506 } else {
507 $post_terms = wp_get_post_terms($s_post->ID, $s_reg_taxonomy, array('fields' => 'ids', 'hide_empty' => false));
508
509 $inner_non_hierarhical_terms['values'] = $post_terms;
510 $inner_non_hierarhical_terms['multiple'] = 1;
511 $tmp_array_element[] = [$this_taxonomy->name => $inner_non_hierarhical_terms];
512 }
513 }
514
515 if ($this->postType == 'attachment') {
516 foreach (SheetsPilotGlobals::$mediaPostTypeFields as $slug => $title) {
517 if( $slug == '_wp_attachment_image_alt' ){
518 $tmp_array_element[]['plugins_' . $slug] = get_post_meta( $s_post->ID, $slug, true );
519 $fields_to_use[] = 'plugins_' . $slug;
520 continue;
521 }
522 if( $slug == '_visual_output' ){
523 $upload_dir = wp_upload_dir();
524 $attach_file_url = trailingslashit( $upload_dir['baseurl'] ).get_post_meta( $s_post->ID, '_wp_attached_file', true );
525 $ext = pathinfo( trailingslashit( $upload_dir['basedir'] ).get_post_meta( $s_post->ID, '_wp_attached_file', true ), PATHINFO_EXTENSION);
526
527 if( in_array( $ext, [ 'jpg', 'jpeg', 'png', 'webp' ] ) ){
528 $preview = wp_get_attachment_image_url( $s_post->ID, 'medium' );
529 $out_html = '
530 <img src="'.esc_attr( $preview ).'" data-full="'.esc_attr( $attach_file_url ).'" data-img="'.esc_attr( $attach_file_url ).'"'.SheetsPilotHelper::getAttachmentImagePreviewDataAttrs( $s_post->ID ).' class="ubai_media_image_output sp_hover_preview">
531 ';
532 }else{
533 $out_html = '<span class="media_file_output dashicons dashicons-'.esc_attr( $ext ).'"></span>';
534 }
535
536
537
538 $tmp_array_element[]['plugins_' . $slug] = $out_html;
539 $fields_to_use[] = 'plugins_' . $slug;
540 continue;
541 }
542 }
543 }
544
545 // add ACF values
546 foreach ($acf_extra_fields as $s_field_data) {
547
548 $defaults = [
549 'multiple' => 0,
550 ];
551
552 $s_field_data = wp_parse_args($s_field_data, $defaults);
553
554 // patch to set multiple = true for checkboxes
555 if ($s_field_data['type'] == 'checkbox') {
556 $s_field_data['multiple'] = 1;
557 }
558
559 //
560 $current_inner_value_out = [];
561 $current_inner_value = get_field($s_field_data['name'], $s_post->ID);
562
563
564 // custom content types processing
565 if ($s_field_data['type'] == 'gallery') {
566 $out_gallery_data = [];
567 switch ($s_field_data['return_format']) {
568 case "array":
569 foreach ((array)$current_inner_value as $s_image) {
570 if( !isset($s_image['ID']) ){ continue; }
571 $out_gallery_data[] = ['id' => $s_image['ID'], 'url' => $s_image['url']];
572 }
573 break;
574 case "url":
575 foreach ($current_inner_value as $s_image_url) {
576 $image_id = SheetsPilotCellEditor::get_image_id_by_url($s_image_url);
577 $out_gallery_data[] = ['id' => (int)$image_id, 'url' => $s_image_url];
578 }
579 break;
580 case "id":
581 foreach ($current_inner_value as $s_image_id) {
582 $out_gallery_data[] = ['id' => $s_image_id, 'url' => wp_get_attachment_url($s_image_id)];
583 }
584 break;
585 }
586
587 $current_inner_value_out['values'] = $out_gallery_data;
588 $current_inner_value = $current_inner_value_out;
589 }
590 if ($s_field_data['type'] == 'image') {
591 //###############
592 if (!$current_inner_value) {
593 $image_id = 0;
594 } else {
595 switch ($s_field_data['return_format']) {
596 case "array":
597 $image_id = $current_inner_value['ID'];
598 break;
599 case "url":
600 $image_id = SheetsPilotCellEditor::get_image_id_by_url($current_inner_value);
601 break;
602 case "id":
603 $image_id = $current_inner_value;
604 break;
605 }
606 }
607
608
609 $thumbnail = wp_get_attachment_url($image_id);
610 $is_placeholder = false;
611 if ($image_id == 0) {
612 $thumbnail = SheetsPilotGlobals::$urlImagePlaceholder;
613 $is_placeholder = true;
614 }
615 $default_placeholder = '<img src="' . $thumbnail . '" data-full="' . $thumbnail . '" data-id="' . $image_id . '"' . SheetsPilotHelper::getAttachmentImagePreviewDataAttrs( $image_id ) . ' class="ubai_featured_image_uploader sp_hover_preview ' . ($is_placeholder ? 'is_placeholder' : '') . '" />';
616
617 $current_inner_value = $default_placeholder;
618 }
619
620
621 // default values for acf
622 if ($s_field_data['type'] == 'select' || $s_field_data['type'] == 'radio' || $s_field_data['type'] == 'checkbox') {
623
624 if ($s_field_data['multiple'] == 0 && !$current_inner_value) {
625 $current_inner_value = '';
626 }
627 if ($s_field_data['multiple'] == 1 && !$current_inner_value) {
628 $current_inner_value = [];
629 }
630
631
632 // patch if switched from multi to single
633 // -----
634 // return array patch
635 if ($s_field_data['return_format'] == 'array') {
636 if (is_array($current_inner_value)) {
637
638 if (isset($current_inner_value['value'])) {
639 $current_inner_value = $current_inner_value['value'];
640 } else {
641 $current_inner_value_tmp = [];
642 foreach ($current_inner_value as $s_cur_val) {
643 $current_inner_value_tmp[] = $s_cur_val['value'];
644 }
645 $current_inner_value = $current_inner_value_tmp;
646 }
647 } else {
648 $current_inner_value = [];
649 }
650 }
651
652
653
654
655 // if return labels - get values from labels
656 if ($s_field_data['return_format'] == 'label' && $s_field_data['multiple'] == 1) {
657 $tmp_inner_values = [];
658 foreach ($s_field_data['choices'] as $key => $value) {
659 if (in_array($value, $current_inner_value)) {
660 $tmp_inner_values[] = $key;
661 }
662 }
663
664 $current_inner_value = $tmp_inner_values;
665 }
666
667
668 if ($s_field_data['return_format'] == 'label' && $s_field_data['multiple'] == 0) {
669 $tmp_inner_values = [];
670 foreach ($s_field_data['choices'] as $key => $value) {
671 if ($value == $current_inner_value) {
672 $tmp_inner_values = $key;
673 }
674 }
675
676 $current_inner_value = $tmp_inner_values;
677 }
678
679
680
681
682 if ($s_field_data['multiple'] == 0) {
683 $current_inner_value = [$current_inner_value];
684 }
685 if ($s_field_data['multiple'] == 1) {
686 $current_inner_value = $current_inner_value;
687 }
688
689 /** def val try */
690 if ($s_field_data['multiple'] == 0) {
691 if (!$current_inner_value || $current_inner_value == '') {
692 $current_inner_value = $s_field_data['default_value'];
693 }
694 }
695 if ($s_field_data['multiple'] == 1) {
696 if (!$current_inner_value || count($current_inner_value) == 0) {
697 $current_inner_value = $s_field_data['default_value'];
698 }
699 }
700
701 /** def val try END */
702
703
704 $current_inner_value_out['values'] = $current_inner_value;
705 $current_inner_value_out['multiple'] = $s_field_data['multiple'];
706
707
708 $current_inner_value = $current_inner_value_out;
709 }
710
711
712
713
714 if ($s_field_data['type'] == 'post_object') {
715
716 if ($s_field_data['multiple'] == 0 && !$current_inner_value) {
717 $current_inner_value = '';
718 }
719 if ($s_field_data['multiple'] == 1 && !$current_inner_value) {
720 $current_inner_value = [];
721 }
722
723 $filter_taxonomy_data = [];
724 if ($s_field_data['taxonomy'] != '') {
725 foreach ($s_field_data['taxonomy'] as $s_tax) {
726 $s_tax_data = explode(':', $s_tax);
727 $filter_taxonomy_data[$s_tax_data[0]][] = $s_tax_data[1];
728 }
729 }
730 $posts_args = [
731 'post_type' => ($s_field_data['post_type'] == '' ? 'any' : $s_field_data['post_type']),
732 'post_status' => ($s_field_data['post_status'] == '' ? 'any' : $s_field_data['post_status']),
733 'showposts' => -1,
734 ];
735
736 if (count($filter_taxonomy_data) > 0) {
737 foreach ($filter_taxonomy_data as $s_tax_name => $tax_value) {
738 $posts_args['tax_query'][] = [
739 'taxonomy' => $s_tax_name,
740 'field' => 'slug',
741 'terms' => $tax_value
742 ];
743 }
744 }
745
746 $all_posts = get_posts($posts_args);
747
748 $posts_list = [];
749 $posts_list[] = ['id' => '', 'name' => SheetsPilotGlobals::$selectPost];
750 foreach ($all_posts as $s_post_inner) {
751 $posts_list[] = ['id' => $s_post_inner->ID, 'name' => $s_post_inner->post_title];
752 }
753
754 if ($s_field_data['multiple'] == 0) {
755
756 if ($s_field_data['return_format'] == 'object') {
757 if ($current_inner_value != '') {
758 $current_inner_value_out['posts'][] = ['id' => $current_inner_value->ID, 'post_title' => $current_inner_value->post_title];
759 $current_inner_value_out['postswname'][] = ['id' => $current_inner_value->ID, 'name' => $current_inner_value->post_title];
760 }
761 } else {
762
763 $current_inner_value_out['posts'][] = ['id' => $current_inner_value, 'post_title' => get_post($current_inner_value)->post_title];
764 $current_inner_value_out['postswname'][] = ['id' => $current_inner_value, 'name' => get_post($current_inner_value)->post_title];
765 }
766 } else {
767 foreach ($current_inner_value as $single_current_value) {
768 if ($s_field_data['return_format'] == 'object') {
769 if ($current_inner_value != '') {
770 $current_inner_value_out['posts'][] = ['id' => $single_current_value->ID, 'post_title' => $single_current_value->post_title];
771 $current_inner_value_out['postswname'][] = ['id' => $single_current_value->ID, 'name' => $single_current_value->post_title];
772 }
773 } else {
774 $current_inner_value_out['posts'][] = ['id' => $single_current_value, 'post_title' => get_post($single_current_value)->post_title];
775 $current_inner_value_out['postswname'][] = ['id' => $single_current_value, 'name' => get_post($single_current_value)->post_title];
776 }
777 }
778 }
779
780 $current_inner_value_out['options'] = $posts_list;
781 $current_inner_value_out['multiple'] = $s_field_data['multiple'];
782
783 $current_inner_value = $current_inner_value_out;
784 }
785
786
787
788 if ($s_field_data['type'] == 'repeater') {
789
790
791 $current_inner_value_out = [];
792 $current_inner_value_out['values'] = SheetsPilotCellEditor::acf_repeater_get_items($s_field_data['name'], $s_post->ID);
793
794 $current_inner_value = $current_inner_value_out;
795 }
796
797
798 if ($s_field_data['type'] == "wysiwyg") {
799 if ($current_inner_value) {
800 $current_inner_value = substr(wp_strip_all_tags($current_inner_value), 0, 100);
801 } else {
802 $current_inner_value = '';
803 }
804 }
805
806 $tmp_array_element[]['acf_' . $s_field_data['name']] = ($current_inner_value ? $current_inner_value : '');
807 }
808
809 // add filter for plugins
810
811 $tmp_array_element = apply_filters('sheetspilot_filter_table_values', $tmp_array_element, $this->postType, $s_post->ID );
812 $fields_to_use = apply_filters('sheetspilot_filter_table_fields', $fields_to_use, $this->postType, $s_post->ID );
813
814
815 // custom fields from plugins
816 foreach (SheetsPilotGlobals::$rankMathFields as $slug => $title) {
817 $tmp_array_element[]['plugins_' . $slug] = get_post_meta($s_post->ID, $slug, true);
818 $fields_to_use[] = 'plugins_' . $slug;
819 continue;
820 }
821 // custom fields from plugins
822 foreach (SheetsPilotGlobals::$yoastFields as $slug => $title) {
823 $tmp_array_element[]['plugins_' . $slug] = get_post_meta($s_post->ID, $slug, true);
824 $fields_to_use[] = 'plugins_' . $slug;
825 continue;
826 }
827 // SEOPress
828 foreach (SheetsPilotGlobals::$seoPress as $slug => $title) {
829 $tmp_array_element[]['plugins_' . $slug] = get_post_meta($s_post->ID, $slug, true);
830 $fields_to_use[] = 'plugins_' . $slug;
831 continue;
832 }
833
834
835
836
837 if ($this->postType == 'product') {
838 foreach (SheetsPilotGlobals::$wooCommerceFields as $slug => $title) {
839
840
841 if ($slug == '_featured') {
842 $product = wc_get_product($s_post->ID);
843 $tmp_array_element[]['plugins_' . $slug] = ($product->is_featured() ? 'yes' : 'no');
844 $fields_to_use[] = 'plugins_' . $slug;
845 continue;
846 }
847 if ($slug == '_visible_in_pos') {
848 $tmp_array_element[]['plugins_' . $slug] = (has_term('pos-hidden', 'pos_product_visibility', $s_post->ID) ? 'no' : 'yes');
849 $fields_to_use[] = 'plugins_' . $slug;
850 continue;
851 }
852 if ($slug == '_product_visibility') {
853 $tmp_array_element[]['plugins_' . $slug] = $product->get_catalog_visibility();
854 $fields_to_use[] = 'plugins_' . $slug;
855 continue;
856 }
857 if ($slug == 'product_type') {
858
859 $out_product_type = 'simple';
860 $product_type = wp_get_object_terms($s_post->ID, 'product_type');
861 if (!empty($product_type) && !is_wp_error($product_type)) {
862 $out_product_type = $product_type[0]->slug;
863 }
864 $current_inner_value_out = [];
865 $current_inner_value_out['values'] = [$out_product_type];
866 $current_inner_value_out['multiple'] = 0;
867
868 $tmp_array_element[]['plugins_' . $slug] = $current_inner_value_out;
869 $fields_to_use[] = 'plugins_' . $slug;
870 continue;
871 }
872 if ($slug == '_upsell_ids' || $slug == '_crosssell_ids') {
873
874 $posts_list = get_post_meta($s_post->ID, $slug, true);
875
876 $current_inner_value_out = [];
877 foreach ($posts_list as $s_post_id) {
878 $current_inner_value_out['posts'][] = ['id' => $s_post_id, 'post_title' => get_post($s_post_id)->post_title];
879 $current_inner_value_out['postswname'][] = ['id' => $s_post_id, 'name' => get_post($s_post_id)->post_title];
880 }
881
882 $current_inner_value_out['values'] = get_post_meta($s_post->ID, $slug, true);
883 $current_inner_value_out['multiple'] = 1;
884
885
886 $tmp_array_element[]['plugins_' . $slug] = $current_inner_value_out;
887 $fields_to_use[] = 'plugins_' . $slug;
888 continue;
889 }
890 if ($slug == 'attributes') {
891 $product = wc_get_product($s_post->ID);
892 $attributes = $product->get_attributes();
893 $count = count($attributes);
894
895
896 $current_inner_value_out = [];
897 $current_inner_value_out['values'] = $count;
898
899 $tmp_array_element[]['plugins_' . $slug] = $current_inner_value_out;
900 $fields_to_use[] = 'plugins_' . $slug;
901 continue;
902 }
903 if ($slug == '_product_image_gallery') {
904 $images = explode(',', get_post_meta($s_post->ID, '_product_image_gallery', true));
905 $images = array_filter($images);
906
907 $out_gallery_data = [];
908 foreach ($images as $s_image_id) {
909 $out_gallery_data[] = ['id' => $s_image_id, 'url' => wp_get_attachment_url($s_image_id)];
910 }
911
912
913 $current_inner_value_out = [];
914 $current_inner_value_out['values'] = $out_gallery_data;
915
916 $tmp_array_element[]['plugins_' . $slug] = $current_inner_value_out;
917 $fields_to_use[] = 'plugins_' . $slug;
918 continue;
919 }
920
921 $tmp_array_element[]['plugins_' . $slug] = get_post_meta($s_post->ID, $slug, true);
922 $fields_to_use[] = 'plugins_' . $slug;
923 }
924 }
925
926
927 if ($this->postType == 'tribe_events') {
928 foreach (SheetsPilotGlobals::$theEventsCalendarFileds as $slug => $title) {
929
930 $tmp_array_element[]['plugins_' . $slug] = get_post_meta($s_post->ID, $slug, true);
931 $fields_to_use[] = 'plugins_' . $slug;
932 }
933 }
934
935
936 // SheetsPilotFunctions::writeDebugFile( dirname( __FILE__ ) . '/$filterdata.txt', array(
937 // 'tmp_array_element' => $tmp_array_element,
938 // 'fields_to_use' => $fields_to_use,
939 // ) );
940
941 // ordering fileterin
942 $tmp_array_element = array_values(
943 array_filter($tmp_array_element, function ($item) use ($fields_to_use) {
944 $key = array_key_first($item);
945 return in_array($key, $fields_to_use, true);
946 })
947 );
948
949
950
951 // order elements if single
952 /*
953 if( $this->is_new_row ){
954
955 $saved_columns_order = SheetsPilotHelper::getEditorPageSettings( SheetsPilotHelper::getEditorPageSettings( 'post_type' ).'_columns_order' );
956 $this->ordered_array = [];
957
958 foreach ($saved_columns_order as $key) {
959 foreach ($tmp_array_element as $item) {
960 if (array_key_exists($key, $item)) {
961 $this->ordered_array[] = $item;
962 break;
963 }
964 }
965 }
966 $tmp_array_element = $this->ordered_array;
967 }
968 */
969 // order elements if single END
970
971
972 $post_data_array[] = $tmp_array_element;
973 }
974
975
976
977 return $post_data_array;
978 }
979
980 /**
981 * get_total_post_count
982 */
983 public function getTotoalPostCount()
984 {
985 $this->args['showposts'] = -1;
986 $this->args['fields'] = 'ids';
987
988
989
990 return count(get_posts($this->args));
991 }
992
993
994 /**
995 * get posts by date range
996 */
997 function getDateQueryByRange($range)
998 {
999
1000 // date range
1001 if (is_array($range)) {
1002 return [
1003 [
1004 'after' => wp_date('Y-m-d', strtotime( $range[0] ) ),
1005 'before' => wp_date('Y-m-d 23:59:59', strtotime( $range[1] ) ),
1006 'inclusive' => true,
1007 ]
1008 ];
1009 }
1010
1011 $today = current_time('timestamp'); // важно для WP timezone
1012
1013 switch ($range) {
1014
1015 case 'today':
1016 return [
1017 [
1018 'year' => wp_date('Y', $today),
1019 'month' => wp_date('m', $today),
1020 'day' => wp_date('d', $today),
1021 ]
1022 ];
1023
1024 case 'last_7_days':
1025 return [
1026 [
1027 'after' => wp_date('Y-m-d', strtotime('-6 days', $today)),
1028 'before' => wp_date('Y-m-d 23:59:59', $today),
1029 'inclusive' => true,
1030 ]
1031 ];
1032
1033 case 'last_30_days':
1034 return [
1035 [
1036 'after' => wp_date('Y-m-d', strtotime('-29 days', $today)),
1037 'before' => wp_date('Y-m-d 23:59:59', $today),
1038 'inclusive' => true,
1039 ]
1040 ];
1041
1042 case 'last_3_months':
1043 return [
1044 [
1045 'after' => wp_date('Y-m-d', strtotime('-3 months', $today)),
1046 'before' => wp_date('Y-m-d 23:59:59', $today),
1047 'inclusive' => true,
1048 ]
1049 ];
1050
1051 case 'last_6_months':
1052 return [
1053 [
1054 'after' => wp_date('Y-m-d', strtotime('-6 months', $today)),
1055 'before' => wp_date('Y-m-d 23:59:59', $today),
1056 'inclusive' => true,
1057 ]
1058 ];
1059
1060 case 'last_12_months':
1061 return [
1062 [
1063 'after' => wp_date('Y-m-d', strtotime('-12 months', $today)),
1064 'before' => wp_date('Y-m-d 23:59:59', $today),
1065 'inclusive' => true,
1066 ]
1067 ];
1068
1069 case 'this_year':
1070 return [
1071 [
1072 'after' => wp_date('Y-01-01', $today),
1073 'before' => wp_date('Y-m-d 23:59:59', $today),
1074 'inclusive' => true,
1075 ]
1076 ];
1077 }
1078
1079 return [];
1080 }
1081
1082 /**
1083 * Apply Elementor active column filter values to a WP_Query args array.
1084 *
1085 * @param array $args Query args.
1086 * @param array $filter_values Selected values: 'yes' (Elementor) and/or 'no' (Non Elementor).
1087 * @return array
1088 */
1089 private function applyElementorActiveFilterToArgs($args, $filter_values)
1090 {
1091 if (empty($filter_values) || ! is_array($filter_values)) {
1092 return $args;
1093 }
1094
1095 $filter_values = array_values(array_intersect($filter_values, ['yes', 'no']));
1096 if (count($filter_values) === 0 || count($filter_values) === 2) {
1097 return $args;
1098 }
1099
1100 if (! isset($args['meta_query'])) {
1101 $args['meta_query'] = [];
1102 }
1103
1104 if (in_array('yes', $filter_values, true)) {
1105 $args['meta_query'][] = [
1106 'key' => '_elementor_edit_mode',
1107 'value' => 'builder',
1108 'compare' => '=',
1109 ];
1110 } else {
1111 $args['meta_query'][] = [
1112 'relation' => 'OR',
1113 [
1114 'key' => '_elementor_edit_mode',
1115 'compare' => 'NOT EXISTS',
1116 ],
1117 [
1118 'key' => '_elementor_edit_mode',
1119 'value' => 'builder',
1120 'compare' => '!=',
1121 ],
1122 ];
1123 }
1124
1125 return $args;
1126 }
1127
1128 /**
1129 * Sort by Elementor active column: ASC = Non Elementor first, DESC = Elementor first.
1130 *
1131 * @param array $args Query args.
1132 * @param string $order Sort direction: asc|desc.
1133 * @return array
1134 */
1135 private function applyElementorActiveSortToArgs($args, $order)
1136 {
1137 $sort_order = strtoupper($order) === 'DESC' ? 'DESC' : 'ASC';
1138 $args['sheetspilot_elementor_active_sort'] = $sort_order;
1139 $args['orderby'] = 'ID';
1140 $args['order'] = 'DESC';
1141 $args['suppress_filters'] = false;
1142
1143 return $args;
1144 }
1145
1146 /**
1147 * Run get_posts(), attaching a LEFT JOIN sort for Elementor when requested.
1148 *
1149 * @param array $args Query args.
1150 * @return array
1151 */
1152 private function runPostsQuery($args)
1153 {
1154 if (! empty($args['sheetspilot_elementor_active_sort'])) {
1155 add_filter('posts_clauses', array($this, 'filterPostsClausesForElementorActiveSort'), 10, 2);
1156 }
1157
1158 $posts = get_posts($args);
1159
1160 if (! empty($args['sheetspilot_elementor_active_sort'])) {
1161 remove_filter('posts_clauses', array($this, 'filterPostsClausesForElementorActiveSort'), 10);
1162 }
1163
1164 return $posts;
1165 }
1166
1167 /**
1168 * Order all posts by Elementor status without excluding posts missing the meta key.
1169 *
1170 * @param array $clauses SQL clauses.
1171 * @param \WP_Query $query Current query.
1172 * @return array
1173 */
1174 public function filterPostsClausesForElementorActiveSort($clauses, $query)
1175 {
1176 $sort_order = $query->get('sheetspilot_elementor_active_sort');
1177 if (! $sort_order) {
1178 return $clauses;
1179 }
1180
1181 global $wpdb;
1182
1183 $sort_order = strtoupper($sort_order) === 'DESC' ? 'DESC' : 'ASC';
1184 $clauses['join'] .= " LEFT JOIN {$wpdb->postmeta} AS sheetspilot_elementor_sort ON ({$wpdb->posts}.ID = sheetspilot_elementor_sort.post_id AND sheetspilot_elementor_sort.meta_key = '_elementor_edit_mode')";
1185 $clauses['groupby'] = "{$wpdb->posts}.ID";
1186 $clauses['orderby'] = "(CASE WHEN sheetspilot_elementor_sort.meta_value = 'builder' THEN 1 ELSE 0 END) {$sort_order}, {$wpdb->posts}.ID DESC";
1187
1188 return $clauses;
1189 }
1190 }
1191