Add related product functions and deprecate those in class.
This commit is contained in:
parent
a74de70dc3
commit
803709cb94
|
@ -21,6 +21,36 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
*/
|
||||
abstract class WC_Abstract_Legacy_Product extends WC_Data {
|
||||
|
||||
/**
|
||||
* Get and return related products.
|
||||
* @deprecated 2.7.0 Use wc_get_related_products instead.
|
||||
*/
|
||||
public function get_related( $limit = 5 ) {
|
||||
_deprecated_function( 'WC_Product::get_related', '2.7', 'wc_get_related_products' );
|
||||
return wc_get_related_products( $this->get_id(), $limit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves related product terms.
|
||||
* @deprecated 2.7.0 Use wc_get_related_terms instead.
|
||||
*/
|
||||
protected function get_related_terms( $term ) {
|
||||
_deprecated_function( 'WC_Product::get_related_terms', '2.7', 'wc_get_related_terms' );
|
||||
return array_merge( array( 0 ), wc_get_related_terms( $this->get_id(), $term ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the related posts query.
|
||||
* @deprecated 2.7.0 Use wc_get_related_products_query instead.
|
||||
*/
|
||||
protected function build_related_query( $cats_array, $tags_array, $exclude_ids, $limit ) {
|
||||
_deprecated_function( 'WC_Product::build_related_query', '2.7', 'wc_get_related_products_query' );
|
||||
return wc_get_related_products_query( $cats_array, $tags_array, $exclude_ids, $limit );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The product's type (simple, variable etc).
|
||||
*
|
||||
|
|
|
@ -2074,57 +2074,6 @@ class WC_Product extends WC_Abstract_Legacy_Product {
|
|||
return absint( $this->shipping_class_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and return related products.
|
||||
*
|
||||
* Notes:
|
||||
* - Results are cached in a transient for faster queries.
|
||||
* - To make results appear random, we query and extra 10 products and shuffle them.
|
||||
* - To ensure we always have enough results, it will check $limit before returning the cached result, if not recalc.
|
||||
* - This used to rely on transient version to invalidate cache, but to avoid multiple transients we now just expire daily.
|
||||
* This means if a related product is edited and no longer related, it won't be removed for 24 hours. Acceptable trade-off for performance.
|
||||
* - Saving a product will flush caches for that product.
|
||||
*
|
||||
* @param int $limit (default: 5) Should be an integer greater than 0.
|
||||
* @return array Array of post IDs
|
||||
*/
|
||||
public function get_related( $limit = 5 ) {
|
||||
global $wpdb;
|
||||
|
||||
$transient_name = 'wc_related_' . $this->get_id();
|
||||
$related_posts = get_transient( $transient_name );
|
||||
$limit = $limit > 0 ? $limit : 5;
|
||||
|
||||
// We want to query related posts if they are not cached, or we don't have enough
|
||||
if ( false === $related_posts || sizeof( $related_posts ) < $limit ) {
|
||||
// Related products are found from category and tag
|
||||
$tags_array = $this->get_related_terms( 'product_tag' );
|
||||
$cats_array = $this->get_related_terms( 'product_cat' );
|
||||
|
||||
// Don't bother if none are set
|
||||
if ( 1 === sizeof( $cats_array ) && 1 === sizeof( $tags_array ) ) {
|
||||
$related_posts = array();
|
||||
} else {
|
||||
// Sanitize
|
||||
$exclude_ids = array_map( 'absint', array_merge( array( 0, $this->get_id() ), $this->get_upsells() ) );
|
||||
|
||||
// Generate query - but query an extra 10 results to give the appearance of random results
|
||||
$query = $this->build_related_query( $cats_array, $tags_array, $exclude_ids, $limit + 10 );
|
||||
|
||||
// Get the posts
|
||||
$related_posts = $wpdb->get_col( implode( ' ', $query ) );
|
||||
}
|
||||
|
||||
set_transient( $transient_name, $related_posts, DAY_IN_SECONDS );
|
||||
}
|
||||
|
||||
// Randomise the results
|
||||
shuffle( $related_posts );
|
||||
|
||||
// Limit the returned results
|
||||
return array_slice( $related_posts, 0, $limit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single product attribute.
|
||||
*
|
||||
|
@ -2301,84 +2250,6 @@ class WC_Product extends WC_Abstract_Legacy_Product {
|
|||
return sprintf( '%s – %s', $identifier, $this->get_title() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves related product terms.
|
||||
*
|
||||
* @param string $term
|
||||
* @return array
|
||||
*/
|
||||
protected function get_related_terms( $term ) {
|
||||
$terms_array = array( 0 );
|
||||
|
||||
$terms = apply_filters( 'woocommerce_get_related_' . $term . '_terms', wp_get_post_terms( $this->get_id(), $term ), $this->get_id() );
|
||||
foreach ( $terms as $term ) {
|
||||
$terms_array[] = $term->term_id;
|
||||
}
|
||||
|
||||
return array_map( 'absint', $terms_array );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the related posts query.
|
||||
*
|
||||
* @param array $cats_array
|
||||
* @param array $tags_array
|
||||
* @param array $exclude_ids
|
||||
* @param int $limit
|
||||
* @return string
|
||||
*/
|
||||
protected function build_related_query( $cats_array, $tags_array, $exclude_ids, $limit ) {
|
||||
global $wpdb;
|
||||
|
||||
$limit = absint( $limit );
|
||||
|
||||
$query = array();
|
||||
$query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p";
|
||||
$query['join'] = " INNER JOIN {$wpdb->postmeta} pm ON ( pm.post_id = p.ID AND pm.meta_key='_visibility' )";
|
||||
$query['join'] .= " INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)";
|
||||
$query['join'] .= " INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)";
|
||||
$query['join'] .= " INNER JOIN {$wpdb->terms} t ON (t.term_id = tt.term_id)";
|
||||
|
||||
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' ) {
|
||||
$query['join'] .= " INNER JOIN {$wpdb->postmeta} pm2 ON ( pm2.post_id = p.ID AND pm2.meta_key='_stock_status' )";
|
||||
}
|
||||
|
||||
$query['where'] = " WHERE 1=1";
|
||||
$query['where'] .= " AND p.post_status = 'publish'";
|
||||
$query['where'] .= " AND p.post_type = 'product'";
|
||||
$query['where'] .= " AND p.ID NOT IN ( " . implode( ',', $exclude_ids ) . " )";
|
||||
$query['where'] .= " AND pm.meta_value IN ( 'visible', 'catalog' )";
|
||||
|
||||
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' ) {
|
||||
$query['where'] .= " AND pm2.meta_value = 'instock'";
|
||||
}
|
||||
|
||||
$relate_by_category = apply_filters( 'woocommerce_product_related_posts_relate_by_category', true, $this->get_id() );
|
||||
$relate_by_tag = apply_filters( 'woocommerce_product_related_posts_relate_by_tag', true, $this->get_id() );
|
||||
|
||||
if ( $relate_by_category || $relate_by_tag ) {
|
||||
$query['where'] .= ' AND (';
|
||||
|
||||
if ( $relate_by_category ) {
|
||||
$query['where'] .= " ( tt.taxonomy = 'product_cat' AND t.term_id IN ( " . implode( ',', $cats_array ) . " ) ) ";
|
||||
if ( $relate_by_tag ) {
|
||||
$query['where'] .= ' OR ';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $relate_by_tag ) {
|
||||
$query['where'] .= " ( tt.taxonomy = 'product_tag' AND t.term_id IN ( " . implode( ',', $tags_array ) . " ) ) ";
|
||||
}
|
||||
|
||||
$query['where'] .= ')';
|
||||
}
|
||||
|
||||
$query['limits'] = " LIMIT {$limit} ";
|
||||
$query = apply_filters( 'woocommerce_product_related_posts_query', $query, $this->get_id() );
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save taxonomy terms.
|
||||
*
|
||||
|
|
|
@ -751,3 +751,123 @@ function wc_get_product_visibility_options() {
|
|||
'hidden' => __( 'Hidden', 'woocommerce' ),
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relateed products.
|
||||
* @param integer $product_id
|
||||
* @param integer $limit
|
||||
* @param array $exclude_ids
|
||||
* @return array
|
||||
*/
|
||||
function wc_get_related_products( $product_id, $limit = 5, $exclude_ids = array() ) {
|
||||
global $wpdb;
|
||||
|
||||
$product_id = absint( $product_id );
|
||||
$exclude_ids = array_map( 'absint', array_merge( array( 0, $product_id ), $exclude_ids ) );
|
||||
$transient_name = 'wc_related_' . $product_id;
|
||||
$related_posts = get_transient( $transient_name );
|
||||
$limit = $limit > 0 ? $limit : 5;
|
||||
|
||||
// We want to query related posts if they are not cached, or we don't have enough
|
||||
if ( false === $related_posts || sizeof( $related_posts ) < $limit ) {
|
||||
// Related products are found from category and tags
|
||||
if ( apply_filters( 'woocommerce_product_related_posts_relate_by_category', true, $product_id ) ) {
|
||||
$cats_array = wc_get_related_terms( $product_id, 'product_cat' );
|
||||
} else {
|
||||
$cats_array = array();
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_product_related_posts_relate_by_tag', true, $product_id ) ) {
|
||||
$tags_array = wc_get_related_terms( $product_id, 'product_tag' );
|
||||
} else {
|
||||
$tags_array = array();
|
||||
}
|
||||
|
||||
// Don't bother if none are set, unless woocommerce_product_related_posts_force_display is set to true in which case all products are related.
|
||||
if ( empty( $cats_array ) && empty( $tags_array ) && ! apply_filters( 'woocommerce_product_related_posts_force_display', false, $product_id ) ) {
|
||||
$related_posts = array();
|
||||
} else {
|
||||
// Generate query - but query an extra 10 results to give the appearance of random results
|
||||
$query = apply_filters( 'woocommerce_product_related_posts_query', wc_get_related_products_query( $cats_array, $tags_array, $exclude_ids, $limit + 10 ), $product_id );
|
||||
|
||||
// Get the posts
|
||||
$related_posts = $wpdb->get_col( implode( ' ', $query ) );
|
||||
}
|
||||
|
||||
set_transient( $transient_name, $related_posts, DAY_IN_SECONDS );
|
||||
}
|
||||
|
||||
// Randomise the results
|
||||
shuffle( $related_posts );
|
||||
|
||||
// Limit the returned results
|
||||
return array_slice( $related_posts, 0, $limit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves related product terms.
|
||||
* @since 2.7.0
|
||||
* @param integer $product_id
|
||||
* @param string $taxonomy
|
||||
* @return array
|
||||
*/
|
||||
function wc_get_related_terms( $product_id, $taxonomy ) {
|
||||
$terms = apply_filters( 'woocommerce_get_related_' . $taxonomy . '_terms', wp_get_post_terms( $product_id, $term ), $product_id );
|
||||
return array_map( 'absint', wp_list_pluck( $terms, 'term_id' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the related posts query.
|
||||
*
|
||||
* @param array $cats_array
|
||||
* @param array $tags_array
|
||||
* @param array $exclude_ids
|
||||
* @param int $limit
|
||||
* @return string
|
||||
*/
|
||||
function wc_get_related_products_query( $cats_array, $tags_array, $exclude_ids, $limit ) {
|
||||
global $wpdb;
|
||||
|
||||
$limit = absint( $limit );
|
||||
$query = array();
|
||||
$query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p";
|
||||
$query['join'] = " INNER JOIN {$wpdb->postmeta} pm ON ( pm.post_id = p.ID AND pm.meta_key='_visibility' )";
|
||||
$query['join'] .= " INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)";
|
||||
$query['join'] .= " INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)";
|
||||
$query['join'] .= " INNER JOIN {$wpdb->terms} t ON (t.term_id = tt.term_id)";
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
|
||||
$query['join'] .= " INNER JOIN {$wpdb->postmeta} pm2 ON ( pm2.post_id = p.ID AND pm2.meta_key='_stock_status' )";
|
||||
}
|
||||
|
||||
$query['where'] = " WHERE 1=1";
|
||||
$query['where'] .= " AND p.post_status = 'publish'";
|
||||
$query['where'] .= " AND p.post_type = 'product'";
|
||||
$query['where'] .= " AND p.ID NOT IN ( " . implode( ',', $exclude_ids ) . " )";
|
||||
$query['where'] .= " AND pm.meta_value IN ( 'visible', 'catalog' )";
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
|
||||
$query['where'] .= " AND pm2.meta_value = 'instock'";
|
||||
}
|
||||
|
||||
if ( $cats_array || $tags_array ) {
|
||||
$query['where'] .= ' AND (';
|
||||
|
||||
if ( $cats_array ) {
|
||||
$query['where'] .= " ( tt.taxonomy = 'product_cat' AND t.term_id IN ( " . implode( ',', $cats_array ) . " ) ) ";
|
||||
if ( $relate_by_tag ) {
|
||||
$query['where'] .= ' OR ';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $tags_array ) {
|
||||
$query['where'] .= " ( tt.taxonomy = 'product_tag' AND t.term_id IN ( " . implode( ',', $tags_array ) . " ) ) ";
|
||||
}
|
||||
|
||||
$query['where'] .= ')';
|
||||
}
|
||||
|
||||
$query['limits'] = " LIMIT {$limit} ";
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ if ( empty( $product ) || ! $product->exists() ) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( ! $related = $product->get_related( $posts_per_page ) ) {
|
||||
if ( ! $related = wc_get_related_products( $product->get_id(), $posts_per_page, $product->get_upsells() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue