Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.recipe-instructions-data{margin-bottom:15px}.recipe-instructions-data .inner-wrapper{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:15px}.recipe-instructions-data .inner-wrapper img{margin-left:15px;max-width:200px}.rank-math-review-notes{margin-top:20px;margin-bottom:20px;float:left;width:100%}.rank-math-review-notes h4{margin-top:0;margin-bottom:20px}
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(()=>{"use strict";const e=lodash,t=wp.i18n,a=wp.hooks,n=wp.data,m=wp.components;(0,a.addFilter)("rank_math_schema_list","rank-math-pro",(function(a){if((0,e.isEmpty)(rankMath.activeTemplates))return a;var l=wp.element.createElement("div",{className:"rank-math-schema-active-templates"},wp.element.createElement("h4",{className:"rank-math-schema-section-title"},(0,t.__)("Global Templates in Use","rank-math-pro")),(0,e.map)(rankMath.activeTemplates,(function(a,l){return wp.element.createElement("div",{key:l,id:"rank-math-schema-item",className:"rank-math-schema-item row"},wp.element.createElement("strong",{className:"rank-math-schema-name"},(0,e.get)(a,"metadata.title",a["@type"])),wp.element.createElement("span",{className:"rank-math-schema-item-actions"},wp.element.createElement(m.Button,{isLink:!0,className:"button rank-math-delete-schema",onClick:function(){return(0,n.dispatch)("rank-math-pro").deleteActiveTemplate(l)}},wp.element.createElement("i",{className:"rm-icon rm-icon-trash"}),wp.element.createElement("span",null,(0,t.__)("Delete","rank-math-pro")))))})));return wp.element.createElement(React.Fragment,null,a,l)}))})();
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
/**
|
||||
* The Schema Module
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use RankMath\Schema\DB;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Rest\Sanitize;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
use WP_Screen;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Admin class.
|
||||
*/
|
||||
class Admin {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'admin_enqueue_scripts', 'overwrite_wplink', 100 );
|
||||
$this->action( 'rank_math/admin/before_editor_scripts', 'admin_scripts' );
|
||||
$this->action( 'rank_math/admin/editor_scripts', 'deregister_scripts', 99 );
|
||||
$this->action( 'save_post', 'save', 10, 2 );
|
||||
$this->action( 'edit_form_after_title', 'render_div' );
|
||||
$this->filter( 'rank_math/filter_metadata', 'filter_metadata', 10, 2 );
|
||||
$this->filter( 'rank_math/settings/snippet/types', 'add_pro_schema_types' );
|
||||
$this->filter( 'rank_math/schema/filter_data', 'update_schema_data' );
|
||||
|
||||
new Taxonomy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update schema data.
|
||||
*
|
||||
* @param array $schemas Schema data.
|
||||
*/
|
||||
public function update_schema_data( $schemas ) {
|
||||
if ( empty( $schemas ) ) {
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
foreach ( $schemas as $schema_key => $schema ) {
|
||||
if ( empty( $schema['review'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
! empty( $schema['review']['positiveNotes'] ) &&
|
||||
! empty( $schema['review']['positiveNotes']['itemListElement'] ) &&
|
||||
is_string( $schema['review']['positiveNotes']['itemListElement'] )
|
||||
) {
|
||||
|
||||
$notes = explode( PHP_EOL, $schema['review']['positiveNotes']['itemListElement'] );
|
||||
$schemas[ $schema_key ]['review']['positiveNotes']['itemListElement'] = [];
|
||||
foreach ( $notes as $key => $note ) {
|
||||
$schemas[ $schema_key ]['review']['positiveNotes']['itemListElement'][] = [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $key + 1,
|
||||
'name' => $note,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
! empty( $schema['review']['negativeNotes'] ) &&
|
||||
! empty( $schema['review']['negativeNotes']['itemListElement'] ) &&
|
||||
is_string( $schema['review']['negativeNotes']['itemListElement'] )
|
||||
) {
|
||||
|
||||
$notes = explode( PHP_EOL, $schema['review']['negativeNotes']['itemListElement'] );
|
||||
$schemas[ $schema_key ]['review']['negativeNotes']['itemListElement'] = [];
|
||||
foreach ( $notes as $key => $note ) {
|
||||
$schemas[ $schema_key ]['review']['negativeNotes']['itemListElement'][] = [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $key + 1,
|
||||
'name' => $note,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Pro schema types in Schema settings choices array.
|
||||
*
|
||||
* @param array $types Schema types.
|
||||
*/
|
||||
public function add_pro_schema_types( $types ) {
|
||||
$types = array_merge(
|
||||
$types,
|
||||
[
|
||||
'dataset' => esc_html__( 'DataSet', 'rank-math-pro' ),
|
||||
'FactCheck' => esc_html__( 'Fact Check', 'rank-math-pro' ),
|
||||
'movie' => esc_html__( 'Movie', 'rank-math-pro' ),
|
||||
]
|
||||
);
|
||||
|
||||
unset( $types['off'] );
|
||||
ksort( $types, SORT_NATURAL | SORT_FLAG_CASE );
|
||||
return [ 'off' => esc_html__( 'None (Click here to set one)', 'rank-math-pro' ) ] + $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite wplink script file.
|
||||
* Rank Math adds new options in the link popup when editing a post.
|
||||
*/
|
||||
public function overwrite_wplink() {
|
||||
if ( ! Admin_Helper::is_post_edit() || Admin_Helper::is_posts_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_deregister_script( 'rank-math-formats' );
|
||||
wp_register_script(
|
||||
'rank-math-formats',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/js/gutenberg-formats.js',
|
||||
[],
|
||||
rank_math_pro()->version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_deregister_script( 'wplink' );
|
||||
wp_register_script( 'wplink', RANK_MATH_PRO_URL . 'assets/admin/js/wplink.js', [ 'jquery', 'wpdialogs' ], rank_math_pro()->version, true );
|
||||
|
||||
wp_localize_script(
|
||||
'wplink',
|
||||
'wpLinkL10n',
|
||||
[
|
||||
'title' => esc_html__( 'Insert/edit link', 'rank-math-pro' ),
|
||||
'update' => esc_html__( 'Update', 'rank-math-pro' ),
|
||||
'save' => esc_html__( 'Add Link', 'rank-math-pro' ),
|
||||
'noTitle' => esc_html__( '(no title)', 'rank-math-pro' ),
|
||||
'noMatchesFound' => esc_html__( 'No matches found.', 'rank-math-pro' ),
|
||||
'linkSelected' => esc_html__( 'Link selected.', 'rank-math-pro' ),
|
||||
'linkInserted' => esc_html__( 'Link inserted.', 'rank-math-pro' ),
|
||||
'relCheckbox' => '<code>rel="nofollow"</code>',
|
||||
'sponsoredCheckbox' => '<code>rel="sponsored"</code>',
|
||||
'aboutCheckbox' => '<code>about</code>',
|
||||
'mentionsCheckbox' => '<code>mentions</code>',
|
||||
'schemaMarkupLabel' => esc_html__( 'Use in Schema Markup', 'rank-math-pro' ),
|
||||
'linkTitle' => esc_html__( 'Link Title', 'rank-math-pro' ),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Styles and Scripts required for the schema functionality on Gutenberg & Classic editor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function admin_scripts() {
|
||||
if ( ! $this->can_enqueue_scripts() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->localize_data();
|
||||
wp_enqueue_style( 'rank-math-schema-pro', RANK_MATH_PRO_URL . 'includes/modules/schema/assets/css/schema.css', [ 'rank-math-schema' ], rank_math_pro()->version );
|
||||
|
||||
wp_enqueue_script(
|
||||
'rank-math-pro-schema-filters',
|
||||
RANK_MATH_PRO_URL . 'includes/modules/schema/assets/js/schemaFilters.js',
|
||||
[
|
||||
'wp-plugins',
|
||||
'wp-components',
|
||||
'wp-hooks',
|
||||
'wp-api-fetch',
|
||||
'lodash',
|
||||
],
|
||||
rank_math_pro()->version,
|
||||
true
|
||||
);
|
||||
|
||||
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
|
||||
if ( $screen instanceof WP_Screen && 'rank_math_schema' === $screen->post_type ) {
|
||||
Helper::add_json( 'isTemplateScreen', true );
|
||||
wp_enqueue_script(
|
||||
'rank-math-pro-schema',
|
||||
rank_math()->plugin_url() . 'includes/modules/schema/assets/js/schema-template.js',
|
||||
[
|
||||
'clipboard',
|
||||
'wp-autop',
|
||||
'wp-components',
|
||||
'wp-editor',
|
||||
'wp-edit-post',
|
||||
'wp-element',
|
||||
'wp-i18n',
|
||||
'wp-plugins',
|
||||
'rank-math-analyzer',
|
||||
],
|
||||
rank_math_pro()->version,
|
||||
true
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script( 'rank-math-schema-pro', RANK_MATH_PRO_URL . 'includes/modules/schema/assets/js/schema.js', [ 'rank-math-schema' ], rank_math_pro()->version, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregister some scripts.
|
||||
*/
|
||||
public function deregister_scripts() {
|
||||
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
|
||||
if ( ! $screen instanceof WP_Screen || 'post' !== $screen->base || Helper::is_elementor_editor() || 'rank_math_schema' !== $screen->post_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_deregister_script( 'rank-math-editor' );
|
||||
wp_deregister_script( 'rank-math-schema' );
|
||||
|
||||
if ( wp_script_is( 'rank-math-pro-editor', 'registered' ) ) {
|
||||
wp_deregister_script( 'rank-math-pro-editor' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render app div
|
||||
*/
|
||||
public function render_div() {
|
||||
$screen = get_current_screen();
|
||||
if ( 'rank_math_schema' !== $screen->post_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Helper::add_json( 'postType', 'rank_math_schema' );
|
||||
|
||||
wp_nonce_field( 'rank_math_schema_template', 'security' );
|
||||
?>
|
||||
<div id="rank-math-schema-template"></div>
|
||||
<textarea name="rank_math_schema" rows="8" cols="80" class="rank-math-schema"></textarea>
|
||||
<input type="text" name="rank_math_schema_meta_id" class="rank-math-schema-meta-id" value="">
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save post data.
|
||||
*
|
||||
* @param int $post_id Post id.
|
||||
* @param object $post Post object.
|
||||
*/
|
||||
public function save( $post_id, $post ) {
|
||||
if (
|
||||
! isset( $_POST['security'] ) ||
|
||||
! wp_verify_nonce( $_POST['security'], 'rank_math_schema_template' ) ||
|
||||
! isset( $_POST['rank_math_schema'] )
|
||||
) {
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
$post_type = get_post_type_object( $post->post_type );
|
||||
if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) {
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
$sanitizer = Sanitize::get();
|
||||
$schema = stripslashes_deep( $_POST['rank_math_schema'] );
|
||||
$schema = json_decode( $schema, true );
|
||||
$schema = $sanitizer->sanitize( 'rank_math_schema', $schema );
|
||||
|
||||
$meta_key = 'rank_math_schema_' . $schema['@type'];
|
||||
update_post_meta( $post_id, $meta_key, $schema );
|
||||
|
||||
// Publish Schema Template post.
|
||||
if ( 'rank_math_schema' === $post->post_type && 'publish' !== $post->post_status ) {
|
||||
wp_update_post(
|
||||
[
|
||||
'ID' => $post_id,
|
||||
'post_status' => 'publish',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add excluded template conditions in the Schema template and remove it from the metadata.
|
||||
*
|
||||
* @param array $meta Meta data to update.
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return array Processed metadata.
|
||||
*/
|
||||
public function filter_metadata( $meta, $request ) {
|
||||
foreach ( $meta as $meta_key => $meta_value ) {
|
||||
if ( ! Str::starts_with( 'rank_math_exclude_template_', $meta_key ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$template_id = absint( \str_replace( 'rank_math_exclude_template_', '', $meta_key ) );
|
||||
$schema_data = DB::get_schemas( $template_id );
|
||||
$meta_id = key( $schema_data );
|
||||
$meta_key = 'rank_math_schema_' . $schema_data[ $meta_id ]['@type'];
|
||||
|
||||
$schema_data[ $meta_id ]['metadata']['displayConditions'][] = [
|
||||
'condition' => 'exclude',
|
||||
'category' => 'singular',
|
||||
'type' => $request->get_param( 'objectType' ),
|
||||
'value' => $request->get_param( 'objectID' ),
|
||||
];
|
||||
|
||||
$db_id = absint( str_replace( 'schema-', '', $meta_id ) );
|
||||
update_metadata_by_mid( 'post', $db_id, $schema_data[ $meta_id ], $meta_key );
|
||||
|
||||
unset( $meta[ "rank_math_exclude_template_{$template_id}" ] );
|
||||
}
|
||||
|
||||
return $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* [get_schema_templates description]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_schema_templates() {
|
||||
$posts = get_posts(
|
||||
[
|
||||
'post_type' => 'rank_math_schema',
|
||||
'posts_per_page' => -1,
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
]
|
||||
);
|
||||
|
||||
if ( empty( $posts ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$templates = [];
|
||||
foreach ( $posts as $post ) {
|
||||
$data = DB::get_template_type( $post->ID );
|
||||
$data['title'] = $post->post_title;
|
||||
$data['id'] = $post->ID;
|
||||
|
||||
$templates[] = $data;
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to enqueue schema scripts on the page.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_enqueue_scripts() {
|
||||
if ( ! Helper::has_cap( 'onpage_snippet' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! Helper::is_divi_frontend_editor() && ! is_admin() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $pagenow;
|
||||
if ( 'edit-tags.php' === $pagenow ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Admin_Helper::is_term_edit() ) {
|
||||
$taxonomy = Param::request( 'taxonomy' );
|
||||
return true !== apply_filters(
|
||||
'rank_math/snippet/remove_taxonomy_data',
|
||||
Helper::get_settings( 'titles.remove_' . $taxonomy . '_snippet_data' ),
|
||||
$taxonomy
|
||||
);
|
||||
}
|
||||
|
||||
return ( Admin_Helper::is_post_edit() || Helper::is_divi_frontend_editor() ) && ! Admin_Helper::is_posts_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add active templates to the schemas json
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_active_templates() {
|
||||
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
|
||||
if ( $screen instanceof WP_Screen && 'rank_math_schema' === $screen->post_type ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$templates = Display_Conditions::get_schema_templates();
|
||||
if ( empty( $templates ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$schemas = [];
|
||||
foreach ( $templates as $template ) {
|
||||
$template['schema']['isTemplate'] = true;
|
||||
$schemas[ $template['id'] ] = $template['schema'];
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Localized data.
|
||||
*/
|
||||
private function localize_data() {
|
||||
$post = get_post();
|
||||
Helper::add_json( 'postStatus', get_post_field( 'post_status', $post ) );
|
||||
Helper::add_json( 'postLink', get_permalink( $post ) );
|
||||
Helper::add_json( 'schemaTemplates', $this->get_schema_templates() );
|
||||
Helper::add_json( 'activeTemplates', $this->get_active_templates() );
|
||||
Helper::add_json( 'accessiblePostTypes', Helper::get_accessible_post_types() );
|
||||
Helper::add_json( 'accessibleTaxonomies', Helper::get_accessible_taxonomies() );
|
||||
Helper::add_json( 'postTaxonomies', $this->get_post_taxonomies() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Post taxonomies.
|
||||
*/
|
||||
private function get_post_taxonomies() {
|
||||
$post_types = Helper::get_accessible_post_types();
|
||||
$data = [];
|
||||
foreach ( $post_types as $post_type ) {
|
||||
$taxonomies = Helper::get_object_taxonomies( $post_type );
|
||||
if ( empty( $taxonomies ) ) {
|
||||
continue;
|
||||
}
|
||||
unset( $taxonomies['off'] );
|
||||
$data[ $post_type ] = [ 'all' => esc_html__( 'All Taxonomies', 'rank-math-pro' ) ] + $taxonomies;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
/**
|
||||
* The Schema AJAX
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use MyThemeShop\Helpers\Param;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Ajax class.
|
||||
*/
|
||||
class Ajax {
|
||||
|
||||
use \RankMath\Traits\Hooker;
|
||||
use \RankMath\Traits\Ajax;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->ajax( 'fetch_from_url', 'fetch_from_url' );
|
||||
$this->ajax( 'get_conditions_data', 'get_conditions_data' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch from url.
|
||||
*/
|
||||
public function fetch_from_url() {
|
||||
$this->verify_nonce( 'rank-math-ajax-nonce' );
|
||||
$this->has_cap_ajax( 'general' );
|
||||
|
||||
$url = Param::post( 'url', false, FILTER_VALIDATE_URL );
|
||||
if ( ! $url || strtolower( substr( $url, 0, 4 ) ) !== 'http' ) {
|
||||
$this->error( esc_html__( 'No url found.', 'rank-math-pro' ) );
|
||||
}
|
||||
|
||||
$parser = new Parser();
|
||||
$output = $parser->from_url( $url );
|
||||
|
||||
if ( is_wp_error( $output ) ) {
|
||||
$this->error( $output->get_error_message() );
|
||||
}
|
||||
|
||||
$this->success( [ 'json' => $output ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get posts/terms/author data.
|
||||
*/
|
||||
public function get_conditions_data() {
|
||||
$this->verify_nonce( 'rank-math-ajax-nonce' );
|
||||
$this->has_cap_ajax( 'general' );
|
||||
|
||||
$method = 'singular' === Param::get( 'category', false ) ? 'get_singular' : 'get_terms';
|
||||
$data = $this->{$method}(
|
||||
Param::get( 'userInput', false ),
|
||||
Param::get( 'type', false ),
|
||||
Param::get( 'value', false ),
|
||||
Param::get( 'postTaxonomy', false )
|
||||
);
|
||||
|
||||
$this->success( [ 'data' => $data ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get posts by searched string & post type.
|
||||
*
|
||||
* @param string $search Searched String.
|
||||
* @param string $type Post Type.
|
||||
* @param int $value Object ID.
|
||||
* @param int $taxonomy Is taxonomy.
|
||||
*/
|
||||
private function get_singular( $search, $type, $value, $taxonomy ) {
|
||||
if ( 'null' === $search && $value ) {
|
||||
|
||||
if ( $taxonomy && taxonomy_exists( $taxonomy ) ) {
|
||||
$data = [
|
||||
'value' => $value,
|
||||
'title' => get_term( $value )->name,
|
||||
];
|
||||
} else {
|
||||
$data = [
|
||||
'value' => $value,
|
||||
'title' => get_the_title( $value ),
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ( $taxonomy && 'all' !== $taxonomy ) {
|
||||
$terms = get_terms(
|
||||
[
|
||||
'taxonomy' => $taxonomy,
|
||||
'fields' => 'id=>name',
|
||||
'search' => $search,
|
||||
'hide_empty' => false,
|
||||
]
|
||||
);
|
||||
|
||||
if ( empty( $terms ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ( $terms as $id => $name ) {
|
||||
$data[] = [
|
||||
'value' => $id,
|
||||
'title' => $name,
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
$posts = get_posts(
|
||||
[
|
||||
'post_type' => $type,
|
||||
's' => $search,
|
||||
'numberposts' => -1,
|
||||
]
|
||||
);
|
||||
|
||||
if ( empty( $posts ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
foreach ( $posts as $post ) {
|
||||
$data[] = [
|
||||
'value' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get terms by searched string and taxonomy.
|
||||
*
|
||||
* @param string $search Searched String.
|
||||
* @param string $type Object type.
|
||||
* @param int $value Term ID.
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
*/
|
||||
private function get_terms( $search, $type, $value, $taxonomy ) {
|
||||
$data = [];
|
||||
if ( 'author' === $type ) {
|
||||
return $this->get_authors( $search, $value );
|
||||
}
|
||||
|
||||
if ( 'null' === $search && $value ) {
|
||||
$term = get_term_by( 'id', absint( $value ), $type );
|
||||
return [
|
||||
'value' => $value,
|
||||
'title' => ! empty( $term ) ? $term->name : '',
|
||||
];
|
||||
}
|
||||
|
||||
$terms = get_terms(
|
||||
[
|
||||
'taxonomy' => $type,
|
||||
'search' => $search,
|
||||
'hide_empty' => false,
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! empty( $terms ) ) {
|
||||
foreach ( $terms as $term ) {
|
||||
$data[] = [
|
||||
'value' => $term->term_id,
|
||||
'title' => $term->name,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get terms by searched string and taxonomy.
|
||||
*
|
||||
* @param string $search Searched String.
|
||||
* @param int $value Term ID.
|
||||
*/
|
||||
private function get_authors( $search, $value ) {
|
||||
if ( 'null' === $search && $value ) {
|
||||
$author = get_user_by( 'id', $value );
|
||||
|
||||
return [
|
||||
'value' => $value,
|
||||
'title' => ! empty( $author ) ? $author->display_name : '',
|
||||
];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
$authors = get_users(
|
||||
[
|
||||
'search' => '*' . $search . '*',
|
||||
'search_columns' => [ 'display_name', 'user_nicename', 'user_login', 'user_email' ],
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! empty( $authors ) ) {
|
||||
foreach ( $authors as $author ) {
|
||||
$data[] = [
|
||||
'value' => $author->ID,
|
||||
'title' => $author->data->display_name,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
* Outputs specific schema code from Schema Template
|
||||
*
|
||||
* @since 2.0.7
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Schema\DB;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Display Conditions class.
|
||||
*/
|
||||
class Display_Conditions {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Display conditions data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $conditions = [];
|
||||
|
||||
/**
|
||||
* Insert Schema data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $insert_schemas = [];
|
||||
|
||||
/**
|
||||
* Get Schema data from Schema Templates post type.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_schema_templates( $data = [], $jsonld = [] ) {
|
||||
global $wpdb;
|
||||
$templates = $wpdb->get_col( "SELECT ID FROM {$wpdb->prefix}posts WHERE post_type='rank_math_schema' AND post_status='publish'" );
|
||||
|
||||
if ( empty( $templates ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$newdata = [];
|
||||
foreach ( $templates as $template ) {
|
||||
self::$conditions = [
|
||||
'general' => '',
|
||||
'singular' => '',
|
||||
'archive' => '',
|
||||
];
|
||||
|
||||
$schema = DB::get_schemas( $template );
|
||||
|
||||
self::prepare_inserted_schemas( current( $schema ) );
|
||||
|
||||
if ( ! self::can_add( current( $schema ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_admin() || Helper::is_divi_frontend_editor() ) {
|
||||
$newdata[] = [
|
||||
'id' => $template,
|
||||
'schema' => current( $schema ),
|
||||
];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::unpublish_jobposting_post( $jsonld, $schema );
|
||||
|
||||
$schema = $jsonld->replace_variables( $schema );
|
||||
$schema = $jsonld->filter( $schema, $jsonld, $data );
|
||||
|
||||
$newdata[] = $schema;
|
||||
}
|
||||
|
||||
return $newdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether schema can be added to current page
|
||||
*
|
||||
* @param array $schema Schema Data.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private static function can_add( $schema ) {
|
||||
if ( empty( $schema ) || empty( $schema['metadata']['displayConditions'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $schema['metadata']['displayConditions'] as $condition ) {
|
||||
$operator = $condition['condition'];
|
||||
if ( 'insert' === $operator ) {
|
||||
// We handle the insert condition in the prepare_inserted_schemas() method.
|
||||
continue;
|
||||
}
|
||||
|
||||
$category = $condition['category'];
|
||||
$taxonomy = ! empty( $condition['postTaxonomy'] ) ? $condition['postTaxonomy'] : '';
|
||||
$type = $condition['type'];
|
||||
$value = $condition['value'];
|
||||
|
||||
$method = "can_add_{$category}";
|
||||
|
||||
// Skip if already confirmed.
|
||||
if ( 'include' === $operator && self::$conditions[ $category ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
self::$conditions[ $category ] = self::$method( $operator, $type, $value, $taxonomy );
|
||||
}
|
||||
|
||||
// Add Schema if the only condition is "Include / Entire Site".
|
||||
if ( ! empty( self::$conditions['general'] ) && 1 === count( $schema['metadata']['displayConditions'] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ( is_singular() || is_admin() ) && isset( self::$conditions['singular'] ) ) {
|
||||
return self::$conditions['singular'];
|
||||
}
|
||||
|
||||
if ( ( is_archive() || is_search() ) && isset( self::$conditions['archive'] ) ) {
|
||||
return self::$conditions['archive'];
|
||||
}
|
||||
|
||||
return ! empty( self::$conditions['general'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare inserted schemas: check if they can be added to current page, and if so, add them to the $insert_schemas static array.
|
||||
*
|
||||
* @param array $schema Schema Data.
|
||||
*/
|
||||
private static function prepare_inserted_schemas( $schema ) {
|
||||
if ( empty( $schema ) || empty( $schema['metadata']['displayConditions'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $schema['metadata']['displayConditions'] as $condition ) {
|
||||
$operator = $condition['condition'];
|
||||
if ( 'insert' !== $operator ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( empty( $schema['metadata']['title'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$in_schema = $condition['category'];
|
||||
if ( 'custom' === $in_schema ) {
|
||||
if ( empty( $condition['value'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$in_schema = $condition['value'];
|
||||
}
|
||||
|
||||
if ( 'ProfilePage' === $in_schema && ! is_singular() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'ProfilePage' === $in_schema && ! empty( $condition['authorID'] ) ) {
|
||||
$author_ids = wp_parse_id_list( $condition['authorID'] );
|
||||
global $post;
|
||||
|
||||
if ( ! in_array( (int) $post->post_author, $author_ids, true ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$with_key = $schema['metadata']['title'];
|
||||
|
||||
self::$insert_schemas[ $in_schema ][] = [
|
||||
'key' => $with_key,
|
||||
'schema' => $schema,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get inserted schemas.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_insertable_schemas() {
|
||||
return self::$insert_schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether schema can be added to current page
|
||||
*
|
||||
* @param string $operator Comparision Operator.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private static function can_add_general( $operator ) {
|
||||
return 'include' === $operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether schema can be added on archive page
|
||||
*
|
||||
* @param string $operator Comparision Operator.
|
||||
* @param string $type Post/Taxonoy type.
|
||||
* @param string $value Post/Term ID.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private static function can_add_archive( $operator, $type, $value ) {
|
||||
if ( 'search' === $type ) {
|
||||
return 'include' === $operator && is_search();
|
||||
}
|
||||
|
||||
if ( ! is_archive() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'all' === $type ) {
|
||||
return 'include' === $operator;
|
||||
}
|
||||
|
||||
if ( 'author' === $type ) {
|
||||
return is_author() && 'include' === $operator && is_author( $value );
|
||||
}
|
||||
|
||||
if ( 'category' === $type ) {
|
||||
return ! is_category() ? self::$conditions['archive'] : 'include' === $operator && is_category( $value );
|
||||
}
|
||||
|
||||
if ( 'post_tag' === $type ) {
|
||||
return ! is_tag() ? self::$conditions['archive'] : 'include' === $operator && is_tag( $value );
|
||||
}
|
||||
|
||||
return 'include' === $operator && is_tax( $type, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether schema can be added on single page
|
||||
*
|
||||
* @param string $operator Comparision Operator.
|
||||
* @param string $type Post/Taxonoy type.
|
||||
* @param string $value Post/Term ID.
|
||||
* @param string $taxonomy Post Taxonomy.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private static function can_add_singular( $operator, $type, $value, $taxonomy ) {
|
||||
$post = is_admin() || is_singular() ? get_post( get_the_ID() ) : [];
|
||||
if ( empty( $post ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'all' === $type ) {
|
||||
return 'include' === $operator;
|
||||
}
|
||||
|
||||
if ( $type !== $post->post_type ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $value ) {
|
||||
return 'include' === $operator;
|
||||
}
|
||||
|
||||
if ( $taxonomy && 'exclude' === $operator ) {
|
||||
return ! has_term( $value, $taxonomy );
|
||||
}
|
||||
|
||||
if ( $taxonomy ) {
|
||||
return 'include' === $operator && has_term( $value, $taxonomy );
|
||||
}
|
||||
|
||||
if ( absint( $post->ID ) === absint( $value ) ) {
|
||||
return 'include' === $operator;
|
||||
}
|
||||
|
||||
return 'exclude' === $operator;
|
||||
}
|
||||
}
|
@@ -0,0 +1,661 @@
|
||||
<?php
|
||||
/**
|
||||
* Outputs specific schema code from Schema Template
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Schema\DB;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
use MyThemeShop\Helpers\HTML;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Schema Frontend class.
|
||||
*/
|
||||
class Frontend {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->filter( 'rank_math/json_ld', 'add_about_mention_attributes', 11 );
|
||||
$this->filter( 'rank_math/json_ld', 'add_template_schema', 8, 2 );
|
||||
$this->filter( 'rank_math/json_ld', 'add_schema_from_shortcode', 8, 2 );
|
||||
$this->filter( 'rank_math/json_ld', 'convert_schema_to_item_list', 99, 2 );
|
||||
$this->filter( 'rank_math/json_ld', 'validate_schema_data', 999 );
|
||||
$this->filter( 'rank_math/json_ld', 'add_subjectof_property', 99 );
|
||||
$this->filter( 'rank_math/json_ld', 'insert_template_schema', 20, 2 );
|
||||
$this->action( 'rank_math/schema/preview/validate', 'validate_preview_data' );
|
||||
$this->filter( 'rank_math/snippet/rich_snippet_itemlist_entity', 'filter_item_list_schema' );
|
||||
$this->filter( 'rank_math/schema/valid_types', 'valid_types' );
|
||||
$this->filter( 'rank_math/snippet/rich_snippet_product_entity', 'add_manufacturer_property' );
|
||||
$this->filter( 'rank_math/snippet/rich_snippet_product_entity', 'remove_empty_offers' );
|
||||
$this->filter( 'rank_math/snippet/rich_snippet_videoobject_entity', 'convert_familyfriendly_property' );
|
||||
$this->filter( 'rank_math/snippet/rich_snippet_podcastepisode_entity', 'convert_familyfriendly_property' );
|
||||
$this->filter( 'rank_math/snippet/rich_snippet_entity', 'schema_entity' );
|
||||
|
||||
new Display_Conditions();
|
||||
new Snippet_Pro_Shortcode();
|
||||
|
||||
if ( $this->do_filter( 'link/remove_schema_attribute', false ) ) {
|
||||
$this->filter( 'the_content', 'remove_schema_attribute', 11 );
|
||||
}
|
||||
|
||||
// Schema Preview.
|
||||
$this->filter( 'query_vars', 'add_query_vars' );
|
||||
$this->filter( 'init', 'add_endpoint' );
|
||||
$this->action( 'template_redirect', 'schema_preview_template' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the 'photos' query variable so WordPress won't mangle it.
|
||||
*
|
||||
* @param array $vars Array of vars.
|
||||
*/
|
||||
public function add_query_vars( $vars ) {
|
||||
$vars[] = 'schema-preview';
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add endpoint
|
||||
*/
|
||||
public function add_endpoint() {
|
||||
add_rewrite_endpoint( 'schema-preview', EP_PERMALINK | EP_PAGES | EP_ROOT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema preview template
|
||||
*/
|
||||
public function schema_preview_template() {
|
||||
global $wp_query;
|
||||
|
||||
// if this is not a request for schema preview or a singular or home object then bail.
|
||||
if (
|
||||
! isset( $wp_query->query_vars['schema-preview'] ) ||
|
||||
( ! is_singular() && ! is_home() && ! is_category() && ! is_tag() && ! is_tax() )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
header( 'Content-Type: application/json' );
|
||||
|
||||
do_action( 'rank_math/json_ld/preview' );
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nofollow and target attributes to link.
|
||||
*
|
||||
* @param string $content Post content.
|
||||
* @return string
|
||||
*/
|
||||
public function remove_schema_attribute( $content ) {
|
||||
preg_match_all( '/<(a\s[^>]+)>/', $content, $matches );
|
||||
if ( empty( $matches ) || empty( $matches[0] ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
foreach ( $matches[0] as $link ) {
|
||||
$attrs = HTML::extract_attributes( $link );
|
||||
|
||||
if ( ! isset( $attrs['data-schema-attribute'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset( $attrs['data-schema-attribute'] );
|
||||
$content = str_replace( $link, '<a' . HTML::attributes_to_string( $attrs ) . '>', $content );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter functiont to extend valid schema types to use in Rank Math generated schema object.
|
||||
*
|
||||
* @param array $types Valid Schema types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function valid_types( $types ) {
|
||||
return array_merge( $types, [ 'movie', 'dataset', 'claimreview' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Code Validation Schema data before displaying it in Preview window.
|
||||
*
|
||||
* @param array $schemas Array of json-ld data.
|
||||
* @return array
|
||||
*
|
||||
* @since 2.6.1
|
||||
*/
|
||||
public function validate_preview_data( $schemas ) {
|
||||
foreach ( $schemas as $schema_key => $schema ) {
|
||||
if ( empty( $schema['subjectOf'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $schema['subjectOf'] as $key => $property ) {
|
||||
if ( empty( $schemas[ $key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$schema['subjectOf'][ $key ] = $schemas[ $key ];
|
||||
unset( $schemas[ $key ] );
|
||||
}
|
||||
|
||||
$schema['subjectOf'] = array_values( $schema['subjectOf'] );
|
||||
$schemas[ $schema_key ] = $schema;
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add FAQ/HowTo schema in subjectOf property of primary schema.
|
||||
*
|
||||
* @param array $schemas Array of json-ld data.
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.62
|
||||
*/
|
||||
public function add_subjectof_property( $schemas ) {
|
||||
if ( empty( $schemas ) ) {
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
foreach ( $schemas as $id => $schema ) {
|
||||
if ( ! Str::starts_with( 'schema-', $id ) && 'richSnippet' !== $id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->add_prop_subjectof( $schema, $schemas );
|
||||
if ( ! empty( $schema['subjectOf'] ) ) {
|
||||
$schemas[ $id ] = $schema;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subjectOf property in current schema entity.
|
||||
*
|
||||
* @param array $entity Schema Entity.
|
||||
* @param array $schemas Array of json-ld data.
|
||||
*
|
||||
* @since 1.0.62
|
||||
*/
|
||||
private function add_prop_subjectof( &$entity, &$schemas ) {
|
||||
if (
|
||||
! isset( $entity['@type'] ) ||
|
||||
empty( $entity['isPrimary'] ) ||
|
||||
! empty( $entity['isCustom'] ) ||
|
||||
in_array( $entity['@type'], [ 'FAQPage', 'HowTo' ], true )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wp_query;
|
||||
$subject_of = [];
|
||||
foreach ( $schemas as $key => $schema ) {
|
||||
if ( ! isset( $schema['@type'] ) || ! in_array( $schema['@type'], [ 'FAQPage', 'HowTo' ], true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $schema['isPrimary'] ) ) {
|
||||
unset( $schema['isPrimary'] );
|
||||
}
|
||||
|
||||
if ( isset( $schema['isCustom'] ) ) {
|
||||
unset( $schema['isCustom'] );
|
||||
}
|
||||
|
||||
if ( isset( $wp_query->query_vars['schema-preview'] ) ) {
|
||||
$subject_of[ $key ] = $schema;
|
||||
continue;
|
||||
}
|
||||
|
||||
$subject_of[] = $schema;
|
||||
unset( $schemas[ $key ] );
|
||||
}
|
||||
|
||||
$entity['subjectOf'] = $subject_of;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Default Schema Data.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function convert_schema_to_item_list( $data, $jsonld ) {
|
||||
$schemas = array_filter(
|
||||
$data,
|
||||
function( $schema ) {
|
||||
if ( isset( $schema['@type'] ) && in_array( $schema['@type'], [ 'Course', 'Movie', 'Recipe', 'Restaurant' ], true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
if ( 2 > count( $schemas ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$data['itemList'] = [
|
||||
'@type' => 'ItemList',
|
||||
'itemListElement' => [],
|
||||
];
|
||||
|
||||
$count = 1;
|
||||
foreach ( $schemas as $id => $schema ) {
|
||||
unset( $data[ $id ] );
|
||||
$schema['url'] = $jsonld->parts['url'] . '#' . $id;
|
||||
|
||||
if ( isset( $schema['isPrimary'] ) ) {
|
||||
unset( $schema['isPrimary'] );
|
||||
}
|
||||
|
||||
$data['itemList']['itemListElement'][] = [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $count,
|
||||
'item' => $schema,
|
||||
];
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Schema data from Schema Templates.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_template_schema( $data, $jsonld ) {
|
||||
$schemas = Display_Conditions::get_schema_templates( $data, $jsonld );
|
||||
if ( empty( $schemas ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ( $schemas as $schema ) {
|
||||
$data = array_merge( $data, $schema );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the appropriate Schema data from Schema Templates.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function insert_template_schema( $data, $jsonld ) {
|
||||
$schema_array = Display_Conditions::get_insertable_schemas();
|
||||
if ( empty( $schema_array ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ( $schema_array as $insert_in => $schemas ) {
|
||||
|
||||
// If the $insert_in is not a @type present in the data, then skip it.
|
||||
$insert_key = false;
|
||||
foreach ( $data as $key => $schema ) {
|
||||
if ( $key === $insert_in ) {
|
||||
$insert_key = $key;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! isset( $schema['@type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $schema['@type'] === $insert_in ) {
|
||||
$insert_key = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! $insert_key ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now insert the schema(s).
|
||||
foreach ( $schemas as $schema ) {
|
||||
$schema_key = $schema['key'];
|
||||
$schema_data = $schema['schema'];
|
||||
|
||||
unset( $schema_data['isPrimary'], $schema_data['isCustom'], $schema_data['isTemplate'], $schema_data['metadata'] );
|
||||
|
||||
$schema_data = $jsonld->replace_variables( $schema_data );
|
||||
|
||||
foreach ( $schema_data as $key => $value ) {
|
||||
if ( ! isset( $data[ $insert_key ][ $key ] ) ) {
|
||||
$data[ $insert_key ][ $key ] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add About & Mention attributes to Webpage schema.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @return array
|
||||
*/
|
||||
public function add_about_mention_attributes( $data ) {
|
||||
if ( ! is_singular() || empty( $data['WebPage'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
global $post;
|
||||
if ( ! $post->post_content ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
preg_match_all( '|<a[^>]+>([^<]+)</a>|', $post->post_content, $matches );
|
||||
if ( empty( $matches ) || empty( $matches[0] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ( $matches[0] as $link ) {
|
||||
$attrs = HTML::extract_attributes( $link );
|
||||
if ( empty( $attrs['data-schema-attribute'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributes = explode( ' ', $attrs['data-schema-attribute'] );
|
||||
if ( in_array( 'about', $attributes, true ) ) {
|
||||
$data['WebPage']['about'][] = [
|
||||
'@type' => 'Thing',
|
||||
'name' => wp_strip_all_tags( $link ),
|
||||
'sameAs' => $attrs['href'],
|
||||
];
|
||||
}
|
||||
|
||||
if ( in_array( 'mentions', $attributes, true ) ) {
|
||||
$data['WebPage']['mentions'][] = [
|
||||
'@type' => 'Thing',
|
||||
'name' => wp_strip_all_tags( $link ),
|
||||
'sameAs' => $attrs['href'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to change the itemList schema data.
|
||||
*
|
||||
* @param array $schema Snippet Data.
|
||||
* @return array
|
||||
*/
|
||||
public function filter_item_list_schema( $schema ) {
|
||||
if ( ! is_archive() ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
$elements = [];
|
||||
$count = 1;
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
$elements[] = [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $count,
|
||||
'url' => get_the_permalink(),
|
||||
];
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
wp_reset_postdata();
|
||||
|
||||
$schema['itemListElement'] = $elements;
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Schema Data.
|
||||
*
|
||||
* @param array $schemas Array of json-ld data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function validate_schema_data( $schemas ) {
|
||||
if ( empty( $schemas ) ) {
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
$validate_types = [ 'Dataset', 'LocalBusiness' ];
|
||||
foreach ( $schemas as $id => $schema ) {
|
||||
$type = isset( $schema['@type'] ) ? $schema['@type'] : '';
|
||||
if ( ! Str::starts_with( 'schema-', $id ) || ! in_array( $type, $validate_types, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hash = [
|
||||
'isPartOf' => true,
|
||||
'publisher' => 'LocalBusiness' === $type,
|
||||
'inLanguage' => 'LocalBusiness' === $type,
|
||||
];
|
||||
|
||||
foreach ( $hash as $property => $value ) {
|
||||
if ( ! $value || ! isset( $schema[ $property ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'Dataset' === $type && 'isPartOf' === $property && ! empty( $schema[ $property ]['@type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset( $schemas[ $id ][ $property ] );
|
||||
}
|
||||
|
||||
if ( 'Dataset' === $type && ! empty( $schema['publisher'] ) ) {
|
||||
$schemas[ $id ]['creator'] = $schema['publisher'];
|
||||
unset( $schemas[ $id ]['publisher'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Schema data from Schema Templates post type.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_schema_from_shortcode( $data, $jsonld ) {
|
||||
if ( ! is_singular() || ! $this->do_filter( 'rank_math/schema/add_shortcode_schema', true ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
global $post;
|
||||
$blocks = parse_blocks( $post->post_content );
|
||||
if ( ! empty( $blocks ) ) {
|
||||
foreach ( $blocks as $block ) {
|
||||
if ( 'rank-math/rich-snippet' !== $block['blockName'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = isset( $block['attrs']['id'] ) ? $block['attrs']['id'] : '';
|
||||
$post_id = isset( $block['attrs']['post_id'] ) ? $block['attrs']['post_id'] : '';
|
||||
|
||||
if ( ! $id && ! $post_id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = array_merge( $data, $this->get_schema_data_by_id( $id, $post_id, $jsonld, $data ) );
|
||||
}
|
||||
}
|
||||
|
||||
$regex = '/\[rank_math_rich_snippet (.*)\]/m';
|
||||
preg_match_all( $regex, $post->post_content, $matches, PREG_SET_ORDER, 0 );
|
||||
if ( ! empty( $matches ) ) {
|
||||
foreach ( $matches as $key => $match ) {
|
||||
parse_str( str_replace( ' ', '&', $match[1] ), $output );
|
||||
|
||||
$post_id = isset( $output['post_id'] ) ? str_replace( [ '"', "'" ], '', $output['post_id'] ) : '';
|
||||
$id = isset( $output['id'] ) ? str_replace( [ '"', "'" ], '', $output['id'] ) : '';
|
||||
$data = array_merge( $data, $this->get_schema_data_by_id( $id, $post_id, $jsonld, $data ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Manufacturer property to Product schema.
|
||||
*
|
||||
* @param array $schema Product schema data.
|
||||
* @return array
|
||||
*/
|
||||
public function add_manufacturer_property( $schema ) {
|
||||
if ( empty( $schema['manufacturer'] ) ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
$type = Helper::get_settings( 'titles.knowledgegraph_type' );
|
||||
$type = 'company' === $type ? 'organization' : 'person';
|
||||
|
||||
$schema['manufacturer'] = [ '@id' => home_url( "/#{$type}" ) ];
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove empty offers data from the Product schema.
|
||||
*
|
||||
* @param array $schema Product schema data.
|
||||
* @return array
|
||||
*/
|
||||
public function remove_empty_offers( $schema ) {
|
||||
if (
|
||||
empty( $schema['offers'] ) ||
|
||||
empty( $schema['review'] ) ||
|
||||
(
|
||||
empty( $schema['review']['positiveNotes'] ) &&
|
||||
empty( $schema['review']['negativeNotes'] )
|
||||
)
|
||||
) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
if ( ! empty( $schema['offers']['price'] ) ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
unset( $schema['offers'] );
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backward compatibility code to move the positiveNotes & negativeNotes properties in review.
|
||||
*
|
||||
* @param array $schema Schema data.
|
||||
* @return array
|
||||
*
|
||||
* @since 3.0.19
|
||||
*/
|
||||
public function schema_entity( $schema ) {
|
||||
if ( empty( $schema['review'] ) ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
if ( ! empty( $schema['positiveNotes'] ) ) {
|
||||
$schema['review']['positiveNotes'] = $schema['positiveNotes'];
|
||||
unset( $schema['positiveNotes'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $schema['negativeNotes'] ) ) {
|
||||
$schema['review']['negativeNotes'] = $schema['negativeNotes'];
|
||||
unset( $schema['negativeNotes'] );
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert isFamilyFriendly property used in Video schema to boolean.
|
||||
*
|
||||
* @param array $schema Video schema data.
|
||||
* @return array
|
||||
*
|
||||
* @since 2.13.0
|
||||
*/
|
||||
public function convert_familyfriendly_property( $schema ) {
|
||||
if ( empty( $schema['isFamilyFriendly'] ) ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
$schema['isFamilyFriendly'] = 'True';
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Schema data by ID.
|
||||
*
|
||||
* @param string $id Schema shortcode ID.
|
||||
* @param int $post_id Post ID.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
* @param array $data Array of json-ld data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_schema_data_by_id( $id, $post_id, $jsonld, $data ) {
|
||||
$schemas = $id ? DB::get_schema_by_shortcode_id( trim( $id ) ) : DB::get_schemas( trim( $post_id ) );
|
||||
$current_post_id = get_the_ID();
|
||||
if (
|
||||
empty( $schemas ) ||
|
||||
(
|
||||
isset( $schemas['post_id'] ) && $current_post_id === (int) $schemas['post_id']
|
||||
) ||
|
||||
$post_id === $current_post_id
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$post_id = isset( $schemas['post_id'] ) ? $schemas['post_id'] : $post_id;
|
||||
$schemas = isset( $schemas['schema'] ) ? [ $schemas['schema'] ] : $schemas;
|
||||
$schemas = $jsonld->replace_variables( $schemas, get_post( $post_id ) );
|
||||
$schemas = $jsonld->filter( $schemas, $jsonld, $data );
|
||||
|
||||
if ( isset( $schemas[0]['isPrimary'] ) ) {
|
||||
unset( $schemas[0]['isPrimary'] );
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* Add Media RSS feed.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Media_RSS class.
|
||||
*/
|
||||
class Media_RSS {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( Helper::get_settings( 'general.disable_media_rss' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->action( 'rss2_ns', 'add_namespace' );
|
||||
$this->action( 'rss2_item', 'add_video_data', 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add namespace to RSS feed.
|
||||
*
|
||||
* @copyright Copyright (C) 2008-2019, Yoast BV
|
||||
* The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
|
||||
*/
|
||||
public function add_namespace() {
|
||||
if ( apply_filters( 'rank_math/rss/add_media_namespace', true ) ) {
|
||||
echo ' xmlns:media="http://search.yahoo.com/mrss/" ';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Video Data in RSS feed.
|
||||
*
|
||||
* @see https://www.rssboard.org/media-rss
|
||||
* @see https://support.google.com/news/publisher-center/answer/9545420?hl=en
|
||||
*/
|
||||
public function add_video_data() {
|
||||
global $post;
|
||||
$video_schema = get_post_meta( $post->ID, 'rank_math_schema_VideoObject', true );
|
||||
if ( empty( $video_schema ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = ! empty( $video_schema['contentUrl'] ) ? $video_schema['contentUrl'] : ( ! empty( $video_schema['embedUrl'] ) ? $video_schema['embedUrl'] : '' );
|
||||
if ( ! $url ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attrs = ! empty( $video_schema['width'] ) ? ' width="' . esc_attr( $video_schema['width'] ) . '"' : '';
|
||||
$attrs .= ! empty( $video_schema['height'] ) ? ' height="' . esc_attr( $video_schema['height'] ) . '"' : '';
|
||||
$duration = ! empty( $video_schema['duration'] ) ? Helper::duration_to_seconds( $video_schema['duration'] ) : '';
|
||||
$name = ! empty( $video_schema['name'] ) ? Helper::replace_vars( $video_schema['name'], $post ) : '';
|
||||
$description = ! empty( $video_schema['description'] ) ? Helper::replace_vars( $video_schema['description'], $post ) : '';
|
||||
$thumbnail = ! empty( $video_schema['thumbnailUrl'] ) ? Helper::replace_vars( $video_schema['thumbnailUrl'], $post ) : '';
|
||||
$tags = ! empty( $video_schema['metadata']['tags'] ) ? Helper::replace_vars( $video_schema['metadata']['tags'] ) : '';
|
||||
$categories = ! empty( $video_schema['metadata']['category'] ) ? Helper::replace_vars( $video_schema['metadata']['category'] ) : '';
|
||||
$rating = ! empty( $video_schema['isFamilyFriendly'] ) ? 'nonadult' : 'adult';
|
||||
|
||||
$this->newline( '<media:content url="' . esc_url( $url ) . '" medium="video"' . $attrs . '>' );
|
||||
$this->newline( '<media:player url="' . esc_url( $url ) . '" />', 3 );
|
||||
|
||||
if ( $name ) {
|
||||
$this->newline( '<media:title type="plain">' . esc_html( $name ) . '</media:title>', 3 );
|
||||
}
|
||||
|
||||
if ( $description ) {
|
||||
$this->newline( '<media:description type="html"><![CDATA[' . wp_kses_post( $description ) . ']]></media:description>', 3 );
|
||||
}
|
||||
|
||||
if ( $thumbnail ) {
|
||||
$this->newline( '<media:thumbnail url="' . esc_url( $thumbnail ) . '" />', 3 );
|
||||
}
|
||||
|
||||
if ( $tags ) {
|
||||
$this->newline( '<media:keywords>' . esc_html( $tags ) . '</media:keywords>', 3 );
|
||||
}
|
||||
|
||||
if ( $categories ) {
|
||||
$this->newline( '<media:category>' . esc_html( $categories ) . '</media:category>', 3 );
|
||||
}
|
||||
|
||||
if ( $rating ) {
|
||||
$this->newline( '<media:rating scheme="urn:simple">' . esc_html( $rating ) . '</media:rating>', 3 );
|
||||
}
|
||||
$this->newline( '</media:content>', 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a newline with indent count.
|
||||
*
|
||||
* @param string $content Content to write.
|
||||
* @param integer $indent Count of indent.
|
||||
*/
|
||||
private function newline( $content, $indent = 0 ) {
|
||||
echo str_repeat( "\t", $indent ) . $content . "\n";
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* The Schema Parser
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use WP_Error;
|
||||
use DOMXpath;
|
||||
use DOMDocument;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Parser class.
|
||||
*/
|
||||
class Parser {
|
||||
|
||||
/**
|
||||
* Get json from url.
|
||||
*
|
||||
* @param string $url Url to fetch html from.
|
||||
*/
|
||||
public function from_url( $url ) {
|
||||
$response = wp_remote_get(
|
||||
$url,
|
||||
[
|
||||
'timeout' => 30,
|
||||
'sslverify' => false,
|
||||
]
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response = wp_remote_retrieve_body( $response );
|
||||
if ( empty( $response ) ) {
|
||||
return new WP_Error( 'body_not_found', esc_html__( 'No html body found.', 'rank-math-pro' ) );
|
||||
}
|
||||
|
||||
return $this->from_html( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get json from html.
|
||||
*
|
||||
* @param string $html HTML to parse.
|
||||
*/
|
||||
public function from_html( $html ) {
|
||||
libxml_use_internal_errors( 1 );
|
||||
|
||||
// DOM.
|
||||
$dom = new DOMDocument();
|
||||
$dom->loadHTML( $html );
|
||||
|
||||
// XPath.
|
||||
$xpath = new DOMXpath( $dom );
|
||||
$scripts = $xpath->query( '//script[@type="application/ld+json"]' );
|
||||
|
||||
$json = [];
|
||||
foreach ( $scripts as $script ) {
|
||||
$json[] = json_decode( trim( $script->nodeValue ) ); // phpcs:ignore
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* The Schema Template Post Type
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Post_Type class.
|
||||
*/
|
||||
class Post_Type {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'init', 'register' );
|
||||
$this->action( 'admin_menu', 'add_menu', 11 );
|
||||
$this->action( 'parent_file', 'parent_file' );
|
||||
$this->action( 'submenu_file', 'submenu_file' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register template post type.
|
||||
*/
|
||||
public function register() {
|
||||
$labels = [
|
||||
'name' => _x( 'Schemas', 'Post Type General Name', 'rank-math-pro' ),
|
||||
'singular_name' => _x( 'Schema', 'Post Type Singular Name', 'rank-math-pro' ),
|
||||
'menu_name' => __( 'Schemas', 'rank-math-pro' ),
|
||||
'name_admin_bar' => __( 'Schema', 'rank-math-pro' ),
|
||||
'all_items' => __( 'All Schemas', 'rank-math-pro' ),
|
||||
'add_new_item' => __( 'Add New Schema', 'rank-math-pro' ),
|
||||
'new_item' => __( 'New Schema', 'rank-math-pro' ),
|
||||
'edit_item' => __( 'Edit Schema', 'rank-math-pro' ),
|
||||
'update_item' => __( 'Update Schema', 'rank-math-pro' ),
|
||||
'view_item' => __( 'View Schema', 'rank-math-pro' ),
|
||||
'view_items' => __( 'View Schemas', 'rank-math-pro' ),
|
||||
'search_items' => __( 'Search schemas', 'rank-math-pro' ),
|
||||
];
|
||||
|
||||
$capability = 'rank_math_onpage_snippet';
|
||||
$args = [
|
||||
'label' => __( 'Schema', 'rank-math-pro' ),
|
||||
'description' => __( 'Rank Math Schema Templates', 'rank-math-pro' ),
|
||||
'labels' => $labels,
|
||||
'supports' => [ 'title' ],
|
||||
'hierarchical' => false,
|
||||
'public' => false,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'menu_position' => 5,
|
||||
'show_in_admin_bar' => false,
|
||||
'show_in_nav_menus' => false,
|
||||
'can_export' => true,
|
||||
'has_archive' => false,
|
||||
'exclude_from_search' => true,
|
||||
'publicly_queryable' => false,
|
||||
'rewrite' => false,
|
||||
'capability_type' => 'page',
|
||||
'capabilities' => [
|
||||
'edit_post' => $capability,
|
||||
'read_post' => $capability,
|
||||
'delete_post' => $capability,
|
||||
'edit_posts' => $capability,
|
||||
'edit_others_posts' => $capability,
|
||||
'publish_posts' => $capability,
|
||||
'read_private_posts' => $capability,
|
||||
'create_posts' => $capability,
|
||||
],
|
||||
'show_in_rest' => true,
|
||||
];
|
||||
|
||||
register_post_type( 'rank_math_schema', $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add post type as submenu.
|
||||
*/
|
||||
public function add_menu() {
|
||||
if ( ! Helper::has_cap( 'onpage_snippet' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_submenu_page(
|
||||
'rank-math',
|
||||
esc_html__( 'Schema Templates', 'rank-math-pro' ),
|
||||
esc_html__( 'Schema Templates', 'rank-math-pro' ),
|
||||
'edit_posts',
|
||||
'edit.php?post_type=rank_math_schema'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix parent active menu
|
||||
*
|
||||
* @param string $file Filename.
|
||||
* @return string
|
||||
*/
|
||||
public function parent_file( $file ) {
|
||||
$screen = get_current_screen();
|
||||
|
||||
if ( in_array( $screen->base, [ 'post', 'edit' ], true ) && 'rank_math_schema' === $screen->post_type ) {
|
||||
$file = 'rank-math';
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix submenu active menu
|
||||
*
|
||||
* @param string $file Filename.
|
||||
* @return string
|
||||
*/
|
||||
public function submenu_file( $file ) {
|
||||
$screen = get_current_screen();
|
||||
|
||||
if ( in_array( $screen->base, [ 'post', 'edit' ], true ) && 'rank_math_schema' === $screen->post_type ) {
|
||||
$file = 'edit.php?post_type=rank_math_schema';
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
}
|
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* The REST API.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Server;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Controller;
|
||||
use RankMath\Helper;
|
||||
use RankMath\Schema\DB;
|
||||
use RankMath\Traits\Meta;
|
||||
use RankMath\Rest\Sanitize;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rest class.
|
||||
*/
|
||||
class Rest extends WP_REST_Controller {
|
||||
|
||||
use Meta;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->namespace = \RankMath\Rest\Rest_Helper::BASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the routes for the objects of the controller.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/saveTemplate',
|
||||
[
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => [ $this, 'save_template' ],
|
||||
'args' => [
|
||||
'schema' => [
|
||||
'required' => true,
|
||||
'description' => esc_html__( 'Schema to add.', 'rank-math-pro' ),
|
||||
'validate_callback' => [ '\\RankMath\\Rest\\Rest_Helper', 'is_param_empty' ],
|
||||
],
|
||||
],
|
||||
'permission_callback' => [ $this, 'get_permissions_check' ],
|
||||
]
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/getVideoData',
|
||||
[
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => [ $this, 'get_video_data' ],
|
||||
'args' => $this->get_video_args(),
|
||||
'permission_callback' => [ '\\RankMath\\Rest\\Rest_Helper', 'can_manage_options' ],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Video details.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return bool Whether the API key matches or not.
|
||||
*/
|
||||
public function get_video_data( WP_REST_Request $request ) {
|
||||
$object_id = $request->get_param( 'objectID' );
|
||||
$url = $request->get_param( 'url' );
|
||||
$post_type = get_post_type( $object_id );
|
||||
if ( false === filter_var( $url, FILTER_VALIDATE_URL ) || ! Helper::get_settings( "titles.pt_{$post_type}_autodetect_video", 'on' ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
global $wp_embed;
|
||||
return ( new \RankMathPro\Schema\Video\Parser( get_post( $object_id ) ) )->get_metadata( $wp_embed->autoembed( $url ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update metadata.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function save_template( WP_REST_Request $request ) {
|
||||
$sanitizer = Sanitize::get();
|
||||
$schema = $request->get_param( 'schema' );
|
||||
$post_id = $request->get_param( 'postId' );
|
||||
|
||||
foreach ( $schema as $id => $value ) {
|
||||
$schema[ $id ] = $sanitizer->sanitize( $id, $value );
|
||||
}
|
||||
|
||||
if ( $post_id ) {
|
||||
DB::delete_schema_data( $post_id );
|
||||
}
|
||||
|
||||
$meta_key = 'rank_math_schema_' . $schema['@type'];
|
||||
$template_id = wp_insert_post(
|
||||
[
|
||||
'ID' => $post_id,
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'rank_math_schema',
|
||||
'post_title' => $schema['metadata']['title'],
|
||||
]
|
||||
);
|
||||
|
||||
update_post_meta( $template_id, $meta_key, $schema );
|
||||
return [
|
||||
'id' => $template_id,
|
||||
'link' => get_edit_post_link( $template_id ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given request has permission to read post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return true|WP_Error True if the request has read access, WP_Error object otherwise.
|
||||
*/
|
||||
public static function get_permissions_check( $request ) { // phpcs:ignore
|
||||
if ( current_user_can( 'edit_posts' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return new WP_Error(
|
||||
'rest_cannot_edit',
|
||||
__( 'Sorry, you are not allowed to save template.', 'rank-math-pro' ),
|
||||
[ 'status' => rest_authorization_required_code() ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get video arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_video_args() {
|
||||
return [
|
||||
'objectID' => [
|
||||
'type' => 'integer',
|
||||
'required' => true,
|
||||
'description' => esc_html__( 'Object unique id', 'rank-math-pro' ),
|
||||
'validate_callback' => [ '\\RankMath\\Rest\\Rest_Helper', 'is_param_empty' ],
|
||||
],
|
||||
'url' => [
|
||||
'required' => true,
|
||||
'description' => esc_html__( 'Video URL.', 'rank-math-pro' ),
|
||||
'validate_callback' => [ '\\RankMath\\Rest\\Rest_Helper', 'is_param_empty' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* The Schema Module
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Schema class.
|
||||
*/
|
||||
class Schema {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->includes();
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Include required files.
|
||||
*/
|
||||
public function includes() {
|
||||
new Admin();
|
||||
new Ajax();
|
||||
new Post_Type();
|
||||
new \RankMath\Schema\Schema();
|
||||
new Frontend();
|
||||
new Video();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function hooks() {
|
||||
$this->action( 'enqueue_block_editor_assets', 'editor_assets', 9 );
|
||||
$this->filter( 'rank_math/schema/block/howto-block', 'add_graph', 11, 2 );
|
||||
$this->filter( 'rank_math/schema/block/howto/content', 'block_content', 11, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Styles and Scripts required for blocks at backend.
|
||||
*/
|
||||
public function editor_assets() {
|
||||
wp_enqueue_script(
|
||||
'rank-math-howto-block',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/js/blocks.js',
|
||||
[],
|
||||
rank_math_pro()->version,
|
||||
true
|
||||
);
|
||||
|
||||
if ( Helper::is_module_active( 'local-seo' ) ) {
|
||||
Helper::add_json( 'previewImage', RANK_MATH_PRO_URL . 'includes/modules/local-seo/assets/img/map-placeholder.jpg' );
|
||||
Helper::add_json( 'mapStyle', Helper::get_settings( 'titles.map_style', 'roadmap' ) );
|
||||
Helper::add_json( 'limitLocations', Helper::get_settings( 'titles.limit_results', 10 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display additional content in the HowTo Block.
|
||||
*
|
||||
* @param string $output Schema data.
|
||||
* @param array $data Output data.
|
||||
* @param array $attributes Schema attributes.
|
||||
*/
|
||||
public function block_content( $output, $data, $attributes ) {
|
||||
$data[] = $this->build_estimated_cost( $attributes );
|
||||
$data[] = $this->build_supplies( $attributes );
|
||||
$data[] = $this->build_tools( $attributes );
|
||||
$data[] = $this->build_materials( $attributes );
|
||||
return join( "\n", $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* FAQ rich snippet.
|
||||
*
|
||||
* @param array $data Array of JSON-LD data.
|
||||
* @param array $block JsonLD Instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_graph( $data, $block ) {
|
||||
$attrs = $block['attrs'];
|
||||
|
||||
$this->add_estimated_cost( $data['howto'], $attrs );
|
||||
$this->add_supplies( $data['howto'], $attrs );
|
||||
$this->add_tools( $data['howto'], $attrs );
|
||||
$this->add_materials( $data['howto'], $attrs );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* [build_estimated_cost description]
|
||||
*
|
||||
* @param [type] $attrs [description].
|
||||
*
|
||||
* @return [type] [description]
|
||||
*/
|
||||
private function build_estimated_cost( $attrs ) {
|
||||
if ( empty( $attrs['estimatedCost'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currency = ! empty( $attrs['estimatedCostCurrency'] ) ? $attrs['estimatedCostCurrency'] : 'USD';
|
||||
|
||||
return sprintf(
|
||||
'<p class="rank-math-howto-estimatedCost"><strong>%2$s</strong> <span>%1$s</span></p>',
|
||||
$attrs['estimatedCost'] . ' ' . $currency,
|
||||
__( 'Estimated Cost:', 'rank-math-pro' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* [build_estimated_cost description]
|
||||
*
|
||||
* @param [type] $attrs [description].
|
||||
*
|
||||
* @return [type] [description]
|
||||
*/
|
||||
private function build_supplies( $attrs ) {
|
||||
if ( empty( $attrs['supply'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$supplies = Str::to_arr_no_empty( $attrs['supply'] );
|
||||
if ( empty( $supplies ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<p class="rank-math-howto-supply"><strong>%2$s</strong> <ul><li>%1$s</li></ul></p>',
|
||||
implode( '</li><li>', $supplies ),
|
||||
__( 'Supply:', 'rank-math-pro' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* [build_estimated_cost description]
|
||||
*
|
||||
* @param [type] $attrs [description].
|
||||
*
|
||||
* @return [type] [description]
|
||||
*/
|
||||
private function build_tools( $attrs ) {
|
||||
if ( empty( $attrs['tools'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tools = Str::to_arr_no_empty( $attrs['tools'] );
|
||||
if ( empty( $tools ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<p class="rank-math-howto-tools"><strong>%2$s</strong> <ul><li>%1$s</li></ul></p>',
|
||||
implode( '</li><li>', $tools ),
|
||||
__( 'Tools:', 'rank-math-pro' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* [build_estimated_cost description]
|
||||
*
|
||||
* @param [type] $attrs [description].
|
||||
*
|
||||
* @return [type] [description]
|
||||
*/
|
||||
private function build_materials( $attrs ) {
|
||||
if ( empty( $attrs['material'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tools = Str::to_arr_no_empty( $attrs['tools'] );
|
||||
if ( empty( $tools ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<p class="rank-math-howto-tools"><strong>%2$s</strong> <span>%1$s</span></p>',
|
||||
$attrs['material'],
|
||||
__( 'Materials:', 'rank-math-pro' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Duration.
|
||||
*
|
||||
* @param [type] $data [description].
|
||||
* @param [type] $attrs [description].
|
||||
*/
|
||||
private function add_estimated_cost( &$data, $attrs ) {
|
||||
if ( empty( $attrs['estimatedCost'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data['estimatedCost'] = [
|
||||
'@type' => 'MonetaryAmount',
|
||||
'currency' => ! empty( $attrs['estimatedCostCurrency'] ) ? $attrs['estimatedCostCurrency'] : 'USD',
|
||||
'value' => $attrs['estimatedCost'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Duration.
|
||||
*
|
||||
* @param [type] $data [description].
|
||||
* @param [type] $attrs [description].
|
||||
*/
|
||||
private function add_supplies( &$data, $attrs ) {
|
||||
if ( empty( $attrs['supply'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$supplies = Str::to_arr_no_empty( $attrs['supply'] );
|
||||
if ( empty( $supplies ) ) {
|
||||
return;
|
||||
}
|
||||
$supply = [];
|
||||
|
||||
foreach ( $supplies as $value ) {
|
||||
$supply[] = [
|
||||
'@type' => 'HowToSupply',
|
||||
'name' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
$data['supply'] = $supply;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Duration.
|
||||
*
|
||||
* @param [type] $data [description].
|
||||
* @param [type] $attrs [description].
|
||||
*/
|
||||
private function add_tools( &$data, $attrs ) {
|
||||
if ( empty( $attrs['tools'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tools = Str::to_arr_no_empty( $attrs['tools'] );
|
||||
|
||||
if ( empty( $tools ) ) {
|
||||
return;
|
||||
}
|
||||
$tool = [];
|
||||
|
||||
foreach ( $tools as $value ) {
|
||||
$tool[] = [
|
||||
'@type' => 'HowToTool',
|
||||
'name' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
$data['tool'] = $tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Duration.
|
||||
*
|
||||
* @param [type] $data [description].
|
||||
* @param [type] $attrs [description].
|
||||
*/
|
||||
private function add_materials( &$data, $attrs ) {
|
||||
if ( empty( $attrs['material'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data['material'] = $attrs['material'];
|
||||
}
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/**
|
||||
* Outputs specific schema code from Schema Template
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Schema\Snippet_Shortcode;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Schema Frontend class.
|
||||
*/
|
||||
class Snippet_Pro_Shortcode extends Snippet_Shortcode {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->filter( 'rank_math/snippet/html', 'add_shortcode_view', 10, 4 );
|
||||
$this->filter( 'rank_math/snippet/after_schema_content', 'show_review_notes' );
|
||||
$this->filter( 'shortcode_atts_rank_math_rich_snippet', 'register_fields_attribute', 10, 4 );
|
||||
$this->filter( 'rank_math/schema/shortcode/filter_attributes', 'filter_attributes', 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter schema fields.
|
||||
*
|
||||
* @param array $schema Schema data.
|
||||
* @param array $atts The user defined shortcode attributes.
|
||||
*
|
||||
* @return array Filtered Schema fields.
|
||||
*/
|
||||
public function filter_attributes( $schema, $atts ) {
|
||||
if ( empty( $atts['fields'] ) ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
$fields = explode( ',', $atts['fields'] );
|
||||
$fields[] = '@type';
|
||||
|
||||
return array_intersect_key( $schema, array_flip( $fields ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters shortcode attributes.
|
||||
*
|
||||
* If the third parameter of the shortcode_atts() function is present then this filter is available.
|
||||
*
|
||||
* @param array $out The output array of shortcode attributes.
|
||||
* @param array $pairs The supported attributes and their defaults.
|
||||
* @param array $atts The user defined shortcode attributes.
|
||||
* @param string $shortcode The shortcode name.
|
||||
*/
|
||||
public function register_fields_attribute( $out, $pairs, $atts, $shortcode ) { // phpcs:ignore
|
||||
return wp_parse_args( $atts, $out );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to change the rank_math_rich_snippet shortcode content.
|
||||
*
|
||||
* @param string $html Shortcode content.
|
||||
* @param string $schema Current Schema data.
|
||||
* @param string $post Current Post Object.
|
||||
* @param string $shortcode Shortcode class instance.
|
||||
*
|
||||
* @return string Shortcode Content.
|
||||
*/
|
||||
public function add_shortcode_view( $html, $schema, $post, $shortcode ) { // phpcs:ignore
|
||||
wp_enqueue_style( 'rank-math-review-pro-snippet', RANK_MATH_PRO_URL . 'includes/modules/schema/assets/css/rank-math-snippet.css', null, rank_math_pro()->version );
|
||||
|
||||
$type = \strtolower( $schema['@type'] );
|
||||
if ( ! in_array( $type, [ 'dataset', 'movie', 'claimreview', 'faqpage', 'howto', 'jobposting', 'product', 'recipe', 'podcastepisode' ], true ) ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
echo '<div id="rank-math-rich-snippet-wrapper">';
|
||||
include "shortcode/$type.php";
|
||||
$this->show_review_notes( $shortcode );
|
||||
echo '</div>';
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display Pros & Cons.
|
||||
*
|
||||
* @since 3.0.18
|
||||
*/
|
||||
public function show_review_notes( $shortcode ) {
|
||||
$labels = [
|
||||
'pros' => __( 'Pros', 'rank-math-pro' ),
|
||||
'cons' => __( 'Cons', 'rank-math-pro' ),
|
||||
];
|
||||
|
||||
/**
|
||||
* Filter: Allow changing the Pros & Cons labels.
|
||||
*
|
||||
* @param array $labels {
|
||||
* @type string $pros Pros label.
|
||||
* @type string $cons Cons label.
|
||||
* }
|
||||
*/
|
||||
$labels = $this->do_filter( 'schema/review_notes_labels', $labels );
|
||||
|
||||
$positive_notes = ! empty( $shortcode->get_field_value( 'positiveNotes' ) ) ? $shortcode->get_field_value( 'positiveNotes' ) : $shortcode->get_field_value( 'review.positiveNotes' );
|
||||
if ( ! empty( $positive_notes['itemListElement'] ) ) {
|
||||
?>
|
||||
<div class="rank-math-review-notes rank-math-review-pros">
|
||||
<h4><?php echo esc_html( $labels['pros'] ); ?></h4>
|
||||
<ul>
|
||||
<?php foreach ( $positive_notes['itemListElement'] as $positive_note ) { ?>
|
||||
<li><?php echo esc_html( $positive_note['name'] ); ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
$negative_notes = ! empty( $shortcode->get_field_value( 'negativeNotes' ) ) ? $shortcode->get_field_value( 'negativeNotes' ) : $shortcode->get_field_value( 'review.negativeNotes' );
|
||||
if ( ! empty( $negative_notes['itemListElement'] ) ) {
|
||||
?>
|
||||
<div class="rank-math-review-notes rank-math-review-cons">
|
||||
<h4><?php echo esc_html( $labels['cons'] ); ?></h4>
|
||||
<ul>
|
||||
<?php foreach ( $negative_notes['itemListElement'] as $negative_note ) { ?>
|
||||
<li><?php echo esc_html( $negative_note['name'] ); ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
/**
|
||||
* The Schema Module
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use RankMath\Schema\DB;
|
||||
use RankMath\Rest\Sanitize;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Arr;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Taxonomy class.
|
||||
*/
|
||||
class Taxonomy extends Admin {
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'init', 'init', 9999 );
|
||||
$this->action( 'rank_math/json_ld', 'add_schema', 11, 2 );
|
||||
|
||||
if (
|
||||
! Helper::has_cap( 'onpage_snippet' ) ||
|
||||
! Admin_Helper::is_term_edit() ||
|
||||
! $this->can_add( Param::request( 'taxonomy' ) )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->action( 'rank_math/admin/editor_scripts', 'enqueue' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add schema-preview rewrite rule for taxonomies.
|
||||
*/
|
||||
public function init() {
|
||||
$taxonomies = Helper::get_accessible_taxonomies();
|
||||
foreach ( $taxonomies as $slug => $taxonomy ) {
|
||||
if ( empty( $taxonomy->rewrite['slug'] ) || ! $this->can_add( $slug ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
add_rewrite_rule(
|
||||
$taxonomy->rewrite['slug'] . '/(.+?)/schema-preview/?$',
|
||||
'index.php?' . $slug . '=$matches[1]&schema-preview=$matches[3]',
|
||||
'top'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Styles and Scripts required for metabox.
|
||||
*/
|
||||
public function enqueue() {
|
||||
global $pagenow;
|
||||
$cmb = cmb2_get_metabox( 'rank_math_metabox' );
|
||||
if ( false === $cmb || 'edit-tags.php' === $pagenow ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$schemas = $this->get_schema_data( $cmb->object_id() );
|
||||
Helper::add_json( 'schemas', $schemas );
|
||||
Helper::add_json( 'customSchemaImage', esc_url( rank_math()->plugin_url() . 'includes/modules/schema/assets/img/custom-schema-builder.jpg' ) );
|
||||
Helper::add_json( 'postLink', get_term_link( (int) $cmb->object_id() ) );
|
||||
Helper::add_json( 'activeTemplates', $this->get_active_templates() );
|
||||
wp_enqueue_style( 'rank-math-schema', rank_math()->plugin_url() . 'includes/modules/schema/assets/css/schema.css', [ 'wp-components', 'rank-math-editor' ], rank_math()->version );
|
||||
wp_enqueue_script( 'rank-math-schema', rank_math()->plugin_url() . 'includes/modules/schema/assets/js/schema-gutenberg.js', [ 'rank-math-editor', 'clipboard' ], rank_math()->version, true );
|
||||
|
||||
wp_enqueue_style( 'rank-math-schema-pro', RANK_MATH_PRO_URL . 'includes/modules/schema/assets/css/schema.css', null, rank_math_pro()->version );
|
||||
wp_enqueue_script(
|
||||
'rank-math-pro-schema-filters',
|
||||
RANK_MATH_PRO_URL . 'includes/modules/schema/assets/js/schemaFilters.js',
|
||||
[
|
||||
'wp-plugins',
|
||||
'wp-components',
|
||||
'wp-hooks',
|
||||
'wp-api-fetch',
|
||||
'lodash',
|
||||
],
|
||||
rank_math_pro()->version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script( 'rank-math-schema-pro', RANK_MATH_PRO_URL . 'includes/modules/schema/assets/js/schema.js', [ 'rank-math-editor' ], rank_math_pro()->version, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Default Schema Data.
|
||||
*
|
||||
* @param array $data Array of json-ld data.
|
||||
* @param JsonLD $jsonld Instance of jsonld.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_schema( $data, $jsonld ) {
|
||||
if ( ! is_category() && ! is_tag() && ! is_tax() ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$queried_object = get_queried_object();
|
||||
if (
|
||||
empty( $queried_object ) ||
|
||||
is_wp_error( $queried_object ) ||
|
||||
! $this->can_add( $queried_object->taxonomy )
|
||||
) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$schemas = DB::get_schemas( $queried_object->term_id, 'termmeta' );
|
||||
if ( empty( $schemas ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ( isset( $data['ItemList'] ) ) {
|
||||
unset( $data['ItemList'] );
|
||||
}
|
||||
|
||||
if ( isset( $data['ProductsPage'] ) ) {
|
||||
unset( $data['ProductsPage'] );
|
||||
}
|
||||
|
||||
if ( isset( $data['WebPage'] ) ) {
|
||||
$data['WebPage']['@type'] = [
|
||||
'WebPage',
|
||||
'CollectionPage',
|
||||
];
|
||||
}
|
||||
|
||||
$schemas = $jsonld->replace_variables( $schemas );
|
||||
$schemas = $jsonld->filter( $schemas, $jsonld, $data );
|
||||
|
||||
return array_merge( $data, $schemas );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Schema Data.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
*
|
||||
* @return array $schemas Schema Data.
|
||||
*/
|
||||
private function get_schema_data( $term_id ) {
|
||||
$schemas = DB::get_schemas( $term_id, 'termmeta' );
|
||||
if ( ! empty( $schemas ) || metadata_exists( 'term', $term_id, 'rank_math_rich_snippet' ) ) {
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add active templates to the schemas json
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_active_templates() {
|
||||
$templates = $this->get_schema_templates();
|
||||
if ( empty( $templates ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$screen = get_current_screen();
|
||||
$schemas = [];
|
||||
foreach ( $templates as $template ) {
|
||||
if ( empty( $template['schema']['metadata']['displayConditions'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$conditions = $template['schema']['metadata']['displayConditions'];
|
||||
$can_add = false;
|
||||
$data = [];
|
||||
|
||||
foreach ( $conditions as $condition ) {
|
||||
$category = $condition['category'];
|
||||
if ( 'archive' !== $category ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$operator = $condition['condition'];
|
||||
if ( ! empty( $data[ $category ] ) && 'exclude' !== $operator ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = $condition['type'];
|
||||
$value = $condition['value'];
|
||||
|
||||
if ( 'general' === $category ) {
|
||||
$data[ $category ] = 'include' === $operator;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $value && absint( Param::get( 'tag_ID' ) ) === $value ) {
|
||||
$data[ $category ] = 'include' === $operator;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( 'all' === $type ) {
|
||||
$data[ $category ] = 'include' === $operator;
|
||||
} elseif ( $type !== $screen->taxonomy ) {
|
||||
$data[ $category ] = false;
|
||||
} elseif ( ! $value ) {
|
||||
$data[ $category ] = 'include' === $operator;
|
||||
} elseif ( Param::get( 'tag_ID' ) !== $value ) {
|
||||
$data[ $category ] = isset( $data[ $category ] ) ? $data[ $category ] : false;
|
||||
} else {
|
||||
$data[ $category ] = 'include' === $operator;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $data['archive'] ) ) {
|
||||
$can_add = $data['archive'];
|
||||
} else {
|
||||
$can_add = ! empty( $data['general'] );
|
||||
}
|
||||
|
||||
if ( $can_add ) {
|
||||
$template['schema']['isTemplate'] = true;
|
||||
$schemas[ $template['id'] ] = $template['schema'];
|
||||
}
|
||||
}
|
||||
|
||||
return $schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can add Schema data on current taxonomy
|
||||
*
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_add( $taxonomy ) {
|
||||
return Helper::get_settings( 'titles.tax_' . $taxonomy . '_add_meta_box' ) &&
|
||||
true !== apply_filters(
|
||||
'rank_math/snippet/remove_taxonomy_data',
|
||||
Helper::get_settings( 'titles.remove_' . $taxonomy . '_snippet_data' ),
|
||||
$taxonomy
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
/**
|
||||
* The Video Schema generator.
|
||||
*
|
||||
* @since 2.0.9
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Schema
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Video_Schema_Generator class.
|
||||
*/
|
||||
class Video_Schema_Generator extends \WP_Background_Process {
|
||||
/**
|
||||
* Prefix.
|
||||
*
|
||||
* (default value: 'wp')
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $prefix = 'rank_math';
|
||||
|
||||
/**
|
||||
* Action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'add_video_schema';
|
||||
|
||||
/**
|
||||
* Main instance
|
||||
*
|
||||
* Ensure only one instance is loaded or can be loaded.
|
||||
*
|
||||
* @return Video_Schema_Generator
|
||||
*/
|
||||
public static function get() {
|
||||
static $instance;
|
||||
|
||||
if ( is_null( $instance ) && ! ( $instance instanceof Video_Schema_Generator ) ) {
|
||||
$instance = new Video_Schema_Generator();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start creating batches.
|
||||
*
|
||||
* @param [type] $posts [description].
|
||||
*/
|
||||
public function start( $posts ) {
|
||||
$chunks = array_chunk( $posts, 10 );
|
||||
foreach ( $chunks as $chunk ) {
|
||||
$this->push_to_queue( $chunk );
|
||||
}
|
||||
|
||||
$this->save()->dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete.
|
||||
*
|
||||
* Override if applicable, but ensure that the below actions are
|
||||
* performed, or, call parent::complete().
|
||||
*/
|
||||
protected function complete() {
|
||||
delete_option( 'rank_math_video_posts' );
|
||||
Helper::add_notification(
|
||||
esc_html__( 'Rank Math: Added Video Schema to posts successfully.', 'rank-math-pro' ),
|
||||
[
|
||||
'type' => 'success',
|
||||
'id' => 'rank_math_video_posts',
|
||||
'classes' => 'rank-math-notice',
|
||||
]
|
||||
);
|
||||
|
||||
parent::complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task to perform
|
||||
*
|
||||
* @param array $posts Posts to process.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function task( $posts ) {
|
||||
try {
|
||||
foreach ( $posts as $post ) {
|
||||
$this->convert( $post );
|
||||
}
|
||||
return false;
|
||||
} catch ( Exception $error ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert post.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*/
|
||||
public function convert( $post_id ) {
|
||||
update_post_meta( $post_id, '_rank_math_video', 'true' );
|
||||
( new Video\Parser( get_post( $post_id ) ) )->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find posts.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function find_posts() {
|
||||
global $wpdb;
|
||||
$posts = get_option( 'rank_math_video_posts' );
|
||||
if ( false !== $posts ) {
|
||||
return $posts;
|
||||
}
|
||||
|
||||
// Schema Posts.
|
||||
$post_types = array_filter(
|
||||
Helper::get_accessible_post_types(),
|
||||
function( $post_type ) {
|
||||
return 'attachment' !== $post_type && Helper::get_settings( "titles.pt_{$post_type}_autodetect_video", 'on' );
|
||||
}
|
||||
);
|
||||
|
||||
$posts = get_posts(
|
||||
[
|
||||
'post_type' => array_keys( $post_types ),
|
||||
'numberposts' => -1,
|
||||
'fields' => 'ids',
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => 'rank_math_schema_VideoObject',
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
update_option( 'rank_math_video_posts', $posts, false );
|
||||
|
||||
return $posts;
|
||||
}
|
||||
}
|
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
/**
|
||||
* The Video Schema.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Conditional;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Video class.
|
||||
*/
|
||||
class Video {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
Video_Schema_Generator::get();
|
||||
|
||||
if ( Conditional::is_rest() ) {
|
||||
$this->filter( 'rank_math/tools/generate_video_schema', 'generate_video_schema' );
|
||||
}
|
||||
|
||||
$this->action( 'rank_math/pre_update_metadata', 'detect_video_in_content', 10, 3 );
|
||||
if ( is_admin() ) {
|
||||
$this->action( 'cmb2_admin_init', 'add_video_settings' );
|
||||
$this->action( 'rank_math/admin/settings/others', 'add_media_rss_field' );
|
||||
$this->filter( 'rank_math/database/tools', 'generate_video_schema_tool' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->action( 'rank_math/opengraph/facebook', 'add_video_tags', 99 );
|
||||
new Media_RSS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add auto-detect Video fields in Titles & Meta settings.
|
||||
*/
|
||||
public function add_video_settings() {
|
||||
foreach ( Helper::get_accessible_post_types() as $post_type ) {
|
||||
$this->action( "rank_math/admin/settings/post-type-{$post_type}", 'add_video_schema_fields', 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add auto-generate video schema settings.
|
||||
*
|
||||
* @param object $cmb CMB2 instance.
|
||||
* @param array $tab Current settings tab.
|
||||
*/
|
||||
public function add_video_schema_fields( $cmb, $tab ) {
|
||||
if ( 'attachment' === $tab['post_type'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field_ids = wp_list_pluck( $cmb->prop( 'fields' ), 'id' );
|
||||
$field_position = array_search( "pt_{$tab['post_type']}_default_article_type", array_keys( $field_ids ), true ) + 1;
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => 'pt_' . $tab['post_type'] . '_autodetect_video',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Autodetect Video', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Populate automatic Video Schema by auto-detecting any video in the content.', 'rank-math-pro' ),
|
||||
'options' => [
|
||||
'off' => esc_html__( 'Default', 'rank-math-pro' ),
|
||||
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
|
||||
],
|
||||
'default' => 'on',
|
||||
],
|
||||
++$field_position
|
||||
);
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => 'pt_' . $tab['post_type'] . '_autogenerate_image',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Autogenerate Image', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Auto-generate image for the auto detected video.', 'rank-math-pro' ),
|
||||
'options' => [
|
||||
'off' => esc_html__( 'Default', 'rank-math-pro' ),
|
||||
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
|
||||
],
|
||||
'default' => 'off',
|
||||
'dep' => [ [ 'pt_' . $tab['post_type'] . '_autodetect_video', 'on' ] ],
|
||||
],
|
||||
++$field_position
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new settings.
|
||||
*
|
||||
* @param object $cmb CMB2 instance.
|
||||
*/
|
||||
public function add_media_rss_field( $cmb ) {
|
||||
$field_ids = wp_list_pluck( $cmb->prop( 'fields' ), 'id' );
|
||||
$field_position = array_search( 'rss_after_content', array_keys( $field_ids ), true ) + 1;
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => 'disable_media_rss',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Remove Media Data from RSS feed', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Remove Media Data from RSS feed', 'rank-math-pro' ),
|
||||
'options' => [
|
||||
'off' => esc_html__( 'Default', 'rank-math-pro' ),
|
||||
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
|
||||
],
|
||||
'default' => 'off',
|
||||
],
|
||||
++$field_position
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the video tags.
|
||||
*
|
||||
* @link https://yandex.com/support/video/partners/open-graph.html#player
|
||||
*
|
||||
* @param OpenGraph $opengraph The current opengraph network object.
|
||||
*/
|
||||
public function add_video_tags( $opengraph ) {
|
||||
if ( ! is_singular() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $post;
|
||||
$video_data = get_post_meta( $post->ID, 'rank_math_schema_VideoObject', true );
|
||||
if ( empty( $video_data ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tags = [
|
||||
'ya:ovs:adult' => ! empty( $video_data['isFamilyFriendly'] ) ? false : true,
|
||||
'ya:ovs:upload_date' => ! empty( $video_data['uploadDate'] ) ? Helper::replace_vars( $video_data['uploadDate'], $post ) : '',
|
||||
'ya:ovs:allow_embed' => ! empty( $video_data['embedUrl'] ) ? 'true' : 'false',
|
||||
];
|
||||
|
||||
foreach ( $tags as $tag => $value ) {
|
||||
$opengraph->tag( $tag, $value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically add Video Schema when post is updated.
|
||||
*
|
||||
* @param int $object_id Object ID.
|
||||
* @param int $object_type Object type.
|
||||
* @param string $content Updated post content.
|
||||
*/
|
||||
public function detect_video_in_content( $object_id, $object_type, $content = '' ) {
|
||||
if ( 'post' !== $object_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post = get_post( $object_id );
|
||||
if ( $content ) {
|
||||
$post->post_content = $content;
|
||||
}
|
||||
|
||||
( new Video\Parser( $post ) )->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add database tools.
|
||||
*
|
||||
* @param array $tools Array of tools.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function generate_video_schema_tool( $tools ) {
|
||||
$posts = Video_Schema_Generator::get()->find_posts();
|
||||
if ( empty( $posts ) ) {
|
||||
return $tools;
|
||||
}
|
||||
|
||||
$generate_video_schema = [
|
||||
'generate_video_schema' => [
|
||||
'title' => esc_html__( 'Generate Video Schema for Old Posts/Pages', 'rank-math-pro' ),
|
||||
'description' => esc_html__( 'Add Video schema to posts which have YouTube or Vimeo Video in the content. Applies to only those Posts/Pages/CPTs in which Autodetect Video Option is On.', 'rank-math-pro' ),
|
||||
'confirm_text' => esc_html__( 'Are you sure you want to add Video Schema to the posts/pages with the video in the content? This action is irreversible.', 'rank-math-pro' ),
|
||||
'button_text' => esc_html__( 'Generate', 'rank-math-pro' ),
|
||||
],
|
||||
];
|
||||
|
||||
$index = array_search( 'recreate_tables', array_keys( $tools ), true );
|
||||
$pos = false === $index ? count( $tools ) : $index + 1;
|
||||
$tools = array_slice( $tools, 0, $pos, true ) + $generate_video_schema + array_slice( $tools, $pos, count( $tools ) - 1, true );
|
||||
|
||||
return $tools;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect Video in the content and add schema.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate_video_schema() {
|
||||
$posts = Video_Schema_Generator::get()->find_posts();
|
||||
if ( empty( $posts ) ) {
|
||||
return esc_html__( 'No posts found to convert.', 'rank-math-pro' );
|
||||
}
|
||||
|
||||
Video_Schema_Generator::get()->start( $posts );
|
||||
|
||||
return esc_html__( 'Conversion started. A success message will be shown here once the process completes. You can close this page.', 'rank-math-pro' );
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - course
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$shortcode->get_description( $schema['claimReviewed'] );
|
||||
$shortcode->get_image();
|
||||
|
||||
?>
|
||||
<div class="rank-math-review-data">
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'URL', 'rank-math-pro' ),
|
||||
'url'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Author Name', 'rank-math-pro' ),
|
||||
'itemReviewed.author.name'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Published Date', 'rank-math-pro' ),
|
||||
'itemReviewed.datePublished'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Appearance Headline', 'rank-math-pro' ),
|
||||
'itemReviewed.appearance.headline'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Appearance URL', 'rank-math-pro' ),
|
||||
'itemReviewed.appearance.url'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Appearance Author', 'rank-math-pro' ),
|
||||
'itemReviewed.appearance.author.name'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Appearance Published Date', 'rank-math-pro' ),
|
||||
'itemReviewed.appearance.datePublished'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Alternate Name', 'rank-math-pro' ),
|
||||
'reviewRating.alternateName'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php $shortcode->show_ratings( 'reviewRating.ratingValue' ); ?>
|
||||
</div>
|
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - course
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$shortcode->get_title();
|
||||
$shortcode->get_image();
|
||||
|
||||
?>
|
||||
<div class="rank-math-review-data">
|
||||
|
||||
<?php $shortcode->get_description(); ?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'URL', 'rank-math-pro' ),
|
||||
'url'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Reference Web page ', 'rank-math-pro' ),
|
||||
'sameAs'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$identifier = $shortcode->get_field_value( 'identifier' );
|
||||
if ( ! empty( $identifier ) ) {
|
||||
$identifiers = explode( PHP_EOL, $identifier );
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Identifier', 'rank-math-pro' ),
|
||||
'<ul><li>' . join( '</li><li>', $identifiers ) . '</li></ul>'
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$keyword = $shortcode->get_field_value( 'keywords' );
|
||||
if ( ! empty( $keyword ) ) {
|
||||
$keywords = explode( PHP_EOL, $keyword );
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Keywords', 'rank-math-pro' ),
|
||||
'<ul><li>' . join( '</li><li>', $keywords ) . '</li></ul>'
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'License', 'rank-math-pro' ),
|
||||
'license'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Catalog', 'rank-math-pro' ),
|
||||
'includedInDataCatalog.name'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Temporal Coverage', 'rank-math-pro' ),
|
||||
'temporalCoverage'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Special Coverage', 'rank-math-pro' ),
|
||||
'spatialCoverage'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$data_sets = $shortcode->get_field_value( 'hasPart' );
|
||||
$labels = [
|
||||
'name' => esc_html__( 'Name', 'rank-math-pro' ),
|
||||
'description' => esc_html__( 'Description', 'rank-math-pro' ),
|
||||
'license' => esc_html__( 'License', 'rank-math-pro' ),
|
||||
];
|
||||
if ( ! empty( $data_sets ) ) {
|
||||
echo '<h3>' . esc_html__( 'Data Sets', 'rank-math-pro' ) . '</h3>';
|
||||
foreach ( $data_sets as $data_set ) {
|
||||
echo '<div>';
|
||||
foreach ( $labels as $key => $label ) {
|
||||
echo "<p><strong>{$label}</strong>: {$data_set[$key]}</p>"; // phpcs:ignore
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$distributions = $shortcode->get_field_value( 'distribution' );
|
||||
$labels = [
|
||||
'encodingFormat' => esc_html__( 'Format', 'rank-math-pro' ),
|
||||
'contentUrl' => esc_html__( 'URL', 'rank-math-pro' ),
|
||||
];
|
||||
if ( ! empty( $distributions ) ) {
|
||||
echo '<h3>' . esc_html__( 'Distribution', 'rank-math-pro' ) . '</h3>';
|
||||
foreach ( $distributions as $distribution ) {
|
||||
echo '<div>';
|
||||
foreach ( $labels as $key => $label ) {
|
||||
echo "<p><strong>{$label}</strong>: {$distribution[$key]}</p>"; // phpcs:ignore
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - FAQPage
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
*/
|
||||
|
||||
use RankMath\Schema\Block_FAQ;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( empty( $schema['mainEntity'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attributes = [
|
||||
'questions' => [],
|
||||
'listStyle' => '',
|
||||
'titleWrapper' => 'h3',
|
||||
'sizeSlug' => 'thumbnail',
|
||||
'listCssClasses' => '',
|
||||
'titleCssClasses' => '',
|
||||
'contentCssClasses' => '',
|
||||
'textAlign' => 'left',
|
||||
];
|
||||
|
||||
foreach ( $schema['mainEntity'] as $index => $main_entity ) {
|
||||
$attributes['questions'][] = [
|
||||
'id' => 'faq-' . ( $index + 1 ),
|
||||
'title' => $main_entity['name'],
|
||||
'content' => $main_entity['acceptedAnswer']['text'],
|
||||
'visible' => 1,
|
||||
'imageID' => 0,
|
||||
'imageUrl' => isset( $main_entity['image'] ) ? $main_entity['image'] : '',
|
||||
];
|
||||
}
|
||||
|
||||
echo Block_FAQ::markup( $attributes ); // phpcs:ignore
|
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - HowTo
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
*/
|
||||
|
||||
use RankMath\Schema\Block_HowTo;
|
||||
use RankMath\Helpers\WordPress;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$has_duration = false;
|
||||
$days = 0;
|
||||
$hours = 0;
|
||||
$minutes = 0;
|
||||
if ( isset( $schema['totalTime'] ) && WordPress::get_formatted_duration( $schema['totalTime'] ) ) {
|
||||
$has_duration = true;
|
||||
$duration = new \DateInterval( $schema['totalTime'] );
|
||||
$days = $duration->d;
|
||||
$hours = $duration->h;
|
||||
$minutes = $duration->i;
|
||||
}
|
||||
|
||||
$attributes = [
|
||||
'days' => $days,
|
||||
'hours' => $hours,
|
||||
'minutes' => $minutes,
|
||||
'hasDuration' => $has_duration,
|
||||
'material' => isset( $schema['material'] ) ? $schema['material'] : '',
|
||||
'imageUrl' => isset( $schema['image']['url'] ) ? $schema['image']['url'] : '',
|
||||
'description' => isset( $schema['description'] ) ? $schema['description'] : '',
|
||||
'estimatedCost' => isset( $schema['estimatedCost']['value'] ) ? $schema['estimatedCost']['value'] : '',
|
||||
'estimatedCostCurrency' => isset( $schema['estimatedCost']['currency'] ) ? $schema['estimatedCost']['currency'] : '',
|
||||
'steps' => [],
|
||||
'supply' => '',
|
||||
'tools' => '',
|
||||
];
|
||||
|
||||
if ( ! empty( $schema['step'] ) ) {
|
||||
foreach ( $schema['step'] as $step ) {
|
||||
$attributes['steps'][] = [
|
||||
'visible' => 1,
|
||||
'title' => $step['name'],
|
||||
'imageUrl' => $step['image']['url'],
|
||||
'content' => $step['itemListElement']['text'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $schema['supply'] ) ) {
|
||||
foreach ( $schema['supply'] as $supply ) {
|
||||
$attributes['supply'] .= $supply['name'] . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $schema['tool'] ) ) {
|
||||
foreach ( $schema['tool'] as $tool ) {
|
||||
$attributes['tools'] .= $tool['name'] . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// No steps.
|
||||
if ( empty( $attributes['steps'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo Block_HowTo::markup( $attributes ); // phpcs:ignore
|
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - Job Posting
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$shortcode->get_title();
|
||||
$shortcode->get_image();
|
||||
?>
|
||||
<div class="rank-math-review-data">
|
||||
|
||||
<?php $shortcode->get_description(); ?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Salary', 'rank-math-pro' ),
|
||||
'baseSalary.value.value'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Salary Currency', 'rank-math-pro' ),
|
||||
'baseSalary.currency'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Payroll', 'rank-math-pro' ),
|
||||
'baseSalary.value.unitText'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Date Posted', 'rank-math-pro' ),
|
||||
'datePosted'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Posting Expiry Date', 'rank-math-pro' ),
|
||||
'validThrough'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Unpublish when expired', 'rank-math-pro' ),
|
||||
'unpublish'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Employment Type ', 'rank-math-pro' ),
|
||||
'employmentType'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Hiring Organization ', 'rank-math-pro' ),
|
||||
'hiringOrganization.name'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Organization URL', 'rank-math-pro' ),
|
||||
'hiringOrganization.sameAs'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Organization Logo', 'rank-math-pro' ),
|
||||
'hiringOrganization.logo'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Job Type', 'rank-math-pro' ),
|
||||
'jobLocationType'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$locations = $shortcode->get_field_value( 'applicantLocationRequirements' );
|
||||
if ( ! empty( $locations ) ) {
|
||||
$locations = array_map(
|
||||
function( $location ) {
|
||||
return ! empty( $location['name'] ) ? $location['name'] : '';
|
||||
},
|
||||
$locations
|
||||
);
|
||||
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Job Location', 'rank-math-pro' ),
|
||||
'<ul><li>' . join( '</li><li>', $locations ) . '</li></ul>'
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Location', 'rank-math-pro' ),
|
||||
'jobLocation.address'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$education = $shortcode->get_field_value( 'educationRequirements' );
|
||||
if ( is_array( $education ) && ! empty( $education ) ) {
|
||||
$education = array_map(
|
||||
function( $credential ) {
|
||||
return ! empty( $credential['credentialCategory'] ) ? ucwords( $credential['credentialCategory'] ) : '';
|
||||
},
|
||||
$education
|
||||
);
|
||||
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Education Required', 'rank-math-pro' ),
|
||||
'<ul><li>' . join( '</li><li>', $education ) . '</li></ul>'
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$experience = $shortcode->get_field_value( 'experienceRequirements' );
|
||||
if ( is_array( $experience ) && ! empty( $experience['monthsOfExperience'] ) ) {
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Experience Required', 'rank-math-pro' ),
|
||||
$experience['monthsOfExperience'] . ' ' . esc_html__( 'Months', 'rank-math-pro' )
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - Movie
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$shortcode->get_title();
|
||||
$shortcode->get_image();
|
||||
|
||||
?>
|
||||
<div class="rank-math-review-data">
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Director', 'rank-math-pro' ),
|
||||
'director'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Date Created', 'rank-math-pro' ),
|
||||
'dateCreated',
|
||||
true
|
||||
);
|
||||
?>
|
||||
|
||||
<?php $shortcode->show_ratings(); ?>
|
||||
</div>
|
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - PodcastEpisode
|
||||
*
|
||||
* @since 3.0.17
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Schema
|
||||
*/
|
||||
|
||||
use RankMath\Helpers\WordPress;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( empty( $schema['associatedMedia'] ) || empty( $schema['associatedMedia']['contentUrl'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_title = get_the_title( $post->ID );
|
||||
$episode_title = $schema['name'];
|
||||
if ( $schema['name'] === $post_title && $post->ID === get_the_ID() ) {
|
||||
$episode_title = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/schema/podcast_episode_title' - Allow changing the title of the podcast episode. Pass false to disable.
|
||||
*
|
||||
* @var string $post_title The title of the podcast episode.
|
||||
*
|
||||
* @param WP_Post $post The post object.
|
||||
* @param array $schema The schema array.
|
||||
*/
|
||||
$episode_title = apply_filters( 'rank_math/schema/podcast_episode_title', $episode_title, $post, $schema );
|
||||
|
||||
$season = ! empty( $schema['partOfSeason'] ) ? $schema['partOfSeason'] : [];
|
||||
$time_required = [];
|
||||
if ( isset( $schema['timeRequired'] ) && WordPress::get_formatted_duration( $schema['timeRequired'] ) ) {
|
||||
$duration = new \DateInterval( $schema['timeRequired'] );
|
||||
$time_required[] = ! empty( $duration->h ) ? sprintf( esc_html__( '%d Hour', 'rank-math-pro' ), $duration->h ) : '';
|
||||
$time_required[] = ! empty( $duration->i ) ? sprintf( esc_html__( '%d Min', 'rank-math-pro' ), $duration->i ) : '';
|
||||
$time_required[] = ! empty( $duration->s ) ?sprintf( esc_html__( '%d Sec', 'rank-math-pro' ), $duration->s ) : '';
|
||||
$time_required = array_filter( $time_required );
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<!-- wp:columns -->
|
||||
<div class="wp-block-columns" style="gap: 2em;">
|
||||
<!-- wp:column -->
|
||||
<?php if ( ! empty( $schema['thumbnailUrl'] ) ) {
|
||||
$image_id = attachment_url_to_postid( $schema['thumbnailUrl'] );
|
||||
$img = '<img src="' . esc_url( $schema['thumbnailUrl'] ) . '" />';
|
||||
|
||||
if ( $image_id ) {
|
||||
$img = wp_get_attachment_image( $image_id, 'medium', false, [ 'class' => 'wp-image-' . $image_id ] );
|
||||
}
|
||||
?>
|
||||
<div class="wp-block-column" style="flex: 0 0 25%;">
|
||||
<!-- wp:image -->
|
||||
<figure class="wp-block-image size-medium is-resized">
|
||||
<?php echo wp_kses_post( $img ); ?>
|
||||
</figure>
|
||||
<!-- /wp:image -->
|
||||
</div>
|
||||
<!-- /wp:column -->
|
||||
<?php } ?>
|
||||
|
||||
<!-- wp:column -->
|
||||
<div class="wp-block-column">
|
||||
<!-- wp:paragraph -->
|
||||
<p>
|
||||
<?php if ( ! empty( $schema['datePublished'] ) ) { ?>
|
||||
<span class="rank-math-podcast-date">
|
||||
<?php echo esc_html( date( "j F", strtotime( $schema['datePublished'] ) ) ); ?>
|
||||
</span> ·
|
||||
<?php } ?>
|
||||
<span>
|
||||
<?php if ( ! empty( $season['seasonNumber'] ) ) { ?>
|
||||
<?php echo esc_html__( 'Season', 'rank-math-pro' ); ?> <?php echo esc_html( $season['seasonNumber'] ); ?>
|
||||
<?php if ( ! empty( $season['name'] ) ) { ?>
|
||||
: <?php if ( ! empty( $season['url'] ) ) { ?>
|
||||
<a href="<?php echo esc_url( $season['url'] ); ?>"><?php echo esc_html( $season['name'] ); ?></a>
|
||||
<?php } else { ?>
|
||||
<?php echo esc_html( $season['name'] ); ?>
|
||||
<?php } ?>
|
||||
<?php } ?> ·
|
||||
<?php } ?>
|
||||
|
||||
<?php if ( ! empty( $schema['episodeNumber'] ) ) { ?>
|
||||
<?php echo esc_html__( 'Episode', 'rank-math-pro' ); ?> <?php echo esc_html( $schema['episodeNumber'] ); ?>
|
||||
<?php } ?>
|
||||
</span>
|
||||
</p>
|
||||
<!-- /wp:paragraph -->
|
||||
|
||||
<?php if ( $episode_title ) { ?>
|
||||
<!-- wp:heading -->
|
||||
<h2>
|
||||
<?php echo esc_html( $episode_title ); ?>
|
||||
</h2>
|
||||
<!-- /wp:heading -->
|
||||
<?php } ?>
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<p>
|
||||
<?php if ( ! empty( $time_required ) ) { ?>
|
||||
<span>
|
||||
<?php echo implode( ', ', $time_required ); ?>
|
||||
</span>
|
||||
·
|
||||
<?php } ?>
|
||||
<?php if ( ! empty( $schema['author'] ) ) { ?>
|
||||
<?php echo esc_html__( 'By', 'rank-math-pro' ); ?> <?php echo esc_html( $schema['author']['name'] ); ?>
|
||||
<?php } ?>
|
||||
</p>
|
||||
<!-- /wp:paragraph -->
|
||||
</div>
|
||||
<!-- /wp:column -->
|
||||
</div>
|
||||
<!-- /wp:columns -->
|
||||
<!-- wp:audio -->
|
||||
<figure class="wp-block-audio">
|
||||
<audio controls src="<?php echo esc_url( $schema['associatedMedia']['contentUrl'] ); ?>"></audio>
|
||||
</figure>
|
||||
<!-- /wp:audio -->
|
||||
|
||||
<?php if ( ! empty( $schema['description'] ) ) { ?>
|
||||
<!-- wp:paragraph -->
|
||||
<p><?php echo esc_html( $schema['description'] ); ?></p>
|
||||
<!-- /wp:paragraph -->
|
||||
<?php } ?>
|
||||
<?php
|
||||
|
||||
echo do_blocks( ob_get_clean() );
|
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - Product
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Schema
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$shortcode->get_title();
|
||||
$shortcode->get_image();
|
||||
|
||||
$offers = $shortcode->get_field_value( 'offers' );
|
||||
$positive_notes = $shortcode->get_field_value( 'review.positiveNotes' );
|
||||
$negative_notes = $shortcode->get_field_value( 'review.negativeNotes' );
|
||||
?>
|
||||
<div class="rank-math-review-data">
|
||||
|
||||
<?php $shortcode->get_description(); ?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Product SKU', 'rank-math-pro' ),
|
||||
'sku'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$brand = $shortcode->get_field_value( 'brand' );
|
||||
if ( ! empty( $brand['url'] ) && ! empty( $brand['name'] ) ) {
|
||||
?>
|
||||
<p>
|
||||
<strong><?php echo esc_html__( 'Product Brand', 'rank-math-pro' ); ?>: </strong>
|
||||
<a href="<?php echo esc_url( $brand['url'] ); ?>"><?php echo esc_html( $brand['name'] ); ?></a>
|
||||
</p>
|
||||
<?php
|
||||
} else {
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Product Brand', 'rank-math-pro' ),
|
||||
'brand.name'
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
if (
|
||||
! empty( $offers['price'] ) ||
|
||||
(
|
||||
empty( $positive_notes ) &&
|
||||
empty( $negative_notes )
|
||||
)
|
||||
) {
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Product Currency', 'rank-math-pro' ),
|
||||
'offers.priceCurrency'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Product Price', 'rank-math-pro' ),
|
||||
'offers.price'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Price Valid Until', 'rank-math-pro' ),
|
||||
'offers.priceValidUntil'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Product In-Stock', 'rank-math-pro' ),
|
||||
'offers.availability'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<?php $shortcode->show_ratings(); ?>
|
||||
|
||||
</div>
|
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode - Recipe
|
||||
*
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Schema
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$shortcode->get_title();
|
||||
$shortcode->get_image();
|
||||
?>
|
||||
<div class="rank-math-review-data">
|
||||
|
||||
<?php $shortcode->get_description(); ?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Type', 'rank-math-pro' ),
|
||||
'recipeCategory'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Cuisine', 'rank-math-pro' ),
|
||||
'recipeCuisine'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Keywords', 'rank-math-pro' ),
|
||||
'keywords'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Recipe Yield', 'rank-math-pro' ),
|
||||
'recipeYield'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Calories', 'rank-math-pro' ),
|
||||
'nutrition.calories'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Preparation Time', 'rank-math-pro' ),
|
||||
'prepTime'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Cooking Time', 'rank-math-pro' ),
|
||||
'cookTime'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Total Time', 'rank-math-pro' ),
|
||||
'totalTime'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Recipe Video Name', 'rank-math-pro' ),
|
||||
'video.name'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Recipe Video Description', 'rank-math-pro' ),
|
||||
'video.description'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Recipe Video Thumbnail', 'rank-math-pro' ),
|
||||
'video.thumbnailUrl'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$videoembed = $shortcode->get_field_value( 'video' );
|
||||
if ( ! empty( $videoembed ) ) {
|
||||
global $wp_embed;
|
||||
if ( ! empty( $videoembed['embedUrl'] ) ) {
|
||||
echo do_shortcode( $wp_embed->autoembed( $videoembed['embedUrl'] ) );
|
||||
} elseif ( ! empty( $videoembed['contentUrl'] ) ) {
|
||||
echo do_shortcode( $wp_embed->autoembed( $videoembed['contentUrl'] ) );
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$ingredient = $shortcode->get_field_value( 'recipeIngredient' );
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Recipe Ingredients', 'rank-math-pro' ),
|
||||
'<ul><li>' . join( '</li><li>', $ingredient ) . '</li></ul>'
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$instructions = $shortcode->get_field_value( 'recipeInstructions' );
|
||||
if ( is_string( $instructions ) ) {
|
||||
$shortcode->get_field(
|
||||
esc_html__( 'Recipe Instructions', 'rank-math-pro' ),
|
||||
'recipeInstructions'
|
||||
);
|
||||
} else {
|
||||
// HowTo Array.
|
||||
if ( isset( $instructions[0]['@type'] ) && 'HowtoStep' === $instructions[0]['@type'] ) {
|
||||
$instructions = wp_list_pluck( $instructions, 'text' );
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Recipe Instructions', 'rank-math-pro' ),
|
||||
'<ul><li>' . join( '</li><li>', $instructions ) . '</li></ul>'
|
||||
);
|
||||
}
|
||||
|
||||
// Single HowToSection data.
|
||||
if ( ! empty( $instructions['itemListElement'] ) ) {
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Recipe Instructions', 'rank-math-pro' ),
|
||||
''
|
||||
);
|
||||
|
||||
$shortcode->output_field(
|
||||
$instructions['name'],
|
||||
'<ul><li>' . join( '</li><li>', wp_list_pluck( $instructions['itemListElement'], 'text' ) ) . '</li></ul>'
|
||||
);
|
||||
}
|
||||
|
||||
// Multiple HowToSection data.
|
||||
if ( isset( $instructions[0]['@type'] ) && 'HowToSection' === $instructions[0]['@type'] ) {
|
||||
$shortcode->output_field(
|
||||
esc_html__( 'Recipe Instructions', 'rank-math-pro' ),
|
||||
''
|
||||
);
|
||||
|
||||
foreach ( $instructions as $section ) {
|
||||
if ( empty( $section['itemListElement'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = '';
|
||||
foreach ( $section['itemListElement'] as $item ) {
|
||||
$url = ! empty( $item['url'] ) ? $item['url'] : '';
|
||||
$name = ! empty( $item['name'] ) ? $item['name'] : '';
|
||||
$image = ! empty( $item['image'] ) ? $item['image']['url'] : '';
|
||||
$text = ! empty( $item['text'] ) ? $item['text'] : '';
|
||||
|
||||
$data .= '<div class="inner-wrapper">';
|
||||
$data .= '<div class="content-wrapper">';
|
||||
$data .= '<h5><a href="' . esc_url( $url ) . '" target="_blank">' . esc_html__( $name ) . '</a></h5>';
|
||||
$data .= '<p>' . esc_html( $text ) . '</p>';
|
||||
$data .= '</div>';
|
||||
$data .= '<img src="' . esc_url( $image ) . '" />';
|
||||
$data .= '</div>';
|
||||
}
|
||||
|
||||
echo '<div class="recipe-instructions-data">';
|
||||
$shortcode->output_field(
|
||||
$section['name'],
|
||||
$data
|
||||
);
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php $shortcode->show_ratings(); ?>
|
||||
|
||||
</div>
|
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* The DailyMotion Video.
|
||||
*
|
||||
* @since 2.7.1
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use MyThemeShop\Helpers\Str;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* DailyMotion class.
|
||||
*/
|
||||
class DailyMotion {
|
||||
|
||||
/**
|
||||
* Match url.
|
||||
*
|
||||
* @param string $url Url to match.
|
||||
* @return bool
|
||||
*/
|
||||
public static function match( $url ) {
|
||||
if ( ! Str::contains( 'dailymotion.com', $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = strtok( basename( $url ), '_' );
|
||||
if ( empty( $id ) ) {
|
||||
return false;
|
||||
}
|
||||
return self::fetch_data( $id, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data.
|
||||
*
|
||||
* @param string $video_id Video ID.
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*
|
||||
* @link https://developer.dailymotion.com/api/#video-fields
|
||||
*/
|
||||
private static function fetch_data( $video_id, $url ) {
|
||||
$data = [
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
];
|
||||
|
||||
$response = wp_remote_get( "https://api.dailymotion.com/video/{$video_id}?fields=title,description,duration,thumbnail_url,width,height,created_time" );
|
||||
if (
|
||||
is_wp_error( $response ) ||
|
||||
! in_array( wp_remote_retrieve_response_code( $response ), [ 200, 204 ], true )
|
||||
) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$content = wp_remote_retrieve_body( $response );
|
||||
$content = json_decode( $content, true );
|
||||
$data = [
|
||||
'name' => ! empty( $content['title'] ) ? $content['title'] : '',
|
||||
'description' => ! empty( $content['description'] ) ? $content['description'] : '',
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
'width' => $content['width'],
|
||||
'height' => $content['height'],
|
||||
'isFamilyFriendly' => true,
|
||||
'duration' => 'PT' . $content['duration'] . 'S',
|
||||
'thumbnail' => $content['thumbnail_url'],
|
||||
'uploadDate' => gmdate( 'Y-m-d\TH:i:s', $content['created_time'] ),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
/**
|
||||
* The Video Parser
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Schema\DB;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Parser class.
|
||||
*/
|
||||
class Parser {
|
||||
|
||||
/**
|
||||
* Post.
|
||||
*
|
||||
* @var WP_Post
|
||||
*/
|
||||
private $post;
|
||||
|
||||
/**
|
||||
* Stored Video URLs.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $urls;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*
|
||||
* @param WP_Post $post Post to parse.
|
||||
*/
|
||||
public function __construct( $post ) {
|
||||
$this->post = $post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save video object.
|
||||
*/
|
||||
public function save() {
|
||||
if (
|
||||
! ( $this->post instanceof \WP_Post ) ||
|
||||
wp_is_post_revision( $this->post->ID ) ||
|
||||
! Helper::get_settings( "titles.pt_{$this->post->post_type}_autodetect_video", 'on' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$content = trim( $this->post->post_content . ' ' . $this->get_custom_fields_data() );
|
||||
if ( empty( $content ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->urls = $this->get_video_urls();
|
||||
$content = apply_filters( 'the_content', $content );
|
||||
$allowed_types = apply_filters( 'media_embedded_in_content_allowed_types', [ 'video', 'embed', 'iframe' ] );
|
||||
$tags = implode( '|', $allowed_types );
|
||||
$videos = [];
|
||||
|
||||
preg_match_all( '#<(?P<tag>' . $tags . ')[^<]*?(?:>[\s\S]*?<\/(?P=tag)>|\s*\/>)#', $content, $matches );
|
||||
if ( ! empty( $matches ) && ! empty( $matches[0] ) ) {
|
||||
foreach ( $matches[0] as $html ) {
|
||||
$videos[] = $this->get_metadata( $html );
|
||||
}
|
||||
}
|
||||
|
||||
$videos = array_merge( $videos, $this->get_links_from_shortcode( $content ) );
|
||||
$videos = array_filter(
|
||||
$videos,
|
||||
function( $video ) {
|
||||
return ! empty( $video['src'] ) ? $video['src'] : false;
|
||||
}
|
||||
);
|
||||
|
||||
if ( empty( $videos ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$schemas = $this->get_default_schema_data();
|
||||
foreach ( $videos as $video ) {
|
||||
$schemas[] = [
|
||||
'@type' => 'VideoObject',
|
||||
'metadata' => [
|
||||
'title' => 'Video',
|
||||
'type' => 'template',
|
||||
'shortcode' => uniqid( 's-' ),
|
||||
'isPrimary' => empty( DB::get_schemas( $this->post->ID ) ),
|
||||
'reviewLocationShortcode' => '[rank_math_rich_snippet]',
|
||||
'category' => '%categories%',
|
||||
'tags' => '%tags%',
|
||||
'isAutoGenerated' => true,
|
||||
],
|
||||
'name' => ! empty( $video['name'] ) ? $video['name'] : '%seo_title%',
|
||||
'description' => ! empty( $video['description'] ) ? $video['description'] : '%seo_description%',
|
||||
'uploadDate' => ! empty( $video['uploadDate'] ) ? $video['uploadDate'] : '%date(Y-m-dTH:i:sP)%',
|
||||
'thumbnailUrl' => ! empty( $video['thumbnail'] ) ? $video['thumbnail'] : '%post_thumbnail%',
|
||||
'embedUrl' => ! empty( $video['embed'] ) ? $video['src'] : '',
|
||||
'contentUrl' => empty( $video['embed'] ) ? $video['src'] : '',
|
||||
'duration' => ! empty( $video['duration'] ) ? $video['duration'] : '',
|
||||
'width' => ! empty( $video['width'] ) ? $video['width'] : '',
|
||||
'height' => ! empty( $video['height'] ) ? $video['height'] : '',
|
||||
'isFamilyFriendly' => ! empty( $video['isFamilyFriendly'] ) ? (bool) $video['isFamilyFriendly'] : true,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ( array_filter( $schemas ) as $schema ) {
|
||||
add_post_meta( $this->post->ID, "rank_math_schema_{$schema['@type']}", $schema );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default schema data.
|
||||
*/
|
||||
private function get_default_schema_data() {
|
||||
if ( ! empty( DB::get_schemas( $this->post->ID ) ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$default_type = Helper::get_default_schema_type( $this->post->ID, true );
|
||||
if ( ! $default_type ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$is_article = in_array( $default_type, [ 'Article', 'NewsArticle', 'BlogPosting' ], true );
|
||||
$schema_data = [];
|
||||
if ( $is_article ) {
|
||||
$schema_data = [
|
||||
'headline' => Helper::get_settings( "titles.pt_{$this->post->post_type}_default_snippet_name" ),
|
||||
'description' => Helper::get_settings( "titles.pt_{$this->post->post_type}_default_snippet_desc" ),
|
||||
'datePublished' => '%date(Y-m-dTH:i:sP)%',
|
||||
'dateModified' => '%modified(Y-m-dTH:i:sP)%',
|
||||
'image' => [
|
||||
'@type' => 'ImageObject',
|
||||
'url' => '%post_thumbnail%',
|
||||
],
|
||||
'author' => [
|
||||
'@type' => 'Person',
|
||||
'name' => '%name%',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$schema_data['@type'] = $default_type;
|
||||
$schema_data['metadata'] = [
|
||||
'title' => Helper::sanitize_schema_title( $default_type ),
|
||||
'type' => 'template',
|
||||
'isPrimary' => true,
|
||||
];
|
||||
|
||||
return [ $schema_data ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Video source from the content.
|
||||
*
|
||||
* @param array $html Video Links.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_metadata( $html ) {
|
||||
preg_match_all( '@src=[\'"]([^"]+)[\'"]@', $html, $matches );
|
||||
if ( empty( $matches ) || empty( $matches[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->get_video_metadata( $matches[1][0] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Video source.
|
||||
*
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*/
|
||||
private function get_video_metadata( $url ) {
|
||||
$url = preg_replace( '/\?.*/', '', $url ); // Remove query string from URL.
|
||||
if (
|
||||
$url &&
|
||||
(
|
||||
is_array( $this->urls ) &&
|
||||
(
|
||||
in_array( $url, $this->urls, true ) ||
|
||||
in_array( $url . '?feature=oembed', $this->urls, true )
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->urls[] = $url;
|
||||
$networks = [
|
||||
'Video\Youtube',
|
||||
'Video\Vimeo',
|
||||
'Video\DailyMotion',
|
||||
'Video\TedVideos',
|
||||
'Video\VideoPress',
|
||||
'Video\WordPress',
|
||||
];
|
||||
|
||||
$data = false;
|
||||
foreach ( $networks as $network ) {
|
||||
$data = \call_user_func( [ '\\RankMathPro\\Schema\\' . $network, 'match' ], $url );
|
||||
if ( is_array( $data ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Save image locally.
|
||||
if ( ! empty( $data['thumbnail'] ) ) {
|
||||
$data['thumbnail'] = $this->save_video_thumbnail( $data );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Video Links from YouTube Embed plugin.
|
||||
*
|
||||
* @param string $content Post Content.
|
||||
* @return array
|
||||
*
|
||||
* Credit ridgerunner (https://stackoverflow.com/users/433790/ridgerunner)
|
||||
*/
|
||||
private function get_links_from_shortcode( $content ) {
|
||||
preg_match_all(
|
||||
'~
|
||||
https?:// # Required scheme. Either http or https.
|
||||
(?:[0-9A-Z-]+\.)? # Optional subdomain.
|
||||
(?: # Group host alternatives.
|
||||
youtu\.be/ # Either youtu.be,
|
||||
| youtube # or youtube.com or
|
||||
(?:-nocookie)? # youtube-nocookie.com
|
||||
\.com # followed by
|
||||
\S*? # Allow anything up to VIDEO_ID,
|
||||
[^\w\s-] # but char before ID is non-ID char.
|
||||
) # End host alternatives.
|
||||
([\w-]{11}) # $1: VIDEO_ID is exactly 11 chars.
|
||||
(?=[^\w-]|$) # Assert next char is non-ID or EOS.
|
||||
(?! # Assert URL is not pre-linked.
|
||||
[?=&+%\w.-]* # Allow URL (query) remainder.
|
||||
(?: # Group pre-linked alternatives.
|
||||
[\'"][^<>]*> # Either inside a start tag,
|
||||
| </a> # or inside <a> element text contents.
|
||||
) # End recognized pre-linked alts.
|
||||
) # End negative lookahead assertion.
|
||||
[?=&+%\w.-]* # Consume any URL (query) remainder.
|
||||
~ix',
|
||||
$content,
|
||||
$matches
|
||||
);
|
||||
|
||||
if ( empty( $matches ) || empty( $matches[1] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
foreach ( $matches[1] as $video_id ) {
|
||||
$data[] = $this->get_video_metadata( "https://www.youtube.com/embed/{$video_id}" );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Video source.
|
||||
*
|
||||
* @param array $data Video data.
|
||||
* @return array
|
||||
*
|
||||
* Credits to m1r0 @ https://gist.github.com/m1r0/f22d5237ee93bcccb0d9
|
||||
*/
|
||||
private function save_video_thumbnail( $data ) {
|
||||
$url = $data['thumbnail'];
|
||||
if ( ! Helper::get_settings( "titles.pt_{$this->post->post_type}_autogenerate_image", 'off' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'WP_Http' ) ) {
|
||||
include_once( ABSPATH . WPINC . '/class-http.php' );
|
||||
}
|
||||
|
||||
$url = explode( '?', $url )[0];
|
||||
$http = new \WP_Http();
|
||||
$response = $http->request( $url );
|
||||
if ( 200 !== $response['response']['code'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$image_title = __( 'Video Thumbnail', 'rank-math-pro' );
|
||||
if ( ! empty( $data['name'] ) ) {
|
||||
$image_title = $data['name'];
|
||||
} elseif ( ! empty( $this->post->post_title ) ) {
|
||||
$image_title = $this->post->post_title;
|
||||
}
|
||||
$filename = substr( sanitize_title( $image_title, 'video-thumbnail' ), 0, 32 ) . '.jpg';
|
||||
|
||||
/**
|
||||
* Filter the filename of the video thumbnail.
|
||||
*
|
||||
* @param string $filename The filename of the video thumbnail.
|
||||
* @param array $data The video data.
|
||||
* @param object $post The post object.
|
||||
*/
|
||||
$filename = apply_filters( 'rank_math/schema/video_thumbnail_filename', $filename, $data, $this->post );
|
||||
|
||||
$upload = wp_upload_bits( sanitize_file_name( $filename ), null, $response['body'] );
|
||||
if ( ! empty( $upload['error'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file_path = $upload['file'];
|
||||
$file_name = basename( $file_path );
|
||||
$file_type = wp_check_filetype( $file_name, null );
|
||||
$wp_upload_dir = wp_upload_dir();
|
||||
|
||||
// Translators: Placeholder is the image title.
|
||||
$attachment_title = sprintf( __( 'Video Thumbnail: %s', 'rank-math-pro' ), $image_title );
|
||||
|
||||
/**
|
||||
* Filter the attachment title of the video thumbnail.
|
||||
*
|
||||
* @param string $attachment_title The attachment title of the video thumbnail.
|
||||
* @param array $data The video data.
|
||||
* @param object $post The post object.
|
||||
*/
|
||||
$attachment_title = apply_filters( 'rank_math/schema/video_thumbnail_attachment_title', $attachment_title, $data, $this->post );
|
||||
|
||||
$post_info = [
|
||||
'guid' => $wp_upload_dir['url'] . '/' . $file_name,
|
||||
'post_mime_type' => $file_type['type'],
|
||||
'post_title' => $attachment_title,
|
||||
'post_content' => '',
|
||||
'post_status' => 'inherit',
|
||||
];
|
||||
|
||||
$attach_id = wp_insert_attachment( $post_info, $file_path, $this->post->ID );
|
||||
|
||||
// Include image.php.
|
||||
require_once( ABSPATH . 'wp-admin/includes/image.php' );
|
||||
|
||||
// Define attachment metadata.
|
||||
$attach_data = wp_generate_attachment_metadata( $attach_id, $file_path );
|
||||
|
||||
// Assign metadata to attachment.
|
||||
wp_update_attachment_metadata( $attach_id, $attach_data );
|
||||
|
||||
return wp_get_attachment_url( $attach_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Video URls stored in VideoObject schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_video_urls() {
|
||||
$schemas = DB::get_schemas( $this->post->ID );
|
||||
if ( empty( $schemas ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$urls = [];
|
||||
foreach ( $schemas as $schema ) {
|
||||
if ( empty( $schema['@type'] ) || 'VideoObject' !== $schema['@type'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$urls[] = ! empty( $schema['embedUrl'] ) ? $schema['embedUrl'] : '';
|
||||
$urls[] = ! empty( $schema['contentUrl'] ) ? $schema['contentUrl'] : '';
|
||||
}
|
||||
|
||||
return array_filter( $urls );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Custom fields data.
|
||||
*/
|
||||
private function get_custom_fields_data() {
|
||||
$custom_fields = Str::to_arr_no_empty( Helper::get_settings( 'sitemap.video_sitemap_custom_fields' ) );
|
||||
if ( empty( $custom_fields ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$content = '';
|
||||
foreach ( $custom_fields as $custom_field ) {
|
||||
$content = $content . ' ' . get_post_meta( $this->post->ID, $custom_field, true );
|
||||
}
|
||||
|
||||
return trim( $content );
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* The TedVideos
|
||||
*
|
||||
* @since 2.7.1
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use RankMath\Helper;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* TedVideos class.
|
||||
*/
|
||||
class TedVideos {
|
||||
|
||||
/**
|
||||
* Match url.
|
||||
*
|
||||
* @param string $url Url to match.
|
||||
* @return bool
|
||||
*/
|
||||
public static function match( $url ) {
|
||||
if ( ! Str::contains( 'ted.com', $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::fetch_data( $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data.
|
||||
*
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*/
|
||||
private static function fetch_data( $url ) {
|
||||
$data = [
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
];
|
||||
|
||||
$response = wp_remote_get( str_replace( 'embed.', '', $url ) );
|
||||
if (
|
||||
is_wp_error( $response ) ||
|
||||
! in_array( wp_remote_retrieve_response_code( $response ), [ 200, 204 ], true )
|
||||
) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$content = wp_remote_retrieve_body( $response );
|
||||
preg_match_all( "/<meta content='(.*?)' itemprop='(width|height|duration|uploadDate)'>/i", $content, $item_props, PREG_SET_ORDER );
|
||||
|
||||
foreach ( $item_props as $item_prop ) {
|
||||
$data[ $item_prop[2] ] = $item_prop[1];
|
||||
}
|
||||
|
||||
preg_match_all( '/<meta name="(title|description)" content="(.*?)" \/>/i', $content, $item_props, PREG_SET_ORDER );
|
||||
foreach ( $item_props as $item_prop ) {
|
||||
$key = 'title' === $item_prop[1] ? 'name' : $item_prop[1];
|
||||
$data[ $key ] = $item_prop[2];
|
||||
}
|
||||
|
||||
preg_match( '/<meta property="og:image" content="(.*?)" \/>/i', $content, $image );
|
||||
$data['thumbnail'] = ! empty( $image ) && isset( $image[1] ) ? $image[1] : '';
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* The VideoPress.
|
||||
*
|
||||
* @since 2.7.1
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use MyThemeShop\Helpers\Str;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* VideoPress class.
|
||||
*/
|
||||
class VideoPress {
|
||||
|
||||
/**
|
||||
* Match url.
|
||||
*
|
||||
* @param string $url Url to match.
|
||||
* @return bool
|
||||
*/
|
||||
public static function match( $url ) {
|
||||
if ( ! Str::contains( 'video.wordpress.com', $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$video_id = str_replace( 'https://video.wordpress.com/embed/', '', $url );
|
||||
if ( ! $video_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::fetch_data( $video_id, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data.
|
||||
*
|
||||
* @param string $video_id Video ID.
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*
|
||||
* @see https://developer.wordpress.com/docs/api/1/get/videos/%24guid/
|
||||
*/
|
||||
private static function fetch_data( $video_id, $url ) {
|
||||
$data = [
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
];
|
||||
|
||||
$response = wp_remote_get( "https://public-api.wordpress.com/rest/v1.1/videos/{$video_id}" );
|
||||
if (
|
||||
is_wp_error( $response ) ||
|
||||
! in_array( wp_remote_retrieve_response_code( $response ), [ 200, 204 ], true )
|
||||
) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$content = wp_remote_retrieve_body( $response );
|
||||
$content = json_decode( $content, true );
|
||||
$data = [
|
||||
'name' => ! empty( $content['title'] ) ? $content['title'] : '',
|
||||
'description' => ! empty( $content['description'] ) ? $content['description'] : '',
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
'width' => isset( $content['width'] ) ? $content['width'] : '',
|
||||
'height' => isset( $content['height'] ) ? $content['height'] : '',
|
||||
'isFamilyFriendly' => true,
|
||||
'duration' => isset( $content['duration'] ) ? 'PT' . $content['duration'] . 'S' : '',
|
||||
'thumbnail' => isset( $content['poster'] ) ? $content['poster'] : '',
|
||||
'uploadDate' => isset( $content['upload_date'] ) ? $content['upload_date'] : '',
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* The Vimeo
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Vimeo class.
|
||||
*/
|
||||
class Vimeo {
|
||||
|
||||
/**
|
||||
* Match url.
|
||||
*
|
||||
* @param string $url Url to match.
|
||||
* @return bool
|
||||
*/
|
||||
public static function match( $url ) {
|
||||
if ( ! Str::contains( 'vimeo.com', $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
preg_match( '#(https?://)?(www.)?(player.)?vimeo.com/([a-z]*/)*([0-9]{6,11})[?]?.*#', $url, $match );
|
||||
if ( empty( $match[5] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::fetch_data( $match[5], $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data.
|
||||
*
|
||||
* @param string $video_id Video ID.
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*/
|
||||
private static function fetch_data( $video_id, $url ) {
|
||||
$data = [
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
];
|
||||
|
||||
$response = wp_remote_get( "http://vimeo.com/api/v2/video/{$video_id}/json" );
|
||||
if (
|
||||
is_wp_error( $response ) ||
|
||||
! in_array( wp_remote_retrieve_response_code( $response ), [ 200, 204 ], true )
|
||||
) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$content = wp_remote_retrieve_body( $response );
|
||||
$content = json_decode( $content, true );
|
||||
$content = $content[0];
|
||||
|
||||
$data = [
|
||||
'name' => ! empty( $content['title'] ) ? $content['title'] : '',
|
||||
'description' => ! empty( $content['description'] ) ? $content['description'] : '',
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
'width' => $content['width'],
|
||||
'height' => $content['height'],
|
||||
'isFamilyFriendly' => true,
|
||||
'duration' => 'PT' . $content['duration'] . 'S',
|
||||
'thumbnail' => $content['thumbnail_large'],
|
||||
'uploadDate' => $content['upload_date'],
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* The WordPress
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WordPress class.
|
||||
*/
|
||||
class WordPress {
|
||||
|
||||
/**
|
||||
* Match url.
|
||||
*
|
||||
* @param string $url Url to match.
|
||||
* @return bool
|
||||
*/
|
||||
public static function match( $url ) {
|
||||
$type = wp_check_filetype( $url, wp_get_mime_types() );
|
||||
|
||||
if ( ! in_array( strtolower( $type['ext'] ), wp_get_video_extensions(), true ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return self::fetch_data( $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data.
|
||||
*
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*/
|
||||
private static function fetch_data( $url ) {
|
||||
$data = [];
|
||||
$attachment_id = attachment_url_to_postid( $url );
|
||||
if ( $attachment_id ) {
|
||||
$video_details = wp_get_attachment_metadata( $attachment_id );
|
||||
$data = [
|
||||
'width' => ! empty( $video_details['width'] ) ? $video_details['width'] : '',
|
||||
'height' => ! empty( $video_details['height'] ) ? $video_details['height'] : '',
|
||||
];
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
[
|
||||
'src' => $url,
|
||||
'embed' => false,
|
||||
],
|
||||
$data
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* The Youtube
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Schema\Video
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Schema\Video;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Youtube class.
|
||||
*/
|
||||
class Youtube {
|
||||
|
||||
/**
|
||||
* Match url.
|
||||
*
|
||||
* @param string $url Url to match.
|
||||
* @return bool
|
||||
*/
|
||||
public static function match( $url ) {
|
||||
if ( ! preg_match( '#^https?://(?:www\.)?(?:youtube\.com/|youtu\.be/)#', $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
preg_match( '%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match );
|
||||
if ( empty( $match[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::fetch_data( $match[1], $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data.
|
||||
*
|
||||
* @param string $video_id Video ID.
|
||||
* @param string $url Video Source.
|
||||
* @return array
|
||||
*/
|
||||
private static function fetch_data( $video_id, $url ) {
|
||||
$data = [
|
||||
'src' => $url,
|
||||
'embed' => true,
|
||||
];
|
||||
|
||||
$response = wp_remote_get( "https://www.youtube.com/watch?v={$video_id}" );
|
||||
if (
|
||||
is_wp_error( $response ) ||
|
||||
! in_array( wp_remote_retrieve_response_code( $response ), [ 200, 204 ], true )
|
||||
) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$content = wp_remote_retrieve_body( $response );
|
||||
preg_match_all( '/<meta itemprop="(width|height|isFamilyFriendly|duration|uploadDate)" content="(.*?)">/i', $content, $item_props, PREG_SET_ORDER );
|
||||
foreach ( $item_props as $item_prop ) {
|
||||
$data[ $item_prop[1] ] = $item_prop[2];
|
||||
}
|
||||
|
||||
preg_match_all( '/<meta name="(title|description)" content="(.*?)">/i', $content, $item_props, PREG_SET_ORDER );
|
||||
foreach ( $item_props as $item_prop ) {
|
||||
$key = 'title' === $item_prop[1] ? 'name' : $item_prop[1];
|
||||
$data[ $key ] = $item_prop[2];
|
||||
}
|
||||
|
||||
preg_match( '/<meta property="og:image" content="(.*?)">/i', $content, $image );
|
||||
$data['thumbnail'] = ! empty( $image ) && isset( $image[1] ) ? $image[1] : '';
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user