Your IP : 216.73.216.162


Current Path : /home/x/b/o/xbodynamge/namtation/wp-content/
Upload File :
Current File : /home/x/b/o/xbodynamge/namtation/wp-content/ImportExport.tar

RankMath/RankMath.php000066600000002063151145361560010503 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\RankMath;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

class RankMath extends ImportExport\Importer {
	/**
	 * A list of plugins to look for to import.
	 *
	 * @since 4.0.0
	 *
	 * @var array
	 */
	public $plugins = [
		[
			'name'     => 'Rank Math SEO',
			'version'  => '1.0',
			'basename' => 'seo-by-rank-math/rank-math.php',
			'slug'     => 'rank-math-seo'
		]
	];

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 *
	 * @param ImportExport\ImportExport $importer the ImportExport class.
	 */
	public function __construct( $importer ) {
		$this->helpers  = new Helpers();
		$this->postMeta = new PostMeta();

		$plugins = $this->plugins;
		foreach ( $plugins as $key => $plugin ) {
			$plugins[ $key ]['class'] = $this;
		}
		$importer->addPlugins( $plugins );
	}


	/**
	 * Imports the settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	protected function importSettings() {
		new GeneralSettings();
		new TitleMeta();
		new Sitemap();
	}
}RankMath/Helpers.php000066600000007433151145361560010406 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\RankMath;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Contains helper methods for the import from Rank Math.
 *
 * @since 4.0.0
 */
class Helpers extends ImportExport\Helpers {
	/**
	 * Converts the macros from Rank Math to our own smart tags.
	 *
	 * @since 4.0.0
	 *
	 * @param  string $string   The string with macros.
	 * @param  string $pageType The page type.
	 * @return string $string   The string with smart tags.
	 */
	public function macrosToSmartTags( $string, $pageType = null ) {
		$macros = $this->getMacros( $pageType );

		if ( preg_match( '#%BLOGDESCLINK%#', (string) $string ) ) {
			$blogDescriptionLink = '<a href="' .
				aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'url' ) ) . '">' .
				aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) ) . ' - ' .
				aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'description' ) ) . '</a>';

			$string = str_replace( '%BLOGDESCLINK%', $blogDescriptionLink, $string );
		}

		if ( preg_match_all( '#%customfield\(([^%\s]*)\)%#', (string) $string, $matches ) && ! empty( $matches[1] ) ) {
			foreach ( $matches[1] as $name ) {
				$string = aioseo()->helpers->pregReplace( "#%customfield\($name\)%#", "#custom_field-$name", $string );
			}
		}

		if ( preg_match_all( '#%customterm\(([^%\s]*)\)%#', (string) $string, $matches ) && ! empty( $matches[1] ) ) {
			foreach ( $matches[1] as $name ) {
				$string = aioseo()->helpers->pregReplace( "#%customterm\($name\)%#", "#tax_name-$name", $string );
			}
		}

		foreach ( $macros as $macro => $tag ) {
			$string = aioseo()->helpers->pregReplace( "#$macro(?![a-zA-Z0-9_])#im", $tag, $string );
		}

		// Strip out all remaining tags.
		$string = aioseo()->helpers->pregReplace( '/%[^\%\s]*\([^\%]*\)%/i', '', aioseo()->helpers->pregReplace( '/%[^\%\s]*%/i', '', $string ) );

		return trim( $string );
	}

	/**
	 * Returns the macro mappings.
	 *
	 * @since 4.1.1
	 *
	 * @param  string $pageType The page type.
	 * @return array  $macros   The macros.
	 */
	protected function getMacros( $pageType = null ) {
		$macros = [
			'%sitename%'         => '#site_title',
			'%blog_title%'       => '#site_title',
			'%blog_description%' => '#tagline',
			'%sitedesc%'         => '#tagline',
			'%sep%'              => '#separator_sa',
			'%post_title%'       => '#post_title',
			'%page_title%'       => '#post_title',
			'%postname%'         => '#post_title',
			'%title%'            => '#post_title',
			'%seo_title%'        => '#post_title',
			'%excerpt%'          => '#post_excerpt',
			'%wc_shortdesc%'     => '#post_excerpt',
			'%category%'         => '#taxonomy_title',
			'%term%'             => '#taxonomy_title',
			'%term_description%' => '#taxonomy_description',
			'%currentdate%'      => '#current_date',
			'%currentday%'       => '#current_day',
			'%currentyear%'      => '#current_year',
			'%currentmonth%'     => '#current_month',
			'%name%'             => '#author_first_name #author_last_name',
			'%author%'           => '#author_first_name #author_last_name',
			'%date%'             => '#post_date',
			'%year%'             => '#current_year',
			'%search_query%'     => '#search_term',
			// RSS Content tags.
			'%AUTHORLINK%'       => '#author_link',
			'%POSTLINK%'         => '#post_link',
			'%BLOGLINK%'         => '#site_link',
			'%FEATUREDIMAGE%'    => '#featured_image'
		];

		switch ( $pageType ) {
			case 'archive':
				$macros['%title%'] = '#archive_title';
				break;
			case 'term':
				$macros['%title%'] = '#taxonomy_title';
				break;
			default:
				$macros['%title%'] = '#post_title';
				break;
		}

		// Strip all other tags.
		$macros['%[^%]*%'] = '';

		return $macros;
	}
}RankMath/TitleMeta.php000066600000047334151145361560010700 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\RankMath;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;
use AIOSEO\Plugin\Common\Models;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Search Appearance settings.
 *
 * @since 4.0.0
 */
class TitleMeta extends ImportExport\SearchAppearance {
	/**
	 * Our robot meta settings.
	 *
	 * @since 4.0.0
	 */
	private $robotMetaSettings = [
		'noindex',
		'nofollow',
		'noarchive',
		'noimageindex',
		'nosnippet'
	];

	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->options = get_option( 'rank-math-options-titles' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateHomePageSettings();
		$this->migratePostTypeSettings();
		$this->migratePostTypeArchiveSettings();
		$this->migrateArchiveSettings();
		$this->migrateRobotMetaSettings();
		$this->migrateKnowledgeGraphSettings();
		$this->migrateSocialMetaSettings();

		$settings = [
			'title_separator' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'separator' ] ],
		];

		aioseo()->importExport->rankMath->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the homepage settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateHomePageSettings() {
		if ( isset( $this->options['homepage_title'] ) ) {
			aioseo()->options->searchAppearance->global->siteTitle =
				aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options['homepage_title'] ) );
		}

		if ( isset( $this->options['homepage_description'] ) ) {
			aioseo()->options->searchAppearance->global->metaDescription =
				aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options['homepage_description'] ) );
		}

		if ( isset( $this->options['homepage_facebook_title'] ) ) {
			aioseo()->options->social->facebook->homePage->title = aioseo()->helpers->sanitizeOption( $this->options['homepage_facebook_title'] );
		}

		if ( isset( $this->options['homepage_facebook_description'] ) ) {
			aioseo()->options->social->facebook->homePage->description = aioseo()->helpers->sanitizeOption( $this->options['homepage_facebook_description'] );
		}

		if ( isset( $this->options['homepage_facebook_image'] ) ) {
			aioseo()->options->social->facebook->homePage->image = esc_url( $this->options['homepage_facebook_image'] );
		}
	}

	/**
	 * Migrates the archive settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateArchiveSettings() {
		$archives = [
			'author',
			'date'
		];

		foreach ( $archives as $archive ) {
			// Reset existing values first.
			foreach ( $this->robotMetaSettings as $robotsMetaName ) {
				aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->$robotsMetaName = false;
			}

			if ( isset( $this->options[ "disable_{$archive}_archives" ] ) ) {
				aioseo()->options->searchAppearance->archives->$archive->show                          = 'off' === $this->options[ "disable_{$archive}_archives" ];
				aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->default = 'on' === $this->options[ "disable_{$archive}_archives" ];
				aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->noindex = 'on' === $this->options[ "disable_{$archive}_archives" ];
			}

			if ( isset( $this->options[ "{$archive}_archive_title" ] ) ) {
				$value = aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options[ "{$archive}_archive_title" ], 'archive' ) );
				if ( 'date' !== $archive ) {
					// Archive Title tag needs to be stripped since we don't support it for author archives.
					$value = aioseo()->helpers->pregReplace( '/#archive_title/', '', $value );
				}
				aioseo()->options->searchAppearance->archives->$archive->title = $value;
			}

			if ( isset( $this->options[ "{$archive}_archive_description" ] ) ) {
				aioseo()->options->searchAppearance->archives->$archive->metaDescription =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options[ "{$archive}_archive_description" ], 'archive' ) );
			}

			if ( ! empty( $this->options[ "{$archive}_custom_robots" ] ) ) {
				aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->default = 'off' === $this->options[ "{$archive}_custom_robots" ];
			}

			if ( ! empty( $this->options[ "{$archive}_robots" ] ) ) {
				foreach ( $this->options[ "{$archive}_robots" ] as $robotsName ) {
					if ( 'index' === $robotsName ) {
						continue;
					}

					if ( 'noindex' === $robotsName ) {
						aioseo()->options->searchAppearance->archives->{$archive}->show = false;
					}

					aioseo()->options->searchAppearance->archives->{$archive}->advanced->robotsMeta->{$robotsName} = true;
				}
			}

			if ( ! empty( $this->options[ "{$archive}_advanced_robots" ] ) ) {
				if ( isset( $this->options[ "{$archive}_advanced_robots" ]['max-snippet'] ) && is_numeric( $this->options[ "{$archive}_advanced_robots" ]['max-snippet'] ) ) {
					aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->maxSnippet = intval( $this->options[ "{$archive}_advanced_robots" ]['max-snippet'] );
				}
				if ( isset( $this->options[ "{$archive}_advanced_robots" ]['max-video-preview'] ) && is_numeric( isset( $this->options[ "{$archive}_advanced_robots" ]['max-video-preview'] ) ) ) {
					aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->maxVideoPreview = intval( $this->options[ "{$archive}_advanced_robots" ]['max-video-preview'] );
				}
				if ( ! empty( $this->options[ "{$archive}_advanced_robots" ]['max-image-preview'] ) ) {
					aioseo()->options->searchAppearance->archives->$archive->advanced->robotsMeta->maxImagePreview =
						aioseo()->helpers->sanitizeOption( lcfirst( $this->options[ "{$archive}_advanced_robots" ]['max-image-preview'] ) );
				}
			}
		}

		if ( isset( $this->options['search_title'] ) ) {
			// Archive Title tag needs to be stripped since we don't support it for search archives.
			$value = aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options['search_title'], 'archive' ) );
			aioseo()->options->searchAppearance->archives->search->title = aioseo()->helpers->pregReplace( '/#archive_title/', '', $value );
		}

		if ( ! empty( $this->options['noindex_search'] ) ) {
			aioseo()->options->searchAppearance->archives->search->show                          = 'off' === $this->options['noindex_search'];
			aioseo()->options->searchAppearance->archives->search->advanced->robotsMeta->default = 'on' === $this->options['noindex_search'];
			aioseo()->options->searchAppearance->archives->search->advanced->robotsMeta->noindex = 'on' === $this->options['noindex_search'];
		}
	}

	/**
	 * Migrates the post type settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migratePostTypeSettings() {
		$supportedSettings = [
			'title',
			'description',
			'custom_robots',
			'robots',
			'advanced_robots',
			'default_rich_snippet',
			'default_article_type',
			'add_meta_box'
		];

		foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
			// Reset existing values first.
			foreach ( $this->robotMetaSettings as $robotsMetaName ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->$robotsMetaName = false;
			}

			foreach ( $this->options as $name => $value ) {
				if ( ! preg_match( "#^pt_{$postType}_(.*)$#", (string) $name, $match ) || ! in_array( $match[1], $supportedSettings, true ) ) {
					continue;
				}

				switch ( $match[1] ) {
					case 'title':
						if ( 'page' === $postType ) {
							$value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
							$value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
						}
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->title =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value ) );
						break;
					case 'description':
						if ( 'page' === $postType ) {
							$value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
							$value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
						}
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->metaDescription =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value ) );
						break;
					case 'custom_robots':
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = 'off' === $value;
						break;
					case 'robots':
						if ( ! empty( $value ) ) {
							foreach ( $value as $robotsName ) {
								if ( 'index' === $robotsName ) {
									continue;
								}

								if ( 'noindex' === $robotsName ) {
									aioseo()->dynamicOptions->searchAppearance->postTypes->{$postType}->show = false;
								}

								aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->$robotsName = true;
							}
						}
						break;
					case 'advanced_robots':
						if ( isset( $value['max-snippet'] ) && is_numeric( $value['max-snippet'] ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->maxSnippet = intval( $value['max-snippet'] );
						}
						if ( isset( $value['max-video-preview'] ) && is_numeric( $value['max-video-preview'] ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->maxVideoPreview = intval( $value['max-video-preview'] );
						}
						if ( ! empty( $value['max-image-preview'] ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->maxImagePreview =
								aioseo()->helpers->sanitizeOption( $value['max-image-preview'] );
						}
						break;
					case 'add_meta_box':
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox = 'on' === $value;
						break;
					case 'default_rich_snippet':
						$value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
						if ( 'off' === lcfirst( $value ) || in_array( $postType, [ 'page', 'attachment' ], true ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->schemaType = 'none';
							break;
						}
						if ( in_array( ucfirst( $value ), ImportExport\SearchAppearance::$supportedSchemaGraphs, true ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->schemaType = ucfirst( $value );
						}
						break;
					case 'default_article_type':
						if ( in_array( $postType, [ 'page', 'attachment' ], true ) ) {
							break;
						}
						$value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
						if ( in_array( ucfirst( $value ), ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = ucfirst( $value );
						} else {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'BlogPosting';
						}
						break;
					default:
						break;
				}
			}
		}
	}

	/**
	 * Migrates the post type archive settings.
	 *
	 * @since 4.0.16
	 *
	 * @return void
	 */
	private function migratePostTypeArchiveSettings() {
		$supportedSettings = [
			'title',
			'description'
		];

		foreach ( aioseo()->helpers->getPublicPostTypes( true, true ) as $postType ) {
			foreach ( $this->options as $name => $value ) {
				if ( ! preg_match( "#^pt_{$postType}_archive_(.*)$#", (string) $name, $match ) || ! in_array( $match[1], $supportedSettings, true ) ) {
					continue;
				}

				switch ( $match[1] ) {
					case 'title':
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->title =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value, 'archive' ) );
						break;
					case 'description':
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->metaDescription =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value, 'archive' ) );
						break;
					default:
						break;
				}
			}
		}
	}


	/**
	 * Migrates the robots meta settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateRobotMetaSettings() {
		// Reset existing values first.
		foreach ( $this->robotMetaSettings as $robotsMetaName ) {
			aioseo()->options->searchAppearance->advanced->globalRobotsMeta->$robotsMetaName = false;
		}

		if ( ! empty( $this->options['robots_global'] ) ) {
			foreach ( $this->options['robots_global'] as $robotsName ) {
				if ( 'index' === $robotsName ) {
					continue;
				}
				aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default     = false;
				aioseo()->options->searchAppearance->advanced->globalRobotsMeta->$robotsName = true;
			}
		}

		if ( ! empty( $this->options['advanced_robots_global'] ) ) {
			aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default = false;

			if ( isset( $this->options['robots_global']['max-snippet'] ) && is_numeric( $this->options['robots_global']['max-snippet'] ) ) {
				aioseo()->options->searchAppearance->advanced->globalRobotsMeta->maxSnippet = intval( $this->options['robots_global']['max-snippet'] );
			}
			if ( isset( $this->options['robots_global']['max-video-preview'] ) && is_numeric( $this->options['robots_global']['max-video-preview'] ) ) {
				aioseo()->options->searchAppearance->advanced->globalRobotsMeta->maxVideoPreview = intval( $this->options['robots_global']['max-video-preview'] );
			}
			if ( ! empty( $this->options['robots_global']['max-image-preview'] ) ) {
				aioseo()->options->searchAppearance->advanced->globalRobotsMeta->maxImagePreview =
					aioseo()->helpers->sanitizeOption( $this->options['robots_global']['max-image-preview'] );
			}
		}

		if ( ! empty( $this->options['noindex_paginated_pages'] ) ) {
			aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default          = false;
			aioseo()->options->searchAppearance->advanced->globalRobotsMeta->noindexPaginated = 'on' === $this->options['noindex_paginated_pages'];
		}
	}

	/**
	 * Migrates the Knowledge Graph settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateKnowledgeGraphSettings() {
		if ( empty( $this->options['knowledgegraph_type'] ) ) {
			return;
		}

		aioseo()->options->searchAppearance->global->schema->siteRepresents =
			'company' === $this->options['knowledgegraph_type'] ? 'organization' : 'person';

		if ( ! empty( $this->options['knowledgegraph_name'] ) && 'company' === $this->options['knowledgegraph_type'] ) {
			aioseo()->options->searchAppearance->global->schema->organizationName = aioseo()->helpers->sanitizeOption( $this->options['knowledgegraph_name'] );
		} elseif ( ! empty( $this->options['knowledgegraph_logo'] ) ) {
			aioseo()->options->searchAppearance->global->schema->person     = 'manual';
			aioseo()->options->searchAppearance->global->schema->personName = aioseo()->helpers->sanitizeOption( $this->options['knowledgegraph_name'] );
		}

		if ( ! empty( $this->options['knowledgegraph_logo'] ) && 'company' === $this->options['knowledgegraph_type'] ) {
			aioseo()->options->searchAppearance->global->schema->organizationLogo = esc_url( $this->options['knowledgegraph_logo'] );
		} elseif ( ! empty( $this->options['knowledgegraph_logo'] ) ) {
			aioseo()->options->searchAppearance->global->schema->person     = 'manual';
			aioseo()->options->searchAppearance->global->schema->personLogo = esc_url( $this->options['knowledgegraph_logo'] );
		}

		$this->migrateKnowledgeGraphPhoneNumber();
	}

	/**
	 * Migrates the Knowledge Graph phone number.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateKnowledgeGraphPhoneNumber() {
		if ( empty( $this->options['phone'] ) ) {
			return;
		}

		$phoneNumber = aioseo()->helpers->sanitizeOption( $this->options['phone'] );
		if ( ! preg_match( '#\+\d+#', (string) $phoneNumber ) ) {
			$notification = Models\Notification::getNotificationByName( 'v3-migration-schema-number' );
			if ( $notification->notification_name ) {
				return;
			}

			Models\Notification::addNotification( [
				'slug'              => uniqid(),
				'notification_name' => 'v3-migration-schema-number',
				'title'             => __( 'Invalid Phone Number for Knowledge Graph', 'all-in-one-seo-pack' ),
				'content'           => sprintf(
					// Translators: 1 - The phone number.
					__( 'We were unable to import the phone number that you previously entered for your Knowledge Graph schema markup.
					As it needs to be internationally formatted, please enter it (%1$s) with the country code, e.g. +1 (555) 555-1234.', 'all-in-one-seo-pack' ),
					"<strong>$phoneNumber</strong>"
				),
				'type'              => 'warning',
				'level'             => [ 'all' ],
				'button1_label'     => __( 'Fix Now', 'all-in-one-seo-pack' ),
				'button1_action'    => 'http://route#aioseo-search-appearance&aioseo-scroll=schema-graph-phone&aioseo-highlight=schema-graph-phone:schema-markup',
				'button2_label'     => __( 'Remind Me Later', 'all-in-one-seo-pack' ),
				'button2_action'    => 'http://action#notification/v3-migration-schema-number-reminder',
				'start'             => gmdate( 'Y-m-d H:i:s' )
			] );

			return;
		}
		aioseo()->options->searchAppearance->global->schema->phone = $phoneNumber;
	}

	/**
	 * Migrates the Social Meta settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateSocialMetaSettings() {
		if ( ! empty( $this->options['open_graph_image'] ) ) {
			$defaultImage = esc_url( $this->options['open_graph_image'] );
			aioseo()->options->social->facebook->general->defaultImagePosts = $defaultImage;
			aioseo()->options->social->twitter->general->defaultImagePosts  = $defaultImage;
		}

		if ( ! empty( $this->options['social_url_facebook'] ) ) {
			aioseo()->options->social->profiles->urls->facebookPageUrl = esc_url( $this->options['social_url_facebook'] );
		}

		if ( ! empty( $this->options['facebook_author_urls'] ) ) {
			aioseo()->options->social->facebook->advanced->enable    = true;
			aioseo()->options->social->facebook->advanced->authorUrl = esc_url( $this->options['facebook_author_urls'] );
		}

		if ( ! empty( $this->options['facebook_admin_id'] ) ) {
			aioseo()->options->social->facebook->advanced->enable  = true;
			aioseo()->options->social->facebook->advanced->adminId = aioseo()->helpers->sanitizeOption( $this->options['facebook_admin_id'] );
		}

		if ( ! empty( $this->options['facebook_app_id'] ) ) {
			aioseo()->options->social->facebook->advanced->enable = true;
			aioseo()->options->social->facebook->advanced->appId  = aioseo()->helpers->sanitizeOption( $this->options['facebook_app_id'] );
		}

		if ( ! empty( $this->options['twitter_author_names'] ) ) {
			aioseo()->options->social->profiles->urls->twitterUrl =
				'https://x.com/' . aioseo()->helpers->sanitizeOption( $this->options['twitter_author_names'] );
		}

		if ( ! empty( $this->options['twitter_card_type'] ) ) {
			preg_match( '#large#', $this->options['twitter_card_type'], $match );
			aioseo()->options->social->twitter->general->defaultCardType = ! empty( $match ) ? 'summary_large_image' : 'summary';
		}
	}

	/**
	 * Migrates the default social image for posts.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateDefaultPostSocialImage() {
		if ( ! empty( $this->options['open_graph_image'] ) ) {
			$defaultImage = esc_url( $this->options['open_graph_image'] );
			aioseo()->options->social->facebook->general->defaultImagePosts = $defaultImage;
			aioseo()->options->social->twitter->general->defaultImagePosts  = $defaultImage;
		}
	}
}RankMath/PostMeta.php000066600000022432151145361560010534 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\RankMath;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\Models;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Imports the post meta from Rank Math.
 *
 * @since 4.0.0
 */
