Skip to content

Instantly share code, notes, and snippets.

@Dudo1985
Created May 6, 2022 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dudo1985/58d8b38e3ccb044678229162b9090f49 to your computer and use it in GitHub Desktop.
Save Dudo1985/58d8b38e3ccb044678229162b9090f49 to your computer and use it in GitHub Desktop.
This fix price = 0 not insert, fix available in version 3.0.7
<?php
if (!defined('ABSPATH')) {
exit('You\'re not allowed to see this page');
} // Exit if accessed directly
/**
* Manage Rich Snippets
*
* This class hook to yasr_filter_existing_schema, get the post meta
* yasr_schema_additional_fields, and depending of the itemType selected
* returns the schema info
*
* @author Dario Curvino <dudo>
*
*/
class YasrRichSnippets {
public function addFilters() {
//Low priority to be sure that shortcodes has run
add_filter('the_content', array($this, 'addSchema'), 99);
add_filter('yasr_filter_schema_title', array($this, 'filter_title'));
add_filter('yasr_filter_existing_schema', array($this, 'additional_schema'), 10, 2);
}
/**
* @param $content
*
* @return string
*/
public function addSchema($content) {
//if both shortcodes ov_rating and visitor votes didn't run, return $content
if (!defined('YASR_OV_ATTRIBUTES') && !defined('YASR_VV_ATTRIBUTES')
&& !defined('YASR_PRO_UR_COMMENT_RICH_SNIPPET')) {
return $content;
}
//Add buddypress compatibility
//If this is a page, return $content without adding schema.
if (function_exists('bp_is_active') && is_page()) {
return $content;
}
if (is_404() || did_action('get_footer') || (!is_singular() && is_main_query())) {
return $content;
}
$post_id = get_the_ID();
$overall_rating = false;
$visitor_votes = false;
//check if ov_rating shortcode has run
if (defined('YASR_OV_ATTRIBUTES')) {
$ov_attributes = json_decode(YASR_OV_ATTRIBUTES, true);
$overall_rating = $ov_attributes;
}
//check if vv has run
if(defined('YASR_VV_ATTRIBUTES')) {
$vv_attributes = json_decode(YASR_VV_ATTRIBUTES, true);
$visitor_votes = $vv_attributes;
}
$script_type = '<script type="application/ld+json">';
$end_script_type = '</script>';
$review_choosen = yasr_get_itemType();
//Use this hook to write your custom microdata from scratch
//if doesn't exists a filter for yasr_filter_schema_jsonld
//$review_chosen value is assigned to $filtered_schema.
$filtered_schema = apply_filters('yasr_filter_schema_jsonld', $review_choosen);
//So check here if $schema != $review_choosen
if ($filtered_schema !== $review_choosen) {
return $content . $script_type . $filtered_schema . $end_script_type;
}
//YASR adds microdata only if is_singular() && is_main_query()
if (is_singular() && is_main_query()) {
$rich_snippet = $this->returnRichSnippets($post_id, $review_choosen, $content, $overall_rating, $visitor_votes);
//If $rich snippet here is not false return microdata
if($rich_snippet !== false) {
return $content . $script_type . json_encode($rich_snippet) . $end_script_type;
}
}
return $content;
} //End function
/**
* Return rich snippets, or false if both aggregateRating and Review are empty after the last filter
*
* @author Dario Curvino <@dudo>
* @since 2.8.0
* @param $post_id
* @param $review_choosen
* @param $content
* @param $overall_rating
* @param $visitor_votes
*
* @return array|bool
*/
public function returnRichSnippets($post_id, $review_choosen, $content, $overall_rating, $visitor_votes) {
$rich_snippet_data = $this->richSnippetsGetData($post_id);
$cleaned_content = wp_strip_all_tags(strip_shortcodes($content));
$rich_snippet = array();
//Add everywhere except for blogPosting
if ($review_choosen !== 'BlogPosting') {
$review = $this->richSnippetsReview($rich_snippet_data, $cleaned_content, $overall_rating);
if($review) {
$rich_snippet['Review'] = $review;
}
//if both are included, google will index AggregateRating instead of Review.
//So, if post is selected as review, exclude AggregateRating
if($rich_snippet_data['is_post_a_review'] !== 'yes') {
$aggregate_rating = $this->richSnippetsAggregateRating($visitor_votes);
if($aggregate_rating) {
$rich_snippet['aggregateRating'] = $this->richSnippetsAggregateRating($visitor_votes);
}
}
}
//Use this hook to manage itemTypes
//if doesn't exists a filter for yasr_filter_existing_schema, put $rich_snippet into $more_rich_snippet
$filtered_rich_snippet = apply_filters('yasr_filter_existing_schema', $rich_snippet, $rich_snippet_data);
if ($filtered_rich_snippet !== $rich_snippet && is_array($filtered_rich_snippet)) {
$rich_snippet = $filtered_rich_snippet;
}
//if review and aggregateRating are still false after the filter, do not return rich snippets
if((!isset($rich_snippet['Review'])) && !isset($rich_snippet['aggregateRating'])) {
return false;
}
return array_merge(
$this->richSnippetsCommon($review_choosen, $rich_snippet_data, $cleaned_content),
$rich_snippet
);
}
/**
* Returns all data that is not in the post meta (author name, date, etc)
*
* @author Dario Curvino <@dudo>
* @since 2.8.0
*
* @param $post_id
*
* @return array|void
*/
public function richSnippetsGetData ($post_id) {
$data_to_return = array();
$data_to_return['author'] = get_the_author();
//use this hook to change the itemType name
$data_to_return['review_name'] = wp_strip_all_tags(apply_filters('yasr_filter_schema_title', $post_id));
$data_to_return['date'] = get_the_date('c');
$data_to_return['date_modified'] = get_the_modified_date('c');
$data_to_return['is_post_a_review'] = get_post_meta($post_id, 'yasr_post_is_review', true);
$logo_image_url = '';
$post_image_url = $logo_image_url; //this will be overwritten if has_post_thumbnail is true
if (YASR_PUBLISHER_LOGO) {
$logo_image_url = YASR_PUBLISHER_LOGO;
$post_image_url = $logo_image_url; //this will be overwritten if has_post_thumbnail is true
$logo_image_url_absolute = $_SERVER['DOCUMENT_ROOT'] . parse_url(YASR_PUBLISHER_LOGO, PHP_URL_PATH);
$post_image_size = @getimagesize($logo_image_url_absolute); //the @ should be useless, just to be safe
$logo_image_size = @getimagesize($logo_image_url_absolute); //the @ should be useless, just to be safe
}
else {
$post_image_size[0] = 0;
$post_image_size[1] = 0;
$logo_image_size[0] = 0;
$logo_image_size[1] = 0;
}
//be sure that getimagesize has returned an array
if(!is_array($post_image_size)) {
$post_image_size[0] = 0;
$post_image_size[1] = 0;
}
if(!is_array($logo_image_size)) {
$logo_image_size[0] = 0;
$logo_image_size[1] = 0;
}
//if exists featuread image get the url and overwrite the variable
if (has_post_thumbnail()) {
$post_image_url = wp_get_attachment_url(get_post_thumbnail_id());
$post_image_url_absolute = $_SERVER['DOCUMENT_ROOT'] . parse_url($post_image_url, PHP_URL_PATH);
$post_image_size = @getimagesize($post_image_url_absolute); //the @ should be useless, just to be safe
}
$publisher_image_index = 'logo';
if (YASR_PUBLISHER_TYPE === 'Person') {
$publisher_image_index = 'image';
}
$data_to_return['publisher'] = array(
'@type' => YASR_PUBLISHER_TYPE,
'name' => wp_strip_all_tags(YASR_PUBLISHER_NAME),
//already sanitized in the settings, just to be safe
$publisher_image_index => array(
'@type' => 'ImageObject',
'url' => $logo_image_url,
'width' => $logo_image_size[0],
'height' => $logo_image_size[1]
),
);
$data_to_return['post_image_url'] = $post_image_url;
$data_to_return['post_image_size'] = $post_image_size;
$data_to_return['logo_image_url'] = $logo_image_url;
$data_to_return['logo_image_size'] = $logo_image_size;
return $data_to_return;
}
/**
* Returns the 'Review' type
*
* @author Dario Curvino <@dudo>
* @since 2.8.0
* @param $rich_snippet_data
* @param $cleaned_content
* @param $overall_rating
*
* @return array|false
*/
private function richSnippetsReview($rich_snippet_data, $cleaned_content, $overall_rating) {
if ($overall_rating) {
$rich_snippet = array(
'@type' => 'Review',
'name' => $rich_snippet_data['review_name'],
'reviewBody' => $cleaned_content,
'author' => array(
'@type' => 'Person',
'name' => $rich_snippet_data['author']
),
'datePublished' => $rich_snippet_data['date'],
'dateModified' => $rich_snippet_data['date_modified'],
'reviewRating' => array(
'@type' => 'Rating',
'ratingValue' => $overall_rating,
'bestRating' => 5,
'worstRating' => 1
),
);
$rich_snippet['publisher'] = $rich_snippet_data['publisher'];
return $rich_snippet;
}
return false;
}
/**
* @author Dario Curvino <@dudo>
* @since 2.8.0
*
* @param $visitor_votes
*
* @return array|false
*/
private function richSnippetsAggregateRating ($visitor_votes) {
if ($visitor_votes && $visitor_votes['sum_votes'] !== 0 && $visitor_votes['number_of_votes'] !== 0) {
$average_rating = $visitor_votes['sum_votes'] / $visitor_votes['number_of_votes'];
$average_rating = round($average_rating, 1);
return array(
'@type' => 'AggregateRating',
'ratingValue' => $average_rating,
'ratingCount' => $visitor_votes['number_of_votes'],
'bestRating' => 5,
'worstRating' => 1,
);
}
return false;
}
/**
* @author Dario Curvino <@dudo>
* @since 2.9.7
* @return array
*/
private function richSnippetsCommon ($review_choosen, $rich_snippet_data, $cleaned_content) {
$rich_snippet = array();
$rich_snippet['@context'] = 'https://schema.org/';
$rich_snippet['@type'] = $review_choosen;
$rich_snippet['name'] = $rich_snippet_data['review_name'];
$rich_snippet['description'] = wp_trim_words($cleaned_content, 55, '...');
$rich_snippet['image'] = array(
'@type' => 'ImageObject',
'url' => $rich_snippet_data['post_image_url'],
'width' => $rich_snippet_data['post_image_size'][0],
'height' => $rich_snippet_data['post_image_size'][1]
);
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $rich_snippet array contains common data for all rich snippets
* @param $rich_snippet_data array contains all data that is not post_meta (author name, date, etc.)
*
* @return array
*/
public function additional_schema($rich_snippet, $rich_snippet_data) {
$post_meta = $this->post_meta();
//avoid undefined
$more_rich_snippet = array();
//get the select itemType
$review_choosen = yasr_get_itemType();
if($review_choosen === 'BlogPosting') {
$more_rich_snippet = $this->blogPosting($rich_snippet, $rich_snippet_data);
}
if($review_choosen === 'Product') {
$more_rich_snippet = $this->itemProduct($post_meta);
}
if($review_choosen === 'LocalBusiness') {
$more_rich_snippet = $this->localBusiness($post_meta);
}
if($review_choosen === 'Recipe') {
$more_rich_snippet = $this->recipe($post_meta);
}
if($review_choosen === 'SoftwareApplication') {
$more_rich_snippet = $this->softwareApplication($post_meta);
}
if($review_choosen === 'Book') {
$more_rich_snippet = $this->book($post_meta);
}
if($review_choosen === 'Movie') {
$more_rich_snippet = $this->movie($post_meta);
}
if(is_array($rich_snippet) && is_array($more_rich_snippet)) {
return array_merge($rich_snippet, $more_rich_snippet);
}
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $rich_snippet
* @param $rich_snippet_data
*
* @return mixed
*/
private function blogPosting($rich_snippet, $rich_snippet_data) {
$rich_snippet['datePublished'] = $rich_snippet_data['date'];
$rich_snippet['headline'] = $rich_snippet_data['review_name'];
$rich_snippet['mainEntityOfPage'] = array(
'@type' => 'WebPage',
'@id' => get_permalink()
);
$rich_snippet['author'] = array(
'@type' => 'Person',
'name' => $rich_snippet_data['author']
);
$rich_snippet['dateModified'] = $rich_snippet_data['date_modified'];
$rich_snippet['image'] = array(
'@type' => 'ImageObject',
'url' => $rich_snippet_data['post_image_url'],
'width' => $rich_snippet_data['post_image_size'][0],
'height' => $rich_snippet_data['post_image_size'][1]
);
//blogposting doesn't allow 'Person' has a publisher
$rich_snippet['publisher'] = $rich_snippet_data['publisher'];
$rich_snippet['publisher']['@type'] = 'Organization';
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $post_meta
*
* @return array
*/
private function itemProduct($post_meta) {
$global_identifer_name = $post_meta['yasr_product_global_identifier_select'];
$rich_snippet['brand'] = $post_meta['yasr_product_brand'];
$rich_snippet['sku'] = $post_meta['yasr_product_sku'];
$rich_snippet[$global_identifer_name] = $post_meta['yasr_product_global_identifier_value'];
if($post_meta['yasr_product_price'] !== '') {
$rich_snippet['offers'] = array(
'@type' => 'Offer',
'price' => $post_meta['yasr_product_price'],
'priceCurrency' => $post_meta['yasr_product_price_currency'],
'priceValidUntil' => $post_meta['yasr_product_price_valid_until'],
'availability' => $post_meta['yasr_product_price_availability'],
'url' => $post_meta['yasr_product_price_url'],
);
}
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $post_meta
*
* @return array
*/
private function localBusiness($post_meta) {
$rich_snippet['address'] = $post_meta['yasr_localbusiness_address'];
$rich_snippet['priceRange'] = $post_meta['yasr_localbusiness_pricerange'];
$rich_snippet['telephone'] = $post_meta['yasr_localbusiness_telephone'];
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @since 2.9.1
* @param $post_meta
*
* @return array
*/
private function recipe($post_meta) {
$instruction_array_clean = array();
$ingredient_array = array();
if(!empty($post_meta['yasr_recipe_recipeinstructions'])) {
$instruction_array = explode(PHP_EOL, $post_meta['yasr_recipe_recipeinstructions']);
$i=0;
foreach ($instruction_array as $instrunction) {
$instruction_array_clean[$i]['@type'] = "HowToStep";
$instruction_array_clean[$i]['text'] = $instrunction;
$i++;
}
}
if(!empty($post_meta['yasr_recipe_recipeingredient'])) {
$ingredient_array = explode(PHP_EOL, $post_meta['yasr_recipe_recipeingredient']);
}
if(!empty($post_meta['yasr_recipe_nutrition'])) {
$rich_snippet['nutrition'] = array(
"@type" => "NutritionInformation",
"calories" => $post_meta['yasr_recipe_nutrition'] . " calories",
);
}
$rich_snippet['author'] = array(
'@type' => 'Person',
'name' => get_the_author()
);
$rich_snippet['cookTime'] = $post_meta['yasr_recipe_cooktime'];
$rich_snippet['description'] = $post_meta['yasr_recipe_description'];
$rich_snippet['keywords'] = $post_meta['yasr_recipe_keywords'];
$rich_snippet['prepTime'] = $post_meta['yasr_recipe_preptime'];
$rich_snippet['recipeCategory'] = $post_meta['yasr_recipe_recipecategory'];
$rich_snippet['recipeCuisine'] = $post_meta['yasr_recipe_recipecuisine'];
$rich_snippet['recipeIngredient'] = $ingredient_array;
$rich_snippet['recipeInstructions'] = $instruction_array_clean;
$rich_snippet['video'] = $post_meta['yasr_recipe_video'];
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $post_meta
*
* @return array
*/
private function softwareApplication($post_meta) {
$rich_snippet['applicationCategory'] = $post_meta['yasr_softwareapplication_category'];
$rich_snippet['operatingSystem'] = $post_meta['yasr_softwareapplication_os'];
if($post_meta['yasr_softwareapplication_price'] !== '') {
$rich_snippet['offers'] = array(
'@type' => 'Offer',
'price' => $post_meta['yasr_softwareapplication_price'],
'priceCurrency' => $post_meta['yasr_softwareapplication_price_currency'],
'priceValidUntil' => $post_meta['yasr_softwareapplication_price_valid_until'],
'availability' => $post_meta['yasr_softwareapplication_price_availability'],
'url' => $post_meta['yasr_softwareapplication_price_url'],
);
}
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $post_meta
*
* @return array
*/
private function book($post_meta) {
if(!empty($post_meta['yasr_book_author'])) {
$rich_snippet['author'] = array(
'@type' => 'Person',
'name' => $post_meta['yasr_book_author'],
);
}
$rich_snippet['bookEdition'] = $post_meta['yasr_book_bookedition'];
$rich_snippet['bookFormat'] = $post_meta['yasr_book_bookformat'];
$rich_snippet['isbn'] = $post_meta['yasr_book_isbn'];
$rich_snippet['numberOfPages'] = $post_meta['yasr_book_number_of_pages'];
return $rich_snippet;
}
/**
* @author Dario Curvino <@dudo>
* @param $post_meta
*
* @return array
*/
private function movie($post_meta) {
$actors_array_clean = array();
$director_array_clean = array();
if(!empty($post_meta['yasr_movie_actor'])) {
$actors_array = explode(PHP_EOL, $post_meta['yasr_movie_actor']);
$i=0;
foreach ($actors_array as $actor) {
$actors_array_clean[$i]['@type'] = "Person";
$actors_array_clean[$i]['name'] = $actor;
$i++;
}
}
$rich_snippet['actor'] = $actors_array_clean;
if(!empty($post_meta['yasr_movie_director'])) {
$director_array = explode(PHP_EOL, $post_meta['yasr_movie_director']);
$i=0;
foreach ($director_array as $director) {
$director_array_clean[$i]['@type'] = "Person";
$director_array_clean[$i]['name'] = $director;
$i++;
}
}
$rich_snippet['director'] = $director_array_clean;
$rich_snippet['duration'] = $post_meta['yasr_movie_duration'];
$rich_snippet['dateCreated'] = $post_meta['yasr_movie_datecreated'];
return $rich_snippet;
}
/**
* Get the postmeta for the itemTypes
*
* @author Dario Curvino <@dudo>
* @return array|mixed
*/
public function post_meta() {
$post_meta = get_post_meta(get_the_ID(), 'yasr_schema_additional_fields', true);
//avoid undefined
if(!is_array($post_meta)) {
$post_meta = array();
}
$array_item_type_info = YASR_SUPPORTED_SCHEMA_TYPES_ADDITIONAL_FIELDS;
foreach ($array_item_type_info as $item_type) {
//avoid undefined
if(!isset($post_meta[$item_type])) {
$post_meta[$item_type] = '';
}
}
return $post_meta;
}
/**
* Filter the title that will be used in the rich snippets
* Use a user defined title if found, or the post title otherwise
* @author Dario Curvino <@dudo>
*
* @param $post_id
*
* @return mixed|string
*/
public function filter_title($post_id) {
$saved_data = $this->post_meta();
//if is not empty, overwrite the title with custom itemType name
if(!empty($saved_data['yasr_schema_title'])) {
$schema_title = $saved_data['yasr_schema_title'];
} else {
//Here I don't use get_the_title because it run after filters are applied.
//This causes that stars near title will appear in schema title
//https://wordpress.stackexchange.com/questions/257499/get-title-without-filterthe-title
$schema_title = get_post_field('post_title', $post_id, 'raw');
}
return $schema_title;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment