Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,100 @@
<?php
/**
* The WooCommerce module - admin side functionality.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
use RankMath\KB;
use RankMath\Admin\Admin_Helper;
use RankMath\Module\Base;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Arr;
defined( 'ABSPATH' ) || exit;
/**
* Admin class.
*/
class Admin extends Base {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$directory = dirname( __FILE__ );
$this->config(
[
'id' => 'woocommerce',
'directory' => $directory,
]
);
parent::__construct();
// Permalink Manager.
$this->filter( 'rank_math/settings/general', 'add_general_settings' );
$this->filter( 'rank_math/flush_fields', 'flush_fields' );
$this->action( 'rank_math/admin/editor_scripts', 'enqueue' );
}
/**
* Enqueue script to analyze product's short description.
*/
public function enqueue() {
$screen = get_current_screen();
if ( ! Admin_Helper::is_post_edit() || 'product' !== $screen->post_type || ! $this->do_filter( 'woocommerce/analyze_short_description', true ) ) {
return;
}
wp_enqueue_script( 'rank-math-description-analysis', rank_math()->plugin_url() . 'includes/modules/woocommerce/assets/js/woocommerce.js', [ 'rank-math-editor' ], rank_math()->version, true );
}
/**
* Add module settings into general optional panel.
*
* @param array $tabs Array of option panel tabs.
*
* @return array
*/
public function add_general_settings( $tabs ) {
Arr::insert(
$tabs,
[
'woocommerce' => [
'icon' => 'rm-icon rm-icon-cart',
'title' => esc_html__( 'WooCommerce', 'rank-math' ),
/* translators: Link to kb article */
'desc' => sprintf( esc_html__( 'Choose how you want Rank Math to handle your WooCommerce SEO. %s.', 'rank-math' ), '<a href="' . KB::get( 'woocommerce-settings', 'Options Panel WooCommerce Tab' ) . '" target="_blank">' . esc_html__( 'Learn more', 'rank-math' ) . '</a>' ),
'file' => $this->directory . '/views/options-general.php',
],
],
7
);
return $tabs;
}
/**
* Fields after updation of which we need to flush rewrite rules.
*
* @param array $fields Fields to flush rewrite rules on.
*
* @return array
*/
public function flush_fields( $fields ) {
$fields[] = 'wc_remove_product_base';
$fields[] = 'wc_remove_category_base';
$fields[] = 'wc_remove_category_parent_slugs';
return $fields;
}
}

View File

