Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
<?php
/**
* The AIOSEO Block Converter imports editor blocks (TOC) from AIOSEO to Rank Math.
*
* @since 1.0.104
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* AIOSEO_Blocks class.
*/
class AIOSEO_Blocks extends \WP_Background_Process {
/**
* TOC Converter.
*
* @var AIOSEO_TOC_Converter
*/
private $toc_converter;
/**
* Action.
*
* @var string
*/
protected $action = 'convert_aioseo_blocks';
/**
* Main instance.
*
* Ensure only one instance is loaded or can be loaded.
*
* @return AIOSEO_Blocks
*/
public static function get() {
static $instance;
if ( is_null( $instance ) && ! ( $instance instanceof AIOSEO_Blocks ) ) {
$instance = new AIOSEO_Blocks();
}
return $instance;
}
/**
* Start creating batches.
*
* @param array $posts Posts to process.
*/
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() {
$posts = get_option( 'rank_math_aioseo_block_posts' );
delete_option( 'rank_math_aioseo_block_posts' );
Helper::add_notification(
// Translators: placeholder is the number of modified posts.
sprintf( _n( 'Blocks successfully converted in %d post.', 'Blocks successfully converted in %d posts.', $posts['count'], 'rank-math' ), $posts['count'] ),
[
'type' => 'success',
'id' => 'rank_math_aioseo_block_posts',
'classes' => 'rank-math-notice',
]
);
parent::complete();
}
/**
* Task to perform.
*
* @param string $posts Posts to process.
*/
public function wizard( $posts ) {
$this->task( $posts );
}
/**
* Task to perform.
*
* @param array $posts Posts to process.
*
* @return bool
*/
protected function task( $posts ) {
try {
remove_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10 );
$this->toc_converter = new AIOSEO_TOC_Converter();
foreach ( $posts as $post_id ) {
$post = get_post( $post_id );
$this->convert( $post );
}
return false;
} catch ( Exception $error ) {
return true;
}
}
/**
* Convert post.
*
* @param WP_Post $post Post object.
*/
public function convert( $post ) {
$dirty = false;
$blocks = $this->parse_blocks( $post->post_content );
$content = '';
if ( isset( $blocks['aioseo/table-of-contents'] ) && ! empty( $blocks['aioseo/table-of-contents'] ) ) {
$dirty = true;
$content = $this->toc_converter->replace( $post->post_content, $blocks['aioseo/table-of-contents'] );
}
if ( $dirty ) {
$post->post_content = $content;
wp_update_post( $post );
}
}
/**
* Find posts with AIOSEO blocks.
*
* @return array
*/
public function find_posts() {
$posts = get_option( 'rank_math_aioseo_block_posts' );
if ( false !== $posts ) {
return $posts;
}
// TOC Posts.
$args = [
's' => 'wp:aioseo/table-of-contents ',
'post_status' => 'any',
'numberposts' => -1,
'fields' => 'ids',
'no_found_rows' => true,
'post_type' => 'any',
];
$toc_posts = get_posts( $args );
$posts_data = [
'posts' => $toc_posts,
'count' => count( $toc_posts ),
];
update_option( 'rank_math_aioseo_block_posts', $posts_data, false );
return $posts_data;
}
/**
* Parse blocks to get data.
*
* @param string $content Post content to parse.
*
* @return array
*/
private function parse_blocks( $content ) {
$parsed_blocks = parse_blocks( $content );
$blocks = [];
foreach ( $parsed_blocks as $block ) {
if ( empty( $block['blockName'] ) ) {
continue;
}
$name = strtolower( $block['blockName'] );
if ( ! isset( $blocks[ $name ] ) || ! is_array( $blocks[ $name ] ) ) {
$blocks[ $name ] = [];
}
if ( ! isset( $block['innerContent'] ) ) {
$block['innerContent'] = [];
}
if ( 'aioseo/table-of-contents' === $name ) {
$block = $this->toc_converter->convert( $block );
$blocks[ $name ][] = \serialize_block( $block );
}
}
return $blocks;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* The AIOSEO TOC Block Converter.
*
* @since 1.0.104
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
defined( 'ABSPATH' ) || exit;
/**
* AIOSEO_TOC_Converter class.
*/
class AIOSEO_TOC_Converter {
/**
* Convert TOC blocks to Rank Math.
*
* @param array $block Block to convert.
*
* @return array
*/
public function convert( $block ) {
$attributes = $block['attrs'];
$headings = [];
$this->get_headings( $attributes['headings'], $headings );
$new_block = [
'blockName' => 'rank-math/toc-block',
'attrs' => [
'title' => '',
'headings' => $headings,
'listStyle' => $attributes['listStyle'] ?? 'ul',
'titleWrapper' => 'h2',
'excludeHeadings' => [],
],
];
$new_block['innerContent'][] = $this->get_html( $block['innerHTML'] );
return $new_block;
}
/**
* Replace block in content.
*
* @param string $post_content Post content.
* @param array $blocks Blocks.
*
* @return string
*/
public function replace( $post_content, $blocks ) {
preg_match_all( '/<!-- wp:aioseo\/table-of-contents.*-->.*<!-- \/wp:aioseo\/table-of-contents -->/iUs', $post_content, $matches );
foreach ( $matches[0] as $index => $match ) {
$post_content = \str_replace( $match, $blocks[ $index ], $post_content );
}
return $post_content;
}
/**
* Get headings from the content.
*
* @param array $data Block data.
* @param array $headings Headings.
*
* @return void
*/
public function get_headings( $data, &$headings ) {
foreach ( $data as $heading ) {
$headings[] = [
'key' => $heading['blockClientId'],
'link' => '#' . $heading['anchor'],
'content' => ! empty( $heading['editedContent'] ) ? $heading['editedContent'] : $heading['content'],
'level' => ! empty( $heading['editedLevel'] ) ? $heading['editedLevel'] : $heading['level'],
'disable' => ! empty( $heading['hidden'] ),
];
if ( ! empty( $heading['headings'] ) ) {
$this->get_headings( $heading['headings'], $headings );
}
}
}
/**
* Get TOC title.
*
* @param string $html Block HTML.
*
* @return string
*/
public function get_toc_title( $html ) {
preg_match( '#<h2.*?>(.*?)</h2>#i', $html, $found );
return ! empty( $found[1] ) ? $found[1] : '';
}
/**
* Generate HTML.
*
* @param string $html Block html.
*
* @return string
*/
private function get_html( $html ) {
$html = str_replace( 'wp-block-aioseo-table-of-contents', 'wp-block-rank-math-toc-block', $html );
$html = str_replace( '<div class="wp-block-rank-math-toc-block"><ul>', '<div class="wp-block-rank-math-toc-block"><nav><ul>', $html );
$html = str_replace( '</ul></div>', '</nav></ul></div>', $html );
return $html;
}
}

View File

@@ -0,0 +1,450 @@
<?php
/**
* The Database_Tools is responsible for the Database Tools inside Status & Tools.
*
* @package RankMath
* @subpackage RankMath\Database_Tools
*/
namespace RankMath\Tools;
use RankMath\Helper;
use RankMath\Helpers\Str;
use RankMath\Installer;
use RankMath\Traits\Hooker;
defined( 'ABSPATH' ) || exit;
/**
* Database_Tools class.
*/
class Database_Tools {
use Hooker;
/**
* Constructor.
*/
public function __construct() {
if ( Helper::is_heartbeat() || ! Helper::is_advanced_mode() ) {
return;
}
Yoast_Blocks::get();
AIOSEO_Blocks::get();
Remove_Schema::get();
Update_Score::get();
$this->hooks();
}
/**
* Register version control hooks.
*/
public function hooks() {
if ( ! Helper::is_plugin_active_for_network() || current_user_can( 'manage_options' ) ) {
$this->filter( 'rank_math/tools/pages', 'add_tools_page', 11 );
}
if ( Helper::is_rest() && Str::ends_with( 'toolsAction', add_query_arg( [] ) ) ) {
foreach ( $this->get_tools() as $id => $tool ) {
if ( ! method_exists( $this, $id ) ) {
continue;
}
add_filter( 'rank_math/tools/' . $id, [ $this, $id ] );
}
}
}
/**
* Display Tools data.
*/
public function display() {
?>
<table class='rank-math-status-table striped rank-math-tools-table widefat rank-math-box'>
<tbody class='tools'>
<?php foreach ( $this->get_tools() as $id => $tool ) : ?>
<tr class='<?php echo sanitize_html_class( $id ); ?>'>
<th>
<h4 class='name'><?php echo esc_html( $tool['title'] ); ?></h4>
<p class="description"><?php echo esc_html( $tool['description'] ); ?></p>
</th>
<td class='run-tool'>
<a href='#' class='button button-large button-link-delete tools-action' data-action='<?php echo esc_attr( $id ); ?>' data-confirm="<?php echo isset( $tool['confirm_text'] ) ? esc_attr( $tool['confirm_text'] ) : 'false'; ?>"><?php echo esc_html( $tool['button_text'] ); ?></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php
}
/**
* Function to clear all the transients from the database.
*/
public function clear_transients() {
global $wpdb;
$transients = $wpdb->get_col(
"SELECT `option_name` AS `name`
FROM $wpdb->options
WHERE `option_name` LIKE '%\\_transient\\_rank_math%'
ORDER BY `option_name`"
);
if ( empty( $transients ) ) {
return [
'status' => 'error',
'message' => __( 'No Rank Math transients found.', 'rank-math' ),
];
}
$count = 0;
foreach ( $transients as $transient ) {
delete_option( $transient );
$count++;
}
// Translators: placeholder is the number of transients deleted.
return sprintf( _n( '%d Rank Math transient cleared.', '%d Rank Math transients cleared.', $count, 'rank-math' ), $count );
}
/**
* Function to reset the SEO Analyzer.
*/
public function clear_seo_analysis() {
$stored = get_option( 'rank_math_seo_analysis_results' );
if ( empty( $stored ) ) {
return [
'status' => 'error',
'message' => __( 'SEO Analyzer data has already been cleared.', 'rank-math' ),
];
}
delete_option( 'rank_math_seo_analysis_results' );
delete_option( 'rank_math_seo_analysis_date' );
return __( 'SEO Analyzer data successfully deleted.', 'rank-math' );
}
/**
* Function to delete all the Internal Links data.
*/
public function delete_links() {
global $wpdb;
$exists = $wpdb->get_var( "SELECT EXISTS ( SELECT 1 FROM {$wpdb->prefix}rank_math_internal_links )" );
if ( empty( $exists ) ) {
return [
'status' => 'error',
'message' => __( 'No Internal Links data found.', 'rank-math' ),
];
}
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}rank_math_internal_links" );
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}rank_math_internal_meta" );
return __( 'Internal Links successfully deleted.', 'rank-math' );
}
/**
* Function to delete all the 404 log items.
*/
public function delete_log() {
global $wpdb;
$exists = $wpdb->get_var( "SELECT EXISTS ( SELECT 1 FROM {$wpdb->prefix}rank_math_404_logs )" );
if ( empty( $exists ) ) {
return [
'status' => 'error',
'message' => __( 'No 404 log data found.', 'rank-math' ),
];
}
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}rank_math_404_logs;" );
return __( '404 Log successfully deleted.', 'rank-math' );
}
/**
* Function to delete all Redirections data.
*/
public function delete_redirections() {
global $wpdb;
$exists = $wpdb->get_var( "SELECT EXISTS ( SELECT 1 FROM {$wpdb->prefix}rank_math_redirections )" );
if ( empty( $exists ) ) {
return [
'status' => 'error',
'message' => __( 'No Redirections found.', 'rank-math' ),
];
}
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}rank_math_redirections;" );
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}rank_math_redirections_cache;" );
return __( 'Redirection rules successfully deleted.', 'rank-math' );
}
/**
* Re-create Database Tables.
*
* @return string
*/
public function recreate_tables() {
// Base.
Installer::create_tables( get_option( 'rank_math_modules', [] ) );
// ActionScheduler.
$this->maybe_recreate_actionscheduler_tables();
// Analytics module.
if ( Helper::is_module_active( 'analytics' ) ) {
as_enqueue_async_action(
'rank_math/analytics/workflow/create_tables',
[],
'rank-math'
);
}
return __( 'Table re-creation started. It might take a couple of minutes.', 'rank-math' );
}
/**
* Recreate ActionScheduler tables if missing.
*/
public function maybe_recreate_actionscheduler_tables() {
global $wpdb;
if ( Helper::is_woocommerce_active() ) {
return;
}
if (
! class_exists( 'ActionScheduler_HybridStore' )
|| ! class_exists( 'ActionScheduler_StoreSchema' )
|| ! class_exists( 'ActionScheduler_LoggerSchema' )
) {
return;
}
$table_list = [
'actionscheduler_actions',
'actionscheduler_logs',
'actionscheduler_groups',
'actionscheduler_claims',
];
$found_tables = $wpdb->get_col( "SHOW TABLES LIKE '{$wpdb->prefix}actionscheduler%'" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
foreach ( $table_list as $table_name ) {
if ( ! in_array( $wpdb->prefix . $table_name, $found_tables, true ) ) {
$this->recreate_actionscheduler_tables();
return;
}
}
}
/**
* Force the data store schema updates.
*/
public function recreate_actionscheduler_tables() {
$store = new \ActionScheduler_HybridStore();
add_action( 'action_scheduler/created_table', [ $store, 'set_autoincrement' ], 10, 2 );
$store_schema = new \ActionScheduler_StoreSchema();
$logger_schema = new \ActionScheduler_LoggerSchema();
$store_schema->register_tables( true );
$logger_schema->register_tables( true );
remove_action( 'action_scheduler/created_table', [ $store, 'set_autoincrement' ], 10 );
}
/**
* Function to convert Yoast blocks in posts to Rank Math blocks (FAQ & HowTo).
*
* @return string
*/
public function yoast_blocks() {
$posts = Yoast_Blocks::get()->find_posts();
if ( empty( $posts['posts'] ) ) {
return [
'status' => 'error',
'message' => __( 'No posts found to convert.', 'rank-math' ),
];
}
Yoast_Blocks::get()->start( $posts['posts'] );
return __( 'Conversion started. A success message will be shown here once the process completes. You can close this page.', 'rank-math' );
}
/**
* Function to convert AIOSEO blocks in posts to Rank Math blocks (TOC).
*
* @return string
*/
public function aioseo_blocks() {
$posts = AIOSEO_Blocks::get()->find_posts();
if ( empty( $posts['posts'] ) ) {
return [
'status' => 'error',
'message' => __( 'No posts found to convert.', 'rank-math' ),
];
}
AIOSEO_Blocks::get()->start( $posts['posts'] );
return __( 'Conversion started. A success message will be shown here once the process completes. You can close this page.', 'rank-math' );
}
/**
* Function to delete old schema data.
*
* @return string
*/
public function delete_old_schema() {
$meta = Remove_Schema::get()->find();
if ( empty( $meta ) ) {
return [
'status' => 'error',
'message' => __( 'No data found to delete.', 'rank-math' ),
];
}
Remove_Schema::get()->start( $meta );
return __( 'Deletion started. A success message will be shown here once the process completes. You can close this page.', 'rank-math' );
}
/**
* Add subpage to Status & Tools screen.
*
* @param array $pages Pages.
* @return array New pages.
*/
public function add_tools_page( $pages ) {
$pages['tools'] = [
'url' => 'status',
'args' => 'view=tools',
'cap' => 'manage_options',
'title' => __( 'Database Tools', 'rank-math' ),
'class' => '\\RankMath\\Tools\\Database_Tools',
];
return $pages;
}
/**
* Get tools.
*
* @return array
*/
private function get_tools() {
$tools = [];
if ( Helper::is_module_active( 'seo-analysis' ) ) {
$tools['clear_seo_analysis'] = [
'title' => __( 'Flush SEO Analyzer Data', 'rank-math' ),
'description' => __( "Need a clean slate or not able to run the SEO Analyzer tool? Flushing the analysis data might fix the issue. Flushing SEO Analyzer data is entirely safe and doesn't remove any critical data from your website.", 'rank-math' ),
'button_text' => __( 'Clear SEO Analyzer', 'rank-math' ),
];
}
$tools['clear_transients'] = [
'title' => __( 'Remove Rank Math Transients', 'rank-math' ),
'description' => __( 'If you see any issue while using Rank Math or one of its options - clearing the Rank Math transients fixes the problem in most cases. Deleting transients does not delete ANY data added using Rank Math.', 'rank-math' ),
'button_text' => __( 'Remove transients', 'rank-math' ),
];
if ( Helper::is_module_active( '404-monitor' ) ) {
$tools['delete_log'] = [
'title' => __( 'Clear 404 Log', 'rank-math' ),
'description' => __( 'Is the 404 error log getting out of hand? Use this option to clear ALL 404 logs generated by your website in the Rank Math 404 Monitor.', 'rank-math' ),
'confirm_text' => __( 'Are you sure you want to delete the 404 log? This action is irreversible.', 'rank-math' ),
'button_text' => __( 'Clear 404 Log', 'rank-math' ),
];
}
$tools['recreate_tables'] = [
'title' => __( 'Re-create Missing Database Tables', 'rank-math' ),
'description' => __( 'Check if required tables exist and create them if not.', 'rank-math' ),
'button_text' => __( 'Re-create Tables', 'rank-math' ),
];
if ( Helper::is_module_active( 'analytics' ) ) {
$tools['analytics_fix_collations'] = [
'title' => __( 'Fix Analytics table collations', 'rank-math' ),
'description' => __( 'In some cases, the Analytics database tables or columns don\'t match with each other, which can cause database errors. This tool can fix that issue.', 'rank-math' ),
'button_text' => __( 'Fix Collations', 'rank-math' ),
];
}
$block_posts = Yoast_Blocks::get()->find_posts();
if ( is_array( $block_posts ) && ! empty( $block_posts['count'] ) ) {
$tools['yoast_blocks'] = [
'title' => __( 'Yoast Block Converter', 'rank-math' ),
'description' => __( 'Convert FAQ, HowTo, & Table of Contents Blocks created using Yoast. Use this option to easily move your previous blocks into Rank Math.', 'rank-math' ),
'confirm_text' => __( 'Are you sure you want to convert Yoast blocks into Rank Math blocks? This action is irreversible.', 'rank-math' ),
'button_text' => __( 'Convert Blocks', 'rank-math' ),
];
}
$aio_block_posts = AIOSEO_Blocks::get()->find_posts();
if ( is_array( $aio_block_posts ) && ! empty( $aio_block_posts['count'] ) ) {
$tools['aioseo_blocks'] = [
'title' => __( 'AIOSEO Block Converter', 'rank-math' ),
'description' => __( 'Convert TOC block created using AIOSEO. Use this option to easily move your previous blocks into Rank Math.', 'rank-math' ),
'confirm_text' => __( 'Are you sure you want to convert AIOSEO blocks into Rank Math blocks? This action is irreversible.', 'rank-math' ),
'button_text' => __( 'Convert Blocks', 'rank-math' ),
];
}
if ( Helper::is_module_active( 'link-counter' ) ) {
$tools['delete_links'] = [
'title' => __( 'Delete Internal Links Data', 'rank-math' ),
'description' => __( 'In some instances, the internal links data might show an inflated number or no number at all. Deleting the internal links data might fix the issue.', 'rank-math' ),
'confirm_text' => __( 'Are you sure you want to delete Internal Links Data? This action is irreversible.', 'rank-math' ),
'button_text' => __( 'Delete Internal Links', 'rank-math' ),
];
}
if ( Helper::is_module_active( 'redirections' ) ) {
$tools['delete_redirections'] = [
'title' => __( 'Delete Redirections Rules', 'rank-math' ),
'description' => __( 'Getting a redirection loop or need a fresh start? Delete all the redirections using this tool. Note: This process is irreversible and will delete ALL your redirection rules.', 'rank-math' ),
'confirm_text' => __( 'Are you sure you want to delete all the Redirection Rules? This action is irreversible.', 'rank-math' ),
'button_text' => __( 'Delete Redirections', 'rank-math' ),
];
}
if ( Helper::is_module_active( 'rich-snippet' ) && ! empty( Remove_Schema::get()->find() ) ) {
$tools['delete_old_schema'] = [
'title' => __( 'Delete Old Schema Data', 'rank-math' ),
'description' => __( 'Delete the schema data from the old format (<1.0.48). Note: This process is irreversible and will delete all the metadata prefixed with rank_math_snippet.', 'rank-math' ),
'confirm_text' => __( 'Are you sure you want to delete the old schema data? This action is irreversible.', 'rank-math' ),
'button_text' => __( 'Delete', 'rank-math' ),
];
}
if ( ! empty( Update_Score::get()->find() ) ) {
$tools['update_seo_score'] = [
'title' => __( 'Update SEO Scores', 'rank-math' ),
'description' => __( 'This tool will calculate the SEO score for the posts/pages that have a Focus Keyword set. Note: This process may take some time and the browser tab must be kept open while it is running.', 'rank-math' ),
'button_text' => __( 'Recalculate Scores', 'rank-math' ),
];
}
/**
* Filters the list of tools available on the Database Tools page.
*
* @param array $tools The tools.
*/
$tools = $this->do_filter( 'database/tools', $tools );
return $tools;
}
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* The Schema Remover tool to remove the meta data from the old format (<1.0.48).
*
* @since 1.0.65
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
use RankMath\Helper;
use RankMath\Admin\Database\Database;
defined( 'ABSPATH' ) || exit;
/**
* Remove_Schema class.
*/
class Remove_Schema extends \WP_Background_Process {
/**
* Action.
*
* @var string
*/
protected $action = 'delete_old_schema';
/**
* Main instance
*
* Ensure only one instance is loaded or can be loaded.
*
* @return Remove_Schema
*/
public static function get() {
static $instance;
if ( is_null( $instance ) && ! ( $instance instanceof Remove_Schema ) ) {
$instance = new Remove_Schema();
}
return $instance;
}
/**
* Start creating batches.
*
* @param array $meta_ids Posts to process.
*/
public function start( $meta_ids ) {
$chunks = array_chunk( $meta_ids, 100 );
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() {
$meta_ids = get_option( 'rank_math_old_schema_data' );
delete_option( 'rank_math_old_schema_data' );
Helper::add_notification(
sprintf( 'Rank Math: Deleted %d schema data successfully.', count( $meta_ids ) ),
[
'type' => 'success',
'id' => 'rank_math_remove_old_schema_data',
'classes' => 'rank-math-notice',
]
);
parent::complete();
}
/**
* Task to perform
*
* @param array $meta_ids Posts to process.
*
* @return bool
*/
protected function task( $meta_ids ) {
try {
foreach ( $meta_ids as $meta_id ) {
delete_metadata_by_mid( 'post', $meta_id );
}
return false;
} catch ( \Exception $error ) {
return true;
}
}
/**
* Find posts with old schema data.
*
* @return array
*/
public function find() {
$meta_ids = get_option( 'rank_math_old_schema_data' );
if ( false !== $meta_ids ) {
return $meta_ids;
}
// Schema Metadata.
$meta_ids = Database::table( 'postmeta' )
->distinct()
->select( 'meta_id' )
->whereLike( 'meta_key', 'rank_math_snippet', '' )
->get();
$meta_ids = wp_list_pluck( $meta_ids, 'meta_id' );
update_option( 'rank_math_old_schema_data', $meta_ids, false );
return $meta_ids;
}
}

View File

@@ -0,0 +1,314 @@
<?php
/**
* The tool to update SEO score on existing posts.
*
* @since 1.0.97
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
use RankMath\Helper;
use RankMath\Helpers\Param;
use RankMath\Traits\Hooker;
use RankMath\Paper\Paper;
use RankMath\Admin\Metabox\Screen;
use RankMath\Schema\DB;
defined( 'ABSPATH' ) || exit;
/**
* Update_Score class.
*/
class Update_Score {
use Hooker;
/**
* Batch size.
*
* @var int
*/
private $batch_size;
/**
* Screen object.
*
* @var object
*/
public $screen;
/**
* Constructor.
*/
public function __construct() {
$this->batch_size = absint( apply_filters( 'rank_math/recalculate_scores_batch_size', 25 ) );
$this->action( 'admin_footer', 'footer_modal' );
$this->filter( 'rank_math/tools/update_seo_score', 'update_seo_score' );
$this->screen = new Screen();
$this->screen->load_screen( 'post' );
if ( Param::get( 'page' ) === 'rank-math-status' && Param::get( 'view' ) === 'tools' ) {
$this->action( 'admin_enqueue_scripts', 'enqueue' );
}
}
/**
* Enqueue scripts & add JSON data needed to update the SEO score on existing posts.
*/
public function enqueue() {
$scripts = [
'lodash' => '',
'wp-data' => '',
'wp-core-data' => '',
'wp-compose' => '',
'wp-components' => '',
'wp-element' => '',
'wp-block-editor' => '',
'rank-math-analyzer' => rank_math()->plugin_url() . 'assets/admin/js/analyzer.js',
];
foreach ( $scripts as $handle => $src ) {
wp_enqueue_script( $handle, $src, [], rank_math()->version, true );
}
global $post;
$temp_post = $post;
if ( is_null( $post ) ) {
$posts = get_posts(
[
'fields' => 'id',
'posts_per_page' => 1,
'post_type' => $this->get_post_types(),
]
);
$post = isset( $posts[0] ) ? $posts[0] : null;
}
$this->screen->localize();
$post = $temp_post;
Helper::add_json( 'totalPostsWithoutScore', $this->find( false ) );
Helper::add_json( 'totalPosts', $this->find( true ) );
Helper::add_json( 'batchSize', $this->batch_size );
}
/**
* Function to Update the SEO score.
*/
public function update_seo_score() {
$args = Param::post( 'args', [], FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$offset = isset( $args['offset'] ) ? absint( $args['offset'] ) : 0;
// We get "paged" when running from the importer.
$paged = Param::post( 'paged', 0 );
if ( $paged ) {
$offset = ( $paged - 1 ) * $this->batch_size;
}
$update_all = ! isset( $args['update_all_scores'] ) || ! empty( $args['update_all_scores'] );
$query_args = [
'post_type' => $this->get_post_types(),
'posts_per_page' => $this->batch_size,
'offset' => $offset,
'orderby' => 'ID',
'order' => 'ASC',
'status' => 'any',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'rank_math_focus_keyword',
'value' => '',
'compare' => '!=',
],
],
];
if ( ! $update_all ) {
$query_args['meta_query'][] = [
'relation' => 'OR',
[
'key' => 'rank_math_seo_score',
'compare' => 'NOT EXISTS',
],
[
'key' => 'rank_math_seo_score',
'value' => '',
'compare' => '=',
],
];
}
$posts = get_posts( $query_args );
if ( empty( $posts ) ) {
return 'complete'; // Don't translate this string.
}
add_filter(
'rank_math/replacements/non_cacheable',
function( $non_cacheable ) {
$non_cacheable[] = 'excerpt';
$non_cacheable[] = 'excerpt_only';
$non_cacheable[] = 'seo_description';
$non_cacheable[] = 'keywords';
$non_cacheable[] = 'focuskw';
return $non_cacheable;
}
);
rank_math()->variables->setup();
$data = [];
foreach ( $posts as $post ) {
$post_id = $post->ID;
$post_type = $post->post_type;
$title = get_post_meta( $post_id, 'rank_math_title', true );
$title = $title ? $title : Paper::get_from_options( "pt_{$post_type}_title", $post, '%title% %sep% %sitename%' );
$keywords = array_map( 'trim', explode( ',', Helper::get_post_meta( 'focus_keyword', $post_id ) ) );
$keyword = $keywords[0];
$values = [
'title' => Helper::replace_vars( '%seo_title%', $post ),
'description' => Helper::replace_vars( '%seo_description%', $post ),
'keywords' => $keywords,
'keyword' => $keyword,
'content' => $post->post_content,
'url' => urldecode( get_the_permalink( $post_id ) ),
'hasContentAi' => ! empty( Helper::get_post_meta( 'contentai_score', $post_id ) ),
];
if ( has_post_thumbnail( $post_id ) ) {
$thumbnail_id = get_post_thumbnail_id( $post_id );
$values['thumbnail'] = get_the_post_thumbnail_url( $post_id );
$values['thumbnailAlt'] = get_post_meta( $thumbnail_id, '_wp_attachment_image_alt', true );
}
if (
( Helper::is_woocommerce_active() && 'product' === $post_type ) ||
( Helper::is_edd_active() && 'download' === $post_type )
) {
$values['isProduct'] = true;
$values['isReviewEnabled'] = 'yes' === get_option( 'woocommerce_enable_reviews', 'yes' );
$schemas = DB::get_schemas( $post_id );
if ( empty( $schemas ) && Helper::get_default_schema_type( $post_id ) ) {
$schemas = [
[ '@type' => Helper::get_default_schema_type( $post_id ) ],
];
}
$schemas = array_filter(
$schemas,
function( $schema ) {
return in_array( $schema['@type'], [ 'WooCommerceProduct', 'EDDProduct', 'Product' ], true );
}
);
$values['hasProductSchema'] = ! empty( $schemas );
}
/**
* Filter the values sent to the analyzer to calculate the SEO score.
*
* @param array $values The values to be sent to the analyzer.
*/
$data[ $post_id ] = $this->do_filter( 'recalculate_score/data', $values, $post_id );
}
return $data;
}
/**
* Ensure only one instance is loaded or can be loaded.
*
* @return Update_Score
*/
public static function get() {
static $instance;
if ( is_null( $instance ) && ! ( $instance instanceof Update_Score ) ) {
$instance = new Update_Score();
}
return $instance;
}
/**
* Find posts with focus keyword but no SEO score.
*
* @param bool $update_all Whether to update all posts or only those without a score.
* @return int
*/
public function find( $update_all = true ) {
global $wpdb;
$post_types = $this->get_post_types();
$placeholder = implode( ', ', array_fill( 0, count( $post_types ), '%s' ) );
$query = "SELECT COUNT(ID) FROM {$wpdb->posts} as p
LEFT JOIN {$wpdb->postmeta} as pm ON p.ID = pm.post_id AND pm.meta_key = 'rank_math_focus_keyword'
WHERE p.post_type IN ({$placeholder}) AND p.post_status = 'publish' AND pm.meta_value != ''";
if ( ! $update_all ) {
$query .= " AND (SELECT COUNT(*) FROM {$wpdb->postmeta} as pm2 WHERE pm2.post_id = p.ID AND pm2.meta_key = 'rank_math_seo_score' AND pm2.meta_value != '') = 0";
}
$update_score_post_ids = $wpdb->get_var( $wpdb->prepare( $query, $post_types ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- It's prepared above.
return (int) $update_score_post_ids;
}
/**
* Modal to show the Update SEO Score progress.
*
* @return array
*/
public function footer_modal() {
if ( Param::get( 'page' ) !== 'rank-math-status' || Param::get( 'view' ) !== 'tools' ) {
return;
}
?>
<div class="rank-math-modal rank-math-modal-update-score">
<div class="rank-math-modal-content">
<div class="rank-math-modal-header">
<h3><?php esc_html_e( 'Recalculating SEO Scores', 'rank-math' ); ?></h3>
<p><?php esc_html_e( 'This process may take a while. Please keep this window open until the process is complete.', 'rank-math' ); ?></p>
</div>
<div class="rank-math-modal-body">
<div class="count">
<?php esc_html_e( 'Calculated:', 'rank-math' ); ?> <span class="update-posts-done">0</span> / <span class="update-posts-total"><?php echo esc_html( $this->find() ); ?></span>
</div>
<div class="progress-bar">
<span></span>
</div>
<div class="rank-math-modal-footer hidden">
<p>
<?php esc_html_e( 'The SEO Scores have been recalculated successfully!', 'rank-math' ); ?>
</p>
<button class="button button-large rank-math-modal-close"><?php esc_html_e( 'Close', 'rank-math' ); ?></button>
</div>
</div>
</div>
</div>
<?php
}
/**
* Get post types.
*
* @return array
*/
private function get_post_types() {
$post_types = get_post_types( [ 'public' => true ] );
if ( isset( $post_types['attachment'] ) ) {
unset( $post_types['attachment'] );
}
return $this->do_filter( 'tool/post_types', array_keys( $post_types ) );
}
}

View File

@@ -0,0 +1,271 @@
<?php
/**
* The Yoast Block Converter imports editor blocks (FAQ, HowTo, Local Business) from Yoast to Rank Math.
*
* @since 1.0.37
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Yoast_Blocks class.
*/
class Yoast_Blocks extends \WP_Background_Process {
/**
* FAQ Converter.
*
* @var Yoast_FAQ_Converter
*/
private $faq_converter;
/**
* FAQ Converter.
*
* @var Yoast_HowTo_Converter
*/
private $howto_converter;
/**
* TOC Converter.
*
* @var Yoast_TOC_Converter
*/
private $toc_converter;
/**
* Local Converter.
*
* @var Yoast_Local_Converter
*/
private $local_converter;
/**
* Action.
*
* @var string
*/
protected $action = 'convert_yoast_blocks';
/**
* Main instance.
*
* Ensure only one instance is loaded or can be loaded.
*
* @return Yoast_Blocks
*/
public static function get() {
static $instance;
if ( is_null( $instance ) && ! ( $instance instanceof Yoast_Blocks ) ) {
$instance = new Yoast_Blocks();
}
return $instance;
}
/**
* Start creating batches.
*
* @param array $posts Posts to process.
*/
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() {
$posts = get_option( 'rank_math_yoast_block_posts' );
delete_option( 'rank_math_yoast_block_posts' );
Helper::add_notification(
// Translators: placeholder is the number of modified posts.
sprintf( _n( 'Blocks successfully converted in %d post.', 'Blocks successfully converted in %d posts.', $posts['count'], 'rank-math' ), $posts['count'] ),
[
'type' => 'success',
'id' => 'rank_math_yoast_block_posts',
'classes' => 'rank-math-notice',
]
);
parent::complete();
}
/**
* Task to perform.
*
* @param string $posts Posts to process.
*/
public function wizard( $posts ) {
$this->task( $posts );
}
/**
* Task to perform.
*
* @param array $posts Posts to process.
*
* @return bool
*/
protected function task( $posts ) {
try {
remove_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10 );
$this->faq_converter = new Yoast_FAQ_Converter();
$this->howto_converter = new Yoast_HowTo_Converter();
$this->local_converter = new Yoast_Local_Converter();
$this->toc_converter = new Yoast_TOC_Converter();
foreach ( $posts as $post_id ) {
$post = get_post( $post_id );
$this->convert( $post );
}
return false;
} catch ( Exception $error ) {
return true;
}
}
/**
* Convert post.
*
* @param WP_Post $post Post object.
*/
public function convert( $post ) {
$dirty = false;
$blocks = $this->parse_blocks( $post->post_content );
$content = '';
if ( isset( $blocks['yoast/faq-block'] ) && ! empty( $blocks['yoast/faq-block'] ) ) {
$dirty = true;
$content = $this->faq_converter->replace( $post->post_content, $blocks['yoast/faq-block'] );
}
if ( isset( $blocks['yoast/how-to-block'] ) && ! empty( $blocks['yoast/how-to-block'] ) ) {
$dirty = true;
$content = $this->howto_converter->replace( $post->post_content, $blocks['yoast/how-to-block'] );
}
if ( isset( $blocks['yoast-seo/table-of-contents'] ) && ! empty( $blocks['yoast-seo/table-of-contents'] ) ) {
$dirty = true;
$content = $this->toc_converter->replace( $post->post_content, $blocks['yoast-seo/table-of-contents'] );
}
if ( ! empty( array_intersect( array_keys( $blocks ), $this->local_converter->yoast_blocks ) ) ) {
$dirty = true;
$content = $this->local_converter->replace( $post->post_content, $blocks );
}
if ( $dirty ) {
$post->post_content = $content;
wp_update_post( $post );
}
}
/**
* Find posts with Yoast blocks.
*
* @return array
*/
public function find_posts() {
$posts = get_option( 'rank_math_yoast_block_posts' );
if ( false !== $posts ) {
return $posts;
}
// FAQs Posts.
$args = [
's' => 'wp:yoast/faq-block',
'post_status' => 'any',
'numberposts' => -1,
'fields' => 'ids',
'no_found_rows' => true,
'post_type' => 'any',
];
$faqs = get_posts( $args );
// HowTo Posts.
$args['s'] = 'wp:yoast/how-to-block';
$howto = get_posts( $args );
// TOC Posts.
$args['s'] = 'wp:yoast-seo/table-of-contents';
$toc = get_posts( $args );
// Local Business Posts.
$args['s'] = ':yoast-seo-local/';
$local_business = get_posts( $args );
$posts = array_merge( $faqs, $howto, $toc, $local_business );
$posts_data = [
'posts' => $posts,
'count' => count( $posts ),
];
update_option( 'rank_math_yoast_block_posts', $posts_data, false );
return $posts_data;
}
/**
* Parse blocks to get data.
*
* @param string $content Post content to parse.
*
* @return array
*/
private function parse_blocks( $content ) {
$parsed_blocks = parse_blocks( $content );
$blocks = [];
foreach ( $parsed_blocks as $block ) {
if ( empty( $block['blockName'] ) ) {
continue;
}
$name = strtolower( $block['blockName'] );
if ( ! isset( $blocks[ $name ] ) || ! is_array( $blocks[ $name ] ) ) {
$blocks[ $name ] = [];
}
if ( ! isset( $block['innerContent'] ) ) {
$block['innerContent'] = [];
}
if ( 'yoast/faq-block' === $name ) {
$block = $this->faq_converter->convert( $block );
$blocks[ $name ][] = \serialize_block( $block );
}
if ( 'yoast/how-to-block' === $name ) {
$block = $this->howto_converter->convert( $block );
$blocks[ $name ][] = \serialize_block( $block );
}
if ( 'yoast-seo/table-of-contents' === $name ) {
$block = $this->toc_converter->convert( $block );
$blocks[ $name ][] = \serialize_block( $block );
}
if ( in_array( $name, $this->local_converter->yoast_blocks, true ) ) {
$block = $this->local_converter->convert( $block );
$blocks[ $name ][] = \serialize_block( $block );
}
}
return $blocks;
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* The Yoast FAQ Block Converter.
*
* @since 1.0.37
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
defined( 'ABSPATH' ) || exit;
/**
* Yoast_FAQ_Converter class.
*/
class Yoast_FAQ_Converter {
/**
* Convert FAQ blocks to Rank Math.
*
* @param array $block Block to convert.
*
* @return array
*/
public function convert( $block ) {
$new_block = [
'blockName' => 'rank-math/faq-block',
'attrs' => [
'listStyle' => '',
'textAlign' => 'left',
'titleWrapper' => 'h3',
'listCssClasses' => '',
'titleCssClasses' => '',
'contentCssClasses' => '',
'questions' => array_map( [ $this, 'get_question' ], $block['attrs']['questions'] ),
'className' => isset( $block['attrs']['className'] ) ? $block['attrs']['className'] : '',
],
];
$new_block['innerContent'][] = $this->get_html( $new_block['attrs'] );
return $new_block;
}
/**
* Replace block in content.
*
* @param string $post_content Post content.
* @param array $blocks Blocks.
*
* @return string
*/
public function replace( $post_content, $blocks ) {
preg_match_all( '/<!-- wp:yoast\/faq-block.*-->.*<!-- \/wp:yoast\/faq-block -->/iUs', $post_content, $matches );
foreach ( $matches[0] as $index => $match ) {
$post_content = \str_replace( $match, $blocks[ $index ], $post_content );
}
return $post_content;
}
/**
* Format questions.
*
* @param array $question Question.
*
* @return array
*/
public function get_question( $question ) {
return [
'id' => uniqid( 'faq-question-' ),
'visible' => true,
'title' => $question['jsonQuestion'],
'content' => $question['jsonAnswer'],
];
}
/**
* Generate HTML.
*
* @param array $attributes Block attributes.
*
* @return string
*/
private function get_html( $attributes ) {
// HTML.
$out = [ '<div class="wp-block-rank-math-faq-block">' ];
// Questions.
foreach ( $attributes['questions'] as $question ) {
if ( empty( $question['title'] ) || empty( $question['content'] ) || empty( $question['visible'] ) ) {
continue;
}
$out[] = '<div class="rank-math-faq-item">';
$out[] = sprintf(
'<%1$s class="rank-math-question">%2$s</%1$s>',
$attributes['titleWrapper'],
$question['title']
);
$out[] = sprintf(
'<div class="rank-math-answer">%2$s</div>',
$attributes['titleWrapper'],
$question['content']
);
$out[] = '</div>';
}
$out[] = '</div>';
return join( '', $out );
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* The Yoast HowTo Block Converter.
*
* @since 1.0.37
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
defined( 'ABSPATH' ) || exit;
/**
* Yoast_HowTo_Converter class.
*/
class Yoast_HowTo_Converter {
/**
* Convert HowTo blocks to Rank Math.
*
* @param array $block Block to convert.
*
* @return array
*/
public function convert( $block ) {
$attrs = $block['attrs'];
$new_block = [
'blockName' => 'rank-math/howto-block',
'attrs' => [
'hasDuration' => isset( $attrs['hasDuration'] ) ? $attrs['hasDuration'] : '',
'days' => isset( $attrs['days'] ) ? $attrs['days'] : '',
'hours' => isset( $attrs['hours'] ) ? $attrs['hours'] : '',
'minutes' => isset( $attrs['minutes'] ) ? $attrs['minutes'] : '',
'description' => isset( $attrs['jsonDescription'] ) ? $attrs['jsonDescription'] : '',
'listStyle' => isset( $attrs['unorderedList'] ) && $attrs['unorderedList'] ? 'ol' : '',
'timeLabel' => isset( $attrs['durationText'] ) ? $attrs['durationText'] : '',
'textAlign' => 'left',
'titleWrapper' => 'h3',
'listCssClasses' => '',
'titleCssClasses' => '',
'contentCssClasses' => '',
'steps' => array_map( [ $this, 'get_step' ], $attrs['steps'] ),
'className' => isset( $attrs['className'] ) ? $attrs['className'] : '',
],
];
$new_block['innerContent'][] = $this->get_html( $new_block['attrs'] );
return $new_block;
}
/**
* Replace block in content.
*
* @param string $post_content Post content.
* @param array $blocks Blocks.
*
* @return string
*/
public function replace( $post_content, $blocks ) {
preg_match_all( '/<!-- wp:yoast\/how-to-block.*-->.*<!-- \/wp:yoast\/how-to-block -->/iUs', $post_content, $matches );
foreach ( $matches[0] as $index => $match ) {
$post_content = \str_replace( $match, $blocks[ $index ], $post_content );
}
return $post_content;
}
/**
* Format steps.
*
* @param array $step Steps.
*
* @return array
*/
public function get_step( $step ) {
return [
'id' => uniqid( 'howto-step-' ),
'visible' => true,
'title' => $step['jsonName'],
'content' => $step['jsonText'],
];
}
/**
* Generate HTML.
*
* @param array $attributes Block attributes.
*
* @return string
*/
private function get_html( $attributes ) {
// HTML.
$out = [ '<div class="wp-block-rank-math-howto-block">' ];
// Steps.
foreach ( $attributes['steps'] as $step ) {
if ( empty( $step['visible'] ) ) {
continue;
}
$out[] = '<div class="rank-math-howto-step">';
if ( ! empty( $step['title'] ) ) {
$out[] = sprintf(
'<%1$s class="rank-math-howto-title">%2$s</%1$s>',
$attributes['titleWrapper'],
$step['title']
);
}
if ( ! empty( $step['content'] ) ) {
$out[] = sprintf(
'<div class="rank-math-howto-content">%1$s</div>',
$step['content']
);
}
$out[] = '</div>';
}
$out[] = '</div>';
return join( '', $out );
}
}

View File

@@ -0,0 +1,142 @@
<?php
/**
* The Yoast Local Business Block Converter.
*
* @since 1.0.48
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Yoast_Local_Converter class.
*/
class Yoast_Local_Converter {
/**
* Yoast's Local Business Blocks.
*
* @var array
*/
public $yoast_blocks = [
'yoast-seo-local/store-locator',
'yoast-seo-local/address',
'yoast-seo-local/map',
'yoast-seo-local/opening-hours',
];
/**
* Convert Local Business blocks to Rank Math.
*
* @param array $block Block to convert.
*
* @return array
*/
public function convert( $block ) {
$block['attrs']['type'] = str_replace( 'yoast-seo-local/', '', $block['blockName'] );
$new_block = [
'blockName' => 'rank-math/local-business',
'attrs' => $this->get_attributes( $block['attrs'] ),
];
$new_block['innerContent'] = '';
return $new_block;
}
/**
* Replace block in content.
*
* @param string $post_content Post content.
* @param array $blocks Blocks.
*
* @return string
*/
public function replace( $post_content, $blocks ) {
foreach ( $blocks as $block_name => $block ) {
if ( ! in_array( $block_name, $this->yoast_blocks, true ) ) {
continue;
}
$block_name = str_replace( 'yoast-seo-local/', '', $block_name );
preg_match_all( "/<!-- wp:yoast-seo-local\/{$block_name}.*-->.*<!-- \/wp:yoast-seo-local\/{$block_name} -->/iUs", $post_content, $matches );
foreach ( $matches[0] as $index => $match ) {
$post_content = \str_replace( $match, $block[ $index ], $post_content );
}
}
return $post_content;
}
/**
* Get Block attributes.
*
* @param array $attrs Yoast Block Attributes.
*/
private function get_attributes( $attrs ) {
$default_opening_days = 'Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday';
if ( 'opening-hours' === $attrs['type'] ) {
$days = explode( ', ', $default_opening_days );
$default_days = [];
foreach ( $days as $day ) {
if ( isset( $attrs[ "show{$day}" ] ) ) {
$default_days[ $day ] = ! empty( $attrs[ "show{$day}" ] );
}
}
if ( ! empty( $default_days ) ) {
$default_opening_days = implode( ',', array_filter( array_keys( $default_days ) ) );
}
}
return [
'type' => isset( $attrs['type'] ) ? $attrs['type'] : 'address',
'locations' => 0,
'terms' => [],
'limit' => isset( $attrs['maxNumber'] ) ? $attrs['maxNumber'] : 0,
'show_company_name' => isset( $attrs['hideName'] ) ? ! $attrs['hideName'] : true,
'show_company_address' => isset( $attrs['hideCompanyAddress'] ) ? ! $attrs['hideCompanyAddress'] : true,
'show_on_one_line' => isset( $attrs['showOnOneLine'] ) ? ! $attrs['showOnOneLine'] : false,
'show_state' => isset( $attrs['showState'] ) ? $attrs['showState'] : true,
'show_country' => isset( $attrs['showCountry'] ) ? $attrs['showCountry'] : true,
'show_telephone' => isset( $attrs['showPhone'] ) ? $attrs['showPhone'] : true,
'show_secondary_number' => isset( $attrs['showPhone2nd'] ) ? $attrs['showPhone2nd'] : true,
'show_fax' => isset( $attrs['showFax'] ) ? $attrs['showFax'] : false,
'show_email' => isset( $attrs['showEmail'] ) ? $attrs['showEmail'] : true,
'show_url' => isset( $attrs['showURL'] ) ? $attrs['showURL'] : true,
'show_logo' => isset( $attrs['showLogo'] ) ? $attrs['showLogo'] : true,
'show_vat_id' => isset( $attrs['showVatId'] ) ? $attrs['showVatId'] : false,
'show_tax_id' => isset( $attrs['showTaxId'] ) ? $attrs['showTaxId'] : false,
'show_coc_id' => isset( $attrs['showCocId'] ) ? $attrs['showCocId'] : false,
'show_priceRange' => isset( $attrs['showPriceRange'] ) ? $attrs['showPriceRange'] : false,
'show_opening_hours' => isset( $attrs['showOpeningHours'] ) ? $attrs['showOpeningHours'] : false,
'show_days' => $default_opening_days,
'hide_closed_days' => isset( $attrs['hideClosedDays'] ) ? $attrs['hideClosedDays'] : false,
'show_opening_now_label' => isset( $attrs['showOpenLabel'] ) ? $attrs['showOpenLabel'] : false,
'opening_hours_note' => isset( $attrs['extraComment'] ) ? $attrs['extraComment'] : '',
'show_map' => isset( $attrs['showMap'] ) ? $attrs['showMap'] : false,
'map_type' => isset( $attrs['mapType'] ) ? $attrs['mapType'] : 'roadmap',
'map_width' => isset( $attrs['mapWidth'] ) ? $attrs['mapWidth'] : '500',
'map_height' => isset( $attrs['mapHeight'] ) ? $attrs['mapHeight'] : '300',
'zoom_level' => isset( $attrs['zoomLevel'] ) ? $attrs['zoomLevel'] : -1,
'allow_zoom' => true,
'allow_scrolling' => isset( $attrs['allowScrolling'] ) ? $attrs['allowScrolling'] : true,
'allow_dragging' => isset( $attrs['allowDragging'] ) ? $attrs['allowDragging'] : true,
'show_route_planner' => isset( $attrs['showRoute'] ) ? $attrs['showRoute'] : true,
'route_label' => Helper::get_settings( 'titles.route_label' ),
'show_category_filter' => isset( $attrs['showCategoryFilter'] ) ? $attrs['showCategoryFilter'] : false,
'show_marker_clustering' => isset( $attrs['markerClustering'] ) ? $attrs['markerClustering'] : true,
'show_infowindow' => isset( $attrs['defaultShowInfoWindow'] ) ? $attrs['defaultShowInfoWindow'] : true,
'show_radius' => isset( $attrs['showRadius'] ) ? $attrs['showRadius'] : true,
'show_nearest_location' => isset( $attrs['showNearest'] ) ? $attrs['showNearest'] : true,
'search_radius' => isset( $attrs['searchRadius'] ) ? $attrs['searchRadius'] : '10',
];
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* The Yoast TOC Block Converter.
*
* @since 1.0.104
* @package RankMath
* @subpackage RankMath\Status
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Tools;
use RankMath\Helpers\HTML;
defined( 'ABSPATH' ) || exit;
/**
* Yoast_TOC_Converter class.
*/
class Yoast_TOC_Converter {
/**
* Convert TOC blocks to Rank Math.
*
* @param array $block Block to convert.
*
* @return array
*/
public function convert( $block ) {
$exclude_headings = [];
if ( ! empty( $block['attrs']['maxHeadingLevel'] ) ) {
for ( $i = $block['attrs']['maxHeadingLevel'] + 1; $i <= 6; $i++ ) {
$exclude_headings[] = "h{$i}";
}
}
$new_block = [
'blockName' => 'rank-math/toc-block',
'attrs' => [
'title' => $this->get_toc_title( $block['innerHTML'] ),
'headings' => $this->get_headings( $block['innerHTML'] ),
'listStyle' => 'ul',
'titleWrapper' => 'h2',
'excludeHeadings' => $exclude_headings,
],
];
$new_block['innerContent'][] = $this->get_html( $block['innerHTML'] );
return $new_block;
}
/**
* Replace block in content.
*
* @param string $post_content Post content.
* @param array $blocks Blocks.
*
* @return string
*/
public function replace( $post_content, $blocks ) {
preg_match_all( '/<!-- wp:yoast-seo\/table-of-contents.*-->.*<!-- \/wp:yoast-seo\/table-of-contents -->/iUs', $post_content, $matches );
foreach ( $matches[0] as $index => $match ) {
$post_content = \str_replace( $match, $blocks[ $index ], $post_content );
}
return $post_content;
}
/**
* Extract headings from the block content.
*
* @param string $content Block content.
*
* @return array
*/
public function get_headings( $content ) {
preg_match_all( '|<a\s*href="([^"]+)"[^>]+>([^<]+)</a>|', $content, $matches );
if ( empty( $matches ) || empty( $matches[0] ) ) {
return [];
}
$headings = [];
foreach ( $matches[0] as $link ) {
$attrs = HTML::extract_attributes( $link );
$headings[] = [
'key' => uniqid( 'toc-' ),
'link' => $attrs['href'] ?? '',
'content' => wp_strip_all_tags( $link ),
'level' => $attrs['data-level'] ?? '',
'disable' => false,
];
}
return $headings;
}
/**
* Get TOC title.
*
* @param string $html Block HTML.
*
* @return string
*/
public function get_toc_title( $html ) {
preg_match( '#<h2.*?>(.*?)</h2>#i', $html, $found );
return ! empty( $found[1] ) ? $found[1] : '';
}
/**
* Generate HTML.
*
* @param string $html Block html.
*
* @return string
*/
private function get_html( $html ) {
$html = str_replace( 'wp-block-yoast-seo-table-of-contents yoast-table-of-contents', 'wp-block-rank-math-toc-block', $html );
$html = str_replace( '</h2><ul>', '</h2><nav><ul>', $html );
$html = str_replace( '</ul></div>', '</nav></ul></div>', $html );
$html = preg_replace( '/data-level="([^"]*)"/', '', $html );
return $html;
}
}