You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1343 lines
42 KiB
PHTML
1343 lines
42 KiB
PHTML
7 months ago
|
<?php
|
||
|
/**
|
||
|
* The AIO SEO Import Class
|
||
|
*
|
||
|
* @since 0.9.0
|
||
|
* @package RankMath
|
||
|
* @subpackage RankMath\Admin\Importers
|
||
|
* @author Rank Math <support@rankmath.com>
|
||
|
*/
|
||
|
|
||
|
namespace RankMath\Admin\Importers;
|
||
|
|
||
|
use RankMath\Helper;
|
||
|
use RankMath\Admin\Admin_Helper;
|
||
|
use RankMath\Redirections\Redirection;
|
||
|
use RankMath\Helpers\DB;
|
||
|
|
||
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
||
|
/**
|
||
|
* AIOSEO class.
|
||
|
*/
|
||
|
class AIOSEO extends Plugin_Importer {
|
||
|
|
||
|
/**
|
||
|
* The plugin name.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $plugin_name = 'All In One SEO Pack';
|
||
|
|
||
|
/**
|
||
|
* Plugin options meta key.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $meta_key = '_aioseop_';
|
||
|
|
||
|
/**
|
||
|
* Option keys to import and clean.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $option_keys = [ 'aioseo_options' ];
|
||
|
|
||
|
/**
|
||
|
* Choices keys to import.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $choices = [ 'settings', 'postmeta', 'termmeta', 'usermeta', 'redirections', 'locations' ];
|
||
|
|
||
|
/**
|
||
|
* AIOSEO settings.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
private $aio_settings = [];
|
||
|
|
||
|
/**
|
||
|
* Get the actions which can be performed for the plugin.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function get_choices() {
|
||
|
$choices = [
|
||
|
'settings' => esc_html__( 'Import Settings', 'rank-math' ) . Admin_Helper::get_tooltip( esc_html__( 'Import AIO SEO plugin settings, global meta, sitemap settings, etc.', 'rank-math' ) ),
|
||
|
'postmeta' => esc_html__( 'Import Post Meta', 'rank-math' ) . Admin_Helper::get_tooltip( esc_html__( 'Import meta information of your posts/pages like the titles, descriptions, robots meta, OpenGraph info, etc.', 'rank-math' ) ),
|
||
|
'usermeta' => esc_html__( 'Import Author Meta', 'rank-math' ) . Admin_Helper::get_tooltip( esc_html__( 'Import Social URLs of your author archive pages.', 'rank-math' ) ),
|
||
|
];
|
||
|
|
||
|
if ( DB::check_table_exists( 'aioseo_terms' ) ) {
|
||
|
$choices['termmeta'] = esc_html__( 'Import Term Meta', 'rank-math' ) . Admin_Helper::get_tooltip( esc_html__( 'Import meta information of your terms like the titles, descriptions, robots meta, OpenGraph info, etc.', 'rank-math' ) );
|
||
|
}
|
||
|
|
||
|
if ( DB::check_table_exists( 'aioseo_redirects' ) ) {
|
||
|
$choices['redirections'] = esc_html__( 'Import Redirections', 'rank-math' ) . Admin_Helper::get_tooltip( esc_html__( 'Import all the redirections you have already set up in AIO SEO Premium.', 'rank-math' ) );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $this->get_location_ids( true ) ) ) {
|
||
|
$choices['locations'] = esc_html__( 'Import Locations', 'rank-math' ) . Admin_Helper::get_tooltip( esc_html__( 'Import Locations Settings.', 'rank-math' ) );
|
||
|
}
|
||
|
|
||
|
return $choices;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Convert Yoast / AIO SEO variables if needed.
|
||
|
*
|
||
|
* @param string $string Value to convert.
|
||
|
* @return string
|
||
|
*/
|
||
|
public function convert_variables( $string ) {
|
||
|
$string = str_replace( '#site_title', '%sitename%', $string );
|
||
|
$string = str_replace( '#tagline', '%sitedesc%', $string );
|
||
|
$string = str_replace( '#separator_sa', '%sep%', $string );
|
||
|
$string = str_replace( '#post_title', '%title%', $string );
|
||
|
$string = str_replace( '#post_excerpt', '%excerpt%', $string );
|
||
|
$string = str_replace( '#post_content', '%excerpt%', $string );
|
||
|
$string = str_replace( '#taxonomy_description', '%term_description%', $string );
|
||
|
$string = str_replace( '#category_description', '%term_description%', $string );
|
||
|
$string = str_replace( '#taxonomy_title', '%term%', $string );
|
||
|
$string = str_replace( '#category', '%term%', $string );
|
||
|
$string = str_replace( '#author_first_name #author_last_name', '%name%', $string );
|
||
|
$string = str_replace( '#current_year', '%currentyear%', $string );
|
||
|
$string = str_replace( '#current_date', '%currentdate%', $string );
|
||
|
$string = str_replace( '#current_day', '%currentday%', $string );
|
||
|
$string = str_replace( '#current_month', '%currentmonth%', $string );
|
||
|
$string = str_replace( '#post_date', '%date%', $string );
|
||
|
$string = str_replace( '#search_term', '%search_query%', $string );
|
||
|
$string = str_replace( '#author_link', '%AUTHORLINK%', $string );
|
||
|
$string = str_replace( '#post_link', '%POSTLINK%', $string );
|
||
|
$string = str_replace( '#site_link', '%BLOGLINK%', $string );
|
||
|
$string = str_replace( '#author_name', '%name%', $string );
|
||
|
$string = str_replace( '#author_bio', '%user_description%', $string );
|
||
|
$string = str_replace( '#archive_date', '%date%', $string );
|
||
|
$string = str_replace( '#breadcrumb_archive_post_type_name', '%s', $string );
|
||
|
$string = str_replace( '#breadcrumb_search_string', '%s', $string );
|
||
|
|
||
|
return $string;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import settings of plugin.
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
protected function settings() {
|
||
|
$this->get_settings();
|
||
|
$this->aio_settings = json_decode( get_option( 'aioseo_options' ), true );
|
||
|
|
||
|
$this->general_settings();
|
||
|
$this->sitemap_settings();
|
||
|
$this->titles_settings();
|
||
|
$this->pro_settings();
|
||
|
$this->update_settings();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Imports redirections data.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function redirections() {
|
||
|
$count = 0;
|
||
|
$table = DB::query_builder( 'aioseo_redirects' );
|
||
|
$redirections = $table->select( '*' )->get();
|
||
|
|
||
|
if ( empty( $redirections ) ) {
|
||
|
return compact( 'count' );
|
||
|
}
|
||
|
|
||
|
Helper::update_modules( [ 'redirections' => 'on' ] );
|
||
|
foreach ( $redirections as $redirection ) {
|
||
|
if ( false !== $this->save_redirection( (array) $redirection ) ) {
|
||
|
$count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return compact( 'count' );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save redirection.
|
||
|
*
|
||
|
* @param array $redirection Redirection object.
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
private function save_redirection( $redirection ) {
|
||
|
if (
|
||
|
empty( $redirection['source_url'] ) ||
|
||
|
empty( $redirection['type'] ) ||
|
||
|
! in_array( $redirection['type'], [ '301', '302', '307', '410', '451' ], true )
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$item = Redirection::from(
|
||
|
[
|
||
|
'sources' => [
|
||
|
[
|
||
|
'ignore' => ! empty( $redirection['ignore_case'] ) ? 'case' : '',
|
||
|
'pattern' => $redirection['source_url'],
|
||
|
'comparison' => isset( $redirection['source_url_match'] ) && 'regex' === $redirection['source_url_match'] ? 'regex' : 'exact',
|
||
|
],
|
||
|
],
|
||
|
'url_to' => isset( $redirection['target_url'] ) ? $redirection['target_url'] : '',
|
||
|
'header_code' => isset( $redirection['type'] ) ? $redirection['type'] : '301',
|
||
|
'status' => empty( $redirection['enabled'] ) ? 'inactive' : 'active',
|
||
|
]
|
||
|
);
|
||
|
|
||
|
return $item->save();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import General Settings.
|
||
|
*/
|
||
|
private function general_settings() {
|
||
|
if ( ! empty( $this->aio_settings['rssContent'] ) ) {
|
||
|
$hash = [
|
||
|
'before' => 'rss_before_content',
|
||
|
'after' => 'rss_after_content',
|
||
|
];
|
||
|
$this->replace( $hash, $this->aio_settings['rssContent'], $this->settings, 'convert_variables' );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $this->aio_settings['breadcrumbs'] ) ) {
|
||
|
$hash = [
|
||
|
'enable' => 'breadcrumbs',
|
||
|
'separator' => 'breadcrumbs_separator',
|
||
|
'homepageLabel' => 'breadcrumbs_home_label',
|
||
|
'breadcrumbPrefix' => 'breadcrumbs_prefix',
|
||
|
'archiveFormat' => 'breadcrumbs_archive_format',
|
||
|
'searchResultFormat' => 'breadcrumbs_search_format',
|
||
|
'errorFormat404' => 'breadcrumbs_404_label',
|
||
|
'showCurrentItem' => 'breadcrumbs_remove_post_title',
|
||
|
];
|
||
|
$this->replace( $hash, $this->aio_settings['breadcrumbs'], $this->settings, 'convert_variables' );
|
||
|
$this->replace( [ 'homepageLink' => 'breadcrumbs_home' ], $this->aio_settings['breadcrumbs'], $this->settings, 'convert_bool' );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $this->aio_settings['webmasterTools'] ) ) {
|
||
|
$hash = [
|
||
|
'google' => 'google_verify',
|
||
|
'bing' => 'bing_verify',
|
||
|
'baidu' => 'baidu_verify',
|
||
|
'yandex' => 'yandex_verify',
|
||
|
'pinterest' => 'pinterest_verify',
|
||
|
];
|
||
|
$this->replace( $hash, $this->aio_settings['webmasterTools'], $this->settings );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sitemap settings.
|
||
|
*/
|
||
|
private function sitemap_settings() {
|
||
|
if ( empty( $this->aio_settings['sitemap'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$sitemap_settings = $this->aio_settings['sitemap'];
|
||
|
$general = ! empty( $sitemap_settings['general'] ) ? $sitemap_settings['general'] : [];
|
||
|
if ( empty( $general ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Sitemap.
|
||
|
if ( isset( $general['enable'] ) ) {
|
||
|
Helper::update_modules( [ 'sitemap' => 'on' ] );
|
||
|
}
|
||
|
|
||
|
$this->sitemap['items_per_page'] = $general['linksPerIndex'];
|
||
|
|
||
|
$all = ! empty( $general['postTypes']['all'] );
|
||
|
foreach ( Helper::get_accessible_post_types() as $post_type ) {
|
||
|
$this->sitemap[ "pt_{$post_type}_sitemap" ] = $all || in_array( $post_type, $general['postTypes']['included'], true ) ? 'on' : 'off';
|
||
|
}
|
||
|
|
||
|
$all = ! empty( $general['taxonomies']['all'] );
|
||
|
foreach ( Helper::get_accessible_taxonomies() as $taxonomy => $object ) {
|
||
|
$this->sitemap[ "tax_{$taxonomy}_sitemap" ] = $all || in_array( $taxonomy, $general['taxonomies']['included'], true ) ? 'on' : 'off';
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $general['advancedSettings'] ) ) {
|
||
|
$this->sitemap_advanced_settings( $general['advancedSettings'] );
|
||
|
}
|
||
|
|
||
|
// HTML Sitemap.
|
||
|
if ( isset( $sitemap_settings['html'] ) ) {
|
||
|
$this->html_sitemap_settings( $sitemap_settings['html'] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Pro Settings.
|
||
|
*/
|
||
|
private function pro_settings() {
|
||
|
$settings = get_option( 'aioseo_options_pro' );
|
||
|
if ( empty( $settings ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$settings = json_decode( $settings, true );
|
||
|
$this->news_sitemap_settings( $settings );
|
||
|
$this->video_sitemap_settings( $settings );
|
||
|
$this->image_seo_settings( $settings );
|
||
|
$this->local_seo_settings( $settings );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Local SEO Settings.
|
||
|
*
|
||
|
* @param array $settings Pro Settings.
|
||
|
*/
|
||
|
private function local_seo_settings( $settings ) {
|
||
|
if ( empty( $settings['localBusiness'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Helper::update_modules( [ 'local-seo' => 'on' ] );
|
||
|
$local_settings = $settings['localBusiness'];
|
||
|
$business = $local_settings['locations']['business'];
|
||
|
|
||
|
$hash = [
|
||
|
'name' => 'knowledgegraph_name',
|
||
|
'image' => 'knowledgegraph_logo',
|
||
|
'businessType' => 'local_business_type',
|
||
|
];
|
||
|
$this->replace( $hash, $business, $this->titles );
|
||
|
$this->titles['url'] = $business['urls']['website'];
|
||
|
|
||
|
// Street Address.
|
||
|
$address = [];
|
||
|
$hash = [
|
||
|
'streetLine1' => 'streetAddress',
|
||
|
'city' => 'addressLocality',
|
||
|
'state' => 'addressRegion',
|
||
|
'zipCode' => 'postalCode',
|
||
|
'country' => 'addressCountry',
|
||
|
];
|
||
|
$this->replace( $hash, $business['address'], $address );
|
||
|
if ( ! empty( $business['address']['streetLine2'] ) ) {
|
||
|
$address['streetAddress'] = $address['streetAddress'] . ', ' . $business['address']['streetLine2'];
|
||
|
}
|
||
|
$this->titles['local_address'] = $address;
|
||
|
|
||
|
if ( ! empty( $business['contact'] ) ) {
|
||
|
$this->titles['email'] = $business['contact']['email'];
|
||
|
|
||
|
$this->titles['phone_numbers'][] = [
|
||
|
'type' => 'customer support',
|
||
|
'number' => $business['contact']['phone'],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $business['payment'] ) ) {
|
||
|
$this->titles['price_range'] = $business['payment']['priceRange'];
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $local_settings['openingHours'] ) ) {
|
||
|
$this->add_opening_hours( $local_settings['openingHours'] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Opening Hours Settings.
|
||
|
*
|
||
|
* @param array $opening_hours Opening Hours.
|
||
|
*/
|
||
|
private function add_opening_hours( $opening_hours ) {
|
||
|
$data = [];
|
||
|
foreach ( $opening_hours['days'] as $day => $opening_hour ) {
|
||
|
if ( ! empty( $opening_hour['closed'] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$data[] = [
|
||
|
'day' => ucfirst( $day ),
|
||
|
'time' => $opening_hour['openTime'] . '-' . $opening_hour['closeTime'],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$this->titles['opening_hours'] = $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Image SEO Settings.
|
||
|
*
|
||
|
* @param array $settings Pro Settings.
|
||
|
*/
|
||
|
private function image_seo_settings( $settings ) {
|
||
|
if ( empty( $settings['image']['format'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Helper::update_modules( [ 'image-seo' => 'on' ] );
|
||
|
$format = $settings['image']['format'];
|
||
|
if ( ! empty( $format['title'] ) ) {
|
||
|
$this->settings['add_img_title'] = $this->convert_variables( $format['title'] );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $format['altTag'] ) ) {
|
||
|
$this->settings['add_img_title'] = $this->convert_variables( $format['altTag'] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Video Sitemap Settings.
|
||
|
*
|
||
|
* @param array $settings Pro Settings.
|
||
|
*/
|
||
|
private function video_sitemap_settings( $settings ) {
|
||
|
if ( empty( $settings['sitemap']['video'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
$video_settings = $settings['sitemap']['video'];
|
||
|
if ( ! empty( $video_settings['enable'] ) ) {
|
||
|
Helper::update_modules( [ 'video-sitemap' => 'on' ] );
|
||
|
}
|
||
|
|
||
|
$this->sitemap['video_sitemap_post_type'] = $video_settings['postTypes']['all'] ? array_keys( Helper::get_accessible_post_types() ) : $video_settings['postTypes']['included'];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import News Sitemap Settings.
|
||
|
*
|
||
|
* @param array $settings Pro Settings.
|
||
|
*/
|
||
|
private function news_sitemap_settings( $settings ) {
|
||
|
if ( empty( $settings['sitemap']['news'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
$news_settings = $settings['sitemap']['news'];
|
||
|
if ( ! empty( $news_settings['enable'] ) ) {
|
||
|
Helper::update_modules( [ 'news-sitemap' => 'on' ] );
|
||
|
}
|
||
|
|
||
|
$this->sitemap['news_sitemap_publication_name'] = ! empty( $news_settings['publicationName'] ) ? $news_settings['publicationName'] : '';
|
||
|
$this->sitemap['news_sitemap_post_type'] = $news_settings['postTypes']['all'] ? array_keys( Helper::get_accessible_post_types() ) : $news_settings['postTypes']['included'];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Sitemap Advanced Settings.
|
||
|
*
|
||
|
* @param array $settings Sitemap Settings.
|
||
|
*/
|
||
|
private function sitemap_advanced_settings( $settings ) {
|
||
|
if ( ! empty( $settings['excludePosts'] ) ) {
|
||
|
$exclude_posts = [];
|
||
|
foreach ( $settings['excludePosts'] as $exclude_post ) {
|
||
|
$exclude_post = json_decode( $exclude_post, true );
|
||
|
$exclude_posts[] = ! empty( $exclude_post['value'] ) ? $exclude_post['value'] : '';
|
||
|
}
|
||
|
|
||
|
$this->sitemap['exclude_posts'] = implode( ', ', $exclude_posts );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $settings['excludeTerms'] ) ) {
|
||
|
$exclude_terms = [];
|
||
|
foreach ( $settings['excludeTerms'] as $exclude_term ) {
|
||
|
$exclude_term = json_decode( $exclude_term, true );
|
||
|
$exclude_terms[] = ! empty( $exclude_term['value'] ) ? $exclude_term['value'] : '';
|
||
|
}
|
||
|
|
||
|
$this->sitemap['exclude_terms'] = $exclude_terms;
|
||
|
}
|
||
|
|
||
|
$this->sitemap['include_images'] = ! empty( $settings['excludeImages'] ) ? 'off' : 'on';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import HTML Sitemap Settings.
|
||
|
*
|
||
|
* @param array $settings HTML Settings.
|
||
|
*/
|
||
|
private function html_sitemap_settings( $settings ) {
|
||
|
if ( empty( $settings ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->sitemap['html_sitemap'] = $settings['enable'] ? 'on' : 'off';
|
||
|
$this->sitemap['html_sitemap_display'] = empty( $settings['pageUrl'] ) ? 'shortcode' : 'page';
|
||
|
if ( ! empty( $settings['pageUrl'] ) ) {
|
||
|
$page = get_page_by_path( basename( $settings['pageUrl'] ) );
|
||
|
if ( ! empty( $page ) ) {
|
||
|
$this->sitemap['html_sitemap_page'] = $page->ID;
|
||
|
} else {
|
||
|
// Create a new page with the sitemap page url.
|
||
|
$this->sitemap['html_sitemap_page'] = wp_insert_post(
|
||
|
[
|
||
|
'post_title' => __( 'HTML Sitemap', 'rank-math' ),
|
||
|
'post_content' => '',
|
||
|
'post_status' => 'publish',
|
||
|
'post_type' => 'page',
|
||
|
'post_name' => basename( $settings['pageUrl'] ),
|
||
|
]
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $settings['postTypes']['all'] ) ) {
|
||
|
$post_types = Helper::get_accessible_post_types();
|
||
|
$post_types = array_keys( $post_types );
|
||
|
foreach ( $post_types as $post_type ) {
|
||
|
$this->sitemap[ 'pt_' . $post_type . '_html_sitemap' ] = in_array( $post_type, $settings['postTypes']['included'], true ) ? 'on' : 'off';
|
||
|
}
|
||
|
} else {
|
||
|
foreach ( $settings['postTypes']['included'] as $post_type ) {
|
||
|
$this->sitemap[ 'pt_' . $post_type . '_html_sitemap' ] = 'on';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $settings['taxonomies']['all'] ) ) {
|
||
|
$taxonomies = Helper::get_accessible_taxonomies();
|
||
|
$taxonomies = array_keys( $taxonomies );
|
||
|
foreach ( $taxonomies as $taxonomy ) {
|
||
|
$this->sitemap[ 'tax_' . $taxonomy . '_html_sitemap' ] = in_array( $taxonomy, $settings['taxonomies']['included'], true ) ? 'on' : 'off';
|
||
|
}
|
||
|
} else {
|
||
|
foreach ( $settings['taxonomies']['included'] as $taxonomy ) {
|
||
|
$this->sitemap[ 'tax_' . $taxonomy . '_html_sitemap' ] = 'on';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Titles & Meta Settings.
|
||
|
*/
|
||
|
private function titles_settings() {
|
||
|
$settings = $this->aio_settings['searchAppearance'];
|
||
|
$hash = [
|
||
|
'separator' => 'title_separator',
|
||
|
'siteTitle' => 'homepage_title',
|
||
|
'metaDescription' => 'homepage_description',
|
||
|
];
|
||
|
|
||
|
$this->replace( $hash, $settings['global'], $this->titles, 'convert_variables' );
|
||
|
|
||
|
$this->titles['noindex_empty_taxonomies'] = $settings['advanced']['noIndexEmptyCat'];
|
||
|
$this->titles['knowledgegraph_type'] = 'organization' === $settings['global']['schema']['siteRepresents'] ? 'company' : 'person';
|
||
|
$this->titles['knowledgegraph_name'] = $settings['global']['schema']['organizationName'];
|
||
|
$this->titles['knowledgegraph_logo'] = $settings['global']['schema']['organizationLogo'];
|
||
|
|
||
|
$robots = $this->get_robots_data( $settings['advanced']['globalRobotsMeta'] );
|
||
|
|
||
|
$this->titles['robots_global'] = $robots['robots'];
|
||
|
$this->titles['advanced_robots_global'] = $robots['advanced_robots'];
|
||
|
|
||
|
$this->social_settings();
|
||
|
$this->archive_settings();
|
||
|
$this->post_types_settings();
|
||
|
$this->taxonomies_settings();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Social Settings.
|
||
|
*/
|
||
|
private function social_settings() {
|
||
|
if ( empty( $this->aio_settings['social'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$hash = [
|
||
|
'adminId' => 'facebook_admin_id',
|
||
|
'appId' => 'facebook_app_id',
|
||
|
'authorUrl' => 'facebook_author_urls',
|
||
|
];
|
||
|
$this->replace( $hash, $this->aio_settings['social']['facebook']['advanced'], $this->titles );
|
||
|
|
||
|
$hash = [
|
||
|
'title' => 'homepage_facebook_title',
|
||
|
'description' => 'homepage_facebook_description',
|
||
|
'image' => 'homepage_facebook_image',
|
||
|
];
|
||
|
$this->replace( $hash, $this->aio_settings['social']['facebook']['homePage'], $this->titles );
|
||
|
|
||
|
$profiles = $this->aio_settings['social']['profiles'];
|
||
|
$profile_urls = $profiles['urls'];
|
||
|
$fb_url = $profile_urls['facebookPageUrl'];
|
||
|
$tw_url = $profile_urls['twitterUrl'];
|
||
|
$additional_urls = $profiles['additionalUrls'];
|
||
|
|
||
|
$profile_urls = array_map(
|
||
|
function( $url ) use ( $fb_url, $tw_url ) {
|
||
|
return $url !== $fb_url && $url !== $tw_url ? $url : false;
|
||
|
},
|
||
|
$profile_urls
|
||
|
);
|
||
|
|
||
|
$urls = array_filter( array_values( $profile_urls ) );
|
||
|
array_merge( $urls, explode( "\n", $additional_urls ) );
|
||
|
|
||
|
$this->titles['social_additional_profiles'] = implode( PHP_EOL, $urls );
|
||
|
$this->titles['social_url_facebook'] = $fb_url;
|
||
|
$this->titles['twitter_author_names'] = str_replace( 'https://twitter.com/', '', $tw_url );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Archive settings.
|
||
|
*/
|
||
|
private function archive_settings() {
|
||
|
$settings = $this->aio_settings['searchAppearance']['archives'];
|
||
|
$author = $settings['author'];
|
||
|
$hash = [
|
||
|
'title' => 'author_archive_title',
|
||
|
'metaDescription' => 'author_archive_description',
|
||
|
];
|
||
|
$this->replace( $hash, $author, $this->titles, 'convert_variables' );
|
||
|
$this->titles['disable_author_archives'] = $author['show'] ? 'off' : 'on';
|
||
|
$this->titles['author_add_meta_box'] = $author['advanced']['showMetaBox'];
|
||
|
$this->titles['author_custom_robots'] = ! $author['advanced']['robotsMeta']['default'];
|
||
|
$robots = $this->get_robots_data( $author['advanced']['robotsMeta'] );
|
||
|
$this->titles['author_robots'] = $robots['robots'];
|
||
|
$this->titles['author_advanced_robots'] = $robots['advanced_robots'];
|
||
|
|
||
|
$date = $settings['date'];
|
||
|
$hash = [
|
||
|
'title' => 'date_archive_title',
|
||
|
'metaDescription' => 'date_archive_description',
|
||
|
];
|
||
|
$this->replace( $hash, $date, $this->titles, 'convert_variables' );
|
||
|
$this->titles['disable_date_archives'] = $date['show'] ? 'off' : 'on';
|
||
|
$robots = $this->get_robots_data( $date['advanced']['robotsMeta'] );
|
||
|
$this->titles['date_archive_robots'] = $robots['robots'];
|
||
|
$this->titles['date_advanced_robots'] = $robots['advanced_robots'];
|
||
|
|
||
|
$this->titles['search_title'] = $this->convert_variables( $settings['search']['title'] );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Post Types settings.
|
||
|
*/
|
||
|
private function post_types_settings() {
|
||
|
$settings = $this->aio_settings['searchAppearance']['dynamic']['postTypes'];
|
||
|
foreach ( Helper::get_accessible_post_types() as $post_type ) {
|
||
|
if ( empty( $settings[ $post_type ] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$hash = [
|
||
|
'title' => "pt_{$post_type}_title",
|
||
|
'metaDescription' => "pt_{$post_type}_description",
|
||
|
'customFields' => "pt_{$post_type}_analyze_fields",
|
||
|
];
|
||
|
$this->replace( $hash, $settings[ $post_type ], $this->titles, 'convert_variables' );
|
||
|
|
||
|
if ( ! empty( $settings[ $post_type ]['schemaType'] ) ) {
|
||
|
$schema_type = strtolower( $settings[ $post_type ]['schemaType'] );
|
||
|
if ( in_array( $schema_type, [ 'article', 'book', 'course', 'dataset', 'event', 'jobposting', 'movie', 'music', 'person', 'product', 'recipe', 'restaurant', 'service', 'software', 'video' ], true ) ) {
|
||
|
$this->titles[ "pt_{$post_type}_default_rich_snippet" ] = $schema_type;
|
||
|
$this->titles[ "pt_{$post_type}_default_article_type" ] = $settings[ $post_type ]['articleType'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$robots = $settings[ $post_type ]['advanced']['robotsMeta'];
|
||
|
if ( ! empty( $robots['default'] ) ) {
|
||
|
$this->titles[ "pt_{$post_type}_custom_robots" ] = 'off';
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$robots = $this->get_robots_data( $robots );
|
||
|
$this->titles[ "pt_{$post_type}_custom_robots" ] = 'on';
|
||
|
$this->titles[ "pt_{$post_type}_robots" ] = $robots['robots'];
|
||
|
$this->titles[ "pt_{$post_type}_advanced_robots" ] = $robots['advanced_robots'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Taxonomies settings.
|
||
|
*/
|
||
|
private function taxonomies_settings() {
|
||
|
if ( ! isset( $this->aio_settings['searchAppearance']['dynamic']['taxonomies'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$settings = $this->aio_settings['searchAppearance']['dynamic']['taxonomies'];
|
||
|
foreach ( Helper::get_accessible_taxonomies() as $taxonomy => $tax_obj ) {
|
||
|
if ( empty( $settings[ $taxonomy ] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$hash = [
|
||
|
'title' => "tax_{$taxonomy}_title",
|
||
|
'metaDescription' => "tax_{$taxonomy}_description",
|
||
|
];
|
||
|
$this->replace( $hash, $settings[ $taxonomy ], $this->titles, 'convert_variables' );
|
||
|
|
||
|
$robots = $this->get_robots_data( $settings[ $taxonomy ]['advanced']['robotsMeta'] );
|
||
|
$this->titles[ "tax_{$taxonomy}_robots" ] = $robots['robots'];
|
||
|
$this->titles[ "tax_{$taxonomy}_advanced_robots" ] = $robots['advanced_robots'];
|
||
|
$this->titles[ "tax_{$taxonomy}_add_meta_box" ] = ! empty( $settings[ $taxonomy ]['show'] ) ? 'on' : '';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Function to get Robots data.
|
||
|
*
|
||
|
* @param array $aioseo_robots AIOSEO robots.
|
||
|
* @return array Robots data.
|
||
|
*/
|
||
|
private function get_robots_data( $aioseo_robots ) {
|
||
|
$robots = [];
|
||
|
$advanced_robots = [];
|
||
|
$keys = [
|
||
|
'maxSnippet' => 'max-snippet',
|
||
|
'maxVideoPreview' => 'max-video-preview',
|
||
|
'maxImagePreview' => 'max-image-preview',
|
||
|
];
|
||
|
foreach ( $aioseo_robots as $key => $value ) {
|
||
|
if ( in_array( $key, [ 'noindex', 'nofollow', 'noarchive', 'noimageindex', 'nosnippet' ], true ) && $value ) {
|
||
|
$robots[] = $key;
|
||
|
}
|
||
|
|
||
|
if ( in_array( $key, [ 'maxSnippet', 'maxVideoPreview', 'maxImagePreview' ], true ) && $value ) {
|
||
|
$advanced_robots[ $keys[ $key ] ] = $value;
|
||
|
}
|
||
|
}
|
||
|
$robots[] = ! in_array( 'noindex', $robots, true ) ? 'index' : '';
|
||
|
|
||
|
return [
|
||
|
'robots' => $robots,
|
||
|
'advanced_robots' => $advanced_robots,
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import post meta of plugin.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function postmeta() {
|
||
|
$this->set_pagination( $this->get_posts( true ) );
|
||
|
$posts = $this->get_posts();
|
||
|
|
||
|
foreach ( $posts as $post ) {
|
||
|
$post_id = (int) $post->post_id;
|
||
|
$post = (array) $post;
|
||
|
$hash = [
|
||
|
'title' => 'rank_math_title',
|
||
|
'description' => 'rank_math_description',
|
||
|
'canonical_url' => 'rank_math_canonical_url',
|
||
|
'og_title' => 'rank_math_facebook_title',
|
||
|
'og_description' => 'rank_math_facebook_description',
|
||
|
'og_image_custom_url' => 'rank_math_facebook_image',
|
||
|
'twitter_title' => 'rank_math_twitter_title',
|
||
|
'twitter_description' => 'rank_math_twitter_description',
|
||
|
'twitter_image_custom_url' => 'rank_math_twitter_image',
|
||
|
];
|
||
|
$this->replace_meta( $hash, $post, $post_id, 'post', 'convert_variables' );
|
||
|
$this->replace_meta( [ 'twitter_use_og' => 'rank_math_twitter_use_facebook' ], $post, $post_id, 'post', 'convert_bool' );
|
||
|
$this->set_object_robots( $post_id, $post, 'post' );
|
||
|
$this->set_keywords( $post_id, $post, 'post' );
|
||
|
$this->add_schema_data( $post_id, $post );
|
||
|
}
|
||
|
|
||
|
return $this->get_pagination_arg();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import term meta of plugin.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function termmeta() {
|
||
|
$this->set_pagination( $this->get_terms( true ) );
|
||
|
$terms = $this->get_terms();
|
||
|
|
||
|
foreach ( $terms as $term ) {
|
||
|
$term_id = $term->term_id;
|
||
|
$term = (array) $term;
|
||
|
$hash = [
|
||
|
'title' => 'rank_math_title',
|
||
|
'description' => 'rank_math_description',
|
||
|
'canonical_url' => 'rank_math_canonical_url',
|
||
|
'og_title' => 'rank_math_facebook_title',
|
||
|
'og_description' => 'rank_math_facebook_description',
|
||
|
'og_image_custom_url' => 'rank_math_facebook_image',
|
||
|
'twitter_title' => 'rank_math_twitter_title',
|
||
|
'twitter_description' => 'rank_math_twitter_description',
|
||
|
'twitter_image_custom_url' => 'rank_math_twitter_image',
|
||
|
];
|
||
|
$this->replace_meta( $hash, $term, $term_id, 'term', 'convert_variables' );
|
||
|
$this->replace_meta( [ 'twitter_use_og' => 'rank_math_twitter_use_facebook' ], $term, $term_id, 'term', 'convert_bool' );
|
||
|
$this->set_object_robots( $term_id, $term, 'term' );
|
||
|
$this->set_keywords( $term_id, $term, 'term' );
|
||
|
}
|
||
|
|
||
|
return [ 'count' => count( $terms ) ];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import user meta of plugin.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function usermeta() {
|
||
|
$this->set_pagination( $this->get_user_ids( true ) );
|
||
|
$user_ids = $this->get_user_ids();
|
||
|
|
||
|
$hash = [
|
||
|
'wpseo_title' => 'rank_math_title',
|
||
|
'wpseo_desc' => 'rank_math_description',
|
||
|
'wpseo_metadesc' => 'rank_math_description',
|
||
|
];
|
||
|
|
||
|
foreach ( $user_ids as $user ) {
|
||
|
$userid = $user->ID;
|
||
|
|
||
|
$facebook_url = get_user_meta( $userid, 'aioseo_facebook_page_url', true );
|
||
|
if ( $facebook_url ) {
|
||
|
update_user_meta( $userid, 'facebook', $facebook_url );
|
||
|
}
|
||
|
|
||
|
$twitter_url = get_user_meta( $userid, 'aioseo_twitter_url', true );
|
||
|
if ( $twitter_url ) {
|
||
|
update_user_meta( $userid, 'twitter', str_replace( 'https://twitter.com/', '', $twitter_url ) );
|
||
|
}
|
||
|
|
||
|
$social_urls = [];
|
||
|
foreach ( [ 'aioseo_instagram_url', 'aioseo_pinterest_url', 'aioseo_youtube_url', 'aioseo_linkedin_url', 'aioseo_tumblr_url', 'aioseo_yelp_page_url', 'aioseo_sound_cloud_url', 'aioseo_wikipedia_url', 'aioseo_myspace_url' ] as $key ) {
|
||
|
$social_urls[] = get_user_meta( $userid, $key, true );
|
||
|
}
|
||
|
|
||
|
$additional_urls = get_user_meta( 4, 'aioseo_profiles_additional_urls', true );
|
||
|
if ( $additional_urls ) {
|
||
|
$social_urls = array_merge( $social_urls, explode( "\n", $additional_urls ) );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $social_urls ) ) {
|
||
|
update_user_meta( $userid, 'additional_profile_urls', implode( ' ', array_filter( $social_urls ) ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->get_pagination_arg();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Deactivate plugin action.
|
||
|
*/
|
||
|
protected function deactivate() {
|
||
|
if ( is_plugin_active( $this->get_plugin_file() ) ) {
|
||
|
deactivate_plugins( $this->get_plugin_file() );
|
||
|
deactivate_plugins( 'aioseo-image-seo/aioseo-image-seo.php' );
|
||
|
deactivate_plugins( 'aioseo-local-business/aioseo-local-business.php' );
|
||
|
deactivate_plugins( 'aioseo-news-sitemap/aioseo-news-sitemap.php' );
|
||
|
deactivate_plugins( 'aioseo-video-sitemap/aioseo-video-sitemap.php' );
|
||
|
deactivate_plugins( 'aioseo-local-business/aioseo-local-business.php' );
|
||
|
deactivate_plugins( 'aioseo-redirects/aioseo-redirects.php' );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all post IDs of all allowed post types only.
|
||
|
*
|
||
|
* @param bool $count If we need count only for pagination purposes.
|
||
|
* @return int|array
|
||
|
*/
|
||
|
private function get_posts( $count = false ) {
|
||
|
$paged = $this->get_pagination_arg( 'page' );
|
||
|
$table = DB::query_builder( 'aioseo_posts' );
|
||
|
|
||
|
return $count ? absint( $table->selectCount( 'ID', 'total' )->getVar() ) :
|
||
|
$table->select( '*' )->page( $paged - 1, $this->items_per_page )->get();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all post IDs of all allowed post types only.
|
||
|
*
|
||
|
* @param bool $count If we need count only for pagination purposes.
|
||
|
* @return int|array
|
||
|
*/
|
||
|
private function get_terms( $count = false ) {
|
||
|
$paged = $this->get_pagination_arg( 'page' );
|
||
|
$table = DB::query_builder( 'aioseo_terms' );
|
||
|
|
||
|
return $count ? absint( $table->selectCount( 'ID', 'total' )->getVar() ) :
|
||
|
$table->select( '*' )->page( $paged - 1, $this->items_per_page )->get();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Schema Data.
|
||
|
*
|
||
|
* @param int $post_id Post ID.
|
||
|
* @param array $post Post data.
|
||
|
*/
|
||
|
private function add_schema_data( $post_id, $post ) {
|
||
|
if ( empty( $post['schema_type'] ) || ! in_array( $post['schema_type'], [ 'SoftwareApplication', 'Product', 'Recipe', 'Course' ], true ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$type = strtolower( $post['schema_type'] );
|
||
|
$type = 'softwareapplication' === $type ? 'software' : $type;
|
||
|
$schema = json_decode( $post['schema_type_options'], true );
|
||
|
$data = $this->$type( $schema[ $type ] );
|
||
|
$schema = [
|
||
|
'metadata' => [
|
||
|
'title' => $data['@type'],
|
||
|
'isPrimary' => true,
|
||
|
'type' => 'template',
|
||
|
'reviewLocation' => 'custom',
|
||
|
'reviewLocationShortcode' => '[rank_math_rich_snippet]',
|
||
|
],
|
||
|
] + $data;
|
||
|
|
||
|
update_post_meta( $post_id, 'rank_math_schema_' . $schema['@type'], $schema );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Software Schema Data.
|
||
|
*
|
||
|
* @param array $data Software schema data.
|
||
|
*/
|
||
|
private function software( $data ) {
|
||
|
$schema = [
|
||
|
'@type' => 'SoftwareApplication',
|
||
|
'name' => ! empty( $data['name'] ) ? $data['name'] : '%seo_title%',
|
||
|
'applicationCategory' => $data['category'],
|
||
|
'offers' => [
|
||
|
'@type' => 'Offer',
|
||
|
'price' => $data['price'],
|
||
|
'priceCurrency' => $data['currency'],
|
||
|
],
|
||
|
];
|
||
|
|
||
|
if ( ! empty( $data['operatingSystems'] ) ) {
|
||
|
$operating_system = array_map(
|
||
|
function( $system ) {
|
||
|
return $system['value'];
|
||
|
},
|
||
|
json_decode( $data['operatingSystems'], true )
|
||
|
);
|
||
|
|
||
|
$schema['operatingSystem'] = implode( ', ', $operating_system );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $data['reviews'] ) ) {
|
||
|
$reviews = json_decode( $data['reviews'][0], true );
|
||
|
$schema['review'] = [
|
||
|
'@type' => 'Review',
|
||
|
'datePublished' => '%date(Y-m-dTH:i:sP)%',
|
||
|
'dateModified' => '%modified(Y-m-dTH:i:sP)%',
|
||
|
'author' => [
|
||
|
'@type' => 'Person',
|
||
|
'name' => '%name%',
|
||
|
],
|
||
|
'reviewRating' => [
|
||
|
'@type' => 'Rating',
|
||
|
'ratingValue' => ! empty( $reviews['rating'] ) ? $reviews['rating'] : '',
|
||
|
],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
return $schema;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Product Schema Data.
|
||
|
*
|
||
|
* @param array $data Product schema data.
|
||
|
*/
|
||
|
private function product( $data ) {
|
||
|
return [
|
||
|
'@type' => 'Product',
|
||
|
'name' => ! empty( $data['name'] ) ? $data['name'] : '%seo_title%',
|
||
|
'description' => ! empty( $data['description'] ) ? $data['description'] : '%seo_description%',
|
||
|
'gtin8' => $data['identifier'],
|
||
|
'brand' => [
|
||
|
'@type' => 'Brand',
|
||
|
'name' => $data['brand'],
|
||
|
],
|
||
|
'offers' => [
|
||
|
'@type' => 'Offer',
|
||
|
'price' => $data['price'],
|
||
|
'priceCurrency' => $data['currency'],
|
||
|
'priceValidUntil' => $data['priceValidUntil'],
|
||
|
'availability' => str_replace( 'https://schema.org/', '', $data['availability'] ),
|
||
|
],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Course Schema Data.
|
||
|
*
|
||
|
* @param array $data Course schema data.
|
||
|
*/
|
||
|
private function course( $data ) {
|
||
|
return [
|
||
|
'@type' => 'Course',
|
||
|
'name' => $data['name'],
|
||
|
'description' => $data['description'],
|
||
|
'provider' => [
|
||
|
'@type' => 'Organization',
|
||
|
'name' => $data['provider'],
|
||
|
],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Recipe Schema Data.
|
||
|
*
|
||
|
* @param array $data Recipe schema data.
|
||
|
*/
|
||
|
private function recipe( $data ) {
|
||
|
$schema = [
|
||
|
'@type' => 'Recipe',
|
||
|
'name' => $data['name'],
|
||
|
'recipeCategory' => $data['dishType'],
|
||
|
'recipeCuisine' => $data['cuisineType'],
|
||
|
'prepTime' => "PT{$data['preparationTime']}M",
|
||
|
'cookTime' => "PT{$data['cookingTime']}M",
|
||
|
'recipeYield' => "PT{$data['servings']}M",
|
||
|
'nutrition' => [
|
||
|
'@type' => 'NutritionInformation',
|
||
|
'calories' => $data['calories'],
|
||
|
],
|
||
|
];
|
||
|
|
||
|
if ( ! empty( $data['keywords'] ) ) {
|
||
|
$keywords = array_map(
|
||
|
function( $keyword ) {
|
||
|
return $keyword['value'];
|
||
|
},
|
||
|
json_decode( $data['keywords'], true )
|
||
|
);
|
||
|
|
||
|
$schema['keywords'] = implode( ', ', $keywords );
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $data['ingredients'] ) ) {
|
||
|
$schema['recipeIngredient'] = array_map(
|
||
|
function( $ingredient ) {
|
||
|
return $ingredient['value'];
|
||
|
},
|
||
|
json_decode( $data['ingredients'], true )
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $data['instructions'] ) ) {
|
||
|
$schema['recipeInstructions'] = [
|
||
|
'@type' => 'HowToSection',
|
||
|
'itemListElement' => [],
|
||
|
];
|
||
|
|
||
|
foreach ( $data['instructions'] as $instruction ) {
|
||
|
$instruction_data = json_decode( $instruction, true );
|
||
|
|
||
|
$schema['recipeInstructions']['itemListElement'][] = [
|
||
|
'@type' => 'HowtoStep',
|
||
|
'text' => $instruction_data['content'],
|
||
|
];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $schema;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set Keywords.
|
||
|
*
|
||
|
* @param int $object_id Object ID.
|
||
|
* @param array $object Object data.
|
||
|
* @param string $object_type Current Object type.
|
||
|
*/
|
||
|
private function set_keywords( $object_id, $object, $object_type ) {
|
||
|
$keywords = [];
|
||
|
$keyphrases = json_decode( $object['keyphrases'], true );
|
||
|
|
||
|
if ( ! empty( $keyphrases['focus']['keyphrase'] ) ) {
|
||
|
$keywords[] = $keyphrases['focus']['keyphrase'];
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $keyphrases['additional'] ) ) {
|
||
|
foreach ( $keyphrases['additional'] as $keyword ) {
|
||
|
$keywords[] = $keyword['keyphrase'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( empty( $keywords ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->update_meta( $object_type, $object_id, 'rank_math_focus_keyword', implode( ',', $keywords ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set object robots meta.
|
||
|
*
|
||
|
* @param int $object_id Object ID.
|
||
|
* @param array $object Object data.
|
||
|
* @param string $object_type Current Object type.
|
||
|
*/
|
||
|
private function set_object_robots( $object_id, $object, $object_type ) {
|
||
|
// Early bail if robots data is set in Rank Math plugin.
|
||
|
if ( ! empty( $this->get_meta( $object_type, $object_id, 'rank_math_robots' ) ) || ! empty( $object['robots_default'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// ROBOTS.
|
||
|
$robots = [];
|
||
|
foreach ( [ 'robots_noindex', 'robots_noarchive', 'robots_nosnippet', 'robots_nofollow', 'robots_noimageindex' ] as $key ) {
|
||
|
if ( empty( $object[ $key ] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$robots[] = str_replace( 'robots_', '', $key );
|
||
|
}
|
||
|
|
||
|
if ( ! in_array( 'noindex', $robots, true ) ) {
|
||
|
$robots[] = 'index';
|
||
|
}
|
||
|
$this->update_meta( $object_type, $object_id, 'rank_math_robots', array_unique( $robots ) );
|
||
|
|
||
|
$advanced_robots = [];
|
||
|
$keys = [
|
||
|
'robots_max_snippet' => 'max-snippet',
|
||
|
'robots_max_videopreview' => 'max-video-preview',
|
||
|
'robots_max_imagepreview' => 'max-image-preview',
|
||
|
];
|
||
|
foreach ( [ 'robots_max_snippet', 'robots_max_videopreview', 'robots_max_imagepreview' ] as $key ) {
|
||
|
if ( empty( $object[ $key ] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$advanced_robots[ $keys[ $key ] ] = $object[ $key ];
|
||
|
}
|
||
|
|
||
|
$this->update_meta( $object_type, $object_id, 'rank_math_advanced_robots', array_unique( $advanced_robots ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replace meta based on key/value hash.
|
||
|
*
|
||
|
* @param array $hash Array of hash for search and replace.
|
||
|
* @param array $source Array for source where to search.
|
||
|
* @param int $object_id Object id for destination where to save.
|
||
|
* @param string $object_type Object type for destination where to save.
|
||
|
* @param bool $convert (Optional) Conversion type. Default: false.
|
||
|
*/
|
||
|
protected function replace_meta( $hash, $source, $object_id, $object_type, $convert = false ) {
|
||
|
foreach ( $hash as $search => $replace ) {
|
||
|
$value = isset( $source[ $search ] ) ? $source[ $search ] : $this->get_meta( $object_type, $object_id, $search );
|
||
|
if ( ! isset( $value ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$this->update_meta(
|
||
|
$object_type,
|
||
|
$object_id,
|
||
|
$replace,
|
||
|
false !== $convert ? $this->$convert( $value ) : $value
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Locations data from Yoast Local plugin.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function locations() {
|
||
|
$this->import_locations_terms();
|
||
|
$this->set_pagination( $this->get_location_ids( true ) );
|
||
|
$locations = $this->get_location_ids();
|
||
|
foreach ( $locations as $location ) {
|
||
|
$args = (array) $location;
|
||
|
unset( $args['ID'] );
|
||
|
$args['post_type'] = 'rank_math_locations';
|
||
|
|
||
|
$post_id = wp_insert_post( $args );
|
||
|
if ( is_wp_error( $post_id ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$post_terms = wp_get_object_terms( $location->ID, 'aioseo-location-category', [ 'fields' => 'slugs' ] );
|
||
|
if ( ! empty( $post_terms ) && ! is_wp_error( $post_terms ) ) {
|
||
|
wp_set_object_terms( $post_id, $post_terms, 'rank_math_location_category', false );
|
||
|
}
|
||
|
|
||
|
$this->locations_meta( $location->ID, $post_id );
|
||
|
}
|
||
|
|
||
|
return $this->get_pagination_arg();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Locations terms.
|
||
|
*/
|
||
|
private function import_locations_terms() {
|
||
|
$terms = get_terms( 'aioseo-location-category' );
|
||
|
if ( empty( $terms ) || is_wp_error( $terms ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
foreach ( $terms as $term ) {
|
||
|
wp_insert_term( $term->name, 'rank_math_location_category', $term );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Import Locations metadata.
|
||
|
*
|
||
|
* @param int $old_post_id Yoast's location id.
|
||
|
* @param int $new_post_id Newly created location id.
|
||
|
*/
|
||
|
private function locations_meta( $old_post_id, $new_post_id ) {
|
||
|
$metas = DB::query_builder( 'aioseo_posts' )->where( 'post_id', $old_post_id )->select()->one();
|
||
|
if ( empty( $metas->local_seo ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$locations_data = json_decode( $metas->local_seo, true );
|
||
|
$locations_meta = ! empty( $locations_data['locations'] ) ? $locations_data['locations']['business'] : [];
|
||
|
$opening_hours = ! empty( $locations_data['openingHours'] ) ? $locations_data['openingHours'] : [];
|
||
|
|
||
|
$schema = [
|
||
|
'metadata' => [
|
||
|
'type' => 'template',
|
||
|
'shortcode' => uniqid( 's-' ),
|
||
|
'isPrimary' => true,
|
||
|
'title' => 'Local Business',
|
||
|
'use_24h_format' => ! empty( $opening_hours['use24hFormat'] ),
|
||
|
'open247' => ! empty( $opening_hours['alwaysOpen'] ),
|
||
|
'timeZone' => ! empty( $opening_hours['timezone'] ),
|
||
|
],
|
||
|
'@type' => $locations_meta['businessType'],
|
||
|
'name' => ! empty( $locations_meta['name'] ) ? $locations_meta['name'] : '%seo_title%',
|
||
|
'url' => ! empty( $locations_meta['urls'] ) ? $locations_meta['urls']['website'] : '%url%',
|
||
|
'address' => ! empty( $locations_meta['address'] ) ? $this->replace_address( $locations_meta['address'] ) : '',
|
||
|
'areaServed' => ! empty( $locations_meta['areaServed'] ) ? $locations_meta['areaServed'] : '',
|
||
|
];
|
||
|
|
||
|
if ( ! empty( $locations_meta['contact'] ) ) {
|
||
|
$contact = $locations_meta['contact'];
|
||
|
$schema['email'] = ! empty( $contact['email'] ) ? $contact['email'] : '';
|
||
|
$schema['telephone'] = ! empty( $contact['phone'] ) ? $contact['phone'] : '';
|
||
|
$schema['faxNumber'] = ! empty( $contact['fax'] ) ? $contact['fax'] : '';
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $locations_meta['ids'] ) ) {
|
||
|
$ids = $locations_meta['ids'];
|
||
|
$schema['vatID'] = ! empty( $ids['vat'] ) ? $ids['vat'] : '';
|
||
|
$schema['taxID'] = ! empty( $ids['tax'] ) ? $ids['tax'] : '';
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $locations_meta['payment'] ) ) {
|
||
|
$payment = $locations_meta['payment'];
|
||
|
$schema['priceRange'] = ! empty( $payment['priceRange'] ) ? $payment['priceRange'] : '';
|
||
|
$schema['paymentAccepted'] = ! empty( $payment['methods'] ) ? $payment['methods'] : '';
|
||
|
|
||
|
if ( ! empty( $payment['currenciesAccepted'] ) ) {
|
||
|
$schema['currenciesAccepted'] = implode(
|
||
|
', ',
|
||
|
array_map(
|
||
|
function( $value ) {
|
||
|
return $value['value'];
|
||
|
},
|
||
|
json_decode( $payment['currenciesAccepted'], true )
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $locations_meta['image'] ) ) {
|
||
|
$schema['logo'] = [
|
||
|
'@type' => 'ImageObject',
|
||
|
'url' => $locations_meta['image'],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$schema['openingHoursSpecification'] = $this->replace_opening_hours( $opening_hours['days'] );
|
||
|
|
||
|
update_post_meta( $new_post_id, 'rank_math_schema_' . $schema['@type'], $schema );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replace Opening Hours data.
|
||
|
*
|
||
|
* @param array $opening_hours Opening Hours data.
|
||
|
* @return array Processed data.
|
||
|
*/
|
||
|
private function replace_opening_hours( $opening_hours ) {
|
||
|
$data = [];
|
||
|
$days = [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ];
|
||
|
foreach ( $days as $day ) {
|
||
|
if ( ! empty( $opening_hours[ $day ]['closed'] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $opening_hours[ $day ]['open24h'] ) ) {
|
||
|
$opens = '00:00';
|
||
|
$closes = '23:59';
|
||
|
} else {
|
||
|
$opens = ! empty( $opening_hours[ $day ]['openTime'] ) ? $opening_hours[ $day ]['openTime'] : '';
|
||
|
$closes = ! empty( $opening_hours[ $day ]['closeTime'] ) ? $opening_hours[ $day ]['closeTime'] : '';
|
||
|
}
|
||
|
|
||
|
if ( ! $opens ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$data[ $day ] = [
|
||
|
'@type' => 'OpeningHoursSpecification',
|
||
|
'dayOfWeek' => ucfirst( $day ),
|
||
|
'opens' => $opens,
|
||
|
'closes' => $closes,
|
||
|
];
|
||
|
}
|
||
|
|
||
|
return array_values( $data );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replace Address data.
|
||
|
*
|
||
|
* @param array $address Address data.
|
||
|
* @return array Processed data.
|
||
|
*/
|
||
|
private function replace_address( $address ) {
|
||
|
$data = [
|
||
|
'@type' => 'PostalAddress',
|
||
|
];
|
||
|
$hash = [
|
||
|
'streetLine1' => 'streetAddress',
|
||
|
'streetLine2' => 'addressLocality',
|
||
|
'state' => 'addressRegion',
|
||
|
'zipCode' => 'postalCode',
|
||
|
'country' => 'addressCountry',
|
||
|
];
|
||
|
|
||
|
foreach ( $hash as $key => $value ) {
|
||
|
$data[ $value ] = isset( $address[ $key ] ) ? $address[ $key ] : '';
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $address['city'] ) ) {
|
||
|
$data['addressLocality'] = $data['addressLocality'] . ', ' . $address['city'];
|
||
|
}
|
||
|
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all location IDs.
|
||
|
*
|
||
|
* @param bool $count If we need count only for pagination purposes.
|
||
|
* @return int|array
|
||
|
*/
|
||
|
private function get_location_ids( $count = false ) {
|
||
|
$paged = $this->get_pagination_arg( 'page' );
|
||
|
$table = DB::query_builder( 'posts' )->where( 'post_type', 'aioseo-location' );
|
||
|
|
||
|
return $count ? absint( $table->selectCount( 'ID', 'total' )->getVar() ) :
|
||
|
$table->select()->page( $paged - 1, $this->items_per_page )->get();
|
||
|
}
|
||
|
}
|