class PostMeta {
	/**
	 * The batch import action name.
	 *
	 * @since 4.0.0
	 * @version 4.8.3 Moved from RankMath class to here.
	 *
	 * @var string
	 */
	public $postActionName = 'aioseo_import_post_meta_rank_math';

	/**
	 * The mapped meta
	 *
	 * @since 4.8.3
	 *
	 * @var array
	 */
	private $mappedMeta = [
		'rank_math_title'                => 'title',
		'rank_math_description'          => 'description',
		'rank_math_canonical_url'        => 'canonical_url',
		'rank_math_focus_keyword'        => 'keyphrases',
		'rank_math_robots'               => '',
		'rank_math_advanced_robots'      => '',
		'rank_math_facebook_title'       => 'og_title',
		'rank_math_facebook_description' => 'og_description',
		'rank_math_facebook_image'       => 'og_image_custom_url',
		'rank_math_twitter_use_facebook' => 'twitter_use_og',
		'rank_math_twitter_title'        => 'twitter_title',
		'rank_math_twitter_description'  => 'twitter_description',
		'rank_math_twitter_image'        => 'twitter_image_custom_url',
		'rank_math_twitter_card_type'    => 'twitter_card',
		'rank_math_primary_category'     => 'primary_term',
		'rank_math_pillar_content'       => 'pillar_content',
	];

	/**
	 * Class constructor.
	 *
	 * @since 4.8.3
	 */
	public function __construct() {
		add_action( $this->postActionName, [ $this, 'importPostMeta' ] );
	}

	/**
	 * Schedules the post meta import.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	public function scheduleImport() {
		try {
			if ( as_next_scheduled_action( $this->postActionName ) ) {
				return;
			}

			if ( ! aioseo()->core->cache->get( 'import_post_meta_rank_math' ) ) {
				aioseo()->core->cache->update( 'import_post_meta_rank_math', time(), WEEK_IN_SECONDS );
			}

			as_schedule_single_action( time(), $this->postActionName, [], 'aioseo' );
		} catch ( \Exception $e ) {
			// Do nothing.
		}
	}

	/**
	 * Get all posts to be imported
	 *
	 * @since 4.8.3
	 *
	 * @param  int   $postsPerAction The number of posts to import per action.
	 * @return array                 The posts to be imported.
	 */
	protected function getPostsToImport( $postsPerAction = 100 ) {
		$publicPostTypes = implode( "', '", aioseo()->helpers->getPublicPostTypes( true ) );
		$timeStarted     = gmdate( 'Y-m-d H:i:s', aioseo()->core->cache->get( 'import_post_meta_rank_math' ) );

		$posts = aioseo()->core->db
			->start( 'posts' . ' as p' )
			->select( 'p.ID, p.post_type' )
			->join( 'postmeta as pm', '`p`.`ID` = `pm`.`post_id`' )
			->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
			->whereRaw( "pm.meta_key LIKE 'rank_math_%'" )
			->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
			->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
			->orderBy( 'p.ID DESC' )
			->groupBy( 'p.ID' )
			->limit( $postsPerAction )
			->run()
			->result();

		return $posts;
	}

	/**
	 * Imports the post meta.
	 *
	 * @since 4.0.0
	 *
	 * @return array The posts that were imported.
	 */
	public function importPostMeta() {
		$postsPerAction = apply_filters( 'aioseo_import_rank_math_posts_per_action', 100 );
		$posts          = $this->getPostsToImport( $postsPerAction );
		if ( ! $posts || ! count( $posts ) ) {
			aioseo()->core->cache->delete( 'import_post_meta_rank_math' );

			return [];
		}

		foreach ( $posts as $post ) {
			$postMeta = aioseo()->core->db
				->start( 'postmeta' . ' as pm' )
				->select( 'pm.meta_key, pm.meta_value' )
				->where( 'pm.post_id', $post->ID )
				->whereRaw( "`pm`.`meta_key` LIKE 'rank_math_%'" )
				->run()
				->result();

			$meta = array_merge( [
				'post_id' => (int) $post->ID,
			], $this->getMetaData( $postMeta, $post ) );

			$aioseoPost = Models\Post::getPost( $post->ID );
			$aioseoPost->set( $meta );
			$aioseoPost->save();

			aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );
		}

		// Clear the Overview cache.
		aioseo()->postSettings->clearPostTypeOverviewCache( $posts[0]->ID );

		if ( count( $posts ) === $postsPerAction ) {
			try {
				as_schedule_single_action( time() + 5, $this->postActionName, [], 'aioseo' );
			} catch ( \Exception $e ) {
				// Do nothing.
			}
		} else {
			aioseo()->core->cache->delete( 'import_post_meta_rank_math' );
		}

		return $posts;
	}

	/**
	 * Get the meta data by post meta.
	 *
	 * @since 4.8.3
	 *
	 * @param object $postMeta The post meta from database.
	 * @param object $post     The post object.
	 * @return array           The meta data.
	 */
	public function getMetaData( $postMeta, $post ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$meta = [
			'post_id'             => $post->ID,
			'robots_default'      => true,
			'robots_noarchive'    => false,
			'canonical_url'       => '',
			'robots_nofollow'     => false,
			'robots_noimageindex' => false,
			'robots_noindex'      => false,
			'robots_noodp'        => false,
			'robots_nosnippet'    => false,
			'keyphrases'          => [
				'focus'      => [ 'keyphrase' => '' ],
				'additional' => []
			],
		];
		foreach ( $postMeta as $record ) {
			$name  = $record->meta_key;
			$value = $record->meta_value;

			if (
				! in_array( $post->post_type, [ 'page', 'attachment' ], true ) &&
				preg_match( '#^rank_math_schema_([^\s]*)$#', (string) $name, $match ) && ! empty( $match[1] )
			) {
				switch ( $match[1] ) {
					case 'Article':
					case 'NewsArticle':
					case 'BlogPosting':
						$meta['schema_type'] = 'Article';
						$meta['schema_type_options'] = wp_json_encode(
							[ 'article' => [ 'articleType' => $match[1] ] ]
						);
						break;
					default:
						break;
				}
			}

			if ( ! in_array( $name, array_keys( $this->mappedMeta ), true ) ) {
				continue;
			}

			switch ( $name ) {
				case 'rank_math_focus_keyword':
					$keyphrases     = array_map( 'trim', explode( ',', $value ) );
					$keyphraseArray = [
						'focus'      => [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $keyphrases[0] ) ],
						'additional' => []
					];
					unset( $keyphrases[0] );
					foreach ( $keyphrases as $keyphrase ) {
						$keyphraseArray['additional'][] = [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $keyphrase ) ];
					}

					$meta['keyphrases'] = $keyphraseArray;
					break;
				case 'rank_math_robots':
					$value = aioseo()->helpers->maybeUnserialize( $value );
					if ( ! empty( $value ) ) {
						$supportedValues        = [ 'index', 'noindex', 'nofollow', 'noarchive', 'noimageindex', 'nosnippet' ];
						$meta['robots_default'] = false;

						foreach ( $supportedValues as $val ) {
							$meta[ "robots_$val" ] = false;
						}

						// This is a separated foreach as we can import any and all values.
						foreach ( $value as $robotsName ) {
							$meta[ "robots_$robotsName" ] = true;
						}
					}
					break;
				case 'rank_math_advanced_robots':
					$value = aioseo()->helpers->maybeUnserialize( $value );
					if ( isset( $value['max-snippet'] ) && is_numeric( $value['max-snippet'] ) ) {
						$meta['robots_default']     = false;
						$meta['robots_max_snippet'] = intval( $value['max-snippet'] );
					}
					if ( isset( $value['max-video-preview'] ) && is_numeric( $value['max-video-preview'] ) ) {
						$meta['robots_default']          = false;
						$meta['robots_max_videopreview'] = intval( $value['max-video-preview'] );
					}
					if ( ! empty( $value['max-image-preview'] ) ) {
						$meta['robots_default']          = false;
						$meta['robots_max_imagepreview'] = aioseo()->helpers->sanitizeOption( lcfirst( $value['max-image-preview'] ) );
					}
					break;
				case 'rank_math_facebook_image':
					$meta['og_image_type']        = 'custom_image';
					$meta[ $this->mappedMeta[ $name ] ] = esc_url( $value );
					break;
				case 'rank_math_twitter_image':
					$meta['twitter_image_type']   = 'custom_image';
					$meta[ $this->mappedMeta[ $name ] ] = esc_url( $value );
					break;
				case 'rank_math_twitter_card_type':
					preg_match( '#large#', (string) $value, $match );
					$meta[ $this->mappedMeta[ $name ] ] = ! empty( $match ) ? 'summary_large_image' : 'summary';
					break;
				case 'rank_math_twitter_use_facebook':
					$meta[ $this->mappedMeta[ $name ] ] = 'on' === $value;
					break;
				case 'rank_math_primary_category':
					$taxonomy                     = 'category';
					$options                      = new \stdClass();
					$options->$taxonomy           = (int) $value;
					$meta[ $this->mappedMeta[ $name ] ] = wp_json_encode( $options );
					break;
				case 'rank_math_title':
				case 'rank_math_description':
					if ( 'page' === $post->post_type ) {
						$value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
						$value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
					}
					$value = aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value );

					$meta[ $this->mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
					break;
				case 'rank_math_pillar_content':
					$meta['pillar_content'] = 'on' === $value ? 1 : 0;
					break;
				default:
					$meta[ $this->mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
					break;
			}
		}

		return $meta;
	}
}RankMath/GeneralSettings.php000066600000005777151145361560012113 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\RankMath;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the General Settings.
 *
 * @since 4.0.0
 */
