Plugin Directory

Changeset 3744394


Ignore:
Timestamp:
10/13/2026 04:02:40 PM (11 days ago)
Author:
twoelevenjay
Message:

Update to version 2.0.9 from GitHub

Location:
discontinued-products
Files:
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • discontinued-products/tags/2.0.9/includes/class-discontinued-products.php

    r3467144 r3744394  
    66 * @since 1.0.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! class_exists( 'Discontinued_Products' ) ) {
    … …  
    7579                 */
    7680                public function maybe_run_data_updater() {
     81                        if ( ! is_admin() || ! current_user_can( 'manage_woocommerce' ) ) {
     82                                return;
     83                        }
    7784                        if ( isset( $_GET['do_update_dp'] ) && check_admin_referer( 'dp_update_nonce', '_wpnonce' ) ) {
    7885                                // Run the data updater.
    … …  
    8188                                return;
    8289                        }
    83                         if ( isset( $_GET['wc-hide-notice'] ) && 'dp_updated' === $_GET['wc-hide-notice'] ) {
     90                        if ( isset( $_GET['wc-hide-notice'], $_GET['_wc_notice_nonce'] ) && 'dp_updated' === $_GET['wc-hide-notice'] && wp_verify_nonce( sanitize_key( wp_unslash( $_GET['_wc_notice_nonce'] ) ), 'woocommerce_hide_notices_nonce' ) ) {
    8491                                delete_transient( 'do_update_dp' );
    8592                                return;
    … …  
    94101                 */
    95102                public static function update_notice() {
     103
     104                        if ( ! current_user_can( 'manage_woocommerce' ) ) {
     105                                return;
     106                        }
    96107
    97108                        $update_dp_transient = get_transient( 'do_update_dp' );
  • discontinued-products/tags/2.0.9/includes/class-dp-csv-import-export.php

    r3467144 r3744394  
    2828                        add_filter( 'woocommerce_csv_product_import_mapping_default_columns', array( $this, 'add_column_to_mapping_screen' ) );
    2929                        add_filter( 'woocommerce_product_import_pre_insert_product_object', array( $this, 'process_import' ), 10, 2 );
     30                        add_action( 'woocommerce_product_import_inserted_product_object', array( $this, 'process_import_terms' ), 10, 2 );
    3031                        add_filter( 'woocommerce_product_export_column_names', array( $this, 'add_export_column' ) );
    3132                        add_filter( 'woocommerce_product_export_product_default_columns', array( $this, 'add_export_column' ) );
    … …  
    8283                public function process_import( $product, $data ) {
    8384
    84                         if ( ! empty( $data['is_discontinued'] ) ) {
    85                                 $product->update_meta_data( '_is_discontinued', $data['is_discontinued'] );
    86                         }
    8785                        if ( ! empty( $data['discontinued_product_text'] ) ) {
    8886                                $product->update_meta_data( '_discontinued_product_text', $data['discontinued_product_text'] );
    8987                        }
    9088                        if ( ! empty( $data['alt_products'] ) ) {
    91                                 $product->update_meta_data( '_alt_products', explode( ', ', $data['alt_products'] ) );
     89                                $product->update_meta_data( '_alt_products', array_values( array_filter( array_map( 'absint', explode( ',', $data['alt_products'] ) ) ) ) );
    9290                        }
    9391                        if ( ! empty( $data['alt_product_text'] ) ) {
    9492                                $product->update_meta_data( '_alt_product_text', $data['alt_product_text'] );
    9593                        }
    96                         if ( ! empty( $data['hide_from_shop'] ) ) {
    97                                 $product->update_meta_data( '_hide_from_shop', $data['hide_from_shop'] );
    98                         }
    99                         if ( ! empty( $data['hide_from_search'] ) ) {
    100                                 $product->update_meta_data( '_hide_from_search', $data['hide_from_search'] );
    101                         }
    102 
    10394                        return $product;
     95                }
     96
     97                /**
     98                 * Save the discontinued, shop and search flags as product_discontinued terms
     99                 * once the imported product has an ID. Only columns present in the file change.
     100                 *
     101                 * @since 2.0.9
     102                 * @param WC_Product $product Imported product.
     103                 * @param array      $data    CSV data read for the product.
     104                 */
     105                public function process_import_terms( $product, $data ) {
     106
     107                        if ( ! is_a( $product, 'WC_Product' ) || ! $product->get_id() ) {
     108                                return;
     109                        }
     110                        $product_id = $product->get_id();
     111                        $groups     = array(
     112                                'is_discontinued'  => array( 'yes' => 'dp-discontinued' ),
     113                                'hide_from_shop'   => array(
     114                                        'hide' => 'dp-hide-shop',
     115                                        'show' => 'dp-show-shop',
     116                                ),
     117                                'hide_from_search' => array(
     118                                        'hide' => 'dp-hide-search',
     119                                        'show' => 'dp-show-search',
     120                                ),
     121                        );
     122
     123                        foreach ( $groups as $column => $map ) {
     124                                if ( ! array_key_exists( $column, $data ) ) {
     125                                        continue;
     126                                }
     127                                $value = strtolower( trim( (string) $data[ $column ] ) );
     128                                if ( 'is_discontinued' === $column && in_array( $value, array( '1', 'true' ), true ) ) {
     129                                        $value = 'yes';
     130                                }
     131                                wp_remove_object_terms( $product_id, array_values( $map ), 'product_discontinued' );
     132                                if ( isset( $map[ $value ] ) ) {
     133                                        wp_add_object_terms( $product_id, $map[ $value ], 'product_discontinued' );
     134                                }
     135                        }
    104136                }
    105137                /**
    … …  
    129161                 */
    130162                public function add_export_data_is_discontinued( $value, $product ) {
    131                         $value = $product->get_meta( '_is_discontinued', true, 'edit' );
    132                         return $value;
     163                        return has_term( 'dp-discontinued', 'product_discontinued', $product->get_id() ) ? 'yes' : '';
    133164                }
    134165
    … …  
    177208                 */
    178209                public function add_export_data_hide_from_shop( $value, $product ) {
    179                         $value = $product->get_meta( '_hide_from_shop', true, 'edit' );
    180                         return $value;
     210                        return $this->get_visibility_value( $product->get_id(), 'shop' );
    181211                }
    182212
    … …  
    189219                 */
    190220                public function add_export_data_hide_from_search( $value, $product ) {
    191                         $value = $product->get_meta( '_hide_from_search', true, 'edit' );
    192                         return $value;
     221                        return $this->get_visibility_value( $product->get_id(), 'search' );
     222                }
     223
     224                /**
     225                 * Read the per product shop or search override from its terms.
     226                 *
     227                 * @since 2.0.9
     228                 * @param int    $product_id Product ID.
     229                 * @param string $context    Either shop or search.
     230                 * @return string hide, show or an empty string for the default.
     231                 */
     232                protected function get_visibility_value( $product_id, $context ) {
     233                        if ( has_term( 'dp-hide-' . $context, 'product_discontinued', $product_id ) ) {
     234                                return 'hide';
     235                        }
     236                        if ( has_term( 'dp-show-' . $context, 'product_discontinued', $product_id ) ) {
     237                                return 'show';
     238                        }
     239                        return '';
    193240                }
    194241
  • discontinued-products/tags/2.0.9/includes/class-dp-discontinued-product.php

    r3467166 r3744394  
    77 */
    88
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
     12
    913if ( ! class_exists( 'DP_Discontinued_Product' ) ) {
    1014        /**
    … …  
    3438                                add_action( 'init', array( $this, 'woocommerce_flush_rewrite_rules' ) );
    3539                                add_action( 'woocommerce_product_query', array( $this, 'exclude_discontinued_products' ), 1000 );
     40                                add_action( 'pre_get_posts', array( $this, 'exclude_discontinued_from_site_search' ), 1000 );
    3641                                add_filter( 'woocommerce_get_shop_page_id', array( $this, 'override_shop_page_id' ), 1, 1 );
    3742                                add_action( 'template_redirect', array( $this, 'add_dp_alt_products' ) );
    … …  
    211216                public static function save( $post_id ) {
    212217
     218                        // WooCommerce verifies its meta box nonce before firing woocommerce_process_product_meta.
     219                        if ( ! current_user_can( 'edit_post', $post_id ) ) {
     220                                return;
     221                        }
     222
    213223                        $terms = array();
    214                         update_post_meta( $post_id, '_discontinued_product_text', filter_input( INPUT_POST, '_discontinued_product_text' ) );
    215                         $alt_products = filter_input( INPUT_POST, 'alt_products', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ) ? filter_input( INPUT_POST, 'alt_products', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ) : array();
     224                        update_post_meta( $post_id, '_discontinued_product_text', sanitize_text_field( (string) filter_input( INPUT_POST, '_discontinued_product_text' ) ) );
     225                        $alt_products = filter_input( INPUT_POST, 'alt_products', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
     226                        $alt_products = is_array( $alt_products ) ? array_values( array_filter( array_map( 'absint', $alt_products ) ) ) : array();
    216227                        update_post_meta( $post_id, '_alt_products', $alt_products );
    217                         update_post_meta( $post_id, '_alt_product_text', filter_input( INPUT_POST, '_alt_product_text' ) );
     228                        update_post_meta( $post_id, '_alt_product_text', sanitize_text_field( (string) filter_input( INPUT_POST, '_alt_product_text' ) ) );
    218229                        $is_discontinued = filter_input( INPUT_POST, '_is_discontinued' );
    219230                        if ( $is_discontinued ) {
    … …  
    257268
    258269                        $dc_shop_page_id = (int) get_option( 'dp_shop_page_id' );
    259                         return ( is_shop() || is_product_category() ) && ( ! $dc_shop_page_id || $this->current_page_id !== $dc_shop_page_id ) && ! is_search();
     270                        return ( is_shop() || is_product_taxonomy() ) && ( ! $dc_shop_page_id || $this->current_page_id !== $dc_shop_page_id ) && ! is_search();
    260271                }
    261272
    … …  
    374385                }
    375386
     387                /**
     388                 * Apply the hide from search setting to the general site search.
     389                 * WooCommerce only runs woocommerce_product_query for product searches,
     390                 * so a plain ?s= search would otherwise list hidden discontinued products.
     391                 * Posts and pages have no product_discontinued terms and are unaffected.
     392                 *
     393                 * @since 2.0.9
     394                 * @param WP_Query $q Main WP Query.
     395                 */
     396                public function exclude_discontinued_from_site_search( $q ) {
     397                        if ( is_admin() || wp_doing_ajax() || ! $q->is_main_query() || ! $q->is_search() ) {
     398                                return;
     399                        }
     400
     401                        // Product searches are already handled through woocommerce_product_query.
     402                        $post_type = $q->get( 'post_type' );
     403                        if ( 'product' === $post_type || ( is_array( $post_type ) && array( 'product' ) === array_values( $post_type ) ) ) {
     404                                return;
     405                        }
     406
     407                        $tax_queries = $this->build_tax_query( $q );
     408                        $q->set( 'tax_query', $tax_queries );
     409                }
     410
    376411
    377412                /**
  • discontinued-products/tags/2.0.9/includes/class-dp-settings.php

    r3177606 r3744394  
    66 * @since 1.1.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! class_exists( 'DP_Settings' ) ) {
  • discontinued-products/tags/2.0.9/includes/class-dp-taxonomy.php

    r3177606 r3744394  
    66 * @since 1.1.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! class_exists( 'DP_Taxonomy' ) ) {
  • discontinued-products/tags/2.0.9/readme.txt

    r3483791 r3744394  
    55Tags: woocommerce, woocommerce products, discontinued products, discontinued, ecommerce
    66Requires at least: 6.0
    7 Tested up to: 6.9
     7Tested up to: 7.1
    88Requires PHP: 7.4
    9 Stable tag: 2.0.8
    10 License: GPLv2 or later
    11 License URI: http://www.gnu.org/licenses/gpl-2.0.html
     9Stable tag: 2.0.9
     10License: GPLv3
     11License URI: https://www.gnu.org/licenses/gpl-3.0.html
    1212
    1313Enables WooCommerce Discontinued Products.
    … …  
    5353
    5454## Changelog
     55
     56= 2.0.9 10.13.2026 =
     57* Fixed - Hide from shop now also applies to product tag and attribute archive pages, not only the shop and category pages.
     58* Fixed - Hide from search now also applies to the general site search, not only the product search.
     59* Fixed - Product CSV export now includes the discontinued, hide from shop and hide from search values.
     60* Fixed - Product CSV import now saves the discontinued, hide from shop and hide from search values directly instead of requiring a data update afterwards.
     61* Fixed - The "discontinued" price class is only added to discontinued products.
     62* Security - Product discontinued text and alternative product fields are sanitized on save and escaped on output.
     63* Security - The data update notice and action now require the manage_woocommerce capability.
     64* Compatibility - Tested with WordPress 7.1.3 and WooCommerce 11.2.1.
    5565
    5666= 2.0.8 03.16.2026 =
  • discontinued-products/tags/2.0.9/woocommerce-discontinued-products.php

    r3483791 r3744394  
    66 * Author: Leon @ 211J
    77 * Author URI: http://211j.com/
    8  * Version: 2.0.8
     8 * Version: 2.0.9
    99 * Requires at least: 6.0
    1010 * Requires PHP: 7.4
    1111 * Text Domain: discontinued-products
    12  * Domain Path: /languages
    1312 * WC requires at least: 8.0
    14  * WC tested up to: 10.6.1
     13 * WC tested up to: 11.2.1
    1514
    1615 * License: GNU General Public License v3.0
    … …  
    1918 * @package woocommerce
    2019 */
     20
     21if ( ! defined( 'ABSPATH' ) ) {
     22        exit;
     23}
    2124
    2225/**
    … …  
    4043
    4144        if ( ! defined( 'DP_VER' ) ) {
    42                 define( 'DP_VER', '2.0.8' );
     45                define( 'DP_VER', '2.0.9' );
    4346        }
    4447
  • discontinued-products/tags/2.0.9/woocommerce-template.php

    r3473146 r3744394  
    66 * @since 1.0.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! function_exists( 'dp_is_discontinued' ) ) {
    … …  
    128132                        $text_option      = get_option( 'dp_discontinued_text' );
    129133                        $text             = dp_alt_products_text( $prod_text_option, $text_option, __( 'This product has been discontinued.', 'discontinued-products' ) );
    130                         $price            = $price . '<br>' . $text;
     134                        $price            = $price . '<br>' . esc_html( $text );
    131135                }
    132136                return $price;
    … …  
    163167         */
    164168        function discontinued_template_price_class( $class ) {
    165                 $class = $class . ' discontinued';
     169                global $product;
     170                if ( is_object( $product ) && is_callable( array( $product, 'get_id' ) ) && dp_is_discontinued( $product->get_id() ) ) {
     171                        $class = $class . ' discontinued';
     172                }
    166173
    167174                return $class;
  • discontinued-products/trunk/includes/class-discontinued-products.php

    r3467144 r3744394  
    66 * @since 1.0.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! class_exists( 'Discontinued_Products' ) ) {
    … …  
    7579                 */
    7680                public function maybe_run_data_updater() {
     81                        if ( ! is_admin() || ! current_user_can( 'manage_woocommerce' ) ) {
     82                                return;
     83                        }
    7784                        if ( isset( $_GET['do_update_dp'] ) && check_admin_referer( 'dp_update_nonce', '_wpnonce' ) ) {
    7885                                // Run the data updater.
    … …  
    8188                                return;
    8289                        }
    83                         if ( isset( $_GET['wc-hide-notice'] ) && 'dp_updated' === $_GET['wc-hide-notice'] ) {
     90                        if ( isset( $_GET['wc-hide-notice'], $_GET['_wc_notice_nonce'] ) && 'dp_updated' === $_GET['wc-hide-notice'] && wp_verify_nonce( sanitize_key( wp_unslash( $_GET['_wc_notice_nonce'] ) ), 'woocommerce_hide_notices_nonce' ) ) {
    8491                                delete_transient( 'do_update_dp' );
    8592                                return;
    … …  
    94101                 */
    95102                public static function update_notice() {
     103
     104                        if ( ! current_user_can( 'manage_woocommerce' ) ) {
     105                                return;
     106                        }
    96107
    97108                        $update_dp_transient = get_transient( 'do_update_dp' );
  • discontinued-products/trunk/includes/class-dp-csv-import-export.php

    r3467144 r3744394  
    2828                        add_filter( 'woocommerce_csv_product_import_mapping_default_columns', array( $this, 'add_column_to_mapping_screen' ) );
    2929                        add_filter( 'woocommerce_product_import_pre_insert_product_object', array( $this, 'process_import' ), 10, 2 );
     30                        add_action( 'woocommerce_product_import_inserted_product_object', array( $this, 'process_import_terms' ), 10, 2 );
    3031                        add_filter( 'woocommerce_product_export_column_names', array( $this, 'add_export_column' ) );
    3132                        add_filter( 'woocommerce_product_export_product_default_columns', array( $this, 'add_export_column' ) );
    … …  
    8283                public function process_import( $product, $data ) {
    8384
    84                         if ( ! empty( $data['is_discontinued'] ) ) {
    85                                 $product->update_meta_data( '_is_discontinued', $data['is_discontinued'] );
    86                         }
    8785                        if ( ! empty( $data['discontinued_product_text'] ) ) {
    8886                                $product->update_meta_data( '_discontinued_product_text', $data['discontinued_product_text'] );
    8987                        }
    9088                        if ( ! empty( $data['alt_products'] ) ) {
    91                                 $product->update_meta_data( '_alt_products', explode( ', ', $data['alt_products'] ) );
     89                                $product->update_meta_data( '_alt_products', array_values( array_filter( array_map( 'absint', explode( ',', $data['alt_products'] ) ) ) ) );
    9290                        }
    9391                        if ( ! empty( $data['alt_product_text'] ) ) {
    9492                                $product->update_meta_data( '_alt_product_text', $data['alt_product_text'] );
    9593                        }
    96                         if ( ! empty( $data['hide_from_shop'] ) ) {
    97                                 $product->update_meta_data( '_hide_from_shop', $data['hide_from_shop'] );
    98                         }
    99                         if ( ! empty( $data['hide_from_search'] ) ) {
    100                                 $product->update_meta_data( '_hide_from_search', $data['hide_from_search'] );
    101                         }
    102 
    10394                        return $product;
     95                }
     96
     97                /**
     98                 * Save the discontinued, shop and search flags as product_discontinued terms
     99                 * once the imported product has an ID. Only columns present in the file change.
     100                 *
     101                 * @since 2.0.9
     102                 * @param WC_Product $product Imported product.
     103                 * @param array      $data    CSV data read for the product.
     104                 */
     105                public function process_import_terms( $product, $data ) {
     106
     107                        if ( ! is_a( $product, 'WC_Product' ) || ! $product->get_id() ) {
     108                                return;
     109                        }
     110                        $product_id = $product->get_id();
     111                        $groups     = array(
     112                                'is_discontinued'  => array( 'yes' => 'dp-discontinued' ),
     113                                'hide_from_shop'   => array(
     114                                        'hide' => 'dp-hide-shop',
     115                                        'show' => 'dp-show-shop',
     116                                ),
     117                                'hide_from_search' => array(
     118                                        'hide' => 'dp-hide-search',
     119                                        'show' => 'dp-show-search',
     120                                ),
     121                        );
     122
     123                        foreach ( $groups as $column => $map ) {
     124                                if ( ! array_key_exists( $column, $data ) ) {
     125                                        continue;
     126                                }
     127                                $value = strtolower( trim( (string) $data[ $column ] ) );
     128                                if ( 'is_discontinued' === $column && in_array( $value, array( '1', 'true' ), true ) ) {
     129                                        $value = 'yes';
     130                                }
     131                                wp_remove_object_terms( $product_id, array_values( $map ), 'product_discontinued' );
     132                                if ( isset( $map[ $value ] ) ) {
     133                                        wp_add_object_terms( $product_id, $map[ $value ], 'product_discontinued' );
     134                                }
     135                        }
    104136                }
    105137                /**
    … …  
    129161                 */
    130162                public function add_export_data_is_discontinued( $value, $product ) {
    131                         $value = $product->get_meta( '_is_discontinued', true, 'edit' );
    132                         return $value;
     163                        return has_term( 'dp-discontinued', 'product_discontinued', $product->get_id() ) ? 'yes' : '';
    133164                }
    134165
    … …  
    177208                 */
    178209                public function add_export_data_hide_from_shop( $value, $product ) {
    179                         $value = $product->get_meta( '_hide_from_shop', true, 'edit' );
    180                         return $value;
     210                        return $this->get_visibility_value( $product->get_id(), 'shop' );
    181211                }
    182212
    … …  
    189219                 */
    190220                public function add_export_data_hide_from_search( $value, $product ) {
    191                         $value = $product->get_meta( '_hide_from_search', true, 'edit' );
    192                         return $value;
     221                        return $this->get_visibility_value( $product->get_id(), 'search' );
     222                }
     223
     224                /**
     225                 * Read the per product shop or search override from its terms.
     226                 *
     227                 * @since 2.0.9
     228                 * @param int    $product_id Product ID.
     229                 * @param string $context    Either shop or search.
     230                 * @return string hide, show or an empty string for the default.
     231                 */
     232                protected function get_visibility_value( $product_id, $context ) {
     233                        if ( has_term( 'dp-hide-' . $context, 'product_discontinued', $product_id ) ) {
     234                                return 'hide';
     235                        }
     236                        if ( has_term( 'dp-show-' . $context, 'product_discontinued', $product_id ) ) {
     237                                return 'show';
     238                        }
     239                        return '';
    193240                }
    194241
  • discontinued-products/trunk/includes/class-dp-discontinued-product.php

    r3467166 r3744394  
    77 */
    88
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
     12
    913if ( ! class_exists( 'DP_Discontinued_Product' ) ) {
    1014        /**
    … …  
    3438                                add_action( 'init', array( $this, 'woocommerce_flush_rewrite_rules' ) );
    3539                                add_action( 'woocommerce_product_query', array( $this, 'exclude_discontinued_products' ), 1000 );
     40                                add_action( 'pre_get_posts', array( $this, 'exclude_discontinued_from_site_search' ), 1000 );
    3641                                add_filter( 'woocommerce_get_shop_page_id', array( $this, 'override_shop_page_id' ), 1, 1 );
    3742                                add_action( 'template_redirect', array( $this, 'add_dp_alt_products' ) );
    … …  
    211216                public static function save( $post_id ) {
    212217
     218                        // WooCommerce verifies its meta box nonce before firing woocommerce_process_product_meta.
     219                        if ( ! current_user_can( 'edit_post', $post_id ) ) {
     220                                return;
     221                        }
     222
    213223                        $terms = array();
    214                         update_post_meta( $post_id, '_discontinued_product_text', filter_input( INPUT_POST, '_discontinued_product_text' ) );
    215                         $alt_products = filter_input( INPUT_POST, 'alt_products', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ) ? filter_input( INPUT_POST, 'alt_products', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ) : array();
     224                        update_post_meta( $post_id, '_discontinued_product_text', sanitize_text_field( (string) filter_input( INPUT_POST, '_discontinued_product_text' ) ) );
     225                        $alt_products = filter_input( INPUT_POST, 'alt_products', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
     226                        $alt_products = is_array( $alt_products ) ? array_values( array_filter( array_map( 'absint', $alt_products ) ) ) : array();
    216227                        update_post_meta( $post_id, '_alt_products', $alt_products );
    217                         update_post_meta( $post_id, '_alt_product_text', filter_input( INPUT_POST, '_alt_product_text' ) );
     228                        update_post_meta( $post_id, '_alt_product_text', sanitize_text_field( (string) filter_input( INPUT_POST, '_alt_product_text' ) ) );
    218229                        $is_discontinued = filter_input( INPUT_POST, '_is_discontinued' );
    219230                        if ( $is_discontinued ) {
    … …  
    257268
    258269                        $dc_shop_page_id = (int) get_option( 'dp_shop_page_id' );
    259                         return ( is_shop() || is_product_category() ) && ( ! $dc_shop_page_id || $this->current_page_id !== $dc_shop_page_id ) && ! is_search();
     270                        return ( is_shop() || is_product_taxonomy() ) && ( ! $dc_shop_page_id || $this->current_page_id !== $dc_shop_page_id ) && ! is_search();
    260271                }
    261272
    … …  
    374385                }
    375386
     387                /**
     388                 * Apply the hide from search setting to the general site search.
     389                 * WooCommerce only runs woocommerce_product_query for product searches,
     390                 * so a plain ?s= search would otherwise list hidden discontinued products.
     391                 * Posts and pages have no product_discontinued terms and are unaffected.
     392                 *
     393                 * @since 2.0.9
     394                 * @param WP_Query $q Main WP Query.
     395                 */
     396                public function exclude_discontinued_from_site_search( $q ) {
     397                        if ( is_admin() || wp_doing_ajax() || ! $q->is_main_query() || ! $q->is_search() ) {
     398                                return;
     399                        }
     400
     401                        // Product searches are already handled through woocommerce_product_query.
     402                        $post_type = $q->get( 'post_type' );
     403                        if ( 'product' === $post_type || ( is_array( $post_type ) && array( 'product' ) === array_values( $post_type ) ) ) {
     404                                return;
     405                        }
     406
     407                        $tax_queries = $this->build_tax_query( $q );
     408                        $q->set( 'tax_query', $tax_queries );
     409                }
     410
    376411
    377412                /**
  • discontinued-products/trunk/includes/class-dp-settings.php

    r3177606 r3744394  
    66 * @since 1.1.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! class_exists( 'DP_Settings' ) ) {
  • discontinued-products/trunk/includes/class-dp-taxonomy.php

    r3177606 r3744394  
    66 * @since 1.1.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! class_exists( 'DP_Taxonomy' ) ) {
  • discontinued-products/trunk/readme.txt

    r3483791 r3744394  
    55Tags: woocommerce, woocommerce products, discontinued products, discontinued, ecommerce
    66Requires at least: 6.0
    7 Tested up to: 6.9
     7Tested up to: 7.1
    88Requires PHP: 7.4
    9 Stable tag: 2.0.8
    10 License: GPLv2 or later
    11 License URI: http://www.gnu.org/licenses/gpl-2.0.html
     9Stable tag: 2.0.9
     10License: GPLv3
     11License URI: https://www.gnu.org/licenses/gpl-3.0.html
    1212
    1313Enables WooCommerce Discontinued Products.
    … …  
    5353
    5454## Changelog
     55
     56= 2.0.9 10.13.2026 =
     57* Fixed - Hide from shop now also applies to product tag and attribute archive pages, not only the shop and category pages.
     58* Fixed - Hide from search now also applies to the general site search, not only the product search.
     59* Fixed - Product CSV export now includes the discontinued, hide from shop and hide from search values.
     60* Fixed - Product CSV import now saves the discontinued, hide from shop and hide from search values directly instead of requiring a data update afterwards.
     61* Fixed - The "discontinued" price class is only added to discontinued products.
     62* Security - Product discontinued text and alternative product fields are sanitized on save and escaped on output.
     63* Security - The data update notice and action now require the manage_woocommerce capability.
     64* Compatibility - Tested with WordPress 7.1.3 and WooCommerce 11.2.1.
    5565
    5666= 2.0.8 03.16.2026 =
  • discontinued-products/trunk/woocommerce-discontinued-products.php

    r3483791 r3744394  
    66 * Author: Leon @ 211J
    77 * Author URI: http://211j.com/
    8  * Version: 2.0.8
     8 * Version: 2.0.9
    99 * Requires at least: 6.0
    1010 * Requires PHP: 7.4
    1111 * Text Domain: discontinued-products
    12  * Domain Path: /languages
    1312 * WC requires at least: 8.0
    14  * WC tested up to: 10.6.1
     13 * WC tested up to: 11.2.1
    1514
    1615 * License: GNU General Public License v3.0
    … …  
    1918 * @package woocommerce
    2019 */
     20
     21if ( ! defined( 'ABSPATH' ) ) {
     22        exit;
     23}
    2124
    2225/**
    … …  
    4043
    4144        if ( ! defined( 'DP_VER' ) ) {
    42                 define( 'DP_VER', '2.0.8' );
     45                define( 'DP_VER', '2.0.9' );
    4346        }
    4447
  • discontinued-products/trunk/woocommerce-template.php

    r3473146 r3744394  
    66 * @since 1.0.0
    77 */
     8
     9if ( ! defined( 'ABSPATH' ) ) {
     10        exit;
     11}
    812
    913if ( ! function_exists( 'dp_is_discontinued' ) ) {
    … …  
    128132                        $text_option      = get_option( 'dp_discontinued_text' );
    129133                        $text             = dp_alt_products_text( $prod_text_option, $text_option, __( 'This product has been discontinued.', 'discontinued-products' ) );
    130                         $price            = $price . '<br>' . $text;
     134                        $price            = $price . '<br>' . esc_html( $text );
    131135                }
    132136                return $price;
    … …  
    163167         */
    164168        function discontinued_template_price_class( $class ) {
    165                 $class = $class . ' discontinued';
     169                global $product;
     170                if ( is_object( $product ) && is_callable( array( $product, 'get_id' ) ) && dp_is_discontinued( $product->get_id() ) ) {
     171                        $class = $class . ' discontinued';
     172                }
    166173
    167174                return $class;
Note: See TracChangeset for help on using the changeset viewer.