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

View File

@@ -0,0 +1,60 @@
<?php
/**
* The Article Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
use RankMath\Traits\Hooker;
defined( 'ABSPATH' ) || exit;
/**
* Article class.
*/
class Article implements Snippet {
use Hooker;
/**
* Article rich snippet.
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$entity = [
'@type' => Helper::get_default_schema_type( $jsonld->post->ID ),
'headline' => $jsonld->parts['title'],
'keywords' => Helper::replace_vars( '%keywords%', $jsonld->post ),
'datePublished' => $jsonld->parts['published'],
'dateModified' => $jsonld->parts['modified'],
'isPrimary' => true,
'articleSection' => Helper::replace_vars( '%primary_taxonomy_terms%', $jsonld->post ),
'author' => ! empty( $data['ProfilePage'] ) ?
[
'@id' => $data['ProfilePage']['@id'],
'name' => $jsonld->parts['author'],
] :
[
'@type' => 'Person',
'name' => $jsonld->parts['author'],
],
];
$jsonld->add_prop( 'publisher', $entity, 'publisher', $data );
if ( ! empty( $jsonld->parts['desc'] ) ) {
$entity['description'] = $jsonld->parts['desc'];
}
return $entity;
}
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* The Author Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
use RankMath\User;
use RankMath\Paper\Paper;
defined( 'ABSPATH' ) || exit;
/**
* Author class.
*/
class Author implements Snippet {
/**
* Add Author entity in JSON-LD data.
*
* @link https://schema.org/Person
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$is_archive_disabled = Helper::get_settings( 'titles.disable_author_archives' );
$author_id = is_singular() ? $jsonld->post->post_author : get_the_author_meta( 'ID' );
$author_name = get_the_author();
$author_url = get_author_posts_url( $author_id );
$data['ProfilePage'] = [
'@type' => 'Person',
'@id' => ! $is_archive_disabled ? $author_url : $jsonld->parts['url'] . '#author',
'name' => $author_name,
'description' => wp_strip_all_tags( stripslashes( $this->get_description( $author_id ) ), true ),
'url' => $is_archive_disabled ? '' : $author_url,
];
$this->add_image( $data['ProfilePage'], $author_id, $jsonld );
$this->add_same_as( $data['ProfilePage'], $author_id );
$this->add_works_for( $data['ProfilePage'], $data );
if ( is_author() && ! empty( $data['WebPage'] ) ) {
$data['ProfilePage']['mainEntityOfPage'] = [
'@id' => $data['WebPage']['@id'],
];
}
return $data;
}
/**
* Add sameAs property to the Person entity.
*
* @param array $entity Author schema data.
* @param int $author_id Author ID.
*/
private function add_same_as( &$entity, $author_id ) {
$same_as = [
get_the_author_meta( 'user_url', $author_id ),
get_user_meta( $author_id, 'facebook', true ),
];
if ( $twitter = get_user_meta( $author_id, 'twitter', true ) ) { // phpcs:ignore
$same_as[] = 'https://twitter.com/' . $twitter;
}
$addional_urls = get_user_meta( $author_id, 'additional_profile_urls', true );
if ( $addional_urls ) {
$same_as = array_merge( $same_as, explode( ' ', $addional_urls ) );
}
$same_as = array_filter( $same_as );
if ( empty( $same_as ) ) {
return;
}
$entity['sameAs'] = array_values( $same_as );
}
/**
* Add image property to the Person entity.
*
* @param array $entity Author schema data.
* @param int $author_id Author ID.
* @param JsonLD $jsonld JsonLD Instance.
*/
private function add_image( &$entity, $author_id, $jsonld ) {
$entity['image'] = [
'@type' => 'ImageObject',
'@id' => get_avatar_url( $author_id ),
'url' => get_avatar_url( $author_id ),
'caption' => get_the_author(),
];
$jsonld->add_prop( 'language', $entity['image'] );
}
/**
* Add worksFor property referencing it to the publisher entity.
*
* @param array $entity Author schema data.
* @param array $data Schema Data.
*/
private function add_works_for( &$entity, $data ) {
if (
empty( $data['publisher'] ) ||
in_array( 'Person', (array) $data['publisher']['@type'], true )
) {
return;
}
$entity['worksFor'] = [ '@id' => $data['publisher']['@id'] ];
}
/**
* Get author description.
*
* @param int $author_id Author ID.
*/
private function get_description( $author_id ) {
$description = User::get_meta( 'description', $author_id );
return $description ? $description : Paper::get_from_options( 'author_archive_description' );
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* The Breadcrumbs Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Frontend\Breadcrumbs as BreadcrumbTrail;
use RankMath\Paper\Paper;
defined( 'ABSPATH' ) || exit;
/**
* Breadcrumbs class.
*/
class Breadcrumbs implements Snippet {
/**
* Generate breadcrumbs JSON-LD.
*
* @link https://schema.org/BreadcrumbList
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$crumbs = BreadcrumbTrail::get() ? BreadcrumbTrail::get()->get_crumbs() : false;
if ( empty( $crumbs ) ) {
return $data;
}
$entity = [
'@type' => 'BreadcrumbList',
'@id' => Paper::get()->get_canonical() . '#breadcrumb',
'itemListElement' => [],
];
$position = 1;
foreach ( $crumbs as $crumb ) {
if ( ! empty( $crumb['hide_in_schema'] ) || empty( $crumb[1] ) ) {
continue;
}
$entity['itemListElement'][] = [
'@type' => 'ListItem',
'position' => $position,
'item' => [
'@id' => $crumb[1],
'name' => $crumb[0],
],
];
$position++;
}
$entity = apply_filters( 'rank_math/snippet/breadcrumb', $entity );
if ( empty( $entity['itemListElement'] ) ) {
return $data;
}
$data['BreadcrumbList'] = $entity;
return $data;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* The Primary Image Class.
*
* @since 1.0.43
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* PrimaryImage class.
*/
class PrimaryImage implements Snippet {
/**
* Add primaryImage entity in JSON-LD data.
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$image = Helper::get_thumbnail_with_fallback( get_the_ID(), 'full' );
if ( empty( $image ) ) {
return $data;
}
$data['primaryImage'] = [
'@type' => 'ImageObject',
'@id' => $image[0],
'url' => $image[0],
'width' => $image[1],
'height' => $image[2],
'caption' => isset( $image['caption'] ) ? $image['caption'] : '',
];
$jsonld->add_prop( 'language', $data['primaryImage'] );
return $data;
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* The Easy Digital Downloads Product Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use EDD_Download;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Product_Edd class.
*/
class Product_Edd {
/**
* Set product data for rich snippet.
*
* @param array $entity Array of JSON-LD entity.
* @param JsonLD $jsonld JsonLD Instance.
*/
public function set_product( &$entity, $jsonld ) {
$product_id = get_the_ID();
$permalink = get_permalink();
$product = new EDD_Download( $product_id );
$entity['url'] = $permalink;
$entity['name'] = $jsonld->post->post_title;
$entity['description'] = Helper::replace_vars( '%seo_description%' );
$entity['category'] = Product::get_category( $product_id, 'download_category' );
$entity['mainEntityOfPage'] = [ '@id' => $jsonld->parts['canonical'] . '#webpage' ];
// SKU.
if ( $product->get_sku() ) {
$entity['sku'] = $product->get_sku();
}
// Offers.
$seller = Product::get_seller( $jsonld );
$variations = $this->has_variations( $product );
if ( false !== $variations ) {
$entity['offers'] = [];
foreach ( $variations as $variation ) {
$offer = [
'@type' => 'Offer',
'description' => $variation['name'],
'price' => $variation['amount'],
'priceCurrency' => edd_get_currency(),
'priceValidUntil' => date( 'Y-12-31', time() + YEAR_IN_SECONDS ),
'url' => $permalink,
'seller' => $seller,
];
// Set Price Specification.
$this->set_price_specification( $variation['amount'], $offer );
$entity['offers'][] = $offer;
}
return;
}
// Single offer.
$entity['offers'] = [
'@type' => 'Offer',
'price' => $product->get_price() ? $product->get_price() : '0',
'priceCurrency' => edd_get_currency(),
'priceValidUntil' => date( 'Y-12-31', time() + YEAR_IN_SECONDS ),
'seller' => $seller,
'url' => $permalink,
];
// Set Price Specification.
$this->set_price_specification( $product->get_price(), $entity['offers'] );
}
/**
* Set price specification.
*
* @param object $price Product price.
* @param array $entity Array of offer entity.
*/
private function set_price_specification( $price, &$entity ) {
if ( ! edd_use_taxes() ) {
return;
}
$entity['priceSpecification'] = [
'price' => $price ? $price : '0',
'priceCurrency' => edd_get_currency(),
'valueAddedTaxIncluded' => edd_prices_include_tax() ? 'true' : 'false',
];
}
/**
* If product is variable, set variations.
*
* @param EDD_Download $product Current product.
*
* @return array|boolean
*/
private function has_variations( $product ) {
if ( ! $product->has_variable_prices() ) {
return false;
}
$variations = $product->get_prices();
return ! empty( $variations ) ? $variations : false;
}
}

View File

@@ -0,0 +1,373 @@
<?php
/**
* The WooCommerce Product Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Product_WooCommerce class.
*/
class Product_WooCommerce {
/**
* Attribute assigner.
*
* @var WC_Attributes
*/
private $attributes;
/**
* Set product data for rich snippet.
*
* @param array $entity Array of JSON-LD entity.
* @param JsonLD $jsonld JsonLD Instance.
*/
public function set_product( &$entity, $jsonld ) {
$product = wc_get_product( get_the_ID() );
$this->attributes = new WC_Attributes( $product );
if ( Helper::is_module_active( 'woocommerce' ) ) {
$brand = \RankMath\WooCommerce\Woocommerce::get_brands( $product->get_id() );
// Brand.
if ( ! empty( $brand ) ) {
$entity['brand'] = [
'@type' => 'Brand',
'name' => $brand,
];
}
}
$entity['name'] = $jsonld->get_product_title( $product );
$entity['description'] = $jsonld->get_product_desc( $product );
$entity['sku'] = $product->get_sku() ? $product->get_sku() : '';
$entity['category'] = Product::get_category( $product->get_id(), 'product_cat' );
$entity['mainEntityOfPage'] = [ '@id' => $jsonld->parts['canonical'] . '#webpage' ];
$this->set_weight( $product, $entity );
$this->set_dimensions( $product, $entity );
$this->set_images( $product, $entity );
$this->set_ratings( $product, $entity );
$this->set_offers( $product, $entity, Product::get_seller( $jsonld ) );
// GTIN numbers need product attributes.
$this->attributes->assign_property( $entity, 'gtin8' );
$this->attributes->assign_property( $entity, 'gtin12' );
$this->attributes->assign_property( $entity, 'gtin13' );
$this->attributes->assign_property( $entity, 'gtin14' );
// Color.
$this->attributes->assign_property( $entity, 'color' );
// Remaining Attributes.
$this->attributes->assign_remaining( $entity );
}
/**
* Set product weight.
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
*/
private function set_weight( $product, &$entity ) {
if ( ! $product->has_weight() ) {
return;
}
$hash = [
'lbs' => 'LBR',
'kg' => 'KGM',
'g' => 'GRM',
'oz' => 'ONZ',
];
$unit = get_option( 'woocommerce_weight_unit' );
$entity['weight'] = [
'@type' => 'QuantitativeValue',
'unitCode' => isset( $hash[ $unit ] ) ? $hash[ $unit ] : 'LBR',
'value' => $product->get_weight(),
];
}
/**
* Set product dimension.
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
*/
private function set_dimensions( $product, &$entity ) {
if ( ! $product->has_dimensions() ) {
return;
}
$hash = [
'in' => 'INH',
'm' => 'MTR',
'cm' => 'CMT',
'mm' => 'MMT',
'yd' => 'YRD',
];
$unit = get_option( 'woocommerce_dimension_unit' );
$code = isset( $hash[ $unit ] ) ? $hash[ $unit ] : '';
$entity['height'] = [
'@type' => 'QuantitativeValue',
'unitCode' => $code,
'value' => $product->get_height(),
];
$entity['width'] = [
'@type' => 'QuantitativeValue',
'unitCode' => $code,
'value' => $product->get_width(),
];
$entity['depth'] = [
'@type' => 'QuantitativeValue',
'unitCode' => $code,
'value' => $product->get_length(),
];
}
/**
* Set product images.
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
*/
private function set_images( $product, &$entity ) {
if ( ! $product->get_image_id() ) {
return;
}
$image = wp_get_attachment_image_src( $product->get_image_id(), 'single-post-thumbnail' );
if ( ! empty( $image ) ) {
$entity['image'][] = [
'@type' => 'ImageObject',
'url' => $image[0],
'height' => $image[2],
'width' => $image[1],
];
}
$gallery = $product->get_gallery_image_ids();
foreach ( $gallery as $image_id ) {
$image = wp_get_attachment_image_src( $image_id, 'single-post-thumbnail' );
if ( empty( $image ) ) {
continue;
}
$entity['image'][] = [
'@type' => 'ImageObject',
'url' => $image[0],
'height' => $image[2],
'width' => $image[1],
];
}
}
/**
* Set product ratings.
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
*/
private function set_ratings( $product, &$entity ) {
if ( $product->get_rating_count() < 1 ) {
return;
}
// Aggregate Rating.
$entity['aggregateRating'] = [
'@type' => 'AggregateRating',
'ratingValue' => $product->get_average_rating(),
'bestRating' => '5',
'ratingCount' => $product->get_rating_count(),
'reviewCount' => $product->get_review_count(),
];
// Reviews.
$comments = get_comments(
[
'post_type' => 'product',
'post_id' => get_the_ID(),
'status' => 'approve',
'parent' => 0,
]
);
$permalink = $product->get_permalink();
foreach ( $comments as $comment ) {
$rating = intval( get_comment_meta( $comment->comment_ID, 'rating', true ) );
if ( ! $rating ) {
continue;
}
$entity['review'][] = [
'@type' => 'Review',
'@id' => $permalink . '#li-comment-' . $comment->comment_ID,
'description' => $comment->comment_content,
'datePublished' => $comment->comment_date,
'reviewRating' => [
'@type' => 'Rating',
'ratingValue' => $rating,
'bestRating' => '5',
'worstRating' => '1',
],
'author' => [
'@type' => 'Person',
'name' => $comment->comment_author,
'url' => $comment->comment_author_url,
],
];
}
}
/**
* Set product offers.
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
* @param array $seller Seller info.
*/
private function set_offers( $product, &$entity, $seller ) {
if ( '' === $product->get_price() ) {
return;
}
if ( true === $this->set_offers_variable( $product, $entity, $seller ) ) {
return;
}
$offer = [
'@type' => 'Offer',
'price' => $product->get_price() ? wc_format_decimal( $product->get_price(), wc_get_price_decimals() ) : '0',
'priceCurrency' => get_woocommerce_currency(),
'priceValidUntil' => $product->is_on_sale() && ! empty( $product->get_date_on_sale_to() ) ? date_i18n( 'Y-m-d', strtotime( $product->get_date_on_sale_to() ) ) : date( 'Y-12-31', time() + YEAR_IN_SECONDS ),
'availability' => $product->is_in_stock() ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',
'itemCondition' => 'NewCondition',
'url' => $product->get_permalink(),
'seller' => $seller,
];
// Set Price Specification.
$this->set_price_specification( $product->get_price(), $offer );
$this->attributes->assign_property( $offer, 'itemCondition' );
$entity['offers'] = $offer;
}
/**
* Set product variable offers.
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
* @param array $seller Seller info.
*/
private function set_offers_variable( $product, &$entity, $seller ) {
if ( ! $product->is_type( 'variable' ) ) {
return false;
}
if ( $this->set_single_variable_offer( $product, $entity, $seller ) ) {
return true;
}
$permalink = $product->get_permalink();
$lowest = wc_format_decimal( $product->get_variation_price( 'min', false ), wc_get_price_decimals() );
$highest = wc_format_decimal( $product->get_variation_price( 'max', false ), wc_get_price_decimals() );
if ( $lowest === $highest ) {
$offer = [
'@type' => 'Offer',
'price' => $lowest,
'priceValidUntil' => date( 'Y-12-31', time() + YEAR_IN_SECONDS ),
];
// Set Price Specification.
$this->set_price_specification( $lowest, $offer );
} else {
$offer = [
'@type' => 'AggregateOffer',
'lowPrice' => $lowest,
'highPrice' => $highest,
'offerCount' => count( $product->get_children() ),
];
}
$offer += [
'priceCurrency' => get_woocommerce_currency(),
'availability' => 'http://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'seller' => $seller,
'url' => $permalink,
];
$entity['offers'] = $offer;
return true;
}
/**
* Set Single Variable Product offer.
*
* Credit @leewillis77: https://github.com/leewillis77/wc-structured-data-option-4
*
* @param object $product Product instance.
* @param array $entity Array of JSON-LD entity.
* @param array $seller Seller info.
*/
private function set_single_variable_offer( $product, &$entity, $seller ) {
$data_store = \WC_Data_Store::load( 'product' );
$variation_id = $data_store->find_matching_product_variation( $product, wp_unslash( $_GET ) );
$variation = $variation_id ? wc_get_product( $variation_id ) : false;
if ( empty( $variation ) ) {
return false;
}
$price_valid_until = date( 'Y-12-31', current_time( 'timestamp', true ) + YEAR_IN_SECONDS );
if ( $variation->is_on_sale() && $variation->get_date_on_sale_to() ) {
$price_valid_until = date( 'Y-m-d', $variation->get_date_on_sale_to()->getTimestamp() );
}
$entity['offers'] = [
'@type' => 'Offer',
'url' => $variation->get_permalink(),
'sku' => $variation->get_sku(),
'price' => wc_format_decimal( $variation->get_price(), wc_get_price_decimals() ),
'priceCurrency' => get_woocommerce_currency(),
'priceValidUntil' => $price_valid_until,
'seller' => $seller,
'availability' => 'http://schema.org/' . ( $variation->is_in_stock() ? 'InStock' : 'OutOfStock' ),
];
return true;
}
/**
* Set price specification.
*
* @param object $price Product price.
* @param array $entity Array of offer entity.
*/
private function set_price_specification( $price, &$entity ) {
if ( ! wc_tax_enabled() ) {
return;
}
$entity['priceSpecification'] = [
'price' => $price ? $price : '0',
'priceCurrency' => get_woocommerce_currency(),
'valueAddedTaxIncluded' => wc_prices_include_tax() ? 'true' : 'false',
];
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* The Product Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
use RankMath\Schema\Product_Edd;
use RankMath\Schema\Product_WooCommerce;
defined( 'ABSPATH' ) || exit;
/**
* Product class.
*/
class Product implements Snippet {
/**
* Hold JsonLD Instance.
*
* @var JsonLD
*/
private $json = '';
/**
* Product rich snippet.
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$entity = [
'@type' => 'Product',
];
if ( Helper::is_woocommerce_active() && is_product() ) {
remove_action( 'wp_footer', [ WC()->structured_data, 'output_structured_data' ], 10 );
remove_action( 'woocommerce_email_order_details', [ WC()->structured_data, 'output_email_structured_data' ], 30 );
$product = new Product_WooCommerce();
$product->set_product( $entity, $jsonld );
}
if ( Helper::is_edd_active() && is_singular( 'download' ) ) {
remove_filter( 'wp_footer', [ \EDD()->structured_data, 'output_structured_data' ] );
remove_action( 'edd_purchase_link_top', 'edd_purchase_link_single_pricing_schema', 10 );
remove_action( 'loop_start', 'edd_microdata_wrapper_open', 10 );
$product = new Product_Edd();
$product->set_product( $entity, $jsonld );
}
return $entity;
}
/**
* Get seller.
*
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public static function get_seller( $jsonld ) {
$site_url = home_url();
$type = Helper::get_settings( 'titles.knowledgegraph_type' );
$seller = [
'@type' => 'person' === $type ? 'Person' : 'Organization',
'@id' => trailingslashit( $site_url ),
'name' => $jsonld->get_website_name(),
'url' => $site_url,
];
if ( 'company' === $type ) {
$seller['logo'] = Helper::get_settings( 'titles.knowledgegraph_logo' );
}
return $seller;
}
/**
* Set product categories.
*
* @param int $product_id Product ID.
* @param string $taxonomy Taxonomy.
*/
public static function get_category( $product_id, $taxonomy ) {
$categories = get_the_terms( $product_id, $taxonomy );
if ( is_wp_error( $categories ) || empty( $categories ) ) {
return;
}
if ( 0 === $categories[0]->parent ) {
return $categories[0]->name;
}
$ancestors = array_reverse( get_ancestors( $categories[0]->term_id, $taxonomy ) );
foreach ( $ancestors as $parent ) {
$term = get_term( $parent, $taxonomy );
$category[] = $term->name;
}
$category[] = $categories[0]->name;
return join( ' > ', $category );
}
}

View File

@@ -0,0 +1,113 @@
<?php
/**
* The Products Page Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Products_Page class.
*/
class Products_Page implements Snippet {
/**
* Sets the Schema structured data on the Products Archive page.
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
if ( ! $this->can_add_snippet_taxonomy() || ! $this->can_add_snippet_shop() ) {
return $data;
}
$data['ProductsPage'] = [
'@context' => 'https://schema.org/',
'@graph' => [],
];
while ( have_posts() ) {
the_post();
$post_id = get_the_ID();
$product = wc_get_product( $post_id );
$url = $jsonld->get_post_url( $post_id );
$part = [
'@type' => 'Product',
'name' => $jsonld->get_product_title( $product ),
'url' => $url,
'@id' => $url,
'description' => $jsonld->get_product_desc( $product ),
];
$data['ProductsPage']['@graph'][] = $part;
}
wp_reset_postdata();
return $data;
}
/**
* Check if structured data can be added on the current Product taxonomy.
*
* @return boolean|string
*/
private function can_add_snippet_taxonomy() {
$queried_object = get_queried_object();
/**
* Allow developer to remove snippet data.
*
* @param bool $unsigned Default: false
* @param string $unsigned Taxonomy Name
*/
if (
! is_shop() &&
(
true === Helper::get_settings( 'titles.remove_' . $queried_object->taxonomy . '_snippet_data' ) ||
true === apply_filters( 'rank_math/snippet/remove_taxonomy_data', false, $queried_object->taxonomy )
)
) {
return false;
}
return true;
}
/**
* Check if structured data can be added on the Shop page.
*
* @return boolean|string
*/
private function can_add_snippet_shop() {
/**
* Allow developer to remove snippet data from Shop page.
*
* @param bool $unsigned Default: false
*/
if (
is_shop() &&
(
true === Helper::get_settings( 'general.remove_shop_snippet_data' ) ||
true === apply_filters( 'rank_math/snippet/remove_shop_data', false )
)
) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* The Publisher Class.
*
* @since 1.0.43
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Publisher class.
*/
class Publisher implements Snippet {
/**
* Generate Organization JSON-LD.
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$type = Helper::get_settings( 'titles.knowledgegraph_type' );
$id = 'company' === $type ? 'organization' : 'person';
$data['publisher'] = [
'@type' => $this->get_publisher_type( $type ),
'@id' => home_url( "/#{$id}" ),
'name' => $jsonld->get_organization_name(),
];
$social_profiles = $jsonld->get_social_profiles();
if ( ! empty( $social_profiles ) ) {
$data['publisher']['sameAs'] = $social_profiles;
}
$jsonld->add_prop( 'image', $data['publisher'] );
if ( empty( $data['publisher']['logo'] ) ) {
return $data;
}
if ( 'person' === $type ) {
$data['publisher']['image'] = $data['publisher']['logo'];
}
if ( ! is_singular() ) {
unset( $data['publisher']['logo'] );
}
return $data;
}
/**
* Get Publisher Type.
*
* @param string $type Knowledgegraph type.
*
* @return string|array
*/
private function get_publisher_type( $type ) {
if ( 'company' === $type ) {
return 'Organization';
}
if ( ! is_singular() ) {
return 'Person';
}
return [ 'Person', 'Organization' ];
}
}

View File

@@ -0,0 +1,141 @@
<?php
/**
* The Singular Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Schema\DB;
defined( 'ABSPATH' ) || exit;
/**
* Singular class.
*/
class Singular implements Snippet {
use Hooker;
/**
* Generate rich snippet.
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$schema = $this->can_add_schema( $jsonld );
if ( false === $schema ) {
return $data;
}
$hook = 'snippet/rich_snippet_' . $schema;
/**
* Short-circuit if 3rd party is interested generating his own data.
*/
$pre = $this->do_filter( $hook, false, $jsonld->parts, $data );
if ( false !== $pre ) {
$data['richSnippet'] = $this->do_filter( $hook . '_entity', $pre );
return $data;
}
$object = $this->get_schema_class( $schema );
if ( false === $object ) {
return $data;
}
$entity = $object->process( $data, $jsonld );
$data['richSnippet'] = $this->do_filter( $hook . '_entity', $entity );
return $data;
}
/**
* Get Schema type.
*
* @param JsonLD $jsonld JsonLD Instance.
*
* @return boolean|string
*/
private function can_add_schema( $jsonld ) {
if ( empty( $jsonld->post_id ) ) {
return false;
}
$schemas = DB::get_schemas( $jsonld->post_id );
if ( ! empty( $schemas ) ) {
$has_product = array_filter(
$schemas,
function( $schema ) {
return ! empty( $schema['@type'] ) && in_array( $schema['@type'], [ 'WooCommerceProduct', 'EDDProduct' ], true );
}
);
return ! empty( $has_product ) ? 'product' : false;
}
if ( metadata_exists( 'post', $jsonld->post_id, 'rank_math_rich_snippet' ) ) {
return Helper::get_post_meta( 'rich_snippet' );
}
if ( ! Helper::can_use_default_schema( $jsonld->post_id ) ) {
return false;
}
return $this->get_default_schema( $jsonld );
}
/**
* Get Default Rich Snippet type from Settings.
*
* @param JsonLD $jsonld JsonLD Instance.
*
* @return string
*/
private function get_default_schema( $jsonld ) {
$schema = Helper::get_default_schema_type( $jsonld->post_id, true );
if ( ! $schema ) {
return false;
}
if ( in_array( $schema, [ 'BlogPosting', 'NewsArticle', 'Article' ], true ) ) {
return 'article';
}
if (
( Helper::is_woocommerce_active() && is_singular( 'product' ) ) ||
( Helper::is_edd_active() && is_singular( 'download' ) )
) {
return 'product';
}
return false;
}
/**
* Get appropriate Schema Class.
*
* @param string $schema Schema type.
* @return bool|Class
*/
private function get_schema_class( $schema ) {
$data = [
'article' => '\\RankMath\\Schema\\Article',
'product' => '\\RankMath\\Schema\\Product',
];
if ( isset( $data[ $schema ] ) && class_exists( $data[ $schema ] ) ) {
return new $data[ $schema ]();
}
return false;
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* Helper class for handling WooComerce product attributes for rich snippets.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
defined( 'ABSPATH' ) || exit;
/**
* WC_Attributes class.
*/
class WC_Attributes {
/**
* Hold product attributes.
*
* @var array
*/
private $_attributes;
/**
* Hold product object.
*
* @var WC_Product
*/
private $_product;
/**
* The Constructor.
*
* @param WC_Product $product The Product.
*/
public function __construct( $product ) {
$this->_product = $product;
$this->_attributes = $product->get_attributes();
}
/**
* Find attribute for property.
*
* @param array $entity Entity to attach data to.
* @param string $needle Assign this property.
*/
public function assign_property( &$entity, $needle ) {
foreach ( $this->_attributes as $key => $attrib ) {
if ( stristr( $key, $needle ) ) {
$entity[ $needle ] = $this->_product->get_attribute( $key );
unset( $this->_attributes[ $key ] );
return;
}
}
}
/**
* Map remaining attributes as PropertyValue.
*
* @param array $entity Entity to attach data to.
*/
public function assign_remaining( &$entity ) {
foreach ( $this->_attributes as $key => $attrib ) {
if ( $attrib['is_visible'] && ! $attrib['is_variation'] ) {
$entity['additionalProperty'][] = [
'@type' => 'PropertyValue',
'name' => $key,
'value' => $this->_product->get_attribute( $key ),
];
}
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* The Webpage Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
use RankMath\Paper\Paper;
defined( 'ABSPATH' ) || exit;
/**
* Webpage class.
*/
class Webpage implements Snippet {
/**
* Generate WebPage JSON-LD.
*
* @link https://schema.org/WebPage
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$entity = [
'@type' => $this->get_type(),
'@id' => Paper::get()->get_canonical() . '#webpage',
'url' => Paper::get()->get_canonical(),
'name' => Paper::get()->get_title(),
];
if ( is_singular() ) {
$entity['datePublished'] = $jsonld->parts['published'];
$entity['dateModified'] = $jsonld->parts['modified'];
}
if ( is_front_page() ) {
$jsonld->add_prop( 'publisher', $entity, 'about', $data );
}
$jsonld->add_prop( 'is_part_of', $entity, 'website' );
$jsonld->add_prop( 'thumbnail', $entity, 'primaryImageOfPage', $data );
$jsonld->add_prop( 'language', $entity );
if ( isset( $data['BreadcrumbList'] ) ) {
$entity['breadcrumb'] = [ '@id' => $data['BreadcrumbList']['@id'] ];
}
$data['WebPage'] = $entity;
return $data;
}
/**
* Get WebPage type depending on the current page.
*
* @return string
*/
private function get_type() {
$about_page = Helper::get_settings( 'titles.local_seo_about_page' );
$contact_page = Helper::get_settings( 'titles.local_seo_contact_page' );
$hash = [
'SearchResultsPage' => is_search(),
'ProfilePage' => is_author(),
'CollectionPage' => is_home() || is_archive(),
'AboutPage' => $about_page && is_page( $about_page ),
'ContactPage' => $contact_page && is_page( $contact_page ),
];
return ! empty( array_filter( $hash ) ) ? key( array_filter( $hash ) ) : 'WebPage';
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* The Website Class.
*
* @since 1.0.13
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Schema;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Website class.
*/
class Website implements Snippet {
/**
* Generate WebSite JSON-LD.
*
* @link https://schema.org/WebSite
*
* @param array $data Array of JSON-LD data.
* @param JsonLD $jsonld JsonLD Instance.
*
* @return array
*/
public function process( $data, $jsonld ) {
$data['WebSite'] = [
'@type' => 'WebSite',
'@id' => home_url( '/#website' ),
'url' => get_home_url(),
'name' => $jsonld->get_website_name(),
];
$alternate_name = Helper::get_settings( 'titles.website_alternate_name' );
if ( $alternate_name ) {
$data['WebSite']['alternateName'] = $alternate_name;
}
$jsonld->add_prop( 'publisher', $data['WebSite'], 'publisher', $data );
$jsonld->add_prop( 'language', $data['WebSite'] );
/**
* Disable the JSON-LD output for the Sitelinks Searchbox.
*
* @param boolean Display or not the JSON-LD for the Sitelinks Searchbox.
*/
if ( apply_filters( 'rank_math/json_ld/disable_search', ! is_front_page() || is_paged() ) ) {
return $data;
}
/**
* Change the search URL in the JSON-LD.
*
* @param string $search_url The search URL with `{search_term_string}` placeholder.
*/
$search_url = apply_filters( 'rank_math/json_ld/search_url', home_url( '/?s={search_term_string}' ) );
$data['WebSite']['potentialAction'] = [
'@type' => 'SearchAction',
'target' => $search_url,
'query-input' => 'required name=search_term_string',
];
return $data;
}
}