class GeneralSettings {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->options = get_option( 'rank-math-options-general' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->isTruSeoDisabled();
		$this->migrateRedirectAttachments();
		$this->migrateStripCategoryBase();
		$this->migrateRssContentSettings();

		$settings = [
			'google_verify'    => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'google' ] ],
			'bing_verify'      => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'bing' ] ],
			'yandex_verify'    => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'yandex' ] ],
			'baidu_verify'     => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'baidu' ] ],
			'pinterest_verify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'pinterest' ] ],
		];

		aioseo()->importExport->rankMath->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Checks whether TruSEO should be disabled.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function isTruSeoDisabled() {
		if ( ! empty( $this->options['frontend_seo_score'] ) ) {
			aioseo()->options->advanced->truSeo = 'on' === $this->options['frontend_seo_score'];
		}
	}

	/**
	 * Migrates the Redirect Attachments setting.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateRedirectAttachments() {
		if ( isset( $this->options['attachment_redirect_urls'] ) ) {
			if ( 'on' === $this->options['attachment_redirect_urls'] ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
			} else {
				aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'disabled';
			}
		}
	}

	/**
	 * Migrates the Strip Category Base setting.
	 *
	 * @since 4.2.0
	 *
	 * @return void
	 */
	private function migrateStripCategoryBase() {
		if ( isset( $this->options['strip_category_base'] ) ) {
			aioseo()->options->searchAppearance->advanced->removeCategoryBase = 'on' === $this->options['strip_category_base'] ? true : false;
		}
	}

	/**
	 * Migrates the RSS content settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateRssContentSettings() {
		if ( isset( $this->options['rss_before_content'] ) ) {
			aioseo()->options->rssContent->before = esc_html( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options['rss_before_content'] ) );
		}

		if ( isset( $this->options['rss_after_content'] ) ) {
			aioseo()->options->rssContent->after = esc_html( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $this->options['rss_after_content'] ) );
		}
	}
}RankMath/Sitemap.php000066600000011643151145361560010404 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\RankMath;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the sitemap settings.
 *
 * @since 4.0.0
 */
class Sitemap {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->options = get_option( 'rank-math-options-sitemap' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateIncludedObjects();
		$this->migrateIncludeImages();
		$this->migrateExcludedPosts();
		$this->migrateExcludedTerms();

		$settings = [
			'items_per_page' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'linksPerIndex' ] ],
		];

		aioseo()->options->sitemap->general->indexes = true;
		aioseo()->importExport->rankMath->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the included post types and taxonomies.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateIncludedObjects() {
		$includedPostTypes  = [];
		$includedTaxonomies = [];

		$allowedPostTypes = array_values( array_diff( aioseo()->helpers->getPublicPostTypes( true ), aioseo()->helpers->getNoindexedPostTypes() ) );
		foreach ( $allowedPostTypes as $postType ) {
			foreach ( $this->options as $name => $value ) {
				if ( preg_match( "#pt_{$postType}_sitemap$#", (string) $name, $match ) && 'on' === $this->options[ $name ] ) {
					$includedPostTypes[] = $postType;
				}
			}
		}

		$allowedTaxonomies = array_values( array_diff( aioseo()->helpers->getPublicTaxonomies( true ), aioseo()->helpers->getNoindexedTaxonomies() ) );
		foreach ( $allowedTaxonomies as $taxonomy ) {
			foreach ( $this->options as $name => $value ) {
				if ( preg_match( "#tax_{$taxonomy}_sitemap$#", (string) $name, $match ) && 'on' === $this->options[ $name ] ) {
					$includedTaxonomies[] = $taxonomy;
				}
			}
		}

		aioseo()->options->sitemap->general->postTypes->included = $includedPostTypes;
		if ( count( $allowedPostTypes ) !== count( $includedPostTypes ) ) {
			aioseo()->options->sitemap->general->postTypes->all = false;
		}

		aioseo()->options->sitemap->general->taxonomies->included = $includedTaxonomies;
		if ( count( $allowedTaxonomies ) !== count( $includedTaxonomies ) ) {
			aioseo()->options->sitemap->general->taxonomies->all = false;
		}
	}

	/**
	 * Migrates the Redirect Attachments setting.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateIncludeImages() {
		if ( ! empty( $this->options['include_images'] ) ) {
			if ( 'off' === $this->options['include_images'] ) {
				aioseo()->options->sitemap->general->advancedSettings->enable        = true;
				aioseo()->options->sitemap->general->advancedSettings->excludeImages = true;
			}
		}
	}

	/**
	 * Migrates the posts that are excluded from the sitemap.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateExcludedPosts() {
		if ( empty( $this->options['exclude_posts'] ) ) {
			return;
		}

		$rmExcludedPosts = array_filter( explode( ',', $this->options['exclude_posts'] ) );
		$excludedPosts   = aioseo()->options->sitemap->general->advancedSettings->excludePosts;

		if ( count( $rmExcludedPosts ) ) {
			foreach ( $rmExcludedPosts as $rmExcludedPost ) {
				$post = get_post( trim( $rmExcludedPost ) );
				if ( ! is_object( $post ) ) {
					continue;
				}

				$excludedPost        = new \stdClass();
				$excludedPost->value = $post->ID;
				$excludedPost->type  = $post->post_type;
				$excludedPost->label = $post->post_title;
				$excludedPost->link  = get_permalink( $post->ID );

				array_push( $excludedPosts, wp_json_encode( $excludedPost ) );
			}
			aioseo()->options->sitemap->general->advancedSettings->enable = true;
		}
		aioseo()->options->sitemap->general->advancedSettings->excludePosts = $excludedPosts;
	}

	/**
	 * Migrates the terms that are excluded from the sitemap.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateExcludedTerms() {
		if ( empty( $this->options['exclude_terms'] ) ) {
			return;
		}

		$rmExcludedTerms = array_filter( explode( ',', $this->options['exclude_terms'] ) );
		$excludedTerms   = aioseo()->options->sitemap->general->advancedSettings->excludeTerms;

		if ( count( $rmExcludedTerms ) ) {
			foreach ( $rmExcludedTerms as $rmExcludedTerm ) {
				$term = get_term( trim( $rmExcludedTerm ) );
				if ( ! is_object( $term ) ) {
					continue;
				}

				$excludedTerm        = new \stdClass();
				$excludedTerm->value = $term->term_id;
				$excludedTerm->type  = $term->taxonomy;
				$excludedTerm->label = $term->name;
				$excludedTerm->link  = get_term_link( $term );

				array_push( $excludedTerms, wp_json_encode( $excludedTerm ) );
			}
			aioseo()->options->sitemap->general->advancedSettings->enable = true;
		}
		aioseo()->options->sitemap->general->advancedSettings->excludeTerms = $excludedTerms;
	}
}SearchAppearance.php000066600000001535151145361560010461 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Migrates the Search Appearance settings.
 *
 * @since 4.0.0
 */
abstract class SearchAppearance {
	/**
	 * The schema graphs we support.
	 *
	 * @since 4.0.0
	 *
	 * @var array
	 */
	public static $supportedSchemaGraphs = [
		'none',
		'WebPage',
		'Article'
	];

	/**
	 * The WebPage graphs we support.
	 *
	 * @since 4.0.0
	 *
	 * @var array
	 */
	public static $supportedWebPageGraphs = [
		'AboutPage',
		'CollectionPage',
		'ContactPage',
		'FAQPage',
		'ItemPage',
		'ProfilePage',
		'RealEstateListing',
		'SearchResultsPage',
		'WebPage'
	];

	/**
	 * The Article graphs we support.
	 *
	 * @since 4.0.0
	 *
	 * @var array
	 */
	public static $supportedArticleGraphs = [
		'Article',
		'BlogPosting',
		'NewsArticle'
	];
}Importer.php000066600000002675151145361560007103 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Imports the settings and meta data from other plugins.
 *
 * @since 4.0.0
 */
abstract class Importer {
	/**
	 * Imports the settings.
	 *
	 * @since 4.2.7
	 *
	 * @return void
	 */
	protected function importSettings() {}

	/**
	 * Imports the post meta.
	 *
	 * @since 4.2.7
	 *
	 * @return void
	 */
	protected function importPostMeta() {}

	/**
	 * Imports the term meta.
	 *
	 * @since 4.2.7
	 *
	 * @return void
	 */
	protected function importTermMeta() {}

	/**
	 * PostMeta class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var Object
	 */
	protected $postMeta = null;

	/**
	 * TermMeta class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var Object
	 */
	protected $termMeta = null;

	/**
	 * Helpers class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var Object
	 */
	public $helpers = null;

	/**
	 * Starts the import.
	 *
	 * @since 4.0.0
	 *
	 * @param  array $options What the user wants to import.
	 * @return void
	 */
	public function doImport( $options = [] ) {
		if ( empty( $options ) ) {
			$this->importSettings();
			$this->importPostMeta();
			$this->importTermMeta();

			return;
		}

		foreach ( $options as $optionName ) {
			switch ( $optionName ) {
				case 'settings':
					$this->importSettings();
					break;
				case 'postMeta':
					$this->postMeta->scheduleImport();
					break;
				default:
					break;
			}
		}
	}
}ImportExport.php000066600000025310151145361560007745 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\Models;

/**
 * Handles the importing/exporting of settings and SEO data.
 *
 * @since 4.0.0
 */
class ImportExport {
	/**
	 * List of plugins for importing.
	 *
	 * @since 4.0.0
	 *
	 * @var array
	 */
	private $plugins = [];

	/**
	 * YoastSeo class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var YoastSeo\YoastSeo
	 */
	public $yoastSeo = null;

	/**
	 * RankMath class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var RankMath\RankMath
	 */
	public $rankMath = null;