@@ -0,0 +1,145 @@
<?php
/**
* Add Open Graph data for the WooCommerce module.
*
* @since 1.0.32
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
use RankMath\OpenGraph\Image as OpenGraph_Image;
defined( 'ABSPATH' ) || exit;
/**
* WC Opengraph class.
*/
class Opengraph extends Sitemap {
/**
* Register hooks.
*/
public function opengraph() {
$this->filter( 'language_attributes', 'og_product_namespace', 11 );
$this->filter( 'rank_math/opengraph/desc', 'og_desc_product_taxonomy' );
$this->action( 'rank_math/opengraph/facebook', 'og_enhancement', 50 );
$this->action( 'rank_math/opengraph/facebook/add_additional_images', 'set_opengraph_image' );
}
/**
* Add the OpenGraph namespace.
*
* @param string $namespace The original namespace.
*
* @return string
*/
public function og_product_namespace( $namespace ) {
if ( is_singular( 'product' ) ) {
$namespace = preg_replace( '/prefix="([^"]+)"/', 'prefix="$1 product: https://ogp.me/ns/product#"', $namespace );
}
return $namespace;
}
/**
* Make sure the OpenGraph description is put out.
*
* @param string $desc The current description, will be overwritten if we're on a product page.
*
* @return string
*/
public function og_desc_product_taxonomy( $desc ) {
if ( is_product_taxonomy() ) {
$term_desc = term_description();
if ( ! empty( $term_desc ) ) {
$desc = wp_strip_all_tags( $term_desc, true );
$desc = strip_shortcodes( $desc );
}
}
return $desc;
}
/**
* Adds the other product images to the OpenGraph output.
*
* @param OpenGraph $opengraph The current opengraph network object.
*/
public function og_enhancement( $opengraph ) {
$product = $this->get_product();
if ( ! is_object( $product ) ) {
return;
}
$brand = WooCommerce::get_brands( get_the_ID() );
if ( ! empty( $brand ) ) {
$opengraph->tag( 'product:brand', $brand );
}
/**
* Allow developers to prevent the output of the price in the OpenGraph tags.
*
* @param bool unsigned Defaults to true.
*/
if ( $this->do_filter( 'woocommerce/og_price', ! $product->is_type( 'variable' ) ) ) {
$opengraph->tag( 'product:price:amount', $product->get_price() );
$opengraph->tag( 'product:price:currency', get_woocommerce_currency() );
}
if ( $product->is_in_stock() ) {
$opengraph->tag( 'product:availability', 'instock' );
}
}
/**
* Adds the opengraph images.
*
* @param OpenGraph_Image $opengraph_image The OpenGraph image to use.
*/
public function set_opengraph_image( OpenGraph_Image $opengraph_image ) {
if ( ! function_exists( 'is_product_category' ) || is_product_category() ) {
global $wp_query;
$cat = $wp_query->get_queried_object();
$thumbnail_id = get_term_meta( $cat->term_id, 'thumbnail_id', true );
$opengraph_image->add_image_by_id( $thumbnail_id );
}
/**
* Passing a truthy value to the filter will effectively short-circuit the process of adding gallery images.
*
* @param bool $return Short-circuit return value. Either false or true.
*/
if ( ! $this->do_filter( 'woocommerce/opengraph/add_gallery_images', false ) ) {
return;
}
$product = $this->get_product();
if ( ! is_object( $product ) ) {
return;
}
$this->set_image_ids( $product, $opengraph_image );
}
/**
* Set images for the given product.
*
* @param WC_Product $product The product to get the image ids for.
* @param OpenGraph_Image $opengraph_image The OpenGraph image to use.
*/
protected function set_image_ids( $product, $opengraph_image ) {
$img_ids = method_exists( $product, 'get_gallery_image_ids' ) ?
$product->get_gallery_image_ids() : $product->get_gallery_attachment_ids();
if ( ! is_array( $img_ids ) || empty( $img_ids ) ) {
return;
}
foreach ( $img_ids as $img_id ) {
$opengraph_image->add_image_by_id( $img_id );
}
}
}

View File

