File: //var/softaculous/sitepad/editor/site-data/plugins/siteseo-pro/main/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';
$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', 'name'];
$is_date_type = ['datePublished', 'dateModified', 'uploadDate', 'startDate', 'endDate', 'foundingDate', 'releaseDate'];
foreach($schema_template[$schema_type] as $property => $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 {
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>';
}
}
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
);
foreach($schema_properties as $key => $value){
if(!empty($value)){
$schema_data[$key] = $value;
}
}
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' => '',
],
];
}
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(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
);
foreach($schema_properties as $key => $value){
if(!empty($value)){
$schema_data[$key] = $value;
}
}
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' => [
'Article Type' => 'Article',
'URL' => '%%post_url%%',
'Headline' => '%%post_title%%',
'Description' => '%%post_excerpt%%',
'Published date' => '%%post_date%%',
'Keywords' => '%%keywords%%',
'Word count' => '%%post_word_count%%',
'Image' => '%%post_thumbnail_url%%',
'Main entity of page' => '',
'Author' => '%%post_author%%',
],
'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':
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_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;
}
}