	/**
	 * SeoPress class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var SeoPress\SeoPress
	 */
	public $seoPress = null;

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->yoastSeo = new YoastSeo\YoastSeo( $this );
		$this->rankMath = new RankMath\RankMath( $this );
		$this->seoPress = new SeoPress\SeoPress( $this );
	}

	/**
	 * Converts the content of a given V3 .ini settings file to an array of settings.
	 *
	 * @since 4.0.0
	 *
	 * @param  string $contents The .ini file contents.
	 * @return array            The settings.
	 */
	public function importIniData( $contents ) {
		$lines = array_filter( preg_split( '/\r\n|\r|\n/', (string) $contents ) );

		$sections     = [];
		$sectionLabel = '';
		$sectionCount = 0;

		foreach ( $lines as $line ) {
			$line = trim( $line );
			// Ignore comments.
			if ( preg_match( '#^;.*#', (string) $line ) || preg_match( '#\<(\?php|script)#', (string) $line ) ) {
				continue;
			}

			$matches = [];
			if ( preg_match( '#^\[(\S+)\]$#', (string) $line, $label ) ) {
				$sectionLabel = strval( $label[1] );
				if ( 'post_data' === $sectionLabel ) {
					$sectionCount++;
				}
				if ( ! isset( $sections[ $sectionLabel ] ) ) {
					$sections[ $sectionLabel ] = [];
				}
			} elseif ( preg_match( "#^(\S+)\s*=\s*'(.*)'$#", (string) $line, $matches ) ) {
				if ( 'post_data' === $sectionLabel ) {
					$sections[ $sectionLabel ][ $sectionCount ][ $matches[1] ] = $matches[2];
				} else {
					$sections[ $sectionLabel ][ $matches[1] ] = $matches[2];
				}
			} elseif ( preg_match( '#^(\S+)\s*=\s*NULL$#', (string) $line, $matches ) ) {
				if ( 'post_data' === $sectionLabel ) {
					$sections[ $sectionLabel ][ $sectionCount ][ $matches[1] ] = '';
				} else {
					$sections[ $sectionLabel ][ $matches[1] ] = '';
				}
			} else {
				continue;
			}
		}

		$sanitizedSections = [];
		foreach ( $sections as $section => $options ) {
			$sanitizedSection = [];
			foreach ( $options as $option => $value ) {
				$sanitizedSection[ $option ] = $this->convertAndSanitize( $value );
			}
			$sanitizedSections[ $section ] = $sanitizedSection;
		}

		$oldOptions = [];
		$postData   = [];
		foreach ( $sanitizedSections as $label => $data ) {
			switch ( $label ) {
				case 'aioseop_options':
					$oldOptions = array_merge( $oldOptions, $data );
					break;
				case 'aiosp_feature_manager_options':
				case 'aiosp_opengraph_options':
				case 'aiosp_sitemap_options':
				case 'aiosp_video_sitemap_options':
				case 'aiosp_schema_local_business_options':
				case 'aiosp_image_seo_options':
				case 'aiosp_robots_options':
				case 'aiosp_bad_robots_options':
					$oldOptions['modules'][ $label ] = $data;
					break;
				case 'post_data':
					$postData = $data;
					break;
				default:
					break;
			}
		}

		if ( ! empty( $oldOptions ) ) {
			aioseo()->migration->migrateSettings( $oldOptions );
		}

		if ( ! empty( $postData ) ) {
			$this->importOldPostMeta( $postData );
		}

		return true;
	}

	/**
	 * Imports the post meta from V3.
	 *
	 * @since 4.0.0
	 *
	 * @param  array $postData The post data.
	 * @return void
	 */
	private function importOldPostMeta( $postData ) {
		$mappedMeta = [
			'_aioseop_title'              => 'title',
			'_aioseop_description'        => 'description',
			'_aioseop_custom_link'        => 'canonical_url',
			'_aioseop_sitemap_exclude'    => '',
			'_aioseop_disable'            => '',
			'_aioseop_noindex'            => 'robots_noindex',
			'_aioseop_nofollow'           => 'robots_nofollow',
			'_aioseop_sitemap_priority'   => 'priority',
			'_aioseop_sitemap_frequency'  => 'frequency',
			'_aioseop_keywords'           => 'keywords',
			'_aioseop_opengraph_settings' => ''
		];

		$excludedPosts        = [];
		$sitemapExcludedPosts = [];

		require_once ABSPATH . 'wp-admin/includes/post.php';
		foreach ( $postData as $post => $values ) {
			$postId = \post_exists( $values['post_title'], '', $values['post_date'] );
			if ( ! $postId ) {
				continue;
			}

			$meta = [
				'post_id' => $postId,
			];

			foreach ( $values as $name => $value ) {
				if ( ! in_array( $name, array_keys( $mappedMeta ), true ) ) {
					continue;
				}

				switch ( $name ) {
					case '_aioseop_sitemap_exclude':
						if ( empty( $value ) ) {
							break;
						}
						$sitemapExcludedPosts[] = $postId;
						break;
					case '_aioseop_disable':
						if ( empty( $value ) ) {
							break;
						}
						$excludedPosts[] = $postId;
						break;
					case '_aioseop_noindex':
					case '_aioseop_nofollow':
						$meta[ $mappedMeta[ $name ] ] = ! empty( $value );
						if ( ! empty( $value ) ) {
							$meta['robots_default'] = false;
						}
						break;
					case '_aioseop_keywords':
						$meta[ $mappedMeta[ $name ] ] = aioseo()->migration->helpers->oldKeywordsToNewKeywords( $value );
						break;
					case '_aioseop_opengraph_settings':
						$class = new \AIOSEO\Plugin\Common\Migration\Meta();
						$meta += $class->convertOpenGraphMeta( $value );
						break;
					default:
						$meta[ $mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
						break;
				}
			}
			$post = Models\Post::getPost( $postId );
			$post->set( $meta );
			$post->save();
		}

		if ( count( $excludedPosts ) ) {
			$deprecatedOptions = aioseo()->internalOptions->internal->deprecatedOptions;
			if ( ! in_array( 'excludePosts', $deprecatedOptions, true ) ) {
				array_push( $deprecatedOptions, 'excludePosts' );
				aioseo()->internalOptions->internal->deprecatedOptions = $deprecatedOptions;
			}

			$posts = aioseo()->options->deprecated->searchAppearance->advanced->excludePosts;

			foreach ( $excludedPosts as $id ) {
				if ( ! intval( $id ) ) {
					continue;
				}
				$post = get_post( $id );
				if ( ! is_object( $post ) ) {
					continue;
				}
				$excludedPost        = new \stdClass();
				$excludedPost->type  = $post->post_type;
				$excludedPost->value = $post->ID;
				$excludedPost->label = $post->post_title;
				$excludedPost->link  = get_permalink( $post );

				$posts[] = wp_json_encode( $excludedPost );
			}
			aioseo()->options->deprecated->searchAppearance->advanced->excludePosts = $posts;
		}

		if ( count( $sitemapExcludedPosts ) ) {
			aioseo()->options->sitemap->general->advancedSettings->enable = true;

			$posts = aioseo()->options->sitemap->general->advancedSettings->excludePosts;
			foreach ( $sitemapExcludedPosts as $id ) {
				if ( ! intval( $id ) ) {
					continue;
				}
				$post = get_post( $id );
				if ( ! is_object( $post ) ) {
					continue;
				}
				$excludedPost        = new \stdClass();
				$excludedPost->type  = $post->post_type;
				$excludedPost->value = $post->ID;
				$excludedPost->label = $post->post_title;
				$excludedPost->link  = get_permalink( $post );

				$posts[] = wp_json_encode( $excludedPost );
			}
			aioseo()->options->sitemap->general->advancedSettings->excludePosts = $posts;
		}
	}

	/**
	 * Unserializes an option value if needed and then sanitizes it.
	 *
	 * @since 4.0.0
	 *
	 * @param  string $value The option value.
	 * @return mixed         The sanitized, converted option value.
	 */
	private function convertAndSanitize( $value ) {
		$value = aioseo()->helpers->maybeUnserialize( $value );

		switch ( gettype( $value ) ) {
			case 'boolean':
				return (bool) $value;
			case 'string':
				return esc_html( wp_strip_all_tags( wp_check_invalid_utf8( trim( $value ) ) ) );
			case 'integer':
				return intval( $value );
			case 'double':
				return floatval( $value );
			case 'array':
				$sanitized = [];
				foreach ( (array) $value as $k => $v ) {
					$sanitized[ $k ] = $this->convertAndSanitize( $v );
				}

				return $sanitized;
			default:
				return '';
		}
	}

	/**
	 * Starts an import.
	 *
	 * @since 4.0.0
	 *
	 * @param  string $plugin  The slug of the plugin to import.
	 * @param  array $settings Which settings to import.
	 * @return void
	 */
	public function startImport( $plugin, $settings ) {
		// First cancel any scans running that might interfere with our import.
		$this->cancelScans();

		foreach ( $this->plugins as $pluginData ) {
			if ( $pluginData['slug'] === $plugin ) {
				$pluginData['class']->doImport( $settings );

				return;
			}
		}
	}

	/**
	 * Cancel scans that are currently running and could conflict with our migration.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function cancelScans() {
		// Figure out how to check if these addons are enabled and then get the action names that way.
		aioseo()->actionScheduler->unschedule( 'aioseo_video_sitemap_scan' );
		aioseo()->actionScheduler->unschedule( 'aioseo_image_sitemap_scan' );
	}

	/**
	 * Checks if an import is currently running.
	 *
	 * @since 4.1.4
	 *
	 * @return boolean True if an import is currently running.
	 */
	public function isImportRunning() {
		$importsRunning = aioseo()->core->cache->get( 'import_%_meta_%' );

		return ! empty( $importsRunning );
	}

	/**
	 * Adds plugins to the import/export.
	 *
	 * @since 4.0.0
	 *
	 * @param  array $plugins The plugins to add.
	 * @return void
	 */
	public function addPlugins( $plugins ) {
		$this->plugins = array_merge( $this->plugins, $plugins );
	}

	/**
	 * Get the plugins we allow importing from.
	 *
	 * @since 4.0.0
	 *
	 * @return array
	 */
	public function plugins() {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
		$plugins          = [];
		$installedPlugins = array_keys( get_plugins() );
		foreach ( $this->plugins as $importerPlugin ) {
			$data = [
				'slug'      => $importerPlugin['slug'],
				'name'      => $importerPlugin['name'],
				'version'   => null,
				'canImport' => false,
				'basename'  => $importerPlugin['basename'],
				'installed' => false
			];

			if ( in_array( $importerPlugin['basename'], $installedPlugins, true ) ) {
				$pluginData = get_file_data( trailingslashit( WP_PLUGIN_DIR ) . $importerPlugin['basename'], [
					'name'    => 'Plugin Name',
					'version' => 'Version',
				] );

				$canImport = false;
				if ( version_compare( $importerPlugin['version'], $pluginData['version'], '<=' ) ) {
					$canImport = true;
				}

				$data['name']      = $pluginData['name'];
				$data['version']   = $pluginData['version'];
				$data['canImport'] = $canImport;
				$data['installed'] = true;
			}

			$plugins[] = $data;
		}

		return $plugins;
	}
}YoastSeo/Helpers.php000066600000011315151145361560010441 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Contains helper methods for the import from Rank Math.
 *
 * @since 4.0.0
 */
class Helpers extends ImportExport\Helpers {
	/**
	 * Converts the macros from Yoast SEO to our own smart tags.
	 *
	 * @since 4.0.0
	 *
	 * @param  string $string   The string with macros.
	 * @param  string $postType The post type.
	 * @param  string $pageType The page type.
	 * @return string $string   The string with smart tags.
	 */
	public function macrosToSmartTags( $string, $postType = null, $pageType = null ) {
		$macros = $this->getMacros( $postType, $pageType );

		if ( preg_match( '#%%BLOGDESCLINK%%#', (string) $string ) ) {
			$blogDescriptionLink = '<a href="' .
				aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'url' ) ) . '">' .
				aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) ) . ' - ' .
				aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'description' ) ) . '</a>';

			$string = str_replace( '%%BLOGDESCLINK%%', $blogDescriptionLink, $string );
		}

		if ( preg_match_all( '#%%cf_([^%]*)%%#', (string) $string, $matches ) && ! empty( $matches[1] ) ) {
			foreach ( $matches[1] as $name ) {
				if ( ! preg_match( '#\s#', (string) $name ) ) {
					$string = aioseo()->helpers->pregReplace( "#%%cf_$name%%#", "#custom_field-$name", $string );
				}
			}
		}

		if ( preg_match_all( '#%%tax_([^%]*)%%#', (string) $string, $matches ) && ! empty( $matches[1] ) ) {
			foreach ( $matches[1] as $name ) {
				if ( ! preg_match( '#\s#', (string) $name ) ) {
					$string = aioseo()->helpers->pregReplace( "#%%tax_$name%%#", "#tax_name-$name", $string );
				}
			}
		}

		foreach ( $macros as $macro => $tag ) {
			$string = aioseo()->helpers->pregReplace( "#$macro(?![a-zA-Z0-9_])#im", $tag, $string );
		}

		// Strip out all remaining tags.
		$string = aioseo()->helpers->pregReplace( '/%[^\%\s]*\([^\%]*\)%/i', '', aioseo()->helpers->pregReplace( '/%[^\%\s]*%/i', '', $string ) );

		return trim( $string );
	}

	/**
	 * Returns the macro mappings.
	 *
	 * @since 4.1.1
	 *
	 * @param  string $postType The post type.
	 * @param  string $pageType The page type.
	 * @return array  $macros   The macros.
	 */
	protected function getMacros( $postType = null, $pageType = null ) {
		$macros = [
			'%%sitename%%'             => '#site_title',
			'%%sitedesc%%'             => '#tagline',
			'%%sep%%'                  => '#separator_sa',
			'%%term_title%%'           => '#taxonomy_title',
			'%%term_description%%'     => '#taxonomy_description',
			'%%category_description%%' => '#taxonomy_description',
			'%%tag_description%%'      => '#taxonomy_description',
			'%%primary_category%%'     => '#taxonomy_title',
			'%%archive_title%%'        => '#archive_title',
			'%%pagenumber%%'           => '#page_number',
			'%%caption%%'              => '#attachment_caption',
			'%%name%%'                 => '#author_first_name #author_last_name',
			'%%user_description%%'     => '#author_bio',
			'%%date%%'                 => '#archive_date',
			'%%currentday%%'           => '#current_day',
			'%%currentmonth%%'         => '#current_month',
			'%%currentyear%%'          => '#current_year',
			'%%searchphrase%%'         => '#search_term',
			'%%AUTHORLINK%%'           => '#author_link',
			'%%POSTLINK%%'             => '#post_link',
			'%%BLOGLINK%%'             => '#site_link',
			'%%category%%'             => '#categories',
			'%%parent_title%%'         => '#parent_title',
			'%%wc_sku%%'               => '#woocommerce_sku',
			'%%wc_price%%'             => '#woocommerce_price',
			'%%wc_brand%%'             => '#woocommerce_brand',
			'%%excerpt%%'              => '#post_excerpt',
			'%%excerpt_only%%'         => '#post_excerpt_only'
			/* '%%tag%%'                  => '',
			'%%id%%'                   => '',
			'%%page%%'                 => '',
			'%%modified%%'             => '',
			'%%pagetotal%%'            => '',
			'%%focuskw%%'              => '',
			'%%term404%%'              => '',
			'%%ct_desc_[^%]*%%'        => '' */
		];

		if ( $postType ) {
			$postType = get_post_type_object( $postType );
			if ( ! empty( $postType ) ) {
				$macros += [
					'%%pt_single%%' => $postType->labels->singular_name,
					'%%pt_plural%%' => $postType->labels->name,
				];
			}
		}

		switch ( $pageType ) {
			case 'archive':
				$macros['%%title%%'] = '#archive_title';
				break;
			case 'term':
				$macros['%%title%%'] = '#taxonomy_title';
				break;
			default:
				$macros['%%title%%'] = '#post_title';
				break;
		}

		// Strip all other tags.
		$macros['%%[^%]*%%'] = '';

		return $macros;
	}
}YoastSeo/SearchAppearance.php000066600000034145151145361560012232 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Search Appearance settings.
 *
 * @since 4.0.0
 */
class SearchAppearance {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Whether the homepage social settings have been imported here.
	 *
	 * @since 4.2.4
	 *
	 * @var bool
	 */
	public $hasImportedHomepageSocialSettings = false;

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->options = get_option( 'wpseo_titles' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateSeparator();
		$this->migrateTitleFormats();
		$this->migrateDescriptionFormats();
		$this->migrateNoindexSettings();
		$this->migratePostTypeSettings();
		$this->migratePostTypeArchiveSettings();
		$this->migrateRedirectAttachments();
		$this->migrateKnowledgeGraphSettings();
		$this->migrateRssContentSettings();
		$this->migrateStripCategoryBase();
		$this->migrateHomepageSocialSettings();
	}