@@ -0,0 +1,267 @@
<?php
/**
* The product permalink watcher class.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Sitepress;
use RankMath\Helpers\Str;
use RankMath\Helpers\Param;
defined( 'ABSPATH' ) || exit;
/**
* Permalink_Watcher class.
*/
class Permalink_Watcher {
use Hooker;
/**
* Hold product base.
*
* @var string
*/
private $product_base;
/**
* Hold product categories.
*
* @var array
*/
private $categories;
/**
* Remove product base.
*
* @var bool
*/
private $remove_product_base;
/**
* Remove category base.
*
* @var bool
*/
private $remove_category_base;
/**
* Remove parent slugs.
*
* @var bool
*/
private $remove_parent_slugs;
/**
* The Constructor.
*/
public function __construct() {
$this->remove_product_base = Helper::get_settings( 'general.wc_remove_product_base' );
$this->remove_category_base = Helper::get_settings( 'general.wc_remove_category_base' );
$this->remove_parent_slugs = Helper::get_settings( 'general.wc_remove_category_parent_slugs' );
if ( $this->remove_product_base && ! (bool) Param::get( 'elementor-preview' ) ) {
$this->filter( 'post_type_link', 'post_type_link', 1, 2 );
}
if ( $this->remove_category_base || $this->remove_parent_slugs ) {
$this->action( 'created_product_cat', 'flush_rules' );
$this->action( 'delete_product_cat', 'flush_rules' );
$this->action( 'edited_product_cat', 'flush_rules' );
$this->filter( 'term_link', 'term_link', 0, 3 );
$this->filter( 'rewrite_rules_array', 'add_rewrite_rules', 99 );
}
}
/**
* Flush rewrite rules (soft flush).
*
* @return void
*/
public function flush_rules() {
flush_rewrite_rules( false );
}
/**
* Replace product permalink according to settings.
*
* @param string $permalink The existing permalink URL.
* @param WP_Post $post WP_Post object.
*
* @return string
*/
public function post_type_link( $permalink, $post ) {
if ( $this->can_change_link( 'product', $post->post_type ) ) {
return $permalink;
}
return str_replace( $this->get_product_base(), '/', $permalink );
}
/**
* Replace category permalink according to settings.
*
* @param string $link Term link URL.
* @param object $term Term object.
* @param string $taxonomy Taxonomy slug.
*
* @return string
*/
public function term_link( $link, $term, $taxonomy ) {
if ( $this->can_change_link( 'product_cat', $taxonomy ) ) {
return $link;
}
$permalink_structure = wc_get_permalink_structure();
$category_base = trailingslashit( $permalink_structure['category_rewrite_slug'] );
$is_language_switcher = ( class_exists( 'Sitepress' ) && strpos( $link, 'lang=' ) );
if ( $this->remove_category_base ) {
$link = str_replace( $category_base, '', $link );
$category_base = '';
}
if ( $this->remove_parent_slugs && ! $is_language_switcher ) {
$link = home_url( user_trailingslashit( $category_base . $term->slug ) );
}
return $link;
}
/**
* Add rewrite rules.
*
* @param array $rules The compiled array of rewrite rules.
*
* @return array
*/
public function add_rewrite_rules( $rules ) {
global $wp_rewrite;
wp_cache_flush();
/**
* Remove WPML filters while getting terms, to get all languages
*/
Sitepress::get()->remove_term_filters();
$feed = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')';
$permalink_structure = wc_get_permalink_structure();
$category_base = $this->remove_category_base ? '' : $permalink_structure['category_rewrite_slug'];
$use_parent_slug = Str::contains( '%product_cat%', $permalink_structure['product_rewrite_slug'] );
$product_rules = [];
$category_rules = [];
foreach ( $this->get_categories() as $category ) {
$cat_path = $this->get_category_fullpath( $category );
$cat_slug = $category_base . ( $this->remove_parent_slugs ? $category['slug'] : $cat_path );
$category_rules[ "{$cat_slug}/?\$" ] = 'index.php?product_cat=' . $category['slug'];
$category_rules[ "{$cat_slug}/embed/?\$" ] = 'index.php?product_cat=' . $category['slug'] . '&embed=true';
$category_rules[ "{$cat_slug}/{$wp_rewrite->feed_base}/{$feed}/?\$" ] = 'index.php?product_cat=' . $category['slug'] . '&feed=$matches[1]';
$category_rules[ "{$cat_slug}/{$feed}/?\$" ] = 'index.php?product_cat=' . $category['slug'] . '&feed=$matches[1]';
$category_rules[ "{$cat_slug}/{$wp_rewrite->pagination_base}/?([0-9]{1,})/?\$" ] = 'index.php?product_cat=' . $category['slug'] . '&paged=$matches[1]';
if ( $this->remove_product_base && $use_parent_slug ) {
$product_rules[ $cat_path . '/([^/]+)/?$' ] = 'index.php?product=$matches[1]';
$product_rules[ $cat_path . '/([^/]+)/' . $wp_rewrite->comments_pagination_base . '-([0-9]{1,})/?$' ] = 'index.php?product=$matches[1]&cpage=$matches[2]';
}
}
/**
* Register WPML filters back
*/
Sitepress::get()->restore_term_filters();
$rules = empty( $rules ) ? [] : $rules;
return $category_rules + $product_rules + $rules;
}
/**
* Returns categories array.
*
* ['category id' => ['slug' => 'category slug', 'parent' => 'parent category id']]
*
* @return array
*/
private function get_categories() {
if ( is_null( $this->categories ) ) {
$categories = get_categories(
[
'taxonomy' => 'product_cat',
'hide_empty' => false,
]
);
$slugs = [];
foreach ( $categories as $category ) {
$slugs[ $category->term_id ] = [
'parent' => $category->parent,
'slug' => $category->slug,
];
}
$this->categories = $slugs;
}
return $this->categories;
}
/**
* Recursively builds category full path.
*
* @param object $category Term object.
*
* @return string
*/
private function get_category_fullpath( $category ) {
$categories = $this->get_categories();
$parent = $category['parent'];
if ( $parent > 0 && array_key_exists( $parent, $categories ) ) {
return $this->get_category_fullpath( $categories[ $parent ] ) . '/' . $category['slug'];
}
return $category['slug'];
}
/**
* Get product base.
*
* @return string
*/
private function get_product_base() {
if ( is_null( $this->product_base ) ) {
$permalink_structure = wc_get_permalink_structure();
$this->product_base = $permalink_structure['product_rewrite_slug'];
if ( strpos( $this->product_base, '%product_cat%' ) !== false ) {
$this->product_base = str_replace( '%product_cat%', '', $this->product_base );
}
$this->product_base = '/' . trim( $this->product_base, '/' ) . '/';
}
return $this->product_base;
}
/**
* Check if the link can be changed or not.
*
* @param string $check Check string.
* @param string $against Against this.
*
* @return bool
*/
private function can_change_link( $check, $against ) {
return $check !== $against || ! get_option( 'permalink_structure' );
}
}

