252 lines
7.3 KiB
PHP
252 lines
7.3 KiB
PHP
<?php
|
|
|
|
/**
|
|
* WP Taxonomies Class.
|
|
*
|
|
* @package WP Product Feed Manager/Data/Classes
|
|
* @version 5.2.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
if ( ! class_exists( 'WPPFM_Taxonomies' ) ) :
|
|
|
|
/**
|
|
* Taxonomies Class
|
|
*/
|
|
class WPPFM_Taxonomies {
|
|
|
|
/**
|
|
* Generates a string of shop taxonomies (like a category string) in the correct order
|
|
*
|
|
* @param string $product_id
|
|
* @param string $tax
|
|
* @param string $separator
|
|
*
|
|
* @since 2.31.0 Update the function to include a primary category selection.
|
|
* @since 2.31.1 Changed the make_shop_taxonomy_string() methode, so it returns the correct value for non-category related attributes.
|
|
* @since 2.33.0 Added a result test after the get_term_by_id call, to prevent an error message.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function make_shop_taxonomies_string( $product_id, $tax = 'product_cat', $separator = ' > ' ) {
|
|
// Only check the category if the attribute is a category attribute.
|
|
$primary_category = 'category' === $tax || 'product_cat' === $tax ? self::get_primary_cat( $product_id) : false;
|
|
|
|
if ( $primary_category ) {
|
|
$cats = $primary_category;
|
|
} else {
|
|
$args = array(
|
|
'taxonomy' => $tax,
|
|
'orderby' => 'parent',
|
|
'order' => 'DESC',
|
|
);
|
|
|
|
// get the post-term ordered with the last child cat first
|
|
$cats = wp_get_post_terms( $product_id, $tax, $args );
|
|
}
|
|
|
|
$result = array();
|
|
|
|
if ( count( $cats ) === 0 ) {
|
|
return '';
|
|
}
|
|
|
|
// anonymous function to get the correct taxonomy string
|
|
$cat_string = function ( $id ) use ( &$result, &$cat_string, $tax ) {
|
|
// get the first term
|
|
$term = get_term_by( 'id', $id, $tax, 'ARRAY_A' );
|
|
|
|
if ( ! $term ) { return; }
|
|
|
|
// check if the term has a parent
|
|
if ( $term['parent'] ) {
|
|
// start the anonymous function again with the parent id
|
|
$cat_string( $term['parent'] );
|
|
}
|
|
|
|
// add the term name to the result
|
|
$result[] = $term['name'];
|
|
};
|
|
|
|
// activate the anonymous function with the term_id
|
|
foreach( $cats as $cat ) {
|
|
$cat_string( $cat->term_id );
|
|
}
|
|
|
|
return implode( $separator, $result );
|
|
}
|
|
|
|
/**
|
|
* Single category path: Yoast/Rank Math primary breadcrumb, or the first assigned term's breadcrumb when no primary is set.
|
|
*
|
|
* Unlike {@see self::make_shop_taxonomies_string()}, this never merges paths from multiple categories.
|
|
*
|
|
* @param int|string $product_id Post ID.
|
|
* @param string $tax Taxonomy slug.
|
|
* @param string $separator Hierarchy separator.
|
|
*
|
|
* @since 3.22.0
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function make_main_product_category_string( $product_id, $tax = 'product_cat', $separator = ' > ' ) {
|
|
$product_id = absint( $product_id );
|
|
if ( ! $product_id ) {
|
|
return '';
|
|
}
|
|
|
|
$term_id = 0;
|
|
|
|
if ( 'category' === $tax || 'product_cat' === $tax ) {
|
|
$primary = self::get_primary_cat( $product_id );
|
|
if ( $primary && isset( $primary[0]->term_id ) ) {
|
|
$term_id = absint( $primary[0]->term_id );
|
|
}
|
|
}
|
|
|
|
if ( ! $term_id ) {
|
|
$terms = wp_get_post_terms(
|
|
$product_id,
|
|
$tax,
|
|
array(
|
|
'orderby' => 'term_id',
|
|
'order' => 'ASC',
|
|
)
|
|
);
|
|
if ( is_wp_error( $terms ) || empty( $terms ) ) {
|
|
return '';
|
|
}
|
|
$term_id = absint( $terms[0]->term_id );
|
|
}
|
|
|
|
return self::get_single_term_taxonomy_breadcrumb_string( $term_id, $tax, $separator );
|
|
}
|
|
|
|
/**
|
|
* Generates a string with all selected categories
|
|
*
|
|
* @param string $post_id
|
|
* @param string $separator
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_shop_categories( $post_id, $separator = ', ' ) {
|
|
$return_string = '';
|
|
|
|
$args = array(
|
|
'taxonomy' => 'product_cat',
|
|
'orderby' => 'term_id',
|
|
);
|
|
|
|
$cats = wp_get_post_terms( $post_id, 'product_cat', $args );
|
|
|
|
foreach ( $cats as $cat ) {
|
|
$return_string .= $cat->name . $separator;
|
|
}
|
|
|
|
return rtrim( $return_string, $separator );
|
|
}
|
|
|
|
/**
|
|
* Returns the product category that is selected as primary (only when Yoast SEO or RankMath plugin is installed)
|
|
*
|
|
* @param string $product_id
|
|
*
|
|
* @return array|boolean
|
|
*/
|
|
public static function get_primary_cat( $product_id ) {
|
|
$primary_cat_id = '';
|
|
|
|
if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) || is_plugin_active_for_network( 'wordpress-seo/wp-seo.php' )
|
|
|| is_plugin_active( 'wordpress-seo-premium/wp-seo-premium.php' ) || is_plugin_active_for_network( 'wordpress-seo-premium/wp-seo-premium.php' ) ) {
|
|
$primary_cat_id = get_post_meta( $product_id, '_yoast_wpseo_primary_product_cat', true );
|
|
}
|
|
|
|
if ( is_plugin_active( 'seo-by-rank-math/rank-math.php' ) || is_plugin_active_for_network( 'seo-by-rank-math/rank-math.php' )
|
|
|| is_plugin_active( 'seo-by-rank-math-pro/rank-math-pro.php' ) || is_plugin_active_for_network( 'seo-by-rank-math-pro/rank-math-pro.php' ) ) {
|
|
$primary_cat_id = get_post_meta( $product_id, 'rank_math_primary_product_cat', true );
|
|
}
|
|
|
|
if ( $primary_cat_id ) {
|
|
$product_cat[0] = get_term( $primary_cat_id, 'product_cat' );
|
|
if ( isset( $product_cat[0]->term_id ) ) {
|
|
return $product_cat;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function get_shop_categories_list() {
|
|
$args = array(
|
|
'hide_empty' => 0,
|
|
'taxonomy' => 'product_cat',
|
|
'hierarchical' => 1,
|
|
'orderby' => 'name',
|
|
'order' => 'ASC',
|
|
// phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- The exclude parameter is necessary to filter out specific categories from category mapping. This is a user-configurable feature and essential functionality.
|
|
'exclude' => apply_filters( 'wppfm_category_mapping_exclude', array() ),
|
|
'exclude_tree' => apply_filters( 'wppfm_category_mapping_exclude_tree', array() ),
|
|
'number' => absint( apply_filters( 'wppfm_category_mapping_max_categories', 0 ) ),
|
|
'child_of' => 0,
|
|
);
|
|
|
|
// see https://developer.wordpress.org/reference/classes/wp_term_query/__construct/ for valid args
|
|
$args = apply_filters( 'wppfm_category_mapping_args', $args );
|
|
|
|
return self::get_cat_hierarchy( 0, $args );
|
|
}
|
|
|
|
/**
|
|
* Builds root-to-leaf names for a single taxonomy term (same ordering as make_shop_taxonomies_string per term).
|
|
*
|
|
* @param int $term_id Term ID.
|
|
* @param string $tax Taxonomy slug.
|
|
* @param string $separator String used between segments.
|
|
*
|
|
* @return string
|
|
*/
|
|
private static function get_single_term_taxonomy_breadcrumb_string( $term_id, $tax, $separator ) {
|
|
$result = array();
|
|
$term_id = absint( $term_id );
|
|
$cat_string = function ( $id ) use ( &$result, &$cat_string, $tax ) {
|
|
$term = get_term_by( 'id', absint( $id ), $tax, 'ARRAY_A' );
|
|
if ( ! $term ) {
|
|
return;
|
|
}
|
|
if ( ! empty( $term['parent'] ) ) {
|
|
$cat_string( $term['parent'] );
|
|
}
|
|
$result[] = $term['name'];
|
|
};
|
|
$cat_string( $term_id );
|
|
|
|
return implode( $separator, $result );
|
|
}
|
|
|
|
private static function get_cat_hierarchy( $parent, $args ) {
|
|
$cats = get_categories( $args );
|
|
$ret = new stdClass;
|
|
|
|
foreach ( $cats as $cat ) {
|
|
if ( $cat->parent == $parent ) {
|
|
$id = $cat->cat_ID;
|
|
$ret->$id = $cat;
|
|
$ret->$id->children = self::get_cat_hierarchy( $id, $args );
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
|
|
// end of WPPFM_Taxonomies_Class
|
|
|
|
endif;
|