	/**
	 * Migrates the title/description separator.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateSeparator() {
		$separators = [
			'sc-dash'   => '-',
			'sc-ndash'  => '&ndash;',
			'sc-mdash'  => '&mdash;',
			'sc-colon'  => ':',
			'sc-middot' => '&middot;',
			'sc-bull'   => '&bull;',
			'sc-star'   => '*',
			'sc-smstar' => '&#8902;',
			'sc-pipe'   => '|',
			'sc-tilde'  => '~',
			'sc-laquo'  => '&laquo;',
			'sc-raquo'  => '&raquo;',
			'sc-lt'     => '&lt;',
			'sc-gt'     => '&gt;',
		];

		if ( ! empty( $this->options['separator'] ) && in_array( $this->options['separator'], array_keys( $separators ), true ) ) {
			aioseo()->options->searchAppearance->global->separator = $separators[ $this->options['separator'] ];
		}
	}

	/**
	 * Migrates the title formats.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateTitleFormats() {
		aioseo()->options->searchAppearance->global->siteTitle =
			aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $this->options['title-home-wpseo'] ) );

		aioseo()->options->searchAppearance->archives->date->title =
			aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $this->options['title-archive-wpseo'], null, 'archive' ) );

		// Archive Title tag needs to be stripped since we don't support it for these two archives.
		$value = aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $this->options['title-author-wpseo'], null, 'archive' ) );
		aioseo()->options->searchAppearance->archives->author->title = aioseo()->helpers->pregReplace( '/#archive_title/', '', $value );

		$value = aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $this->options['title-search-wpseo'], null, 'archive' ) );
		aioseo()->options->searchAppearance->archives->search->title = aioseo()->helpers->pregReplace( '/#archive_title/', '', $value );
	}

	/**
	 * Migrates the description formats.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateDescriptionFormats() {
		$settings = [
			'metadesc-home-wpseo'    => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'metaDescription' ] ],
			'metadesc-author-wpseo'  => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'metaDescription' ] ],
			'metadesc-archive-wpseo' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'metaDescription' ] ],
		];

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options, true );
	}

	/**
	 * Migrates the noindex settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateNoindexSettings() {
		if ( ! empty( $this->options['noindex-author-wpseo'] ) ) {
			aioseo()->options->searchAppearance->archives->author->show = false;
			aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->default = false;
			aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->noindex = true;
		} else {
			aioseo()->options->searchAppearance->archives->author->show = true;
		}

		if ( ! empty( $this->options['noindex-archive-wpseo'] ) ) {
			aioseo()->options->searchAppearance->archives->date->show = false;
			aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->default = false;
			aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->noindex = true;
		} else {
			aioseo()->options->searchAppearance->archives->date->show = true;
		}
	}

	/**
	 * Migrates the post type settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migratePostTypeSettings() {
		$supportedSettings = [
			'title',
			'metadesc',
			'noindex',
			'display-metabox-pt',
			'schema-page-type',
			'schema-article-type'
		];

		foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
			foreach ( $this->options as $name => $value ) {
				if ( ! preg_match( "#(.*)-$postType$#", (string) $name, $match ) || ! in_array( $match[1], $supportedSettings, true ) ) {
					continue;
				}

				switch ( $match[1] ) {
					case 'title':
						if ( 'page' === $postType ) {
							$value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
							$value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
						}
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->title =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType ) );
						break;
					case 'metadesc':
						if ( 'page' === $postType ) {
							$value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
							$value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
						}
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->metaDescription =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType ) );
						break;
					case 'noindex':
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = empty( $value ) ? true : false;
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = empty( $value ) ? true : false;
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = empty( $value ) ? false : true;
						break;
					case 'display-metabox-pt':
						if ( empty( $value ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox = false;
						}
						break;
					case 'schema-page-type':
						$value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
						if ( in_array( $postType, [ 'post', 'page', 'attachment' ], true ) ) {
							break;
						}
						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->schemaType = 'WebPage';
						if ( in_array( $value, ImportExport\SearchAppearance::$supportedWebPageGraphs, true ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->webPageType = $value;
						}
						break;
					case 'schema-article-type':
						$value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
						if ( 'none' === lcfirst( $value ) ) {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'none';
							break;
						}

						aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'Article';
						if ( in_array( $value, ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
							if ( ! in_array( $postType, [ 'page', 'attachment' ], true ) ) {
								aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = $value;
							}
						} else {
							aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'BlogPosting';
						}
						break;
					default:
						break;
				}
			}
		}
	}

	/**
	 * Migrates the post type archive settings.
	 *
	 * @since 4.0.16
	 *
	 * @return void
	 */
	private function migratePostTypeArchiveSettings() {
		$supportedSettings = [
			'title',
			'metadesc',
			'noindex'
		];

		foreach ( aioseo()->helpers->getPublicPostTypes( true, true ) as $postType ) {
			foreach ( $this->options as $name => $value ) {
				if ( ! preg_match( "#(.*)-ptarchive-$postType$#", (string) $name, $match ) || ! in_array( $match[1], $supportedSettings, true ) ) {
					continue;
				}

				switch ( $match[1] ) {
					case 'title':
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->title =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType, 'archive' ) );
						break;
					case 'metadesc':
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->metaDescription =
							aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType, 'archive' ) );
						break;
					case 'noindex':
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->show = empty( $value ) ? true : false;
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->default = empty( $value ) ? true : false;
						aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->noindex = empty( $value ) ? false : true;
						break;
					default:
						break;
				}
			}
		}
	}

	/**
	 * Migrates the Knowledge Graph settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateKnowledgeGraphSettings() {
		if ( ! empty( $this->options['company_or_person'] ) ) {
			aioseo()->options->searchAppearance->global->schema->siteRepresents =
				'company' === $this->options['company_or_person'] ? 'organization' : 'person';
		}

		$settings = [
			'company_or_person_user_id' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'person' ] ],
			'person_logo'               => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'personLogo' ] ],
			'person_name'               => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'personName' ] ],
			'company_name'              => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'organizationName' ] ],
			'company_logo'              => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'organizationLogo' ] ],
			'org-email'                 => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'email' ] ],
			'org-phone'                 => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'phone' ] ],
			'org-description'           => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'organizationDescription' ] ],
			'org-founding-date'         => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'foundingDate' ] ],
		];

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );

		// Additional Info
		// Reset data
		aioseo()->options->noConflict()->searchAppearance->global->schema->numberOfEmployees->reset();

		$numberOfEmployees = $this->options['org-number-employees'];
		if ( ! empty( $numberOfEmployees ) ) {
			list( $num1, $num2 ) = explode( '-', $numberOfEmployees );

			if ( $num2 ) {
				aioseo()->options->noConflict()->searchAppearance->global->schema->numberOfEmployees->isRange = true;
				aioseo()->options->noConflict()->searchAppearance->global->schema->numberOfEmployees->from    = (int) $num1;
				aioseo()->options->noConflict()->searchAppearance->global->schema->numberOfEmployees->to      = (int) $num2;
			} else {
				aioseo()->options->noConflict()->searchAppearance->global->schema->numberOfEmployees->number = (int) $num1;
			}
		}
	}

	/**
	 * Migrates the RSS content settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateRssContentSettings() {
		if ( isset( $this->options['rssbefore'] ) ) {
			aioseo()->options->rssContent->before = esc_html( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $this->options['rssbefore'] ) );
		}

		if ( isset( $this->options['rssafter'] ) ) {
			aioseo()->options->rssContent->after = esc_html( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $this->options['rssafter'] ) );
		}
	}

	/**
	 * Migrates the Redirect Attachments setting.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateRedirectAttachments() {
		aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = empty( $this->options['disable-attachment'] ) ? 'disabled' : 'attachment';
	}

	/**
	 * Migrates the strip category base option.
	 *
	 * @since 4.2.0
	 *
	 * @return void
	 */
	private function migrateStripCategoryBase() {
		aioseo()->options->searchAppearance->advanced->removeCategoryBase = empty( $this->options['stripcategorybase'] ) ? false : true;
	}

	/**
	 * Migrate the social settings for the homepage.
	 *
	 * @since 4.2.4
	 *
	 * @return void
	 */
	private function migrateHomepageSocialSettings() {
		if (
			empty( $this->options['open_graph_frontpage_title'] ) &&
			empty( $this->options['open_graph_frontpage_desc'] ) &&
			empty( $this->options['open_graph_frontpage_image'] )
		) {
			return;
		}

		$this->hasImportedHomepageSocialSettings = true;

		$settings = [
			// These settings can also be found in the SocialMeta class, but Yoast recently moved them here.
			// We'll still keep them in the other class for backwards compatibility.
			'open_graph_frontpage_title' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'title' ] ],
			'open_graph_frontpage_desc'  => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'description' ] ],
			'open_graph_frontpage_image' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'image' ] ]
		];

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options, true );
	}
}YoastSeo/YoastSeo.php000066600000004174151145361560010612 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

class YoastSeo extends ImportExport\Importer {
	/**
	 * A list of plugins to look for to import.
	 *
	 * @since 4.0.0
	 *
	 * @var array
	 */
	public $plugins = [
		[
			'name'     => 'Yoast SEO',
			'version'  => '14.0',
			'basename' => 'wordpress-seo/wp-seo.php',
			'slug'     => 'yoast-seo'
		],
		[
			'name'     => 'Yoast SEO Premium',
			'version'  => '14.0',
			'basename' => 'wordpress-seo-premium/wp-seo-premium.php',
			'slug'     => 'yoast-seo-premium'
		],
	];

	/**
	 * The post action name.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	public $postActionName = 'aioseo_import_post_meta_yoast_seo';

	/**
	 * The user action name.
	 *
	 * @since 4.1.4
	 *
	 * @var string
	 */
	public $userActionName = 'aioseo_import_user_meta_yoast_seo';

	/**
	 * UserMeta class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var UserMeta
	 */
	private $userMeta = null;

	/**
	 * SearchAppearance class instance.
	 *
	 * @since 4.2.7
	 *
	 * @var SearchAppearance
	 */
	public $searchAppearance = null;

	/**
	 * The post action name.
	 *
	 * @since 4.0.0
	 *
	 * @param ImportExport\ImportExport $importer The main importer class.
	 */
	public function __construct( $importer ) {
		$this->helpers  = new Helpers();
		$this->postMeta = new PostMeta();
		$this->userMeta = new UserMeta();

		add_action( $this->postActionName, [ $this->postMeta, 'importPostMeta' ] );
		add_action( $this->userActionName, [ $this->userMeta, 'importUserMeta' ] );

		$plugins = $this->plugins;
		foreach ( $plugins as $key => $plugin ) {
			$plugins[ $key ]['class'] = $this;
		}
		$importer->addPlugins( $plugins );
	}

	/**
	 * Imports the settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	protected function importSettings() {
		new GeneralSettings();
		$this->searchAppearance = new SearchAppearance();
		// NOTE: The Social Meta settings need to be imported after the Search Appearance ones because some imports depend on what was imported there.
		new SocialMeta();
		$this->userMeta->scheduleImport();
	}
}YoastSeo/PostMeta.php000066600000025720151145361560010600 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;
use AIOSEO\Plugin\Common\Models;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Imports the post meta from Yoast SEO.
 *
 * @since 4.0.0
 */
class PostMeta {
	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function scheduleImport() {
		try {
			if ( as_next_scheduled_action( aioseo()->importExport->yoastSeo->postActionName ) ) {
				return;
			}

			if ( ! aioseo()->core->cache->get( 'import_post_meta_yoast_seo' ) ) {
				aioseo()->core->cache->update( 'import_post_meta_yoast_seo', time(), WEEK_IN_SECONDS );
			}

			as_schedule_single_action( time(), aioseo()->importExport->yoastSeo->postActionName, [], 'aioseo' );
		} catch ( \Exception $e ) {
			// Do nothing.
		}
	}

	/**
	 * Imports the post meta.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	public function importPostMeta() {
		$postsPerAction  = apply_filters( 'aioseo_import_yoast_seo_posts_per_action', 100 );
		$publicPostTypes = implode( "', '", aioseo()->helpers->getPublicPostTypes( true ) );
		$timeStarted     = gmdate( 'Y-m-d H:i:s', aioseo()->core->cache->get( 'import_post_meta_yoast_seo' ) );

		$posts = aioseo()->core->db
			->start( 'posts' . ' as p' )
			->select( 'p.ID, p.post_type' )
			->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
			->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
			->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
			->orderBy( 'p.ID DESC' )
			->limit( $postsPerAction )
			->run()
			->result();

		if ( ! $posts || ! count( $posts ) ) {
			aioseo()->core->cache->delete( 'import_post_meta_yoast_seo' );

			return;
		}

		$mappedMeta = [
			'_yoast_wpseo_title'                 => 'title',
			'_yoast_wpseo_metadesc'              => 'description',
			'_yoast_wpseo_canonical'             => 'canonical_url',
			'_yoast_wpseo_meta-robots-noindex'   => 'robots_noindex',
			'_yoast_wpseo_meta-robots-nofollow'  => 'robots_nofollow',
			'_yoast_wpseo_meta-robots-adv'       => '',
			'_yoast_wpseo_focuskw'               => '',
			'_yoast_wpseo_focuskeywords'         => '',
			'_yoast_wpseo_opengraph-title'       => 'og_title',
			'_yoast_wpseo_opengraph-description' => 'og_description',
			'_yoast_wpseo_opengraph-image'       => 'og_image_custom_url',
			'_yoast_wpseo_twitter-title'         => 'twitter_title',
			'_yoast_wpseo_twitter-description'   => 'twitter_description',
			'_yoast_wpseo_twitter-image'         => 'twitter_image_custom_url',
			'_yoast_wpseo_schema_page_type'      => '',
			'_yoast_wpseo_schema_article_type'   => '',
			'_yoast_wpseo_is_cornerstone'        => 'pillar_content'
		];

		foreach ( $posts as $post ) {
			$postMeta = aioseo()->core->db
				->start( 'postmeta' . ' as pm' )
				->select( 'pm.meta_key, pm.meta_value' )
				->where( 'pm.post_id', $post->ID )
				->whereRaw( "`pm`.`meta_key` LIKE '_yoast_wpseo_%'" )
				->run()
				->result();

			$featuredImage = get_the_post_thumbnail_url( $post->ID );
			$meta          = [
				'post_id'                  => (int) $post->ID,
				'twitter_use_og'           => true,
				'og_image_type'            => $featuredImage ? 'featured' : 'content',
				'pillar_content'           => 0,
				'canonical_url'            => '',
				'robots_default'           => true,
				'robots_noarchive'         => false,
				'robots_nofollow'          => false,
				'robots_noimageindex'      => false,
				'robots_noindex'           => false,
				'robots_noodp'             => false,
				'robots_nosnippet'         => false,
				'title'                    => '',
				'description'              => '',
				'og_title'                 => '',
				'og_description'           => '',
				'og_image_custom_url'      => '',
				'twitter_title'            => '',
				'twitter_description'      => '',
				'twitter_image_custom_url' => '',
				'twitter_image_type'       => 'default'
			];

			if ( ! $postMeta || ! count( $postMeta ) ) {
				$aioseoPost = Models\Post::getPost( (int) $post->ID );
				$aioseoPost->set( $meta );
				$aioseoPost->save();

				aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );
				continue;
			}

			$title = '';
			foreach ( $postMeta as $record ) {
				$name  = $record->meta_key;
				$value = $record->meta_value;

				// Handles primary taxonomy terms.
				// We need to handle it separately because it's stored in a different format.
				if ( false !== stripos( $name, '_yoast_wpseo_primary_' ) ) {
					sscanf( $name, '_yoast_wpseo_primary_%s', $taxonomy );
					if ( null === $taxonomy ) {
						continue;
					}

					$options = new \stdClass();
					if ( isset( $meta['primary_term'] ) ) {
						$options = json_decode( $meta['primary_term'] );
					}

					$options->$taxonomy   = (int) $value;
					$meta['primary_term'] = wp_json_encode( $options );
				}

				if ( ! in_array( $name, array_keys( $mappedMeta ), true ) ) {
					continue;
				}

				switch ( $name ) {
					case '_yoast_wpseo_meta-robots-noindex':
					case '_yoast_wpseo_meta-robots-nofollow':
						if ( (bool) $value ) {
							$meta[ $mappedMeta[ $name ] ] = (bool) $value;
							$meta['robots_default']       = false;
						}
						break;
					case '_yoast_wpseo_meta-robots-adv':
						$supportedValues = [ 'index', 'noarchive', 'noimageindex', 'nosnippet' ];
						foreach ( $supportedValues as $val ) {
							$meta[ "robots_$val" ] = false;
						}

						// This is a separated foreach so we can import any and all values.
						$values = explode( ',', $value );
						if ( $values ) {
							$meta['robots_default'] = false;

							foreach ( $values as $value ) {
								$meta[ "robots_$value" ] = true;
							}
						}
						break;
					case '_yoast_wpseo_canonical':
						$meta[ $mappedMeta[ $name ] ] = esc_url( $value );
						break;
					case '_yoast_wpseo_opengraph-image':
						$meta['og_image_type']        = 'custom_image';
						$meta[ $mappedMeta[ $name ] ] = esc_url( $value );
						break;
					case '_yoast_wpseo_twitter-image':
						$meta['twitter_use_og']       = false;
						$meta['twitter_image_type']   = 'custom_image';
						$meta[ $mappedMeta[ $name ] ] = esc_url( $value );
						break;
					case '_yoast_wpseo_schema_page_type':
						$value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
						if ( in_array( $post->post_type, [ 'post', 'page', 'attachment' ], true ) ) {
							break;
						}

						if ( ! in_array( $value, ImportExport\SearchAppearance::$supportedWebPageGraphs, true ) ) {
							break;
						}

						$meta[ $mappedMeta[ $name ] ] = 'WebPage';
						$meta['schema_type_options']  = wp_json_encode( [
							'webPage' => [
								'webPageType' => $value
							]
						] );
						break;
					case '_yoast_wpseo_schema_article_type':
						$value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
						if ( 'none' === lcfirst( $value ) ) {
							$meta[ $mappedMeta[ $name ] ] = 'None';
							break;
						}

						if ( in_array( $post->post_type, [ 'page', 'attachment' ], true ) ) {
							break;
						}

						$options = new \stdClass();
						if ( isset( $meta['schema_type_options'] ) ) {
							$options = json_decode( $meta['schema_type_options'] );
						}

						$options->article = [ 'articleType' => 'Article' ];
						if ( in_array( $value, ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
							$options->article = [ 'articleType' => $value ];
						} else {
							$options->article = [ 'articleType' => 'BlogPosting' ];
						}

						$meta['schema_type']         = 'Article';
						$meta['schema_type_options'] = wp_json_encode( $options );
						break;
					case '_yoast_wpseo_focuskw':
						$focusKeyphrase = [
							'focus' => [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $value ) ]
						];

						// Merge with existing keyphrases if the array key already exists.
						if ( ! empty( $meta['keyphrases'] ) ) {
							$meta['keyphrases'] = array_merge( $meta['keyphrases'], $focusKeyphrase );
						} else {
							$meta['keyphrases'] = $focusKeyphrase;
						}
						break;
					case '_yoast_wpseo_focuskeywords':
						$keyphrases = [];
						if ( ! empty( $meta[ $mappedMeta[ $name ] ] ) ) {
							$keyphrases = (array) json_decode( $meta[ $mappedMeta[ $name ] ] );
						}

						$yoastKeyphrases = json_decode( $value, true );
						if ( is_array( $yoastKeyphrases ) ) {
							foreach ( $yoastKeyphrases as $yoastKeyphrase ) {
								if ( ! empty( $yoastKeyphrase['keyword'] ) ) {
									$keyphrase = [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $yoastKeyphrase['keyword'] ) ];

									if ( ! isset( $keyphrases['additional'] ) ) {
										$keyphrases['additional'] = [];
									}

									$keyphrases['additional'][] = $keyphrase;
								}
							}
						}

						if ( ! empty( $keyphrases ) ) {
							// Merge with existing keyphrases if the array key already exists.
							if ( ! empty( $meta['keyphrases'] ) ) {
								$meta['keyphrases'] = array_merge( $meta['keyphrases'], $keyphrases );
							} else {
								$meta['keyphrases'] = $keyphrases;
							}
						}
						break;
					case '_yoast_wpseo_title':
					case '_yoast_wpseo_metadesc':
					case '_yoast_wpseo_opengraph-title':
					case '_yoast_wpseo_opengraph-description':
					case '_yoast_wpseo_twitter-title':
					case '_yoast_wpseo_twitter-description':
						if ( 'page' === $post->post_type ) {
							$value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
							$value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
						}

						if ( '_yoast_wpseo_twitter-title' === $name || '_yoast_wpseo_twitter-description' === $name ) {
							$meta['twitter_use_og'] = false;
						}

						$value = aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, 'post', $post->post_type );

						if ( '_yoast_wpseo_title' === $name ) {
							$title = $value;
						}

						$meta[ $mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
						break;
					case '_yoast_wpseo_is_cornerstone':
						$meta['pillar_content'] = (bool) $value ? 1 : 0;
						break;
					default:
						$meta[ $mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
						break;
				}
			}

			// Resetting the `twitter_use_og` option if the user has a custom title and no twitter title.
			if ( $meta['twitter_use_og'] && $title && empty( $meta['twitter_title'] ) ) {
				$meta['twitter_use_og'] = false;
				$meta['twitter_title']  = $title;
			}

			$aioseoPost = Models\Post::getPost( (int) $post->ID );
			$aioseoPost->set( $meta );
			$aioseoPost->save();

			aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );

			// Clear the Overview cache.
			aioseo()->postSettings->clearPostTypeOverviewCache( $post->ID );
		}

		if ( count( $posts ) === $postsPerAction ) {
			try {
				as_schedule_single_action( time() + 5, aioseo()->importExport->yoastSeo->postActionName, [], 'aioseo' );
			} catch ( \Exception $e ) {
				// Do nothing.
			}
		} else {
			aioseo()->core->cache->delete( 'import_post_meta_yoast_seo' );
		}
	}
}YoastSeo/GeneralSettings.php000066600000002233151145361560012134 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the General Settings.
 *
 * @since 4.0.0
 */
class GeneralSettings {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->options = get_option( 'wpseo' );
		if ( empty( $this->options ) ) {
			return;
		}