View File

@@ -0,0 +1,215 @@
<?php
/**
* The WooCommerce module's product redirection features.
*
* @since 1.0.32
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Sitepress;
use RankMath\Helpers\Param;
use RankMath\Helpers\Str;
use RankMath\Redirections\Redirection;
defined( 'ABSPATH' ) || exit;
/**
* WooCommerce class.
*/
class Product_Redirection {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
if ( Helper::is_module_active( 'redirections' ) ) {
$this->filter( 'rank_math/redirection/pre_search', 'pre_redirection', 10, 3 );
return;
}
$this->action( 'wp', 'redirect' );
}
/**
* Pre-filter the redirection.
*
* @param string $check Check.
* @param string $uri Current URL.
* @param string $full_uri Full URL.
*
* @return string|array
*/
public function pre_redirection( $check, $uri, $full_uri ) {
if ( $new_link = $this->get_redirection_url() ) { // phpcs:ignore
return [
'url_to' => $new_link,
'header_code' => 301,
];
}
return $check;
}
/**
* Redirect product with base to the new link.
*/
public function redirect() {
if ( $link = $this->get_redirection_url() ) { // phpcs:ignore
Helper::redirect( $link, 301 );
exit;
}
}
/**
* Get Product URL.
*
* @return string Modified URL
*/
private function get_redirection_url() {
if ( ! $this->can_redirect() ) {
return false;
}
$url = $this->get_source_url();
$is_product = is_product();
$permalink_structure = wc_get_permalink_structure();
$base = $is_product ? $permalink_structure['product_base'] : $permalink_structure['category_base'];
$base = explode( '/', ltrim( $base, '/' ) );
$new_link = $url;
// Early Bail if new_link length is less then the base.
if ( count( explode( '/', $new_link ) ) <= count( $base ) ) {
return false;
}
// On Single product page redirect base with shop and product.
if ( $is_product ) {
$base[] = 'product';
$base[] = 'shop';
$new_link = $this->remove_base_from_url( $new_link );
}
foreach ( array_unique( $base ) as $remove ) {
if ( '%product_cat%' === $remove ) {
continue;
}
$new_link = ! Str::starts_with( '/', $new_link ) ? '/' . $new_link : $new_link;
$new_link = preg_replace( "#/{$remove}/#i", '', $new_link, 1 );
}
$new_link = implode( '/', array_map( 'rawurlencode', explode( '/', ltrim( $new_link, '/' ) ) ) ); // encode everything but slashes.
return $new_link === $this->strip_ignored_parts( $url ) ? false : trailingslashit( home_url( strtolower( $new_link ) ) );
}
/**
* Remove all bases from the product link.
*
* @param string $link Product link.
* @return string Modified URL
*/
private function remove_base_from_url( $link ) {
if ( is_feed() ) {
return $link;
}
if ( Sitepress::get()->is_active() ) {
global $sitepress_settings;
// Early bail if auto-translation is enabled in WPML.
if (
isset( $sitepress_settings['custom_posts_sync_option'] ) &&
isset( $sitepress_settings['custom_posts_sync_option']['product'] ) &&
2 === (int) $sitepress_settings['custom_posts_sync_option']['product']
) {
return $link;
}
}
$link = trim( str_replace( Helper::get_home_url(), '', get_permalink() ), '/' );
return $link;
}
/**
* Get source URL.
*
* @return string
*/
private function get_source_url() {
global $wp;
$url = defined( 'TRP_PLUGIN_DIR' ) ? $wp->request : Param::server( 'REQUEST_URI' );
$url = str_replace( home_url( '/' ), '', $url );
$url = urldecode( $url );
$url = trim( Redirection::strip_subdirectory( $url ), '/' );
$url = explode( '?', $url );
$url = trim( $url[0], '/' );
if ( $this->is_amp_endpoint() ) {
$url = \str_replace( '/' . \amp_get_slug(), '', $url );
}
return $url;
}
/**
* Is AMP url.
*
* @return bool
*/
private function is_amp_endpoint() {
return \function_exists( 'is_amp_endpoint' ) && \function_exists( 'amp_is_canonical' ) && is_amp_endpoint() && ! amp_is_canonical();
}
/**
* Remove unneeded parts from the URI.
*
* @param string $uri Original URI.
*
* @return string
*/
private function strip_ignored_parts( $uri ) {
$ignore_url_parts = [
'#/comment-page-([0-9]{1,})$#',
];
$ignore_url_parts = $this->do_filter( 'woocommerce/product_redirection_ignore_url_parts', $ignore_url_parts );
foreach ( $ignore_url_parts as $pattern ) {
$uri = preg_replace( $pattern, '', $uri );
}
return implode( '/', array_map( 'rawurlencode', explode( '/', $uri ) ) );
}
/**
* Can redirect to the new product link.
*
* @return bool
*/
private function can_redirect() {
global $wp_query;
if (
$this->do_filter( 'woocommerce/product_redirection', true ) &&
! isset( $_GET['elementor-preview'] ) && // phpcs:ignore
! isset( $wp_query->query_vars['schema-preview'] ) &&
( ( Helper::get_settings( 'general.wc_remove_product_base' ) && is_product() ) ||
( Helper::get_settings( 'general.wc_remove_category_base' ) && is_product_category() ) )
) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* WooCommerce product sitemaps adjustments.
*
* @since 1.0.32
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
use RankMath\Helper;
use RankMath\Helpers\Str;
use RankMath\Helpers\Attachment;
defined( 'ABSPATH' ) || exit;
/**
* WC Sitemap class.
*/
class Sitemap {
/**
* Register hooks.
*/
public function sitemap() {
$this->filter( 'rank_math/sitemap/exclude_post_type', 'sitemap_exclude_post_type', 10, 2 );
$this->filter( 'rank_math/sitemap/post_type_archive_link', 'sitemap_taxonomies', 10, 2 );
$this->filter( 'rank_math/sitemap/post_type_archive_link', 'sitemap_post_type_archive_link', 10, 2 );
$this->filter( 'rank_math/sitemap/urlimages', 'add_product_images_to_xml_sitemap', 10, 2 );
}
/**
* Make sure product variations and shop coupons are not included in the XML sitemap.
*
* @param bool $bool Whether or not to include this post type in the XML sitemap.
* @param string $post_type The post type of the post.
*
* @return bool
*/
public function sitemap_exclude_post_type( $bool, $post_type ) {
if ( in_array( $post_type, [ 'product_variation', 'shop_coupon' ], true ) ) {
return true;
}
return $bool;
}
/**
* Make sure product attribute taxonomies are not included in the XML sitemap.
*
* @param bool $bool Whether or not to include this post type in the XML sitemap.
* @param string $taxonomy The taxonomy to check against.
*
* @return bool
*/
public function sitemap_taxonomies( $bool, $taxonomy ) {
if ( in_array( $taxonomy, [ 'product_type', 'product_shipping_class', 'shop_order_status' ], true ) ) {
return true;
}
if ( Str::starts_with( 'pa_', $taxonomy ) ) {
return true;
}
return $bool;
}
/**
* Filters the archive link on the product sitemap.
*
* @param string $link The archive link.
* @param string $post_type The post type to check against.
*
* @return bool
*/
public function sitemap_post_type_archive_link( $link, $post_type ) {
if ( 'product' !== $post_type || ! function_exists( 'wc_get_page_id' ) ) {
return $link;
}
$shop_page_id = wc_get_page_id( 'shop' );
$home_page_id = (int) get_option( 'page_on_front' );
if ( 1 > $shop_page_id || 'publish' !== get_post_status( $shop_page_id ) || $home_page_id === $shop_page_id ) {
return false;
}
$robots = Helper::get_post_meta( 'robots', $shop_page_id );
if ( ! empty( $robots ) && is_array( $robots ) && in_array( 'noindex', $robots, true ) ) {
return false;
}
return $link;
}
/**
* Add the product gallery images to the XML sitemap.
*
* @param array $images The array of images for the post.
* @param int $post_id The ID of the post object.
*
* @return array
*/
public function add_product_images_to_xml_sitemap( $images, $post_id ) {
if ( metadata_exists( 'post', $post_id, '_product_image_gallery' ) ) {
$product_gallery = get_post_meta( $post_id, '_product_image_gallery', true );
$attachments = array_filter( explode( ',', $product_gallery ) );
foreach ( $attachments as $attachment_id ) {
$image_src = wp_get_attachment_image_src( $attachment_id, 'full' );
if ( empty( $image_src ) ) {
continue;
}
$image = [
'src' => $this->do_filter( 'sitemap/xml_img_src', $image_src[0], $post_id ),
'title' => get_the_title( $attachment_id ),
'alt' => Attachment::get_alt_tag( $attachment_id ),
];
$images[] = $image;
unset( $image, $image_src );
}
}
return $images;
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* Register additional variables for WooCommerce.
*
* @since 1.0.32
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
defined( 'ABSPATH' ) || exit;
/**
* WC Variables class.
*/
class WC_Vars extends Opengraph {
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'rank_math/vars/register_extra_replacements', 'register' );
}
/**
* Registers variable replacements for WooCommerce products.
*/
public function register() {
rank_math_register_var_replacement(
'wc_price',
[
'name' => esc_html__( 'Product\'s price.', 'rank-math' ),
'description' => esc_html__( 'Product\'s price of the current product', 'rank-math' ),
'variable' => 'wc_price',
'example' => $this->get_product_price(),
],
[ $this, 'get_product_price' ]
);
rank_math_register_var_replacement(
'wc_sku',
[
'name' => esc_html__( 'Product\'s SKU.', 'rank-math' ),
'description' => esc_html__( 'Product\'s SKU of the current product', 'rank-math' ),
'variable' => 'wc_sku',
'example' => $this->get_product_sku(),
],
[ $this, 'get_product_sku' ]
);
rank_math_register_var_replacement(
'wc_shortdesc',
[
'name' => esc_html__( 'Product\'s short description.', 'rank-math' ),
'description' => esc_html__( 'Product\'s short description of the current product', 'rank-math' ),
'variable' => 'wc_shortdesc',
'example' => $this->get_short_description(),
],
[ $this, 'get_short_description' ]
);
rank_math_register_var_replacement(
'wc_brand',
[
'name' => esc_html__( 'Product\'s brand.', 'rank-math' ),
'description' => esc_html__( 'Product\'s brand of the current product', 'rank-math' ),
'variable' => 'wc_brand',
'example' => $this->get_product_brand(),
],
[ $this, 'get_product_brand' ]
);
}
/**
* Retrieves the product price.
*
* @return string
*/
public function get_product_price() {
$product = $this->get_product();
if ( ! is_object( $product ) ) {
return '';
}
if ( method_exists( $product, 'get_price' ) ) {
return wp_strip_all_tags( wc_price( $product->get_price() ), true );
}
return '';
}
/**
* Retrieves the product SKU.
*
* @return string
*/
public function get_product_sku() {
$product = $this->get_product();
if ( ! is_object( $product ) ) {
return '';
}
if ( method_exists( $product, 'get_sku' ) ) {
return $product->get_sku();
}
return '';
}
/**
* Checks if product class has a short description method.
* Otherwise it returns the value of the post_excerpt from the post attribute.
*
* @param WC_Product $product The product.
*
* @return string
*/
public function get_short_description( $product = null ) {
if ( empty( $product ) ) {
$product = $this->get_product();
}
if ( ! is_object( $product ) ) {
return '';
}
if ( method_exists( $product, 'get_short_description' ) ) {
return $product->get_short_description();
}
return $product->post->post_excerpt;
}
/**
* Retrieves the product brand.
*
* @return string
*/
public function get_product_brand() {
$product = $this->get_product();
if ( ! is_object( $product ) ) {
return '';
}
return $this->get_brands( $product->get_id() );
}
}

View File

@@ -0,0 +1,283 @@
<?php
/**
* The WooCommerce module.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\WooCommerce
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\WooCommerce;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Str;
use RankMath\Helpers\Param;
defined( 'ABSPATH' ) || exit;
/**
* WooCommerce class.
*/
class WooCommerce extends WC_Vars {
use Hooker;
/**
* Holds the product object.
*
* @var WC_Product
*/
private $product = null;
/**
* Remove product base.
*
* @var bool
*/
private $remove_product_base;
/**
* Remove category base.
*
* @var bool
*/
private $remove_category_base;
/**
* Remove parent slugs.
*
* @var bool
*/
private $remove_parent_slugs;
/**
* The Constructor.
*/
public function __construct() {
$this->remove_product_base = Helper::get_settings( 'general.wc_remove_product_base' );
$this->remove_category_base = Helper::get_settings( 'general.wc_remove_category_base' );
$this->remove_parent_slugs = Helper::get_settings( 'general.wc_remove_category_parent_slugs' );
if ( is_admin() ) {
new Admin();
}
$this->integrations();
if ( $this->remove_product_base || $this->remove_category_base ) {
new Product_Redirection();
}
new Permalink_Watcher();
parent::__construct();
}
/**
* Initialize integrations.
*/
public function integrations() {
if ( is_admin() ) {
return;
}
// Permalink Manager.
if ( $this->remove_product_base ) {
$this->action( 'request', 'request', 11 );
}
if ( Helper::get_settings( 'general.wc_remove_generator' ) ) {
remove_action( 'get_the_generator_html', 'wc_generator_tag', 10 );
remove_action( 'get_the_generator_xhtml', 'wc_generator_tag', 10 );
}
$this->sitemap();
$this->opengraph();
$this->filter( 'rank_math/frontend/description', 'metadesc' );
$this->filter( 'rank_math/frontend/robots', 'robots' );
}
/**
* Replace request if product was found.
*
* @param array $request Current request.
*
* @return array
*/
public function request( $request ) {
global $wp, $wpdb;
$url = $wp->request;
if ( empty( $url ) ) {
return $request;
}
$replace = [];
$url = explode( '/', $url );
$slug = array_pop( $url );
if ( 'feed' === $slug ) {
$replace['feed'] = $slug;
$slug = array_pop( $url );
}
if ( 'amp' === $slug ) {
$replace['amp'] = $slug;
$slug = array_pop( $url );
}
if ( 0 === strpos( $slug, 'comment-page-' ) ) {
$replace['cpage'] = substr( $slug, strlen( 'comment-page-' ) );
$slug = array_pop( $url );
}
if ( 0 === strpos( $slug, 'schema-preview' ) ) {
$replace['schema-preview'] = '';
$slug = array_pop( $url );
}
$query = "SELECT COUNT(ID) as count_id FROM {$wpdb->posts} WHERE post_name = %s AND post_type = %s";
$num = intval( $wpdb->get_var( $wpdb->prepare( $query, [ $slug, 'product' ] ) ) ); // phpcs:ignore
if ( $num > 0 ) {
$replace['page'] = '';
$replace['name'] = $slug;
$replace['product'] = $slug;
$replace['post_type'] = 'product';
return $replace;
}
return $request;
}
/**
* Change robots for WooCommerce pages according to the settings.
*
* @param array $robots Array of robots to sanitize.
*
* @return array Modified robots.
*/
public function robots( $robots ) {
// Early Bail if current page is Woocommerce OnePage Checkout.
if ( function_exists( 'is_wcopc_checkout' ) && is_wcopc_checkout() ) {
return $robots;
}
if ( is_cart() || is_checkout() || is_account_page() ) {
remove_action( 'wp_head', 'wc_page_noindex' );
return [
'index' => 'noindex',
'follow' => 'follow',
];
}
return $robots;
}
/**
* Returns the meta description. Checks which value should be used when the given meta description is empty.
*
* It will use the short_description if that one is set. Otherwise it will use the full
* product description limited to 156 characters. If everything is empty, it will return an empty string.
*
* @param string $metadesc The meta description to check.
*
* @return string The meta description.
*/
public function metadesc( $metadesc ) {
if ( '' !== $metadesc || ! is_singular( 'product' ) ) {
return $metadesc;
}
$product = $this->get_product_by_id( get_the_id() );
if ( ! is_object( $product ) ) {
return '';
}
$short_desc = $this->get_short_description( $product );
if ( '' !== $short_desc ) {
return $short_desc;
}
$long_desc = $this->get_long_description( $product );
return '' !== $long_desc ? Str::truncate( $long_desc, 156 ) : '';
}
/**
* Returns the product for given product_id.
*
* @param int $product_id The id to get the product for.
*
* @return null|WC_Product
*/
protected function get_product_by_id( $product_id ) {
if ( function_exists( 'wc_get_product' ) ) {
return wc_get_product( $product_id );
}
if ( function_exists( 'get_product' ) ) {
return get_product( $product_id );
}
return null;
}
/**
* Checks if product class has a description method.
* Otherwise it returns the value of the post_content.
*
* @param WC_Product $product The product.
*
* @return string
*/
protected function get_long_description( $product ) {
if ( method_exists( $product, 'get_description' ) ) {
return $product->get_description();
}
return $product->post->post_content;
}
/**
* Returns the product object when the current page is the product page.
*
* @return null|WC_Product
*/
public function get_product() {
if ( ! is_null( $this->product ) ) {
return $this->product;
}
$product_id = Param::get( 'post', get_queried_object_id(), FILTER_VALIDATE_INT );
$this->product = (
! function_exists( 'wc_get_product' ) ||
! $product_id ||
(
! is_admin() &&
! is_singular( 'product' )
)
) ? null : wc_get_product( $product_id );
return $this->product;
}
/**
* Returns the array of brand taxonomy.
*
* @param int $product_id The id to get the product brands for.
*
* @return bool|array
*/
public static function get_brands( $product_id ) {
$brand = '';
$taxonomy = Helper::get_settings( 'general.product_brand' );
if ( $taxonomy && taxonomy_exists( $taxonomy ) ) {
$brands = get_the_terms( $product_id, $taxonomy );
$brand = is_wp_error( $brands ) || empty( $brands[0] ) ? '' : $brands[0]->name;
}
return apply_filters( 'rank_math/woocommerce/product_brand', $brand );
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,83 @@
<?php
/**
* WooCommerce general settings.
*
* @package RankMath
* @subpackage RankMath\WooCommerce
*/
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
$cmb->add_field(
[
'id' => 'wc_remove_product_base',
'type' => 'toggle',
'name' => esc_html__( 'Remove base', 'rank-math' ),
'desc' => sprintf(
/* translators: 1. Example text 2. Example text */
esc_html__( 'Remove prefix like %1$s from product URL chosen at %2$s', 'rank-math' ),
'<code>/shop/*</code>, <code>/product/*</code>',
'<br /><code>' . __( 'WordPress Dashboard > Settings > Permalinks > Product permalinks Example: default: /product/accessories/action-figures/acme/ - becomes: /accessories/action-figures/acme/', 'rank-math' ) . '</code>'
),
'default' => 'off',
'classes' => 'rank-math-advanced-option',
]
);
$cmb->add_field(
[
'id' => 'wc_remove_category_base',
'type' => 'toggle',
'name' => esc_html__( 'Remove category base', 'rank-math' ),
'desc' => esc_html__( 'Remove prefix from category URL.', 'rank-math' ) .
'<br><code>' . esc_html__( 'default: /product-category/accessories/action-figures/ - changed: /accessories/action-figures/', 'rank-math' ) . '</code>',
'default' => 'off',
'classes' => 'rank-math-advanced-option',
]
);
$cmb->add_field(
[
'id' => 'wc_remove_category_parent_slugs',
'type' => 'toggle',
'name' => esc_html__( ' Remove parent slugs', 'rank-math' ),
'desc' => esc_html__( 'Remove parent slugs from category URL.', 'rank-math' ) .
'<br><code>' . esc_html__( 'default: /product-category/accessories/action-figures/ - changed: /product-category/action-figures/', 'rank-math' ) . '</code>',
'default' => 'off',
'classes' => 'rank-math-advanced-option',
]
);
$cmb->add_field(
[
'id' => 'wc_remove_generator',
'type' => 'toggle',
'name' => esc_html__( 'Remove Generator Tag', 'rank-math' ),
'desc' => esc_html__( 'Remove WooCommerce generator tag from the source code.', 'rank-math' ),
'default' => 'on',
'classes' => 'rank-math-advanced-option',
]
);
$cmb->add_field(
[
'id' => 'remove_shop_snippet_data',
'type' => 'toggle',
'name' => esc_html__( 'Remove Schema Markup on Shop Archives', 'rank-math' ),
'desc' => esc_html__( 'Remove Schema Markup Data from WooCommerce Shop archive pages.', 'rank-math' ),
'default' => 'on',
'classes' => 'rank-math-advanced-option',
]
);
$cmb->add_field(
[
'id' => 'product_brand',
'type' => 'select',
'name' => esc_html__( 'Brand', 'rank-math' ),
'desc' => esc_html__( 'Select Product Brand Taxonomy to use in Schema.org & OpenGraph markup.', 'rank-math' ),
'options' => Helper::get_object_taxonomies( 'product', 'choices', false ),
]
);