X7ROOT File Manager
Current Path:
/var/softaculous/sitepad/editor/site-data/plugins/siteseo-pro/main
var
/
softaculous
/
sitepad
/
editor
/
site-data
/
plugins
/
siteseo-pro
/
main
/
??
..
??
admin.php
(15.5 KB)
??
ai.php
(9.16 KB)
??
ajax.php
(30.77 KB)
??
breadcrumbs.php
(7.68 KB)
??
googleconsole.php
(37.28 KB)
??
googlenews.php
(3.79 KB)
??
gscsetup.php
(13.8 KB)
??
importschema.php
(4.26 KB)
??
install.php
(2.54 KB)
??
llmtxtfile.php
(2.76 KB)
??
plugin-update-checker.php
(52.57 KB)
??
redirectmanager.php
(6.9 KB)
??
registerblocks.php
(1.57 KB)
??
rsssitemap.php
(6.95 KB)
??
settings
??
structureddata.php
(49.52 KB)
??
tags.php
(14.13 KB)
??
videositemap.php
(13.7 KB)
Editing: structureddata.php
<?php /* * SITESEO * https://siteseo.io * (c) SITSEO Team */ namespace SiteSEOPro; if(!defined('ABSPATH')){ die('Hacking Attempt !'); } class StructuredData{ static function display_metabox(){ global $post; if(is_front_page() || is_home()){ $post_id = get_option('page_on_front'); if(!$post_id && is_home()){ $post_id = get_option('page_for_posts'); } } else{ $post_id = $post ? $post->ID : 0; } $schema_type = ''; $custom_schema = ''; if(!empty($post_id)){ $schema_type = !empty(get_post_meta($post_id, '_siteseo_structured_data_type', true)) ? get_post_meta($post_id, '_siteseo_structured_data_type', true) : ''; $schema_properties = !empty(get_post_meta($post_id, '_siteseo_structured_data_properties', true)) ? get_post_meta($post_id, '_siteseo_structured_data_properties', true) : ''; $custom_schema = !empty(get_post_meta($post_id, '_siteseo_structured_data_custom', true)) ? get_post_meta($post_id, '_siteseo_structured_data_custom', true) : ''; } $schema_types['Article'] = 'Article'; $schema_types['NewsArticle'] = 'News Article'; $schema_types['Blogposting'] = 'Blog post'; $schema_types['Product'] = 'Product'; $schema_types['Recipe'] = 'Recipe'; $schema_types['Restaurant'] = 'Restaurant'; $schema_types['Course'] = 'Course'; $schema_types['LocalBusiness'] = 'Local Business'; $schema_types['Person'] = 'Person'; $schema_types['Organization'] = 'Organization'; $schema_types['Book'] = 'Book Recording'; $schema_types['MusicRecording'] = 'Music Album'; $schema_types['SoftwareApplication'] = 'Software Application'; $schema_types['VideoObject'] = 'Video'; $schema_types['Event'] = 'Event'; $schema_types['JobPosting'] = 'Job Posting'; $schema_types['CustomSchema'] = 'Custom Schema'; $schema_types['PodcastEpisode'] = 'Podcast Episode'; $custom_schema_placeholder = json_encode([ 'type' => 'object', 'properties' => [ 'placeholder' => ['type' => 'string'], 'description' => ['type' => 'integer'] ] ], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); /* Show global schema notice if aplicable for current content */ $global_schema_names = self::check_global_schema_is_applicable(); // Output the notice if any applicable schemas if(!empty($global_schema_names)){ echo'<div class="siteseo-metabox-option-wrap"> <div class="siteseo-notice is-warning">'.wp_kses_post(implode(', ', array_unique($global_schema_names))). ' global schemas are in use for this item. <a href="'.esc_url(admin_url('admin.php?page=siteseo-pro-page')).'">Click here to manage them</a></div> </div>'; } echo'<div class="siteseo-metabox-option-wrap"> <div class="siteseo-metabox-label-wrap"> <label for="siteseo_structured_data_type">'.esc_html__('Select Schema Types','siteseo-pro').'</label> </div> <div class="siteseo-metabox-input-wrap"> <select name="siteseo_structured_data_type" class="siteseo_structured_data_type" id="siteseo_structured_data_type"> <option value="">'.esc_html__('None', 'siteseo-pro').'</option>'; foreach($schema_types as $type => $label){ echo '<option value="'.esc_attr($type).'" '.selected($schema_type, $type, false).'>'.esc_html($label).'</option>'; } echo'</select> </input> </div> </div>'; $schema_template = self::get_schema_properties(); echo'<div class="siteseo-schema-flex-container"> <div class="siteseo-metabox-schema" style="'.(empty($schema_type) || $schema_type === 'CustomSchema' ? 'display:none;' : '').'"> <div class="siteseo-schema-properties">'; if(!empty($schema_type) && isset($schema_template[$schema_type]) && $schema_type !== 'CustomSchema'){ $is_textarea = ['description', 'instructions', 'reviewBody', 'questions', 'step', 'ingredients', 'recipeInstructions', 'courseDescription', 'bookDescription', 'softwareRequirements', 'menu']; $is_date_type = ['datePublished', 'dateModified', 'uploadDate', 'startDate', 'endDate', 'foundingDate', 'releaseDate']; $is_bool_type = ['isFamilyFriendly']; $is_required_field = ['contentUrl']; foreach($schema_template[$schema_type] as $property => $default){ if(!is_array($default)){ echo '<p><h4 for="siteseo_schema_property_'.esc_attr($property).'">'.esc_html(ucfirst(preg_replace('/([a-z])([A-Z])/', '$1 $2', $property))).':</h4>'; if(in_array($property, $is_textarea)){ echo '<textarea name="schema_properties['.esc_attr($property).']" id="siteseo_schema_property_' .esc_attr($property).'" rows="3" class="widefat">'.esc_textarea(isset($schema_properties[$property]) ? $schema_properties[$property] : '').'</textarea>'; } else if(in_array($property, $is_date_type)){ echo '<input type="datetime-local" name="schema_properties['.esc_attr($property).']" id="siteseo_schema_property_'.esc_attr($property).'" value="' .esc_attr(isset($schema_properties[$property]) ? $schema_properties[$property] : '').'" class="widefat">'; } else if(in_array($property, $is_bool_type)){ echo '<select name="schema_properties['.esc_attr($property).']" id="siteseo_schema_property_'.esc_attr($property).'" value="' .esc_attr(isset($schema_properties[$property]) ? $schema_properties[$property] : '').'" class="widefat"> <option value="false">No</option> <option value="true">Yes</option> </select>'; } else if(($property === 'duration') && $schema_type === 'PodcastEpisode'){ echo '<span>'.esc_html__('Enter The duration in the ISO-8601 fromat. Example - PT30M, PT20M30S .','siteseo-pro').'</span> <input type="text" name="schema_properties['.esc_attr($property).']" id="siteseo_schema_property_'.esc_attr($property).'" value="' .esc_attr(isset($schema_properties[$property]) ? $schema_properties[$property] : '').'" class="widefat">'; } else if(($property === 'image') && $schema_type === 'PodcastEpisode'){ echo '<div class="siteseo-image-upload-wrapper" style="display:flex; gap:10px; align-items:center;"> <input type="text" name="schema_properties['.esc_attr($property).']" id="siteseo_schema_property_'.esc_attr($property).'" value="' .esc_attr(isset($schema_properties[$property]) ? $schema_properties[$property] : '').'" class="widefat"> <button type="button" class="button siteseo-image-upload-btn" data-target="#siteseo_schema_property_'.esc_attr($property).'">'.esc_html__('Upload Image', 'siteseo-pro').'</button> </div>'; } else{ echo '<input type="text" name="schema_properties['.esc_attr($property).']" id="siteseo_schema_property_'.esc_attr($property).'" value="' .esc_attr(isset($schema_properties[$property]) ? $schema_properties[$property] : '').'" class="widefat">'; } echo '</p>'; }else{ foreach($default as $innerKey => $innerDefault){ if($innerKey === '@type') continue; echo '<p><h4 for="siteseo_schema_property_'.esc_attr($innerKey).'">'.esc_html(ucfirst(preg_replace('/([a-z])([A-Z])/', '$1 $2', $innerKey))) . (in_array($innerKey, $is_required_field) ? ' (Required)*' : '').':</h4>'; if(in_array($innerKey, $is_textarea)){ echo '<textarea name="schema_properties['.esc_attr($innerKey).']" id="siteseo_schema_property_' .esc_attr($innerKey).'" rows="3" class="widefat">'.esc_textarea(isset($schema_properties[$innerKey]) ? $schema_properties[$innerKey] : '').'</textarea>'; } else if(in_array($innerKey, $is_date_type)){ echo '<input type="datetime-local" name="schema_properties['.esc_attr($innerKey).']" id="siteseo_schema_property_'.esc_attr($innerKey).'" value="' .esc_attr(isset($schema_properties[$innerKey]) ? $schema_properties[$innerKey] : '').'" class="widefat">'; } else { echo '<input type="text" name="schema_properties['.esc_attr($innerKey).']" id="siteseo_schema_property_'.esc_attr($innerKey).'" value="' .esc_attr(isset($schema_properties[$innerKey]) ? $schema_properties[$innerKey] : '').'" class="widefat" '.(in_array($innerKey, $is_required_field) ? 'required' : '').'>'; } echo '</p>'; } } } } echo '</div> </div> <div class="siteseo_custom_schema_container" style="'.((empty($schema_type) || $schema_type !== 'CustomSchema') ? 'display:none;' : '').'"> <h4>'.esc_html__('Custom Schema', 'siteseo-pro').'</h4> <span class="siteseo-json-error"></span> <p> <textarea name="siteseo_structured_data_custom" placeholder="'.esc_attr($custom_schema_placeholder).'" rows="10" class="siteseo_structured_data_custom widefat code">'. (!empty($custom_schema) ? esc_textarea(json_encode($custom_schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)) : '').'</textarea> </p> <p class="description">'. // translators: %1$s and %2$s are the opening and closing <a> tags around "Read here". sprintf(esc_html__('Create your custom schema as per guidelines. %1$sRead here%2$s.', 'siteseo-pro'), '<a href="https://schema.org/docs/schemas.html" target="_blank" rel="noopener noreferrer">', '</a>').'</p> </div> <div class="siteseo-metabox-option-wrap"> <div class="siteseo-schema-preview" style="'.(empty($schema_type) ? 'display:none;' : '').'"> <div class="siteseo-schema-preview-header"><h4>'.esc_html__('JSON-LD Preview', 'siteseo-pro').'</h4> <a class="button" id="siteseo_validate_schema">'.esc_html__('Google Validation', 'siteseo-pro').'</a> </div> <pre id="siteseo_schema_preview" class="siteseo_schema_preview">'; if($schema_type === 'CustomSchema' && !empty($custom_schema)){ echo '<div id="siteseo_highlighter">'.esc_textarea(json_encode($custom_schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)).'</div>'; } elseif (!empty($schema_type) && !empty($schema_properties)){ $schema_data = array( '@context' => 'https://schema.org', '@type' => $schema_type ); $podcastSchemaData = array( '@context' => 'https://schema.org', '@type' => 'PodcastEpisode', 'associatedMedia' => array( '@type' => 'MediaObject', ), 'partOfSeason' => array( '@type' => 'PodcastSeason', ), 'partOfSeries' => array( '@type' => 'PodcastSeries', ) ); if($schema_type === 'PodcastEpisode'){ foreach($schema_properties as $key => $value){ if(!empty($value)){ if($key === 'contentUrl'){ $podcastSchemaData['associatedMedia'][$key] = $value; } else if(in_array($key, ['seasonUrl', 'seasonName', 'seasonNumber'])){ if($key === 'seasonNumber'){ $podcastSchemaData['partOfSeason']['seasonNumber'] = $value; } else { $podcastSchemaData['partOfSeason'][strtolower(str_replace("season", "", $key))] = $value; } }else if(in_array($key, ['seriesUrl', 'seriesName'])){ $podcastSchemaData['partOfSeries'][strtolower(str_replace("series", "", $key))] = $value; }else{ $podcastSchemaData[$key] = $value; } } } }else{ foreach($schema_properties as $key => $value){ if(!empty($value)){ $schema_data[$key] = $value; } } } if($schema_type === 'PodcastEpisode'){ echo'<div id="siteseo_highlighter" class="siteseo_highlighter">'.esc_html(json_encode($podcastSchemaData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)).'</div>'; }else{ echo'<div id="siteseo_highlighter" class="siteseo_highlighter">'.esc_html(json_encode($schema_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)).'</div>'; } } else{ echo'<div>'.esc_html__('No schema has been selected.', 'siteseo-pro').'</div>'; } echo'</pre> </div> </div></div>'; } static function check_global_schema_is_applicable(){ $auto_global_schema = get_option('siteseo_auto_schema'); $applicable_types = []; if(empty($auto_global_schema['schemas'])){ return; } $queried_obj = get_queried_object(); foreach($auto_global_schema['schemas'] as $schema){ $show = false; /** ------------------------- ** Check display_on rules **-------------------------**/ if(!empty($schema['display_on'])){ foreach($schema['display_on'] as $display){ switch($display){ case 'entire_website': $show = true; break; case 'all_singulars': $show = in_array(get_post_type(), ['post', 'page', 'product']); break; case 'front_page': if(function_exists('is_front_page') && is_front_page()) $show = true; break; case 'all_posts': $show = get_post_type() === 'post'; break; case 'all_pages': case 'all_page': $show = get_post_type() === 'page'; break; case 'all_product': $show = get_post_type() === 'product'; break; case 'all_product_categories': if(get_post_type() === 'product' && has_term('', 'product_cat', $queried_obj)) $show = true; break; case 'all_product_tags': if(get_post_type() === 'product' && has_term('', 'product_tag', $queried_obj)) $show = true; break; case 'all_category': case 'all_taxonomy': if(in_array(get_post_type(), ['category', 'post_tag', 'custom_taxonomy'])) $show = true; break; case 'all_custom_layouts': $show = get_post_type() === 'custom_layout'; break; case 'specific_targets': if(!empty($schema['specific_targets']) && is_array($schema['specific_targets'])){ $show = in_array(get_queried_object_id(), $schema['specific_targets']); } break; } if($show) break; // stop checking other display_on rules } } if(!$show) continue; // skip if display_on does not match /* ------------------------- * Check display_not_on rules * -------------------------*/ $excluded = false; if(!empty($schema['display_not_on'])){ foreach($schema['display_not_on'] as $not){ // Skip 'none' if($not === 'none') continue; // Handle string rules if(is_string($not)){ switch($not){ case 'entire_website': $excluded = true; break; case 'all_posts': if(get_post_type() === 'post') $excluded = true; break; case 'all_pages': case 'all_page': if(get_post_type() === 'page') $excluded = true; break; case 'all_product': if(get_post_type() === 'product') $excluded = true; break; case 'all_category': case 'all_taxonomy': if(in_array(get_post_type(), ['category', 'post_tag', 'custom_taxonomy'])) $excluded = true; break; case 'all_product_categories': if(get_post_type() === 'product' && has_term('', 'product_cat', $queried_obj)) $excluded = true; break; case 'all_product_tags': if(get_post_type() === 'product' && has_term('', 'product_tag', $queried_obj)) $excluded = true; break; } } // Handle (specific targets) if(is_array($not) && isset($not['type']) && $not['type'] === 'specific_targets'){ if(!empty($not['targets'])){ $queried_name = is_object($queried_obj) && isset($queried_obj->name) ? $queried_obj->name : ''; $targets = (array) $not['targets']; foreach($targets as $target){ if((string)$target === (string)get_queried_object_id() || (string)$target === $queried_name){ $excluded = true; break 2; // exit both loops } } } } if($excluded) break; } } if(!$excluded){ $applicable_types[] = '<strong>' . esc_html($schema['type']) . '</strong>'; } } return $applicable_types; } static function get_schema_properties(){ return [ 'Article'=> [ 'headline' => '', 'author' => '', 'datePublished' => '', 'dateModified' => '', 'publisher' => '', 'description' => '', ], 'Blogposting' => [ 'headline' => '', 'author' => '', 'datePublished' => '', 'dateModified' => '', 'publisher' => '', 'description' => '', ], 'Course' => [ 'name' => '', 'Description' => '', 'provider' => '', 'availableLanguage' => '', 'coursePrerequisites' =>'', 'courseCode' => '', 'hasCourseInstance' => '', 'timeRequired' => '', 'educationalCredentialAwarded' => '', ], 'MusicRecording' => [ 'name' => '', 'byArtist' => '', 'duration' => '', 'recordingOf' => '', 'inAlbum' => '', 'datePublished' => '', 'releasedEvent' => '', 'abstract' => '', ], 'Book' => [ 'name' => '', 'author' => '', 'bookEdition' => '', 'isbn' => '', 'publisher' => '', 'datePublished' => '', 'abstract' => '', 'inLanguage' => '', ], 'Restaurant' => [ 'name' => '', 'address' => '', 'hasMenu' => '', 'telephone' => '', 'priceRange' => '', 'openingHours' => '', ], 'SoftwareApplication' => [ 'name' => '', 'applicationCategory' => '', 'applicationSubCategory' => '', 'availableOnDevice' => '', 'operatingSystem' => '', 'softwareVersion' => '', 'softwareRequirements' => '', 'downloadUrl' => '', ], 'VideoObject' => [ 'name' => '', 'description' => '', 'thumbnailUrl' => '', 'uploadDate' => '', 'embedUrl' => '', 'publisher' =>'', 'creator' => '', ], 'Event' => [ 'name' => '', 'startDate' => '', 'endDate' => '', 'location' => '', 'description' => '', 'offers' => '', 'organizer' => '', 'performer' => '', ], 'Recipe' => [ 'name' => '', 'author' => '', 'description' => '', 'cookTime' => '', 'cookingMethod' => '', 'prepTime' => '', 'totalTime' => '', 'recipeYield' => '', 'recipeCategory' => '', 'recipeCuisine' => '', 'recipeInstructions' => '', ], 'Person' =>[ 'name' => '', 'jobTitle' => '', 'email' => '', 'telephone' => '', 'address' => '', ], 'Organization' => [ 'name' => '', 'url' =>'', 'description' => '', 'email' => '', 'founder' => '', 'foundingDate' => '', 'numberOfEmployees' => '', 'location' => '', ], 'JobPosting' =>[ 'name' => '', 'industry' => '', 'title' => '', 'totalJobOpenings' => '', 'skills' => '', 'jobBenefits' => '', 'jobLocationType' => '', ], 'NewsArticle' =>[ 'headline' => '', 'author' => '', 'datePublished' => '', 'dateModified' => '', 'publisher' => '', 'description' => '', ], 'Product' =>[ 'name' => '', 'description' => '', 'brand' => '', 'category' => '', 'releaseDate' => '', 'size' => '', ], 'LocalBusiness' =>[ 'legalName' => '', 'founder' => '', 'address' => '', 'email' => '', 'numberOfEmployees' => '', 'telephone' => '', 'taxID' => '', 'vatID' => '', ], 'PodcastEpisode' =>[ 'name' => '', 'description' => '', 'datePublished' => '', 'duration' => '', 'episodeNumber' => '', 'image' => '', 'isFamilyFriendly' => '', 'url' => '', 'author' => '', 'associatedMedia' => [ '@type' => 'MediaObject', 'contentUrl' => '' ], 'partOfSeason' => [ '@type' => 'PodcastSeason', 'seasonName' => '', 'seasonUrl' => '', 'seasonNumber' => '' ], 'partOfSeries' => [ '@type' => 'PodcastSeries', 'seriesName' => '', 'seriesUrl' => '' ] ] ]; } static function save_metabox($post_id, $post){ // Security Check if(!isset($_POST['siteseo_metabox_nonce']) || !wp_verify_nonce(sanitize_text_field($_POST['siteseo_metabox_nonce']), 'siteseo_metabox_nonce')){ return $post_id; } //Post type object $post_type = get_post_type_object($post->post_type); //Check permission if(!current_user_can($post_type->cap->edit_post, $post_id)){ return $post_id; } if(isset($_POST['siteseo_structured_data_type'])){ update_post_meta($post_id, '_siteseo_structured_data_type', sanitize_text_field($_POST['siteseo_structured_data_type'])); } else{ delete_post_meta($post_id, '_siteseo_structured_data_type'); } if(isset($_POST['siteseo_structured_data_custom'])){ $decode_schema = json_decode(wp_unslash($_POST['siteseo_structured_data_custom']), true); if(json_last_error() === JSON_ERROR_NONE){ update_post_meta($post_id, '_siteseo_structured_data_custom', $decode_schema); } } else{ delete_post_meta($post_id, '_siteseo_structured_data_custom'); } if(isset($_POST['schema_properties']) && is_array($_POST['schema_properties'])){ $properties = array(); $text_area_fields = array('description', 'instructions', 'reviewBody', 'questions', 'step', 'ingredients','recipeInstructions', 'courseDescription', 'bookDescription', 'softwareRequirements', 'menu'); foreach($_POST['schema_properties'] as $key => $value){ if(is_array($value)){ foreach($value as $innerKey => $innerVal){ if(in_array($key, $text_area_fields)){ $properties[$key] = sanitize_textarea_field($value); }else{ $properties[$key] = sanitize_text_field($value); } } }else{ if(in_array($key, $text_area_fields)){ $properties[$key] = sanitize_textarea_field($value); } else{ $properties[$key] = sanitize_text_field($value); } } } update_post_meta($post_id, '_siteseo_structured_data_properties', $properties); } else{ delete_post_meta($post_id, '_siteseo_structured_data_properties'); } } static function render(){ global $siteseo, $post; if(empty($siteseo->pro['toggle_state_stru_data'])){ return; // disable } self::inject_global_schema(); // call auto global schema if(empty($siteseo->pro['enable_structured_data'])){ return; } if(!is_singular()){ return; } $schema_type = !empty(get_post_meta($post->ID , '_siteseo_structured_data_type', true)) ? get_post_meta($post->ID, '_siteseo_structured_data_type', true) : ''; if($schema_type === 'CustomSchema'){ $custom_schema = !empty(get_post_meta($post->ID , '_siteseo_structured_data_custom', true)) ? get_post_meta($post->ID, '_siteseo_structured_data_custom', true) : ''; if(!empty($custom_schema)){ echo'<script type="application/ld+json">'.json_encode($custom_schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).'</script>' . "\n"; } } else { $schema_properties = !empty(get_post_meta($post->ID, '_siteseo_structured_data_properties', true)) ? get_post_meta($post->ID, '_siteseo_structured_data_properties', true) : ''; if(!empty($schema_type) && is_array($schema_properties)){ $schema_data = array( '@context' => 'https://schema.org', '@type' => $schema_type ); $podcastSchemaData = array( '@context' => 'https://schema.org', '@type' => 'PodcastEpisode', 'associatedMedia' => array( '@type' => 'MediaObject', ), 'partOfSeason' => array( '@type' => 'PodcastSeason', ), 'partOfSeries' => array( '@type' => 'PodcastSeries', ) ); if($schema_type === 'PodcastEpisode'){ foreach($schema_properties as $key => $value){ if(!empty($value)){ if($key === 'contentUrl'){ $podcastSchemaData['associatedMedia'][$key] = $value; }else if(in_array($key, ['seasonUrl', 'seasonName', 'seasonNumber'])){ if($key === 'seasonNumber'){ $podcastSchemaData['partOfSeason']['seasonNumber'] = $value; } else { $podcastSchemaData['partOfSeason'][strtolower(str_replace("season", "", $key))] = $value; } }else if(in_array($key, ['seriesUrl', 'seriesName'])){ $podcastSchemaData['partOfSeries'][strtolower(str_replace("series", "", $key))] = $value; }else{ $podcastSchemaData[$key] = $value; } } } }else{ foreach($schema_properties as $key => $value){ if(!empty($value)){ $schema_data[$key] = $value; } } } if($schema_type === 'PodcastEpisode'){ echo'<script type="application/ld+json">'.json_encode($podcastSchemaData, JSON_UNESCAPED_SLASHES).'</script>' . "\n"; }else{ echo'<script type="application/ld+json">'.json_encode($schema_data, JSON_UNESCAPED_SLASHES).'</script>' . "\n"; } } } } static function inject_global_schema(){ global $siteseo; $options = get_option('siteseo_auto_schema'); $post_id = get_queried_object_id(); if(empty($options['schemas'])){ return; } $graph = []; foreach($options['schemas'] as $schema){ $display = true; // If no WooCommerce then not render product schema if($schema['type'] === 'Product' && (!class_exists('WooCommerce') && !class_exists('KKART'))){ continue; } if(!empty($schema['display_on'])){ $display = false; foreach($schema['display_on'] as $rule){ if(is_array($rule) && isset($rule['type']) && $rule['type'] === 'specific_targets'){ $targets = explode(',', $rule['targets']); if(self::check_specific_targets($targets)){ $display = true; break; } } elseif(self::check_display_rule_list([$rule])){ $display = true; break; } } } if($display && !empty($schema['display_not_on'])){ foreach($schema['display_not_on'] as $rule){ if(is_array($rule) && isset($rule['type']) && $rule['type'] === 'specific_targets'){ $targets = explode(',', $rule['targets']); if(self::check_specific_targets($targets)){ $display = false; break; } } elseif(self::check_display_rule_list([$rule])){ $display = false; break; } } } if($display){ $schema_json = self::generate_schema_json($schema); if(!empty($schema_json)){ $graph[] = $schema_json; } } } if(!empty($graph)){ $output = [ '@context' => 'https://schema.org', '@graph' => $graph ]; echo '<script type="application/ld+json">'. wp_json_encode($output, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) .'</script>' . "\n"; } } static function check_display_rule_list($rules){ if(empty($rules)){ return false; } global $post; foreach($rules as $rule){ if(is_string($rule)){ switch($rule){ case 'entire_website': return true; case 'all_singulars': if(is_singular()){ return true; } break; case 'front_page': if(is_front_page()){ return true; } break; case 'all_posts': if(is_singular('post')){ return true; } break; case 'all_pages': if(is_singular('page')){ return true; } break; case 'all_custom_layouts': if(function_exists('is_custom_layout') && is_custom_layout()){ return true; } break; case 'all_product': if(function_exists('is_product') && is_product()){ return true; } break; case 'all_product_categories': if(function_exists('is_product_category') && is_product_category()){ return true; } break; case 'all_product_tags': if(function_exists('is_product_tag') && is_product_tag()){ return true; } break; } } if(is_array($rule) && isset($rule['type']) && $rule['type'] === 'specific_targets' && !empty($rule['targets'])){ $targets = (array) $rule['targets']; foreach($targets as $target_slug){ if(self::check_target_match($target_slug)){ return true; } } } } return false; } static function check_specific_targets($targets){ if(empty($targets)){ return false; } $post_id = get_queried_object_id(); global $post; foreach($targets as $target){ $target = trim($target); // Check by post ID if(is_numeric($target) && (int)$target === $post_id){ return true; } // Check by slug for singular pages if(is_singular() && $post && $post->post_name === $target){ return true; } // Check for special pages if($target === 'home' && is_front_page()){ return true; } if($target === 'blog' && is_home()){ return true; } // Check for archive pages if(is_archive()){ $queried_object = get_queried_object(); if(is_category() && $queried_object instanceof \WP_Term && $queried_object->slug === $target){ return true; } if(is_tag() && $queried_object instanceof \WP_Term && $queried_object->slug === $target){ return true; } if(is_tax() && $queried_object instanceof \WP_Term && $queried_object->slug === $target){ return true; } if(is_post_type_archive() && $queried_object instanceof \WP_Post_Type && $queried_object->name === $target){ return true; } } } return false; } static function check_target_match($slug){ global $post; if(is_singular()){ if($post && $post->post_name === $slug){ return true; } } if(is_archive()){ if(get_query_var('category_name') === $slug || get_query_var('tag') === $slug){ return true; } } return false; } static function generate_schema_json($schema){ if(empty($schema['type'])){ return null; } $post_id = get_queried_object_id(); // Special case handling if($schema['type'] === 'BreadcrumbList'){ return [ '@type' => 'BreadcrumbList', '@id' => get_permalink($post_id) . '#breadcrumblist', 'itemListElement' => self::get_breadcrumb_items() ]; } if($schema['type'] === 'SearchAction'){ return self::get_search_action(); } // Normal schema generation $json = [ '@type' => $schema['type'], 'name' => $schema['name'], ]; // Process properties if they exist if(!empty($schema['properties'])){ $processed_properties = self::process_properties_recursive($schema['properties'], $schema['type']); // Merge processed properties with basic schema structure $json = array_merge($json, $processed_properties); } // Add @id if URL exists in the processed properties if(!empty($json['url'])){ $type_fragment = strtolower($schema['type']); $json['@id'] = $json['url'] . '#' . $type_fragment; } return $json; } static function process_properties_recursive($properties, $properties_def = []){ $result = []; foreach($properties as $prop_key => $prop_value){ $prop_key = trim($prop_key); if(is_array($prop_value)){ // This is a nested array - process recursively $nested_result = self::process_properties_recursive($prop_value, $properties_def); if(!empty($nested_result)){ // Use the property key as the nested object key $result[$prop_key] = $nested_result; } } else{ // This is a regular property value $property_name = isset($properties_def[$prop_key]) ? $properties_def[$prop_key] : $prop_key; $actual_value = self::replace_suggestion_variables($prop_value); if(!empty($property_name) && !empty($actual_value)){ $result[$property_name] = $actual_value; } } } return $result; } static function get_search_action(){ return [ '@type' => 'SearchAction', '@id' => get_home_url() . '#searchaction', 'target' => get_home_url() . '/?s={search_term_string}', 'query-input' => 'required name=search_term_string' ]; } static function get_breadcrumb_items(){ global $post; $post_id = get_queried_object_id(); $items = []; // Home $items[] = [ '@type' => 'ListItem', 'position' => 1, 'item' => [ '@id' => get_home_url(), 'name' => 'Home' ] ]; // Category $categories = get_the_category($post_id); if($categories){ $cat = $categories[0]; $items[] = [ '@type' => 'ListItem', 'position' => 2, 'item' => [ '@id' => get_category_link($cat->term_id), 'name' => $cat->name ] ]; } // Current post/page $items[] = [ '@type' => 'ListItem', 'position' => 3, 'item' => [ '@id' => get_permalink($post_id), 'name' => get_the_title($post_id) ] ]; return $items; } static function auto_schema(){ return [ 'Article' => [ 'URL' => '%%post_url%%', 'Headline' => '%%post_title%%', 'Description' => '%%post_excerpt%%', 'Date Published' => '%%post_date%%', 'Date Modified' => '%%post_modified_date%%', 'Keywords' => '%%keywords%%', 'Word count' => '%%post_word_count%%', 'Image' => '%%post_thumbnail_url%%', 'Main entity of page' => '', 'Author' => [ '@type' => 'Person', 'name' => '%%post_author%%', 'URL' => '%%post_url%%', ], ], 'WebSite' => [ 'Name' => '%%sitetitle%%', 'Description' => '%%site_description%%', 'URL' => '%%site_url%%', 'Potential Action' => '', 'Publisher' => '', 'In Language' => '%%site_language%%', ], 'WebPage' => [ 'Name' => '%%current_page_title%%', 'URL' => '%%current_page_url%%', 'Breadcrumb List' => '', 'Description' => '%%post_excerpt%%', 'Publisher' => '%%post_author%%', 'In Language' => '%%site_language%%', ], 'BreadcrumbList' => [], 'SearchAction' => [], 'Person' => [ 'Name' => '%%author_display_name%%', 'URL' => '%%author_url%%', 'Given name' => '%%author_first_name%%', 'Family name' => '%%author_last_name%%', 'Brand' => '%%sitetitle%%', 'Main entity of page' => '', 'Description' => '%%site_description%%', 'Image' => '%%author_avatar%%', 'Same as' => '', ], 'Product' => [ 'Name' => '%%post_title%%', 'Description' => '%%product_desc%%', 'Brand' => [ 'Name' => '%%sitetitle%%', 'URL' => '%%post_url%%', ], 'Image' => [ 'URL' => '%%product_img_url%%', 'Image Width' => '%%product_img_width%%', 'Image Height'=> '%%product_img_height%%', ], 'AggregateRating' => [ 'Type' => 'AggregateRating', 'Rating Value'=> '%%product_rating_value%%', 'Review Count'=> '%%product_review_count%%', ], 'Offers' => [ 'Type' => 'Offer', 'Price' => '%%product_price%%', 'Price Currency' => '%%product_currency%%', 'Availability' => '%%product_stock_status%%', ], ], ]; } static function replace_suggestion_variables($content){ global $post; // Remove wrapping %% if present return preg_replace_callback('/%%(.+?)%%/', function($matches){ return self::load_suggestion_data($matches[1]); }, $content); } static function load_suggestion_data($variable){ global $post; if(empty($variable)){ return ''; } switch($variable){ case 'site_url': return site_url(); case 'sitetitle': return get_bloginfo('name'); case 'site_description': return get_bloginfo('description'); case 'site_language': return get_locale(); case 'post_id': case 'post_title': case 'post_url': case 'post_date': case 'post_excerpt': case 'post_slug': case 'post_thumbnail_url': case 'post_category': case 'post_tags': case 'post_author': case 'post_word_count': case 'post_modified_date': case 'post_date': if(empty($post)){ return ''; } return self::load_post_suggestion_data($variable); case 'author_id': case 'author_first_name': case 'author_last_name': case 'author_display_name': case 'author_website': case 'author_bio': case 'author_avatar': case 'author_desc': case 'author_title': case 'author_email': case 'author_nickname': case 'author_url': return self::load_author_suggestion_data($variable); case 'user_id': case 'user_email': case 'user_first_name': case 'user_last_name': case 'user_post_url': case 'user_desc': return self::load_user_suggestion_data($variable); case 'current_page_title': return get_the_title(); case 'current_page_url': return get_permalink(); } // WooCommerce if(function_exists('wc_get_product') && is_singular('product') && strpos($variable, 'product_') === 0){ $product = wc_get_product($post->ID); if(!empty($product)){ switch($variable){ case 'product_img_url': case 'product_img_width': case 'product_img_height': return self::woo_img_suggestion_data($variable, $product); case 'product_desc': return $product->get_short_description(); case 'product_full_desc': return $product->get_description(); case 'product_price': return $product->get_price(); case 'product_currency': return get_woocommerce_currency(); case 'product_rating_value': return $product->get_average_rating(); case 'product_review_count': return $product->get_review_count(); case 'product_stock_status': return $product->is_in_stock() ? 'In Stock' : 'Out of Stock'; } } } return ''; } static function load_post_suggestion_data($variable){ global $post; if(empty($variable) || empty($post)){ return ''; } $post_id = isset($post->ID) ? $post->ID : 0; switch($variable){ case 'post_id': return $post_id; case 'post_title': return get_the_title($post_id); case 'post_url': return get_permalink($post_id); case 'post_date': $post_time = get_post_time('U', true, $post_id); return gmdate('c', $post_time); case 'post_modified_date': $post_modified_time = get_post_modified_time('U', true, $post_id); return gmdate('c', $post_modified_time); case 'post_excerpt': $post_excerpt = get_the_excerpt($post_id); if(strlen($post_excerpt) > 160){ $post_excerpt = substr($post_excerpt, 0, 160); $post_excerpt = substr($post_excerpt, 0, strrpos($post_excerpt, ' ')) . '...'; } return $post_excerpt; case 'post_slug': return basename(get_permalink($post_id)); case 'post_thumbnail_url': return get_the_post_thumbnail_url($post, 'full'); case 'post_category': $post_category = get_the_category($post_id); return !empty($post_category) ? $post_category[0]->name : ''; case 'post_tags': $post_tags = wp_get_post_tags($post_id, ['fields' => 'names']); return !empty($post_tags) ? implode(', ', $post_tags) : ''; case 'post_author': return get_the_author(); case 'post_word_count': $post_content = wp_strip_all_tags($post->post_content); return str_word_count($post_content); case 'keywords': return get_post_meta($post_id, '_siteseo_analysis_target_kw', true); } return ''; } static function load_author_suggestion_data($variable){ global $post; $author_id = isset($post->post_author) ? $post->post_author : get_current_user_id(); $post_id = isset($post->ID) ? $post->ID : 0; switch($variable){ case 'author_id': return $author_id; case 'author_first_name': return get_the_author_meta('first_name', $author_id); case 'author_last_name': return get_the_author_meta('last_name', $author_id); case 'author_display_name': return get_the_author_meta('display_name', $author_id); case 'author_website': return get_the_author_meta('url', $author_id); case 'author_bio': case 'author_desc': return get_the_author_meta('description', $author_id); case 'author_avatar': return get_avatar_url($author_id); case 'author_title': return get_the_author_meta('title', $author_id); case 'author_email': return get_the_author_meta('user_email', $author_id); case 'author_nickname': return get_the_author_meta('nickname', $author_id); case 'author_url': return get_author_posts_url($post_id); } return ''; } static function load_user_suggestion_data($variable){ $user_id = get_current_user_id(); $user_data = get_userdata($user_id); switch($variable){ case 'user_id': return $user_id; case 'user_email': return isset($user_data->user_email) ? $user_data->user_email : ''; case 'user_first_name': return isset($user_data->first_name) ? $user_data->first_name : ''; case 'user_last_name': return isset($user_data->last_name) ? $user_data->last_name : ''; case 'user_post_url': return get_author_posts_url($user_id); case 'user_desc': return get_user_meta($user_id, 'description', true); } return ''; } static function woo_img_suggestion_data($variable, $product){ $image_id = $product->get_image_id(); // Gets the featured image Id switch($variable){ case 'product_img_url': return $image_id ? wp_get_attachment_url($image_id) : ''; case 'product_img_height': case 'product_img_width': $image_size = $image_id ? wp_get_attachment_metadata($image_id) : null; if($variable == 'product_img_height'){ return isset($image_size['height']) ? $image_size['height'] : ''; } return $image_width = isset($image_size['width']) ? $image_size['width'] : ''; } return ''; } static function suggestion_variables(){ $tags = [ '%%author_title%%' => 'Author title', '%%author_desc%%' => 'Autor desc', '%%author_email%%' => 'Author email', '%%author_first_name%%' => 'Author first name', '%%author_last_name%%' => 'Author last name', '%%author_id%%' => 'Author id', '%%author_nickname%%' => 'Author Nickname', '%%author_website_url%%' => 'Author website url', '%%category%%' => 'Category', '%%_category_title_%%' => 'Category title', '%%_category_description_%%' => 'Category description', '%%tag_title%%' => 'Tag title', '%%tag_description' => 'Tag description', '%%sitetitle%%' => 'Site title', '%%siteurl%%' => 'Site url', '%%post_title%%' => 'Post title', '%%post_id%%' => 'Post Id', '%%post_url%%' => 'Post url', '%%post_slug%%' => 'Post Slug', '%%post_word_count%%' => 'Post word count', '%%post_tags%%' => 'Post tags', '%%post_category%%' => 'Post category', '%%post_thumbnail_url%%' => 'Post thumbnail', '%%post_date%%' => 'Post date', '%%post_modified_date%%' => 'post modified date', '%%post_author%%' => 'Post Author', '%%current_page_title%%' => 'Current Page title', '%%current_page_url%%' => 'Current Page url', '%%user_email%%' => 'User mail', '%%user_description%%' => 'User desc', '%%user_first_name%%' => 'User first name', '%%user_last_name%%' => 'User last name', '%%user_post_url%%' => 'User post url', '%%site_language%%' => 'Wordpress site language', '%%author_url%%' => 'Author URL', '%%author_avatar%%' => 'Author Avatar', ]; if(class_exists('WooCommerce') || class_exists('KKART')){ $tags = array_merge($tags, [ '%%product_desc%%' => 'Product Short Description', '%%product_full_desc%%' => 'Product Full Description', '%%product_img_url%%' => 'Product Image', '%%product_img_width%%' => 'Product Image Width', '%%product_img_height%%' => 'Product Image Height', '%%product_rating_value%%' => 'Product Rating Value', '%%product_review_count%%' => 'Product Review Count', '%%product_price%%' => 'Product Price', '%%product_currency%%' => 'Product Currency', '%%product_stock_status%%' => 'Product Stock Status', ]); } return $tags; } static function suggestion_schema_button(){ $suggest_variable = self::suggestion_variables(); echo'<div class="siteseo-suggestions-wrapper"> <div class="siteseo-suggetion" style="margin-left:80px;margin-top:5px"> <div class="siteseo-search-box-container"> <input type="text" class="siteseo-search-box" placeholder="Search a tag..."> </div> <div class="siteseo-suggestions-container">'; foreach($suggest_variable as $key =>$value){ echo'<div class="section">'.esc_html($value).' <div class="item"> <div class="tag">'.esc_html($key).'</div> </div> </div>'; } echo '</div> </div> </div>'; } static function process_nested_properties($properties_data){ $result = []; foreach($properties_data as $key => $value){ if(is_array($value)){ // multi-dimensional array $result[$key] = self::process_nested_properties($value); continue; } // This is a regular property - sanitize and format the key $special_cases = [ 'URL' => 'url', 'ID' => 'id', 'Image URL' => 'imageUrl', 'Price Currency' => 'priceCurrency', 'Published date' => 'datePublished', 'Modified date' => 'dateModified', 'Is part of' => 'isPartOf', 'Image' => 'image', 'Brand' => 'brand', 'Type' => '@type', 'AggregateRating' => 'aggregateRating', 'Rating Value' => 'ratingValue', 'Word count' => 'wordCount', 'In Language' => 'inLanguage', 'Breadcrumb List' => 'breadcrumbList', ]; if(isset($special_cases[$key])){ $formatted_key = $special_cases[$key]; } else{ $formatted_key = lcfirst(str_replace(' ', '', ucwords($key))); } $result[$formatted_key] = sanitize_text_field(wp_unslash($value)); } return $result; } static function generate_podcast_feed(){ global $siteseo; if(empty($siteseo->pro['toggle_state_podcast'])){ return; } $posts = get_posts([ 'post_type' => 'post', 'post_status' => 'publish', 'numberposts' => 50, 'order' => 'DESC', 'orderby' => 'date', 'has_password' => false, 'no_found_rows' => true, 'meta_query' => [ ['key' => '_siteseo_robots_index', 'compare' => 'NOT EXISTS'] ] ]); header('Content-Type: application/rss+xml; charset=' . sanitize_text_field(get_option('blog_charset')), true); echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"> <channel> <title><![CDATA['.esc_html(!empty($siteseo->pro['podcast_name']) ? $siteseo->pro['podcast_name'] : '').']]></title> <description><![CDATA['.esc_html(!empty($siteseo->pro['podcast_desc']) ? $siteseo->pro['podcast_desc'] : '').']]></description> <link>'.esc_url(!empty($siteseo->pro['podcast_url']) ? $siteseo->pro['podcast_url'] : '').'</link> <language>'.esc_html(!empty($siteseo->pro['podcast_lang']) ? $siteseo->pro['podcast_lang'] : '').'</language>'.(!empty($siteseo->pro['copyright_text']) ? PHP_EOL.' <copyright>'.esc_html($siteseo->pro['copyright_text']).'</copyright>' : '').' <itunes:subtitle>'.esc_html(!empty($siteseo->pro['podcast_name']) ? $siteseo->pro['podcast_name'] : '').'</itunes:subtitle> <itunes:author>'.esc_html(!empty($siteseo->pro['podcast_author']) ? $siteseo->pro['podcast_author'] : '').'</itunes:author> <itunes:category text="'.esc_html(!empty($siteseo->pro['podcast_category']) ? $siteseo->pro['podcast_category'] : '').'" /> <itunes:summary><![CDATA['.esc_html(!empty($siteseo->pro['podcast_desc']) ? $siteseo->pro['podcast_desc'] : '').']]></itunes:summary> <itunes:explicit>'.esc_html(!empty($siteseo->pro['is_explicit']) ? $siteseo->pro['is_explicit'] : '').'</itunes:explicit> <itunes:owner> <itunes:name>'.esc_html(!empty($siteseo->pro['owner_name']) ? $siteseo->pro['owner_name'] : '').'</itunes:name> <itunes:email>'.esc_html(!empty($siteseo->pro['owner_email']) ? $siteseo->pro['owner_email'] : '').'</itunes:email> </itunes:owner> <itunes:image href="'.esc_url(!empty($siteseo->pro['podcast_image']) ? $siteseo->pro['podcast_image'] : '').'" />'; foreach($posts as $post){ $schema = get_post_meta($post->ID, '_siteseo_structured_data_properties', true); if(empty($schema) || empty($schema['contentUrl'])){ continue; } echo '<item> <title><![CDATA[' . (!empty($schema['name']) ? esc_html($schema['name']) : esc_html(get_the_title($post->ID))) . ']]></title> <link>' . (!empty($schema['url']) ? esc_url($schema['url']) : esc_url($siteseo->pro['podcast_url'])) . '</link> <description><![CDATA[' . (!empty($schema['description']) ? esc_html(wp_strip_all_tags($schema['description'])) : esc_html(get_the_excerpt($post->ID))) . ']]></description> <enclosure url="' . esc_url(!empty($siteseo->pro['podcast_prefix']) ? $siteseo->pro['podcast_prefix'] . '/' . $schema['contentUrl'] : $schema['contentUrl']) . '" type="audio/mpeg" length="0"/> <guid isPermaLink="true">' . (!empty($schema['url']) ? esc_url($schema['url']) : esc_url($siteseo->pro['podcast_url'])) . '</guid> <pubDate>' . (!empty($schema['datePublished']) ? esc_html(gmdate(DATE_RSS, strtotime($schema['datePublished']))) : '') . '</pubDate> <itunes:title>' . esc_html(!empty($schema['name']) ? $schema['name'] : get_the_title($post->ID)) . '</itunes:title> <itunes:summary><![CDATA[' . (!empty($schema['description']) ? esc_html(wp_strip_all_tags($schema['description'])) : esc_html(get_the_excerpt($post->ID))) . ']]></itunes:summary> <itunes:author>' . esc_html(!empty($schema['author']) ? $schema['author'] : $siteseo->pro['podcast_author']) . '</itunes:author> <itunes:duration>' . esc_html(!empty($schema['duration']) ? self::iso8601_to_HMS($schema['duration']) : '') . '</itunes:duration> <itunes:episode>' . esc_html(!empty($schema['episodeNumber']) ? $schema['episodeNumber'] : '') . '</itunes:episode> <itunes:explicit>' . esc_html(!empty($schema['isFamilyFriendly']) ? $schema['isFamilyFriendly'] : 'no') . '</itunes:explicit> <itunes:image href="' . esc_url(!empty($schema['image']) ? $schema['image'] : $siteseo->pro['podcast_image']) . '" />' .(!empty($schema['seasonName'])? '<itunes:season>' . esc_html(!empty($schema['seasonNumber']) ? $schema['seasonNumber'] : '1') . '</itunes:season>': '') . '</item>'; } wp_reset_postdata(); echo ' </channel> </rss>'; exit; } static function iso8601_to_HMS($duration){ if(empty($duration)) return; $interval = new \DateInterval($duration); $hours = $interval->h + ($interval->d * 24); $minutes = $interval->i; $seconds = $interval->s; return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); } static function register_podcast_feed(){ add_feed('podcast', '\SiteSEOPro\StructuredData::generate_podcast_feed'); } }
Upload File
Create Folder