Changeset 2844136
- Timestamp:
- 01/05/2023 02:49:33 PM (3 years ago)
- Location:
- setary
- Files:
-
- 2 added
- 8 edited
- 1 copied
-
tags/1.0.0 (copied) (copied from setary/trunk)
-
tags/1.0.0/README.md (modified) (2 diffs)
-
tags/1.0.0/inc/bootstrap.php (modified) (1 diff)
-
tags/1.0.0/inc/class-meta.php (added)
-
tags/1.0.0/inc/class-products-with-variations.php (modified) (6 diffs)
-
tags/1.0.0/setary.php (modified) (3 diffs)
-
trunk/README.md (modified) (2 diffs)
-
trunk/inc/bootstrap.php (modified) (1 diff)
-
trunk/inc/class-meta.php (added)
-
trunk/inc/class-products-with-variations.php (modified) (6 diffs)
-
trunk/setary.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
setary/tags/1.0.0/README.md
r2823229 r2844136 1 1 === Setary — Inventory Management for WooCommerce === 2 2 Requires at least: 5.7 3 Tested up to: 6. 0.23 Tested up to: 6.1.1 4 4 Requires PHP: 5.6 5 Stable tag: 0.5.15 Stable tag: 1.0.0 6 6 License: MIT 7 7 License URI: https://opensource.org/licenses/MIT … … 54 54 == Changelog == 55 55 56 = v1.0.0 (2023-01-05) = 57 * [new] Enabled [column filtering](https://setary.com/docs/how-to-filter-products-in-setary/?utm_source=setary&utm_medium=changelog) 58 * [new] Enabled [meta data columns](https://setary.com/docs/how-to-edit-product-meta-data-in-setary/?utm_source=setary&utm_medium=changelog) 59 * [new] Enabled [column show/hide](https://setary.com/docs/how-to-show-hide-columns-in-setary/?utm_source=setary&utm_medium=changelog) 60 56 61 = v0.5.1 (2022-11-23) = 57 62 * [fix] Fix string declaration error for < PHP8 -
setary/tags/1.0.0/inc/bootstrap.php
r2795354 r2844136 37 37 'upload_image' => __NAMESPACE__ . '\\Upload_Image', 38 38 'media_list' => __NAMESPACE__ . '\\Media_List', 39 'meta' => __NAMESPACE__ . '\\Meta', 39 40 // https://setary.wp.loc/wp-json/wc/setary/info/. 40 41 'info' => __NAMESPACE__ . '\\Info', -
setary/tags/1.0.0/inc/class-products-with-variations.php
r2822462 r2844136 14 14 use WP_REST_Request; 15 15 use WP_REST_Server; 16 17 18 /** 19 * Helper internal class to work with WHERE SQL to use as closures 20 * 21 * @package Setary 22 */ 23 class FilterByBetween { 24 public function __construct($query, $data) { 25 $this->query = $query; 26 $this->data = $data; 27 } 28 29 30 public function filter($where = '') { 31 global $wpdb; 32 33 $where .= call_user_func_array([ $wpdb, 'prepare' ], array_merge( [$this->query], $this->data )); 34 35 return $where; 36 } 37 } 16 38 17 39 /** … … 142 164 // 63 => 'grouped_products', 143 165 // 64 => 'menu_order', 144 //65 => 'meta_data',166 65 => 'meta_data', 145 167 ]; 146 168 147 169 $request->set_param( '_fields', $params ); 148 170 171 /** 172 * Ensure we get the variation image ID, and not the parent product image ID. 173 * 174 * @see WC_Product_Variation::get_image_id() 175 */ 176 add_filter( 'woocommerce_product_variation_get_image_id', function( $image_id, $product ) { 177 return $product->get_image_id( 'edit' ); 178 }, 10, 2 ); 179 180 /** 181 * Prevent shuffling of related products. 182 */ 149 183 add_filter( 'woocommerce_product_related_posts_shuffle', '__return_false' ); 150 184 … … 159 193 * @return array 160 194 */ 195 161 196 public function filter_response_by_context( $data, $context ) { 162 197 $item = parent::filter_response_by_context( $data, $context ); … … 171 206 $item['formatted_cross_sell_ids'] = $this->format_ids( $item['cross_sell_ids'] ); 172 207 208 // If manage stock is "parent", then really it means "No". 209 $item['manage_stock'] = $item['manage_stock'] && 'parent' !== $item['manage_stock']; 210 173 211 return $item; 174 212 } … … 193 231 */ 194 232 public function get_items( $request ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded -- WordPress code 195 196 /* 197 SELECT id FROM wp_posts pp WHERE post_type IN('product', 'product_variation') AND ((pp.post_status <> 'trash' AND pp.post_status <> 'auto-draft')) ORDER BY IF(pp.post_parent > 0, pp.post_parent, pp.id), pp.id; 198 */ 233 global $wpdb; 234 235 $this->filters = json_decode( $request->get_param('filters'), true ); 199 236 200 237 $query_args = $this->prepare_objects_query( $request ); 201 238 $query_args['post_type'] = [ 'product', 'product_variation' ]; 239 240 foreach($this->filters as $filter) { 241 if( ! $filter['active'] ) { 242 continue; 243 } 244 245 if( empty( $filter['from'] ) ) { 246 $filter['from'] = 0; 247 } 248 if( empty( $filter['to'] ) ) { 249 $filter['to'] = PHP_INT_MAX; 250 } 251 252 $key = isset($filter['filterData']) && !empty($filter['filterData']) ? $filter['filterData'] : $filter['data']; 253 254 if( ! empty( $filter['taxonomy'] ) && 'query' === $filter['mode'] ) { 255 $terms = get_terms( $filter['taxonomy'], [ 'search' => $filter['query'], 'fields' => 'ids' ] ); 256 257 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 258 $query_args, 259 array( 260 'taxonomy' => $filter['taxonomy'], 261 'field' => 'term_id', 262 'operator' => 'IN', 263 'terms' => $terms, 264 ) 265 ); 266 continue; 267 } 268 269 if ( ! empty( $filter['mode'] ) && 'empty' === $filter['mode'] ) { 270 if( 'name' === $key ) { 271 add_filter( 'posts_where', [ new FilterByBetween(" AND ({$wpdb->prefix}posts.post_title IS NULL OR {$wpdb->prefix}posts.post_title = '')", array()), 'filter' ]); 272 } else if( 'slug' === $key ) { 273 add_filter( 'posts_where', [ new FilterByBetween(" AND ({$wpdb->prefix}posts.post_name IS NULL OR {$wpdb->prefix}posts.post_name = '')", array()), 'filter' ]); 274 } else if( ! empty( $filter['taxonomy'] ) ) { 275 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 276 $query_args, 277 [ 278 'relation' => 'OR', 279 [ 280 'taxonomy' => $filter['taxonomy'], 281 'operator' => 'NOT EXISTS', 282 ], 283 [ 284 'taxonomy' => $filter['taxonomy'], 285 'field' => 'slug', 286 'operator' => 'IN', 287 'terms' => ['uncategorized'], 288 ] 289 ] 290 ); 291 } else if( in_array( $key, [ '_sku', '_regular_price', '_sale_price', '_stock' ], true) ) { 292 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 293 $query_args, 294 [ 295 'relation' => 'OR', 296 [ 297 'key' => $key, 298 'value' => '', 299 'compare' => '=', 300 ], 301 [ 302 'key' => $key, 303 'value' => '0', 304 'compare' => '=', 305 ], 306 [ 307 'key' => $key, 308 'compare' => 'NOT EXISTS', 309 'value' => 'null', 310 ] 311 ] 312 ); 313 } else { 314 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 315 $query_args, 316 [ 317 'relation' => 'OR', 318 [ 319 'key' => $key, 320 'value' => '', 321 'compare' => '=', 322 ], 323 [ 324 'key' => $key, 325 'value' => '0', 326 'compare' => '=', 327 ], 328 [ 329 'key' => $key, 330 'compare' => 'NOT EXISTS', 331 'value' => 'null', 332 ] 333 ] 334 ); 335 } 336 continue; 337 } 338 339 if( 'id' === $key ) { 340 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.ID BETWEEN %d AND %d", array( floatval($filter['from']), floatval($filter['to']) )), 'filter' ]); 341 } else if( 'type' === $key ) { 342 if( in_array( 'variation', $filter['query'], true ) ) { 343 $query_args['post_type'] = [ 'product_variation' ]; 344 } else { 345 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 346 $query_args, 347 array( 348 'taxonomy' => 'product_type', 349 'field' => 'slug', 350 'terms' => $filter['query'], 351 ) 352 ); 353 } 354 } else if( 'parent_id' === $key ) { 355 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.post_parent BETWEEN %d AND %d", array( floatval($filter['from']), floatval($filter['to']) )), 'filter' ]); 356 } else if( 'name' === $key ) { 357 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.post_title LIKE %s", array( '%' . $filter['query'] . '%' )), 'filter' ]); 358 } else if( 'slug' === $key ) { 359 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.post_name LIKE %s", array( '%' . $filter['query'] . '%' )), 'filter' ]); 360 } else if( in_array( $key, [ 'backorders', 'manage_stock' ], true) ) { 361 // if( 'manage_stock' === $key && in_array('parent', $filter['query']) ) { 362 // continue; 363 // } else { 364 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 365 $query_args, 366 array( 367 'key' => '_' . $key, 368 'value' => $filter['query'], 369 'compare' => 'IN', 370 ) 371 ); 372 // } 373 } else if( 'featured' === $key ) { 374 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 375 $query_args, 376 array( 377 'taxonomy' => 'product_visibility', 378 'field' => 'slug', 379 'operator' => in_array( 'no', $filter['query'], true ) ? 'NOT IN' : 'IN', 380 'terms' => ['featured'], 381 ) 382 ); 383 } else if( in_array( $key, [ 'catalog_visibility' ], true) ) { 384 $terms = []; 385 386 // public/wp/wp-content/plugins/woocommerce/includes/data-stores/class-wc-product-data-store-cpt.php:411 387 388 if(!in_array( 'visible', $filter['query'], true )) { 389 if( in_array( 'search', $filter['query'], true ) ) { 390 $terms['exclude-from-catalog'] = 'exclude-from-catalog'; 391 } 392 if( in_array( 'catalog', $filter['query'], true ) ) { 393 $terms['exclude-from-search'] = 'exclude-from-search'; 394 } 395 if( in_array( 'hidden', $filter['query'], true ) ) { 396 $terms['exclude-from-catalog'] = 'exclude-from-search'; 397 $terms['exclude-from-search'] = 'exclude-from-search'; 398 } 399 400 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 401 $query_args, 402 array( 403 'taxonomy' => 'product_visibility', 404 'field' => 'slug', 405 'operator' => 'IN', 406 'terms' => $terms, 407 ) 408 ); 409 } 410 } else if( 'status' === $key ) { 411 $query_args['post_status'] = $filter['query']; 412 } else if( 'images' === $key ) { 413 global $wpdb; 414 415 $sql = trim(" 416 SELECT post_id from ( 417 SELECT pm.post_id, SUM((CHAR_LENGTH(meta_value) - CHAR_LENGTH(REPLACE(meta_value, ',', '')) + 1)) cou FROM {$wpdb->prefix}postmeta pm WHERE pm.meta_key IN('_product_image_gallery', '_thumbnail_id') GROUP BY pm.post_id 418 ) p WHERE 1 %s; 419 "); 420 421 if('one' === $filter['mode']) { 422 $sql = sprintf($sql, ' AND cou = 1 '); 423 $ids = $wpdb->get_col($sql); 424 425 $query_args['post__in'] = $ids; 426 } else if('many' === $filter['mode']) { 427 $sql = sprintf($sql, ' AND cou > 1 '); 428 $ids = $wpdb->get_col($sql); 429 430 $query_args['post__in'] = $ids; 431 } else if('no' === $filter['mode']) { 432 $ids = $wpdb->get_col(sprintf($sql, '')); 433 $query_args['post__not_in'] = $ids; 434 } else if('query' === $filter['mode']) { 435 $attachment_ids = get_posts([ 436 'post_type' => 'attachment', 437 'posts_per_page' => -1, 438 's' => $filter['query'], 439 'fields' => 'ids' 440 ]); 441 442 $sql = trim(" 443 SELECT post_id from ( 444 SELECT pm.post_id, GROUP_CONCAT(pm.meta_value) imgs FROM {$wpdb->prefix}postmeta pm WHERE pm.meta_key IN('_product_image_gallery', '_thumbnail_id') GROUP BY pm.post_id 445 ) p WHERE p.imgs REGEXP %s; 446 "); 447 $match = []; 448 foreach ($attachment_ids as $attachment_id) { 449 $match[] = '((?:,|^)' . $attachment_id . '(?:,|$))'; 450 } 451 452 $ids = $wpdb->get_col($wpdb->prepare($sql, implode('|', $match))); 453 $query_args['post__in'] = $ids; 454 } 455 } else if( ! empty( $filter['query'] ) ) { 456 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 457 $query_args, 458 array( 459 'key' => $key, 460 'value' => $filter['query'], 461 'compare' => is_array($filter['query']) ? 'IN' : 'LIKE', 462 ) 463 ); 464 } else if( $filter['type'] === 'numeric' ) { 465 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 466 $query_args, 467 array( 468 'key' => $key, 469 'value' => array( floatval($filter['from']), floatval($filter['to']) ), 470 'type' => 'numeric', 471 'compare' => 'BETWEEN', 472 ) 473 ); 474 } 475 } 202 476 203 477 if ( is_wp_error( current( $query_args ) ) ) { … … 263 537 264 538 /** 539 * Push tax query to object with AND condition 540 * 541 * @param array $args Query args. 542 * @param array $meta_query Meta query. 543 * @return mixed array 544 */ 545 protected function add_tax_query( $args, $tax_query ) { 546 if ( empty( $args['tax_query'] ) ) { 547 $args['tax_query'] = array(); 548 } 549 550 $args['tax_query'][] = $tax_query; 551 552 return $args['tax_query']; 553 } 554 555 protected function get_attributes( $product ) { 556 $attributes = array(); 557 558 if ( $product->is_type( 'variation' ) ) { 559 $_product = wc_get_product( $product->get_parent_id() ); 560 foreach ( $product->get_variation_attributes() as $attribute_name => $attribute ) { 561 $name = str_replace( 'attribute_', '', $attribute_name ); 562 563 if ( empty( $attribute ) && '0' !== $attribute ) { 564 continue; 565 } 566 567 // Taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`. 568 if ( 0 === strpos( $attribute_name, 'attribute_pa_' ) ) { 569 $option_term = get_term_by( 'slug', $attribute, $name ); 570 $attributes[] = array( 571 'id' => wc_attribute_taxonomy_id_by_name( $name ), 572 'name' => $this->get_attribute_taxonomy_name( $name, $_product ), 573 'option' => $option_term && ! is_wp_error( $option_term ) ? $option_term->name : $attribute, 574 ); 575 } else { 576 $attributes[] = array( 577 'id' => 0, 578 'slug' => $name, 579 'name' => $this->get_attribute_taxonomy_name( $name, $_product ), 580 'option' => $attribute, 581 ); 582 } 583 } 584 } else { 585 foreach ( $product->get_attributes() as $attribute ) { 586 $attributes[] = array( 587 'id' => $attribute['is_taxonomy'] ? wc_attribute_taxonomy_id_by_name( $attribute['name'] ) : 0, 588 'taxonomy' => $attribute['is_taxonomy'] ? $attribute['name'] : null, 589 'name' => $this->get_attribute_taxonomy_name( $attribute['name'], $product ), 590 'position' => (int) $attribute['position'], 591 'visible' => (bool) $attribute['is_visible'], 592 'variation' => (bool) $attribute['is_variation'], 593 'options' => $this->get_attribute_options( $product->get_id(), $attribute ), 594 ); 595 } 596 } 597 598 return $attributes; 599 } 600 601 /** 265 602 * Format categories for response. 266 603 * -
setary/tags/1.0.0/setary.php
r2823229 r2844136 10 10 * Author: Setary 11 11 * 12 * Version: 0.5.112 * Version: 1.0.0 13 13 * Requires at least: 5.7 14 14 * Tested up to: 6.0.2 … … 23 23 define( 'SETARY_PATH', \plugin_dir_path( __FILE__ ) ); 24 24 define( 'SETARY_URL', \plugins_url( '/', __FILE__ ) ); 25 define( 'SETARY_VERSION', ' 0.5.1' );25 define( 'SETARY_VERSION', '1.0.0' ); 26 26 define( 'SETARY_SITE_URL', 'https://setary.com/' ); 27 27 define( 'SETARY_APP_URL', 'https://setary.com/app/' ); … … 46 46 include_once __DIR__ . '/inc/class-upload-image.php'; 47 47 include_once __DIR__ . '/inc/class-media-list.php'; 48 include_once __DIR__ . '/inc/class-meta.php'; 48 49 include_once __DIR__ . '/inc/class-info.php'; 49 50 include_once __DIR__ . '/inc/bootstrap.php'; -
setary/trunk/README.md
r2823229 r2844136 1 1 === Setary — Inventory Management for WooCommerce === 2 2 Requires at least: 5.7 3 Tested up to: 6. 0.23 Tested up to: 6.1.1 4 4 Requires PHP: 5.6 5 Stable tag: 0.5.15 Stable tag: 1.0.0 6 6 License: MIT 7 7 License URI: https://opensource.org/licenses/MIT … … 54 54 == Changelog == 55 55 56 = v1.0.0 (2023-01-05) = 57 * [new] Enabled [column filtering](https://setary.com/docs/how-to-filter-products-in-setary/?utm_source=setary&utm_medium=changelog) 58 * [new] Enabled [meta data columns](https://setary.com/docs/how-to-edit-product-meta-data-in-setary/?utm_source=setary&utm_medium=changelog) 59 * [new] Enabled [column show/hide](https://setary.com/docs/how-to-show-hide-columns-in-setary/?utm_source=setary&utm_medium=changelog) 60 56 61 = v0.5.1 (2022-11-23) = 57 62 * [fix] Fix string declaration error for < PHP8 -
setary/trunk/inc/bootstrap.php
r2795354 r2844136 37 37 'upload_image' => __NAMESPACE__ . '\\Upload_Image', 38 38 'media_list' => __NAMESPACE__ . '\\Media_List', 39 'meta' => __NAMESPACE__ . '\\Meta', 39 40 // https://setary.wp.loc/wp-json/wc/setary/info/. 40 41 'info' => __NAMESPACE__ . '\\Info', -
setary/trunk/inc/class-products-with-variations.php
r2822462 r2844136 14 14 use WP_REST_Request; 15 15 use WP_REST_Server; 16 17 18 /** 19 * Helper internal class to work with WHERE SQL to use as closures 20 * 21 * @package Setary 22 */ 23 class FilterByBetween { 24 public function __construct($query, $data) { 25 $this->query = $query; 26 $this->data = $data; 27 } 28 29 30 public function filter($where = '') { 31 global $wpdb; 32 33 $where .= call_user_func_array([ $wpdb, 'prepare' ], array_merge( [$this->query], $this->data )); 34 35 return $where; 36 } 37 } 16 38 17 39 /** … … 142 164 // 63 => 'grouped_products', 143 165 // 64 => 'menu_order', 144 //65 => 'meta_data',166 65 => 'meta_data', 145 167 ]; 146 168 147 169 $request->set_param( '_fields', $params ); 148 170 171 /** 172 * Ensure we get the variation image ID, and not the parent product image ID. 173 * 174 * @see WC_Product_Variation::get_image_id() 175 */ 176 add_filter( 'woocommerce_product_variation_get_image_id', function( $image_id, $product ) { 177 return $product->get_image_id( 'edit' ); 178 }, 10, 2 ); 179 180 /** 181 * Prevent shuffling of related products. 182 */ 149 183 add_filter( 'woocommerce_product_related_posts_shuffle', '__return_false' ); 150 184 … … 159 193 * @return array 160 194 */ 195 161 196 public function filter_response_by_context( $data, $context ) { 162 197 $item = parent::filter_response_by_context( $data, $context ); … … 171 206 $item['formatted_cross_sell_ids'] = $this->format_ids( $item['cross_sell_ids'] ); 172 207 208 // If manage stock is "parent", then really it means "No". 209 $item['manage_stock'] = $item['manage_stock'] && 'parent' !== $item['manage_stock']; 210 173 211 return $item; 174 212 } … … 193 231 */ 194 232 public function get_items( $request ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded -- WordPress code 195 196 /* 197 SELECT id FROM wp_posts pp WHERE post_type IN('product', 'product_variation') AND ((pp.post_status <> 'trash' AND pp.post_status <> 'auto-draft')) ORDER BY IF(pp.post_parent > 0, pp.post_parent, pp.id), pp.id; 198 */ 233 global $wpdb; 234 235 $this->filters = json_decode( $request->get_param('filters'), true ); 199 236 200 237 $query_args = $this->prepare_objects_query( $request ); 201 238 $query_args['post_type'] = [ 'product', 'product_variation' ]; 239 240 foreach($this->filters as $filter) { 241 if( ! $filter['active'] ) { 242 continue; 243 } 244 245 if( empty( $filter['from'] ) ) { 246 $filter['from'] = 0; 247 } 248 if( empty( $filter['to'] ) ) { 249 $filter['to'] = PHP_INT_MAX; 250 } 251 252 $key = isset($filter['filterData']) && !empty($filter['filterData']) ? $filter['filterData'] : $filter['data']; 253 254 if( ! empty( $filter['taxonomy'] ) && 'query' === $filter['mode'] ) { 255 $terms = get_terms( $filter['taxonomy'], [ 'search' => $filter['query'], 'fields' => 'ids' ] ); 256 257 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 258 $query_args, 259 array( 260 'taxonomy' => $filter['taxonomy'], 261 'field' => 'term_id', 262 'operator' => 'IN', 263 'terms' => $terms, 264 ) 265 ); 266 continue; 267 } 268 269 if ( ! empty( $filter['mode'] ) && 'empty' === $filter['mode'] ) { 270 if( 'name' === $key ) { 271 add_filter( 'posts_where', [ new FilterByBetween(" AND ({$wpdb->prefix}posts.post_title IS NULL OR {$wpdb->prefix}posts.post_title = '')", array()), 'filter' ]); 272 } else if( 'slug' === $key ) { 273 add_filter( 'posts_where', [ new FilterByBetween(" AND ({$wpdb->prefix}posts.post_name IS NULL OR {$wpdb->prefix}posts.post_name = '')", array()), 'filter' ]); 274 } else if( ! empty( $filter['taxonomy'] ) ) { 275 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 276 $query_args, 277 [ 278 'relation' => 'OR', 279 [ 280 'taxonomy' => $filter['taxonomy'], 281 'operator' => 'NOT EXISTS', 282 ], 283 [ 284 'taxonomy' => $filter['taxonomy'], 285 'field' => 'slug', 286 'operator' => 'IN', 287 'terms' => ['uncategorized'], 288 ] 289 ] 290 ); 291 } else if( in_array( $key, [ '_sku', '_regular_price', '_sale_price', '_stock' ], true) ) { 292 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 293 $query_args, 294 [ 295 'relation' => 'OR', 296 [ 297 'key' => $key, 298 'value' => '', 299 'compare' => '=', 300 ], 301 [ 302 'key' => $key, 303 'value' => '0', 304 'compare' => '=', 305 ], 306 [ 307 'key' => $key, 308 'compare' => 'NOT EXISTS', 309 'value' => 'null', 310 ] 311 ] 312 ); 313 } else { 314 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 315 $query_args, 316 [ 317 'relation' => 'OR', 318 [ 319 'key' => $key, 320 'value' => '', 321 'compare' => '=', 322 ], 323 [ 324 'key' => $key, 325 'value' => '0', 326 'compare' => '=', 327 ], 328 [ 329 'key' => $key, 330 'compare' => 'NOT EXISTS', 331 'value' => 'null', 332 ] 333 ] 334 ); 335 } 336 continue; 337 } 338 339 if( 'id' === $key ) { 340 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.ID BETWEEN %d AND %d", array( floatval($filter['from']), floatval($filter['to']) )), 'filter' ]); 341 } else if( 'type' === $key ) { 342 if( in_array( 'variation', $filter['query'], true ) ) { 343 $query_args['post_type'] = [ 'product_variation' ]; 344 } else { 345 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 346 $query_args, 347 array( 348 'taxonomy' => 'product_type', 349 'field' => 'slug', 350 'terms' => $filter['query'], 351 ) 352 ); 353 } 354 } else if( 'parent_id' === $key ) { 355 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.post_parent BETWEEN %d AND %d", array( floatval($filter['from']), floatval($filter['to']) )), 'filter' ]); 356 } else if( 'name' === $key ) { 357 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.post_title LIKE %s", array( '%' . $filter['query'] . '%' )), 'filter' ]); 358 } else if( 'slug' === $key ) { 359 add_filter( 'posts_where', [ new FilterByBetween(" AND {$wpdb->prefix}posts.post_name LIKE %s", array( '%' . $filter['query'] . '%' )), 'filter' ]); 360 } else if( in_array( $key, [ 'backorders', 'manage_stock' ], true) ) { 361 // if( 'manage_stock' === $key && in_array('parent', $filter['query']) ) { 362 // continue; 363 // } else { 364 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 365 $query_args, 366 array( 367 'key' => '_' . $key, 368 'value' => $filter['query'], 369 'compare' => 'IN', 370 ) 371 ); 372 // } 373 } else if( 'featured' === $key ) { 374 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 375 $query_args, 376 array( 377 'taxonomy' => 'product_visibility', 378 'field' => 'slug', 379 'operator' => in_array( 'no', $filter['query'], true ) ? 'NOT IN' : 'IN', 380 'terms' => ['featured'], 381 ) 382 ); 383 } else if( in_array( $key, [ 'catalog_visibility' ], true) ) { 384 $terms = []; 385 386 // public/wp/wp-content/plugins/woocommerce/includes/data-stores/class-wc-product-data-store-cpt.php:411 387 388 if(!in_array( 'visible', $filter['query'], true )) { 389 if( in_array( 'search', $filter['query'], true ) ) { 390 $terms['exclude-from-catalog'] = 'exclude-from-catalog'; 391 } 392 if( in_array( 'catalog', $filter['query'], true ) ) { 393 $terms['exclude-from-search'] = 'exclude-from-search'; 394 } 395 if( in_array( 'hidden', $filter['query'], true ) ) { 396 $terms['exclude-from-catalog'] = 'exclude-from-search'; 397 $terms['exclude-from-search'] = 'exclude-from-search'; 398 } 399 400 $query_args['tax_query'] = $this->add_tax_query( // WPCS: slow query ok. 401 $query_args, 402 array( 403 'taxonomy' => 'product_visibility', 404 'field' => 'slug', 405 'operator' => 'IN', 406 'terms' => $terms, 407 ) 408 ); 409 } 410 } else if( 'status' === $key ) { 411 $query_args['post_status'] = $filter['query']; 412 } else if( 'images' === $key ) { 413 global $wpdb; 414 415 $sql = trim(" 416 SELECT post_id from ( 417 SELECT pm.post_id, SUM((CHAR_LENGTH(meta_value) - CHAR_LENGTH(REPLACE(meta_value, ',', '')) + 1)) cou FROM {$wpdb->prefix}postmeta pm WHERE pm.meta_key IN('_product_image_gallery', '_thumbnail_id') GROUP BY pm.post_id 418 ) p WHERE 1 %s; 419 "); 420 421 if('one' === $filter['mode']) { 422 $sql = sprintf($sql, ' AND cou = 1 '); 423 $ids = $wpdb->get_col($sql); 424 425 $query_args['post__in'] = $ids; 426 } else if('many' === $filter['mode']) { 427 $sql = sprintf($sql, ' AND cou > 1 '); 428 $ids = $wpdb->get_col($sql); 429 430 $query_args['post__in'] = $ids; 431 } else if('no' === $filter['mode']) { 432 $ids = $wpdb->get_col(sprintf($sql, '')); 433 $query_args['post__not_in'] = $ids; 434 } else if('query' === $filter['mode']) { 435 $attachment_ids = get_posts([ 436 'post_type' => 'attachment', 437 'posts_per_page' => -1, 438 's' => $filter['query'], 439 'fields' => 'ids' 440 ]); 441 442 $sql = trim(" 443 SELECT post_id from ( 444 SELECT pm.post_id, GROUP_CONCAT(pm.meta_value) imgs FROM {$wpdb->prefix}postmeta pm WHERE pm.meta_key IN('_product_image_gallery', '_thumbnail_id') GROUP BY pm.post_id 445 ) p WHERE p.imgs REGEXP %s; 446 "); 447 $match = []; 448 foreach ($attachment_ids as $attachment_id) { 449 $match[] = '((?:,|^)' . $attachment_id . '(?:,|$))'; 450 } 451 452 $ids = $wpdb->get_col($wpdb->prepare($sql, implode('|', $match))); 453 $query_args['post__in'] = $ids; 454 } 455 } else if( ! empty( $filter['query'] ) ) { 456 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 457 $query_args, 458 array( 459 'key' => $key, 460 'value' => $filter['query'], 461 'compare' => is_array($filter['query']) ? 'IN' : 'LIKE', 462 ) 463 ); 464 } else if( $filter['type'] === 'numeric' ) { 465 $query_args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok. 466 $query_args, 467 array( 468 'key' => $key, 469 'value' => array( floatval($filter['from']), floatval($filter['to']) ), 470 'type' => 'numeric', 471 'compare' => 'BETWEEN', 472 ) 473 ); 474 } 475 } 202 476 203 477 if ( is_wp_error( current( $query_args ) ) ) { … … 263 537 264 538 /** 539 * Push tax query to object with AND condition 540 * 541 * @param array $args Query args. 542 * @param array $meta_query Meta query. 543 * @return mixed array 544 */ 545 protected function add_tax_query( $args, $tax_query ) { 546 if ( empty( $args['tax_query'] ) ) { 547 $args['tax_query'] = array(); 548 } 549 550 $args['tax_query'][] = $tax_query; 551 552 return $args['tax_query']; 553 } 554 555 protected function get_attributes( $product ) { 556 $attributes = array(); 557 558 if ( $product->is_type( 'variation' ) ) { 559 $_product = wc_get_product( $product->get_parent_id() ); 560 foreach ( $product->get_variation_attributes() as $attribute_name => $attribute ) { 561 $name = str_replace( 'attribute_', '', $attribute_name ); 562 563 if ( empty( $attribute ) && '0' !== $attribute ) { 564 continue; 565 } 566 567 // Taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`. 568 if ( 0 === strpos( $attribute_name, 'attribute_pa_' ) ) { 569 $option_term = get_term_by( 'slug', $attribute, $name ); 570 $attributes[] = array( 571 'id' => wc_attribute_taxonomy_id_by_name( $name ), 572 'name' => $this->get_attribute_taxonomy_name( $name, $_product ), 573 'option' => $option_term && ! is_wp_error( $option_term ) ? $option_term->name : $attribute, 574 ); 575 } else { 576 $attributes[] = array( 577 'id' => 0, 578 'slug' => $name, 579 'name' => $this->get_attribute_taxonomy_name( $name, $_product ), 580 'option' => $attribute, 581 ); 582 } 583 } 584 } else { 585 foreach ( $product->get_attributes() as $attribute ) { 586 $attributes[] = array( 587 'id' => $attribute['is_taxonomy'] ? wc_attribute_taxonomy_id_by_name( $attribute['name'] ) : 0, 588 'taxonomy' => $attribute['is_taxonomy'] ? $attribute['name'] : null, 589 'name' => $this->get_attribute_taxonomy_name( $attribute['name'], $product ), 590 'position' => (int) $attribute['position'], 591 'visible' => (bool) $attribute['is_visible'], 592 'variation' => (bool) $attribute['is_variation'], 593 'options' => $this->get_attribute_options( $product->get_id(), $attribute ), 594 ); 595 } 596 } 597 598 return $attributes; 599 } 600 601 /** 265 602 * Format categories for response. 266 603 * -
setary/trunk/setary.php
r2823229 r2844136 10 10 * Author: Setary 11 11 * 12 * Version: 0.5.112 * Version: 1.0.0 13 13 * Requires at least: 5.7 14 14 * Tested up to: 6.0.2 … … 23 23 define( 'SETARY_PATH', \plugin_dir_path( __FILE__ ) ); 24 24 define( 'SETARY_URL', \plugins_url( '/', __FILE__ ) ); 25 define( 'SETARY_VERSION', ' 0.5.1' );25 define( 'SETARY_VERSION', '1.0.0' ); 26 26 define( 'SETARY_SITE_URL', 'https://setary.com/' ); 27 27 define( 'SETARY_APP_URL', 'https://setary.com/app/' ); … … 46 46 include_once __DIR__ . '/inc/class-upload-image.php'; 47 47 include_once __DIR__ . '/inc/class-media-list.php'; 48 include_once __DIR__ . '/inc/class-meta.php'; 48 49 include_once __DIR__ . '/inc/class-info.php'; 49 50 include_once __DIR__ . '/inc/bootstrap.php';
Note: See TracChangeset
for help on using the changeset viewer.