		$settings = [
			'googleverify'       => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'google' ] ],
			'msverify'           => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'bing' ] ],
			'yandexverify'       => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'yandex' ] ],
			'baiduverify'        => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'baidu' ] ],
			'enable_xml_sitemap' => [ 'type' => 'boolean', 'newOption' => [ 'sitemap', 'general', 'enable' ] ]
		];

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
	}
}YoastSeo/SocialMeta.php000066600000014250151145361560011061 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\Models;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Social Meta.
 *
 * @since 4.0.0
 */
class SocialMeta {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function __construct() {
		$this->options = get_option( 'wpseo_social' );

		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateSocialUrls();
		$this->migrateFacebookSettings();
		$this->migrateTwitterSettings();
		$this->migrateFacebookAdminId();
		$this->migrateSiteName();
		$this->migrateArticleTags();
		$this->migrateAdditionalTwitterData();

		$settings = [
			'pinterestverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'pinterest' ] ]
		];

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the Social URLs.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateSocialUrls() {
		$settings = [
			'facebook_site' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'facebookPageUrl' ] ],
			'instagram_url' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'instagramUrl' ] ],
			'linkedin_url'  => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'linkedinUrl' ] ],
			'myspace_url'   => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'myspaceUrl' ] ],
			'pinterest_url' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'pinterestUrl' ] ],
			'youtube_url'   => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'youtubeUrl' ] ],
			'wikipedia_url' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'wikipediaUrl' ] ],
			'wordpress_url' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'wordPressUrl' ] ],
		];

		if ( ! empty( $this->options['twitter_site'] ) ) {
			aioseo()->options->social->profiles->urls->twitterUrl =
				'https://x.com/' . aioseo()->helpers->sanitizeOption( $this->options['twitter_site'] );
		}

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the Facebook settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateFacebookSettings() {
		if ( ! empty( $this->options['og_default_image'] ) ) {
			$defaultImage = esc_url( $this->options['og_default_image'] );
			aioseo()->options->social->facebook->general->defaultImagePosts       = $defaultImage;
			aioseo()->options->social->facebook->general->defaultImageSourcePosts = 'default';

			aioseo()->options->social->twitter->general->defaultImagePosts       = $defaultImage;
			aioseo()->options->social->twitter->general->defaultImageSourcePosts = 'default';
		}

		$settings = [
			'opengraph' => [ 'type' => 'boolean', 'newOption' => [ 'social', 'facebook', 'general', 'enable' ] ],
		];

		if ( ! aioseo()->importExport->yoastSeo->searchAppearance->hasImportedHomepageSocialSettings ) {
			// These settings were moved to the Search Appearance tab of Yoast, but we'll leave this here to support older versions.
			// However, we want to make sure we import them only if the other ones aren't set.
			$settings = array_merge( $settings, [
				'og_frontpage_title' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'title' ] ],
				'og_frontpage_desc'  => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'description' ] ],
				'og_frontpage_image' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'image' ] ]
			] );
		}

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options, true );

		// Migrate home page object type.
		aioseo()->options->social->facebook->homePage->objectType = 'website';
		if ( 'page' === get_option( 'show_on_front' ) ) {
			$staticHomePageId = get_option( 'page_on_front' );

			// We must check if the ID exists because one might select the static homepage option but not actually set one.
			if ( ! $staticHomePageId ) {
				return;
			}

			$aioseoPost = Models\Post::getPost( (int) $staticHomePageId );
			$aioseoPost->set( [
				'og_object_type' => 'website'
			] );
			$aioseoPost->save();
		}
	}

	/**
	 * Migrates the Twitter settings.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateTwitterSettings() {
		$settings = [
			'twitter'           => [ 'type' => 'boolean', 'newOption' => [ 'social', 'twitter', 'general', 'enable' ] ],
			'twitter_card_type' => [ 'type' => 'string', 'newOption' => [ 'social', 'twitter', 'general', 'defaultCardType' ] ],
		];

		aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the Facebook admin ID.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	private function migrateFacebookAdminId() {
		if ( ! empty( $this->options['fbadminapp'] ) ) {
			aioseo()->options->social->facebook->advanced->enable = true;
			aioseo()->options->social->facebook->advanced->adminId = aioseo()->helpers->sanitizeOption( $this->options['fbadminapp'] );
		}
	}

	/**
	 * Yoast sets the og:site_name to '#site_title';
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateSiteName() {
		aioseo()->options->social->facebook->general->siteName = '#site_title';
	}

	/**
	 * Yoast uses post tags by default, so we need to enable this.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateArticleTags() {
		aioseo()->options->social->facebook->advanced->enable              = true;
		aioseo()->options->social->facebook->advanced->generateArticleTags = true;
		aioseo()->options->social->facebook->advanced->usePostTagsInTags   = true;
		aioseo()->options->social->facebook->advanced->useKeywordsInTags   = false;
		aioseo()->options->social->facebook->advanced->useCategoriesInTags = false;
	}

	/**
	 * Enable additional Twitter Data.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateAdditionalTwitterData() {
		aioseo()->options->social->twitter->general->additionalData = true;
	}
}YoastSeo/UserMeta.php000066600000005176151145361560010574 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;
use AIOSEO\Plugin\Common\Models;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Imports the user meta from Yoast SEO.
 *
 * @since 4.0.0
 */
class UserMeta {
	/**
	 * Class constructor.
	 *
	 * @since 4.0.0
	 */
	public function scheduleImport() {
		aioseo()->actionScheduler->scheduleSingle( aioseo()->importExport->yoastSeo->userActionName, 30 );

		if ( ! aioseo()->core->cache->get( 'import_user_meta_yoast_seo' ) ) {
			aioseo()->core->cache->update( 'import_user_meta_yoast_seo', 0, WEEK_IN_SECONDS );
		}
	}

	/**
	 * Imports the post meta.
	 *
	 * @since 4.0.0
	 *
	 * @return void
	 */
	public function importUserMeta() {
		$usersPerAction = 100;
		$offset         = aioseo()->core->cache->get( 'import_user_meta_yoast_seo' );

		$usersMeta = aioseo()->core->db
			->start( aioseo()->core->db->db->usermeta . ' as um', true )
			->whereRaw( "um.meta_key IN ('facebook', 'twitter', 'instagram', 'linkedin', 'myspace', 'pinterest', 'soundcloud', 'tumblr', 'wikipedia', 'youtube', 'mastodon', 'bluesky', 'threads')" )
			->whereRaw( "um.meta_value != ''" )
			->limit( $usersPerAction, $offset )
			->run()
			->result();

		if ( ! $usersMeta || ! count( $usersMeta ) ) {
			aioseo()->core->cache->delete( 'import_user_meta_yoast_seo' );

			return;
		}

		$mappedMeta = [
			'facebook'   => 'aioseo_facebook_page_url',
			'twitter'    => 'aioseo_twitter_url',
			'instagram'  => 'aioseo_instagram_url',
			'linkedin'   => 'aioseo_linkedin_url',
			'myspace'    => 'aioseo_myspace_url',
			'pinterest'  => 'aioseo_pinterest_url',
			'soundcloud' => 'aioseo_sound_cloud_url',
			'tumblr'     => 'aioseo_tumblr_url',
			'wikipedia'  => 'aioseo_wikipedia_url',
			'youtube'    => 'aioseo_youtube_url',
			'bluesky'    => 'aioseo_bluesky_url',
			'threads'    => 'aioseo_threads_url',
			'mastodon'   => 'aioseo_profiles_additional_urls'
		];

		foreach ( $usersMeta as $meta ) {
			if ( isset( $mappedMeta[ $meta->meta_key ] ) ) {
				$value = 'twitter' === $meta->meta_key ? 'https://x.com/' . $meta->meta_value : $meta->meta_value;
				update_user_meta( $meta->user_id, $mappedMeta[ $meta->meta_key ], $value );
			}
		}

		if ( count( $usersMeta ) === $usersPerAction ) {
			aioseo()->core->cache->update( 'import_user_meta_yoast_seo', 100 + $offset, WEEK_IN_SECONDS );
			aioseo()->actionScheduler->scheduleSingle( aioseo()->importExport->yoastSeo->userActionName, 5, [], true );
		} else {
			aioseo()->core->cache->delete( 'import_user_meta_yoast_seo' );
		}
	}
}SeoPress/Titles.php000066600000026226151145361560010307 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Titles Settings.
 *
 * @since 4.1.4
 */
class Titles {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_titles_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		if (
			! empty( $this->options['seopress_titles_archives_author_title'] ) ||
			! empty( $this->options['seopress_titles_archives_author_desc'] ) ||
			! empty( $this->options['seopress_titles_archives_author_noindex'] )
			) {
			aioseo()->options->searchAppearance->archives->author->show = true;
		}

		if (
			! empty( $this->options['seopress_titles_archives_date_title'] ) ||
			! empty( $this->options['seopress_titles_archives_date_desc'] ) ||
			! empty( $this->options['seopress_titles_archives_date_noindex'] )
			) {
			aioseo()->options->searchAppearance->archives->date->show = true;
		}

		if (
			! empty( $this->options['seopress_titles_archives_search_title'] ) ||
			! empty( $this->options['seopress_titles_archives_search_desc'] )
			) {
			aioseo()->options->searchAppearance->archives->search->show = true;
		}

		$this->migrateTitleFormats();
		$this->migrateDescriptionFormats();
		$this->migrateNoIndexFormats();
		$this->migratePostTypeSettings();
		$this->migrateTaxonomiesSettings();
		$this->migrateArchiveSettings();
		$this->migrateAdvancedSettings();

