Plugin Directory

Changeset 2844136


Ignore:
Timestamp:
01/05/2023 02:49:33 PM (3 years ago)
Author:
setaryapp
Message:

Update to version 1.0.0 from GitHub

Location:
setary
Files:
2 added
8 edited
1 copied

Legend:

Unmodified
Added
Removed
  • setary/tags/1.0.0/README.md

    r2823229 r2844136  
    11=== Setary — Inventory Management for WooCommerce ===
    22Requires at least: 5.7
    3 Tested up to: 6.0.2
     3Tested up to: 6.1.1
    44Requires PHP: 5.6
    5 Stable tag: 0.5.1
     5Stable tag: 1.0.0
    66License: MIT
    77License URI: https://opensource.org/licenses/MIT
     
    5454== Changelog ==
    5555
     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
    5661= v0.5.1 (2022-11-23) =
    5762* [fix] Fix string declaration error for < PHP8
  • setary/tags/1.0.0/inc/bootstrap.php

    r2795354 r2844136  
    3737        'upload_image' => __NAMESPACE__ . '\\Upload_Image',
    3838        'media_list'   => __NAMESPACE__ . '\\Media_List',
     39        'meta'         => __NAMESPACE__ . '\\Meta',
    3940        // https://setary.wp.loc/wp-json/wc/setary/info/.
    4041        'info'         => __NAMESPACE__ . '\\Info',
  • setary/tags/1.0.0/inc/class-products-with-variations.php

    r2822462 r2844136  
    1414use WP_REST_Request;
    1515use WP_REST_Server;
     16
     17
     18/**
     19 * Helper internal class to work with WHERE SQL to use as closures
     20 *
     21 * @package Setary
     22 */
     23class 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}
    1638
    1739/**
     
    142164            // 63 => 'grouped_products',
    143165            // 64 => 'menu_order',
    144             // 65 => 'meta_data',
     166            65 => 'meta_data',
    145167        ];
    146168
    147169        $request->set_param( '_fields', $params );
    148170
     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         */
    149183        add_filter( 'woocommerce_product_related_posts_shuffle', '__return_false' );
    150184
     
    159193     * @return array
    160194     */
     195
    161196    public function filter_response_by_context( $data, $context ) {
    162197        $item = parent::filter_response_by_context( $data, $context );
     
    171206        $item['formatted_cross_sell_ids'] = $this->format_ids( $item['cross_sell_ids'] );
    172207
     208        // If manage stock is "parent", then really it means "No".
     209        $item['manage_stock'] = $item['manage_stock'] && 'parent' !== $item['manage_stock'];
     210
    173211        return $item;
    174212    }
     
    193231     */
    194232    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 );
    199236
    200237        $query_args              = $this->prepare_objects_query( $request );
    201238        $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        }
    202476
    203477        if ( is_wp_error( current( $query_args ) ) ) {
     
    263537
    264538    /**
     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    /**
    265602     * Format categories for response.
    266603     *
  • setary/tags/1.0.0/setary.php

    r2823229 r2844136  
    1010 * Author:            Setary
    1111 *
    12  * Version:           0.5.1
     12 * Version:           1.0.0
    1313 * Requires at least: 5.7
    1414 * Tested up to:      6.0.2
     
    2323define( 'SETARY_PATH', \plugin_dir_path( __FILE__ ) );
    2424define( 'SETARY_URL', \plugins_url( '/', __FILE__ ) );
    25 define( 'SETARY_VERSION', '0.5.1' );
     25define( 'SETARY_VERSION', '1.0.0' );
    2626define( 'SETARY_SITE_URL', 'https://setary.com/' );
    2727define( 'SETARY_APP_URL', 'https://setary.com/app/' );
     
    4646    include_once __DIR__ . '/inc/class-upload-image.php';
    4747    include_once __DIR__ . '/inc/class-media-list.php';
     48    include_once __DIR__ . '/inc/class-meta.php';
    4849    include_once __DIR__ . '/inc/class-info.php';
    4950    include_once __DIR__ . '/inc/bootstrap.php';
  • setary/trunk/README.md

    r2823229 r2844136  
    11=== Setary — Inventory Management for WooCommerce ===
    22Requires at least: 5.7
    3 Tested up to: 6.0.2
     3Tested up to: 6.1.1
    44Requires PHP: 5.6
    5 Stable tag: 0.5.1
     5Stable tag: 1.0.0
    66License: MIT
    77License URI: https://opensource.org/licenses/MIT
     
    5454== Changelog ==
    5555
     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
    5661= v0.5.1 (2022-11-23) =
    5762* [fix] Fix string declaration error for < PHP8
  • setary/trunk/inc/bootstrap.php

    r2795354 r2844136  
    3737        'upload_image' => __NAMESPACE__ . '\\Upload_Image',
    3838        'media_list'   => __NAMESPACE__ . '\\Media_List',
     39        'meta'         => __NAMESPACE__ . '\\Meta',
    3940        // https://setary.wp.loc/wp-json/wc/setary/info/.
    4041        'info'         => __NAMESPACE__ . '\\Info',
  • setary/trunk/inc/class-products-with-variations.php

    r2822462 r2844136  
    1414use WP_REST_Request;
    1515use WP_REST_Server;
     16
     17
     18/**
     19 * Helper internal class to work with WHERE SQL to use as closures
     20 *
     21 * @package Setary
     22 */
     23class 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}
    1638
    1739/**
     
    142164            // 63 => 'grouped_products',
    143165            // 64 => 'menu_order',
    144             // 65 => 'meta_data',
     166            65 => 'meta_data',
    145167        ];
    146168
    147169        $request->set_param( '_fields', $params );
    148170
     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         */
    149183        add_filter( 'woocommerce_product_related_posts_shuffle', '__return_false' );
    150184
     
    159193     * @return array
    160194     */
     195
    161196    public function filter_response_by_context( $data, $context ) {
    162197        $item = parent::filter_response_by_context( $data, $context );
     
    171206        $item['formatted_cross_sell_ids'] = $this->format_ids( $item['cross_sell_ids'] );
    172207
     208        // If manage stock is "parent", then really it means "No".
     209        $item['manage_stock'] = $item['manage_stock'] && 'parent' !== $item['manage_stock'];
     210
    173211        return $item;
    174212    }
     
    193231     */
    194232    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 );
    199236
    200237        $query_args              = $this->prepare_objects_query( $request );
    201238        $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        }
    202476
    203477        if ( is_wp_error( current( $query_args ) ) ) {
     
    263537
    264538    /**
     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    /**
    265602     * Format categories for response.
    266603     *
  • setary/trunk/setary.php

    r2823229 r2844136  
    1010 * Author:            Setary
    1111 *
    12  * Version:           0.5.1
     12 * Version:           1.0.0
    1313 * Requires at least: 5.7
    1414 * Tested up to:      6.0.2
     
    2323define( 'SETARY_PATH', \plugin_dir_path( __FILE__ ) );
    2424define( 'SETARY_URL', \plugins_url( '/', __FILE__ ) );
    25 define( 'SETARY_VERSION', '0.5.1' );
     25define( 'SETARY_VERSION', '1.0.0' );
    2626define( 'SETARY_SITE_URL', 'https://setary.com/' );
    2727define( 'SETARY_APP_URL', 'https://setary.com/app/' );
     
    4646    include_once __DIR__ . '/inc/class-upload-image.php';
    4747    include_once __DIR__ . '/inc/class-media-list.php';
     48    include_once __DIR__ . '/inc/class-meta.php';
    4849    include_once __DIR__ . '/inc/class-info.php';
    4950    include_once __DIR__ . '/inc/bootstrap.php';
Note: See TracChangeset for help on using the changeset viewer.