		$settings = [
			'seopress_titles_sep' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'separator' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options, true );
	}

	/**
	 * Migrates the title formats.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateTitleFormats() {
		$settings = [
			'seopress_titles_home_site_title'       => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'siteTitle' ] ],
			'seopress_titles_archives_author_title' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'title' ] ],
			'seopress_titles_archives_date_title'   => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'title' ] ],
			'seopress_titles_archives_search_title' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'search', 'title' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options, true );
	}

	/**
	 * Migrates the description formats.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateDescriptionFormats() {
		$settings = [
			'seopress_titles_home_site_desc'       => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'metaDescription' ] ],
			'seopress_titles_archives_author_desc' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'metaDescription' ] ],
			'seopress_titles_archives_date_desc'   => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'metaDescription' ] ],
			'seopress_titles_archives_search_desc' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'search', 'metaDescription' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options, true );
	}

	/**
	 * Migrates the NoIndex formats.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateNoIndexFormats() {
		$settings = [
			'seopress_titles_archives_author_noindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'show' ] ],
			'seopress_titles_archives_date_noindex'   => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'show' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the post type settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migratePostTypeSettings() {
		$titles = $this->options['seopress_titles_single_titles'];
		if ( empty( $titles ) ) {
			return;
		}

		foreach ( $titles as $postType => $options ) {
			if ( ! aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
				continue;
			}

			if ( ! empty( $options['title'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->title =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['title'] ) );
			}

			if ( ! empty( $options['description'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->metaDescription =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['description'] ) );
			}

			if ( ! empty( $options['enable'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox = false;
			}

			if ( ! empty( $options['noindex'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = false;
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = true;
			}

			if ( ! empty( $options['nofollow'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = false;
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->nofollow = true;
			}

			if ( ! empty( $options['date'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showDateInGooglePreview = false;
			}

			if ( ! empty( $options['thumb_gcs'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showPostThumbnailInSearch = true;
			}
		}
	}

	/**
	 * Migrates the taxonomies settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateTaxonomiesSettings() {
		$titles = ! empty( $this->options['seopress_titles_tax_titles'] ) ? $this->options['seopress_titles_tax_titles'] : '';
		if ( empty( $titles ) ) {
			return;
		}

		foreach ( $titles as $taxonomy => $options ) {
			if ( ! aioseo()->dynamicOptions->searchAppearance->taxonomies->has( $taxonomy ) ) {
				continue;
			}

			if ( ! empty( $options['title'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->title =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['title'] ) );
			}

			if ( ! empty( $options['description'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->metaDescription =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['description'] ) );
			}

			if ( ! empty( $options['enable'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->showMetaBox = false;
			}

			if ( ! empty( $options['noindex'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->show = false;
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->default = false;
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->noindex = true;
			}

			if ( ! empty( $options['nofollow'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->show = false;
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->default = false;
				aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->nofollow = true;
			}
		}
	}

	/**
	 * Migrates the archives settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateArchiveSettings() {
		$titles = $this->options['seopress_titles_archive_titles'];
		if ( empty( $titles ) ) {
			return;
		}

		foreach ( $titles as $archive => $options ) {
			if ( ! aioseo()->dynamicOptions->searchAppearance->archives->has( $archive ) ) {
				continue;
			}

			if ( ! empty( $options['title'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->title =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['title'] ) );
			}

			if ( ! empty( $options['description'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->metaDescription =
					aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['description'] ) );
			}

			if ( ! empty( $options['noindex'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->show = false;
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->default = false;
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->noindex = true;
			}

			if ( ! empty( $options['nofollow'] ) ) {
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->show = false;
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->default = false;
				aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->nofollow = true;
			}
		}
	}

	/**
	 * Migrates the advanced settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateAdvancedSettings() {
		if (
			! empty( $this->options['seopress_titles_noindex'] ) || ! empty( $this->options['seopress_titles_nofollow'] ) || ! empty( $this->options['seopress_titles_noodp'] ) ||
			! empty( $this->options['seopress_titles_noimageindex'] ) || ! empty( $this->options['seopress_titles_noarchive'] ) ||
			! empty( $this->options['seopress_titles_nosnippet'] ) || ! empty( $this->options['seopress_titles_paged_noindex'] )
		) {
			aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default = false;
		}

		$settings = [
			'seopress_titles_noindex'       => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noindex' ] ],
			'seopress_titles_nofollow'      => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'nofollow' ] ],
			'seopress_titles_noodp'         => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noodp' ] ],
			'seopress_titles_noimageindex'  => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noimageindex' ] ],
			'seopress_titles_noarchive'     => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noarchive' ] ],
			'seopress_titles_nosnippet'     => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'nosnippet' ] ],
			'seopress_titles_paged_noindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noindexPaginated' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}
}SeoPress/PostMeta.php000066600000015547151145361560010603 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\Models;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Imports the post meta from SEOPress.
 *
 * @since 4.1.4
 */
class PostMeta {
	/**
	 * The mapped meta
	 *
	 * @since 4.1.4
	 *
	 * @var array
	 */
	private $mappedMeta = [
		'_seopress_analysis_target_kw'   => '',
		'_seopress_robots_archive'       => 'robots_noarchive',
		'_seopress_robots_canonical'     => 'canonical_url',
		'_seopress_robots_follow'        => 'robots_nofollow',
		'_seopress_robots_imageindex'    => 'robots_noimageindex',
		'_seopress_robots_index'         => 'robots_noindex',
		'_seopress_robots_odp'           => 'robots_noodp',
		'_seopress_robots_snippet'       => 'robots_nosnippet',
		'_seopress_social_twitter_desc'  => 'twitter_description',
		'_seopress_social_twitter_img'   => 'twitter_image_custom_url',
		'_seopress_social_twitter_title' => 'twitter_title',
		'_seopress_social_fb_desc'       => 'og_description',
		'_seopress_social_fb_img'        => 'og_image_custom_url',
		'_seopress_social_fb_title'      => 'og_title',
		'_seopress_titles_desc'          => 'description',
		'_seopress_titles_title'         => 'title',
		'_seopress_robots_primary_cat'   => 'primary_term'
	];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function scheduleImport() {
		if ( aioseo()->actionScheduler->scheduleSingle( aioseo()->importExport->seoPress->postActionName, 0 ) ) {
			if ( ! aioseo()->core->cache->get( 'import_post_meta_seopress' ) ) {
				aioseo()->core->cache->update( 'import_post_meta_seopress', time(), WEEK_IN_SECONDS );
			}
		}
	}

	/**
	 * Imports the post meta.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	public function importPostMeta() {
		$postsPerAction  = apply_filters( 'aioseo_import_seopress_posts_per_action', 100 );
		$publicPostTypes = implode( "', '", aioseo()->helpers->getPublicPostTypes( true ) );
		$timeStarted     = gmdate( 'Y-m-d H:i:s', aioseo()->core->cache->get( 'import_post_meta_seopress' ) );

		$posts = aioseo()->core->db
			->start( 'posts as p' )
			->select( 'p.ID, p.post_type' )
			->join( 'postmeta as pm', '`p`.`ID` = `pm`.`post_id`' )
			->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
			->whereRaw( "pm.meta_key LIKE '_seopress_%'" )
			->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
			->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
			->groupBy( 'p.ID' )
			->orderBy( 'p.ID DESC' )
			->limit( $postsPerAction )
			->run()
			->result();

		if ( ! $posts || ! count( $posts ) ) {
			aioseo()->core->cache->delete( 'import_post_meta_seopress' );

			return;
		}

		foreach ( $posts as $post ) {
			$postMeta = aioseo()->core->db
				->start( 'postmeta' . ' as pm' )
				->select( 'pm.meta_key, pm.meta_value' )
				->where( 'pm.post_id', $post->ID )
				->whereRaw( "`pm`.`meta_key` LIKE '_seopress_%'" )
				->run()
				->result();

			$meta = array_merge( [
				'post_id' => (int) $post->ID,
			], $this->getMetaData( $postMeta, $post->ID ) );

			if ( ! $postMeta || ! count( $postMeta ) ) {
				$aioseoPost = Models\Post::getPost( (int) $post->ID );
				$aioseoPost->set( $meta );
				$aioseoPost->save();

				aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );

				continue;
			}

			$aioseoPost = Models\Post::getPost( (int) $post->ID );
			$aioseoPost->set( $meta );
			$aioseoPost->save();

			aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );

			// Clear the Overview cache.
			aioseo()->postSettings->clearPostTypeOverviewCache( $post->ID );
		}

		if ( count( $posts ) === $postsPerAction ) {
			aioseo()->actionScheduler->scheduleSingle( aioseo()->importExport->seoPress->postActionName, 5, [], true );
		} else {
			aioseo()->core->cache->delete( 'import_post_meta_seopress' );
		}
	}

	/**
	 * Get the meta data by post meta.
	 *
	 * @since 4.1.4
	 *
	 * @param object $postMeta The post meta from database.
	 * @return array           The meta data.
	 */
	public function getMetaData( $postMeta, $postId ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$meta = [
			'robots_default'      => true,
			'robots_noarchive'    => false,
			'canonical_url'       => '',
			'robots_nofollow'     => false,
			'robots_noimageindex' => false,
			'robots_noindex'      => false,
			'robots_noodp'        => false,
			'robots_nosnippet'    => false,
			'twitter_use_og'      => aioseo()->options->social->twitter->general->useOgData,
			'twitter_title'       => '',
			'twitter_description' => ''
		];
		foreach ( $postMeta as $record ) {
			$name  = $record->meta_key;
			$value = $record->meta_value;

			if ( ! in_array( $name, array_keys( $this->mappedMeta ), true ) ) {
				continue;
			}

			switch ( $name ) {
				case '_seopress_analysis_target_kw':
					$keyphrases     = array_map( 'trim', explode( ',', $value ) );
					$keyphraseArray = [
						'focus'      => [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $keyphrases[0] ) ],
						'additional' => []
					];
					unset( $keyphrases[0] );
					foreach ( $keyphrases as $keyphrase ) {
						$keyphraseArray['additional'][] = [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $keyphrase ) ];
					}

					$meta['keyphrases'] = $keyphraseArray;
					break;
				case '_seopress_robots_snippet':
				case '_seopress_robots_archive':
				case '_seopress_robots_imageindex':
				case '_seopress_robots_odp':
				case '_seopress_robots_follow':
				case '_seopress_robots_index':
					if ( 'yes' === $value ) {
						$meta['robots_default']             = false;
						$meta[ $this->mappedMeta[ $name ] ] = true;
					}
					break;
				case '_seopress_social_twitter_img':
					$meta['twitter_use_og']             = false;
					$meta['twitter_image_type']         = 'custom_image';
					$meta[ $this->mappedMeta[ $name ] ] = esc_url( $value );
					break;
				case '_seopress_social_twitter_desc':
				case '_seopress_social_twitter_title':
					$meta['twitter_use_og']             = false;
					$meta[ $this->mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
					break;
				case '_seopress_social_fb_img':
					$meta['og_image_type']              = 'custom_image';
					$meta[ $this->mappedMeta[ $name ] ] = esc_url( $value );
					break;
				case '_seopress_robots_primary_cat':
					$taxonomy                           = 'category';
					$options                            = new \stdClass();
					$options->$taxonomy                 = (int) $value;
					$meta[ $this->mappedMeta[ $name ] ] = wp_json_encode( $options );
					break;
				case '_seopress_titles_title':
				case '_seopress_titles_desc':
					$value = aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $value );
				default:
					$meta[ $this->mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
					break;
			}
		}

		return $meta;
	}
}SeoPress/Helpers.php000066600000007264151145361560010446 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Contains helper methods for the import from SEOPress.
 *
 * @since 4.1.4
 */
class Helpers extends ImportExport\Helpers {
	/**
	 * Converts the macros from SEOPress to our own smart tags.
	 *
	 * @since 4.1.4
	 *
	 * @param  string $string   The string with macros.
	 * @param  string $postType The post type.
	 * @return string           The string with smart tags.
	 */
	public function macrosToSmartTags( $string, $postType = null ) {
		$macros = $this->getMacros( $postType );

		foreach ( $macros as $macro => $tag ) {
			$string = aioseo()->helpers->pregReplace( "#$macro(?![a-zA-Z0-9_])#im", $tag, $string );
		}

		return trim( $string );
	}

	/**
	 * Returns the macro mappings.
	 *
	 * @since 4.1.4
	 *
	 * @param  string $postType The post type.
	 * @param  string $pageType The page type.
	 * @return array  $macros   The macros.
	 */
	protected function getMacros( $postType = null, $pageType = null ) {
		$macros = [
			'%%sep%%'                   => '#separator_sa',
			'%%sitetitle%%'             => '#site_title',
			'%%sitename%%'              => '#site_title',
			'%%tagline%%'               => '#tagline',
			'%%sitedesc%%'              => '#tagline',
			'%%title%%'                 => '#site_title',
			'%%post_title%%'            => '#post_title',
			'%%post_excerpt%%'          => '#post_excerpt',
			'%%excerpt%%'               => '#post_excerpt',
			'%%post_content%%'          => '#post_content',
			'%%post_url%%'              => '#permalink',
			'%%post_date%%'             => '#post_date',
			'%%post_permalink%%'        => '#permalink',
			'%%date%%'                  => '#post_date',
			'%%post_author%%'           => '#author_name',
			'%%post_category%%'         => '#categories',
			'%%_category_title%%'       => '#taxonomy_title',
			'%%_category_description%%' => '#taxonomy_description',
			'%%tag_title%%'             => '#taxonomy_title',
			'%%tag_description%%'       => '#taxonomy_description',
			'%%term_title%%'            => '#taxonomy_title',
			'%%term_description%%'      => '#taxonomy_description',
			'%%search_keywords%%'       => '#search_term',
			'%%current_pagination%%'    => '#page_number',
			'%%page%%'                  => '#page_number',
			'%%archive_title%%'         => '#archive_title',
			'%%archive_date%%'          => '#archive_date',
			'%%wc_single_price%%'       => '#woocommerce_price',
			'%%wc_sku%%'                => '#woocommerce_sku',
			'%%currentday%%'            => '#current_day',
			'%%currentmonth%%'          => '#current_month',
			'%%currentmonth_short%%'    => '#current_month',
			'%%currentyear%%'           => '#current_year',
			'%%currentdate%%'           => '#current_date',
			'%%author_first_name%%'     => '#author_first_name',
			'%%author_last_name%%'      => '#author_last_name',
			'%%author_website%%'        => '#author_link',
			'%%author_nickname%%'       => '#author_first_name',
			'%%author_bio%%'            => '#author_bio',
			'%%currentmonth_num%%'      => '#current_month',
		];

		if ( $postType ) {
			$postType = get_post_type_object( $postType );
			if ( ! empty( $postType ) ) {
				$macros += [
					'%%cpt_plural%%' => $postType->labels->name,
				];
			}
		}

		switch ( $pageType ) {
			case 'archive':
				$macros['%%title%%'] = '#archive_title';
				break;
			case 'term':
				$macros['%%title%%'] = '#taxonomy_title';
				break;
			default:
				$macros['%%title%%'] = '#post_title';
				break;
		}

		// Strip all other tags.
		$macros['%%[^%]*%%'] = '';

		return $macros;
	}
}SeoPress/SocialMeta.php000066600000012322151145361560011054 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Social Meta Settings.
 *
 * @since 4.1.4
 */
class SocialMeta {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_social_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateSocialUrls();
		$this->migrateKnowledge();
		$this->migrateFacebookSettings();
		$this->migrateTwitterSettings();
	}

	/**
	 * Migrates Basic Social Profiles URLs.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateSocialUrls() {
		$settings = [
			'seopress_social_accounts_facebook'   => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'facebookPageUrl' ] ],
			'seopress_social_accounts_twitter'    => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'twitterUrl' ] ],
			'seopress_social_accounts_pinterest'  => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'pinterestUrl' ] ],
			'seopress_social_accounts_instagram'  => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'instagramUrl' ] ],
			'seopress_social_accounts_youtube'    => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'youtubeUrl' ] ],
			'seopress_social_accounts_linkedin'   => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'linkedinUrl' ] ],
			'seopress_social_accounts_myspace'    => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'myspaceUrl' ] ],
			'seopress_social_accounts_soundcloud' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'soundCloudUrl' ] ],
			'seopress_social_accounts_tumblr'     => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'tumblrUrl' ] ],
			'seopress_social_accounts_wordpress'  => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'wordPressUrl' ] ],
			'seopress_social_accounts_bluesky'    => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'blueskyUrl' ] ],
			'seopress_social_accounts_threads'    => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'threadsUrl' ] ]
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates Knowledge Graph data.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateKnowledge() {
		$type = 'organization';
		if ( ! empty( $this->options['seopress_social_knowledge_type'] ) ) {
			$type = strtolower( $this->options['seopress_social_knowledge_type'] );
			if ( 'person' === $type ) {
				aioseo()->options->searchAppearance->global->schema->person = 'manual';
			}
		}

		aioseo()->options->searchAppearance->global->schema->siteRepresents = $type;

		$settings = [
			'seopress_social_knowledge_img'   => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', $type . 'Logo' ] ],
			'seopress_social_knowledge_name'  => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', $type . 'Name' ] ],
			'seopress_social_knowledge_phone' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'phone' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the Facebook settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateFacebookSettings() {
		if ( ! empty( $this->options['seopress_social_facebook_admin_id'] ) || ! empty( $this->options['seopress_social_facebook_app_id'] ) ) {
			aioseo()->options->social->facebook->advanced->enable = true;
		}

		$settings = [
			'seopress_social_facebook_og'       => [ 'type' => 'boolean', 'newOption' => [ 'social', 'facebook', 'general', 'enable' ] ],
			'seopress_social_facebook_img'      => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'image' ] ],
			'seopress_social_facebook_admin_id' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'advanced', 'adminId' ] ],
			'seopress_social_facebook_app_id'   => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'advanced', 'appId' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the Twitter settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateTwitterSettings() {
		if ( ! empty( $this->options['seopress_social_twitter_card_img_size'] ) ) {
			$twitterCard = ( 'large' === $this->options['seopress_social_twitter_card_img_size'] ) ? 'summary-card' : 'summary';
			aioseo()->options->social->twitter->general->defaultCardType = $twitterCard;
		}

		$settings = [
			'seopress_social_twitter_card'     => [ 'type' => 'boolean', 'newOption' => [ 'social', 'twitter', 'general', 'enable' ] ],
			'seopress_social_twitter_card_img' => [ 'type' => 'string', 'newOption' => [ 'social', 'twitter', 'homePage', 'image' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}
}SeoPress/Breadcrumbs.php000066600000003403151145361560011264 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Breadcrumb settings.
 *
 * @since 4.1.4
 */
class Breadcrumbs {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_pro_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrate();
	}

	/**
	 * Migrates the Breadcrumbs settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrate() {
		if ( ! empty( $this->options['seopress_breadcrumbs_i18n_search'] ) ) {
			aioseo()->options->breadcrumbs->searchResultFormat = sprintf( '%1$s #breadcrumb_archive_post_type_name', $this->options['seopress_breadcrumbs_i18n_search'] );
		}

		if ( ! empty( $this->options['seopress_breadcrumbs_remove_blog_page'] ) ) {
			aioseo()->options->breadcrumbs->showBlogHome = false;
		}

		$settings = [
			'seopress_breadcrumbs_enable'    => [ 'type' => 'boolean', 'newOption' => [ 'breadcrumbs', 'enable' ] ],
			'seopress_breadcrumbs_separator' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'separator' ] ],
			'seopress_breadcrumbs_i18n_home' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'homepageLabel' ] ],
			'seopress_breadcrumbs_i18n_here' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'breadcrumbPrefix' ] ],
			'seopress_breadcrumbs_i18n_404'  => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'errorFormat404' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}
}SeoPress/Sitemap.php000066600000003600151145361560010434 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Sitemap Settings.
 *
 * @since 4.1.4
 */
class Sitemap {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_xml_sitemap_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migratePostTypesInclude();
		$this->migrateTaxonomiesInclude();

		$settings = [
			'seopress_xml_sitemap_general_enable' => [ 'type' => 'boolean', 'newOption' => [ 'sitemap', 'general', 'enable' ] ],
			'seopress_xml_sitemap_author_enable'  => [ 'type' => 'boolean', 'newOption' => [ 'sitemap', 'general', 'author' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the post types to include in sitemap settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	public function migratePostTypesInclude() {
		$postTypesMigrate = $this->options['seopress_xml_sitemap_post_types_list'];
		$postTypesInclude = [];

		foreach ( $postTypesMigrate as $postType => $options ) {
			$postTypesInclude[] = $postType;
		}

		aioseo()->options->sitemap->general->postTypes->included = $postTypesInclude;
	}

	/**
	 * Migrates the taxonomies to include in sitemap settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	public function migrateTaxonomiesInclude() {
		$taxonomiesMigrate = $this->options['seopress_xml_sitemap_taxonomies_list'];
		$taxonomiesInclude = [];

		foreach ( $taxonomiesMigrate as $taxonomy => $options ) {
			$taxonomiesInclude[] = $taxonomy;
		}

		aioseo()->options->sitemap->general->taxonomies->included = $taxonomiesInclude;
	}
}SeoPress/Analytics.php000066600000001527151145361560010767 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the Analytics Settings.
 *
 * @since 4.1.4
 */
class Analytics {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_google_analytics_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		$settings = [
			'seopress_google_analytics_other_tracking' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'miscellaneousVerification' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}
}SeoPress/Rss.php000066600000002242151145361560007602 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the RSS settings.
 *
 * @since 4.1.4
 */
class Rss {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_pro_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateRss();
	}

	/**
	 * Migrates the RSS settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	public function migrateRss() {
		if ( ! empty( $this->options['seopress_rss_before_html'] ) ) {
			aioseo()->options->rssContent->before = esc_html( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $this->options['seopress_rss_before_html'] ) );
		}

		if ( ! empty( $this->options['seopress_rss_after_html'] ) ) {
			aioseo()->options->rssContent->after = esc_html( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $this->options['seopress_rss_after_html'] ) );
		}
	}
}SeoPress/GeneralSettings.php000066600000010307151145361560012132 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the General Settings.
 *
 * @since 4.1.4
 */
class GeneralSettings {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * List of our access control roles.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $roles = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_advanced_option_name' );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->roles = aioseo()->access->getRoles();

		$this->migrateBlockMetaboxRoles();
		$this->migrateBlockContentAnalysisRoles();
		$this->migrateAttachmentRedirects();

		$settings = [
			'seopress_advanced_advanced_google'    => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'google' ] ],
			'seopress_advanced_advanced_bing'      => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'bing' ] ],
			'seopress_advanced_advanced_pinterest' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'pinterest' ] ],
			'seopress_advanced_advanced_yandex'    => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'yandex' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates Block AIOSEO metabox setting.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateBlockMetaboxRoles() {
		$seoPressRoles = ! empty( $this->options['seopress_advanced_security_metaboxe_role'] ) ? $this->options['seopress_advanced_security_metaboxe_role'] : '';
		if ( empty( $seoPressRoles ) ) {
			return;
		}

		$roleSettings = [ 'useDefault', 'pageAnalysis', 'pageGeneralSettings', 'pageSocialSettings', 'pageSchemaSettings', 'pageAdvancedSettings' ];

		foreach ( $seoPressRoles as $wpRole => $value ) {
			$role = $this->roles[ $wpRole ];
			if ( empty( $role ) || aioseo()->access->isAdmin( $role ) ) {
				continue;
			}

			if ( aioseo()->options->accessControl->has( $role ) ) {
				foreach ( $roleSettings as $setting ) {
					aioseo()->options->accessControl->$role->$setting = false;
				}
			} elseif ( aioseo()->dynamicOptions->accessControl->has( $role ) ) {
				foreach ( $roleSettings as $setting ) {
					aioseo()->dynamicOptions->accessControl->$role->$setting = false;
				}
			}
		}
	}

	/**
	 * Migrates Block Content analysis metabox setting.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateBlockContentAnalysisRoles() {
		$seoPressRoles = ! empty( $this->options['seopress_advanced_security_metaboxe_ca_role'] ) ? $this->options['seopress_advanced_security_metaboxe_ca_role'] : '';
		if ( empty( $seoPressRoles ) ) {
			return;
		}

		$roleSettings = [ 'useDefault', 'pageAnalysis' ];

		foreach ( $seoPressRoles as $wpRole => $value ) {
			$role = $this->roles[ $wpRole ];
			if ( empty( $role ) || aioseo()->access->isAdmin( $role ) ) {
				continue;
			}

			if ( aioseo()->options->accessControl->has( $role ) ) {
				foreach ( $roleSettings as $setting ) {
					aioseo()->options->accessControl->$role->$setting = false;
				}
			} elseif ( aioseo()->dynamicOptions->accessControl->has( $role ) ) {
				foreach ( $roleSettings as $setting ) {
					aioseo()->dynamicOptions->accessControl->$role->$setting = false;
				}
			}
		}
	}

	/**
	 * Migrates redirect attachment pages settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	private function migrateAttachmentRedirects() {
		if ( ! empty( $this->options['seopress_advanced_advanced_attachments'] ) ) {
			aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
		}

		if ( ! empty( $this->options['seopress_advanced_advanced_attachments_file'] ) ) {
			aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment';
		}

		if ( empty( $this->options['seopress_advanced_advanced_attachments'] ) && empty( $this->options['seopress_advanced_advanced_attachments_file'] ) ) {
			aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'disabled';
		}
	}
}SeoPress/SeoPress.php000066600000002761151145361560010604 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AIOSEO\Plugin\Common\ImportExport;

class SeoPress extends ImportExport\Importer {
	/**
	 * A list of plugins to look for to import.
	 *
	 * @since 4.1.4
	 *
	 * @var array
	 */
	public $plugins = [
		[
			'name'     => 'SEOPress',
			'version'  => '4.0',
			'basename' => 'wp-seopress/seopress.php',
			'slug'     => 'seopress'
		],
		[
			'name'     => 'SEOPress PRO',
			'version'  => '4.0',
			'basename' => 'wp-seopress-pro/seopress-pro.php',
			'slug'     => 'seopress-pro'
		],
	];

	/**
	 * The post action name.
	 *
	 * @since 4.1.4
	 *
	 * @var string
	 */
	public $postActionName = 'aioseo_import_post_meta_seopress';

	/**
	 * The post action name.
	 *
	 * @since 4.1.4
	 *
	 * @param ImportExport\ImportExport $importer The main importer class.
	 */
	public function __construct( $importer ) {
		$this->helpers  = new Helpers();
		$this->postMeta = new PostMeta();
		add_action( $this->postActionName, [ $this->postMeta, 'importPostMeta' ] );

		$plugins = $this->plugins;
		foreach ( $plugins as $key => $plugin ) {
			$plugins[ $key ]['class'] = $this;
		}
		$importer->addPlugins( $plugins );
	}

	/**
	 * Imports the settings.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	protected function importSettings() {
		new GeneralSettings();
		new Analytics();
		new SocialMeta();
		new Titles();
		new Sitemap();
		new RobotsTxt();
		new Rss();
		new Breadcrumbs();
	}
}SeoPress/RobotsTxt.php000066600000002357151145361560011012 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound

/**
 * Migrates the robots.txt settings.
 *
 * @since 4.1.4
 */
class RobotsTxt {
	/**
	 * List of options.
	 *
	 * @since 4.2.7
	 *
	 * @var array
	 */
	private $options = [];

	/**
	 * Class constructor.
	 *
	 * @since 4.1.4
	 */
	public function __construct() {
		$this->options = get_option( 'seopress_pro_option_name', [] );
		if ( empty( $this->options ) ) {
			return;
		}

		$this->migrateRobotsTxt();

		$settings = [
			'seopress_robots_enable' => [ 'type' => 'boolean', 'newOption' => [ 'tools', 'robots', 'enable' ] ],
		];

		aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
	}

	/**
	 * Migrates the robots.txt.
	 *
	 * @since 4.1.4
	 *
	 * @return void
	 */
	public function migrateRobotsTxt() {
		$lines = ! empty( $this->options['seopress_robots_file'] ) ? (string) $this->options['seopress_robots_file'] : '';

		if ( $lines ) {
			$allRules = aioseo()->robotsTxt->extractRules( $lines );

			aioseo()->options->tools->robots->rules = aioseo()->robotsTxt->prepareRobotsTxt( $allRules );
		}
	}
}Helpers.php000066600000004430151145361560006673 0ustar00<?php
namespace AIOSEO\Plugin\Common\ImportExport;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Contains helper methods for the import from other plugins.
 *
 * @since 4.0.0
 */
abstract class Helpers {
	/**
	 * Converts macros to smart tags.
	 *
	 * @since 4.1.3
	 *
	 * @param  string $value The string with macros.
	 * @return string        The string with macros converted.
	 */
	abstract public function macrosToSmartTags( $value );

	/**
	 * Maps a list of old settings from V3 to their counterparts in V4.
	 *
	 * @since 4.0.0
	 *
	 * @param  array $mappings      The old settings, mapped to their new settings.
	 * @param  array $group         The old settings group.
	 * @param  bool  $convertMacros Whether to convert the old V3 macros to V4 smart tags.
	 * @return void
	 */
	public function mapOldToNew( $mappings, $group, $convertMacros = false ) {
		if (
			! is_array( $mappings ) ||
			! is_array( $group ) ||
			! count( $mappings ) ||
			! count( $group )
		) {
			return;
		}

		$mainOptions    = aioseo()->options->noConflict();
		$dynamicOptions = aioseo()->dynamicOptions->noConflict();
		foreach ( $mappings as $name => $values ) {
			if ( ! isset( $group[ $name ] ) ) {
				continue;
			}

			$error      = false;
			$options    = ! empty( $values['dynamic'] ) ? $dynamicOptions : $mainOptions;
			$lastOption = '';
			for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
				$lastOption = $values['newOption'][ $i ];
				if ( ! $options->has( $lastOption, false ) ) {
					$error = true;
					break;
				}

				if ( count( $values['newOption'] ) - 1 !== $i ) {
					$options = $options->$lastOption;
				}
			}

			if ( $error ) {
				continue;
			}

			switch ( $values['type'] ) {
				case 'boolean':
					if ( ! empty( $group[ $name ] ) ) {
						$options->$lastOption = true;
						break;
					}
					$options->$lastOption = false;
					break;
				case 'integer':
				case 'float':
					$value = aioseo()->helpers->sanitizeOption( $group[ $name ] );
					if ( $value ) {
						$options->$lastOption = $value;
					}
					break;
				default:
					$value = $group[ $name ];
					if ( $convertMacros ) {
						$value = $this->macrosToSmartTags( $value );
					}
					$options->$lastOption = aioseo()->helpers->sanitizeOption( $value );
					break;
			}
		}
	}
}