mpty( $reviews[0] ) ) {
$reviewData = json_decode( $reviews[0] );
if ( empty( $reviewData ) ) {
break;
}
$graph['properties']['rating']['value'] = $reviewData->rating;
$graph['properties']['review'] = [
'headline' => $reviewData->headline,
'content' => $reviewData->content,
'author' => $reviewData->author
];
}
break;
case 'WebPage':
if ( 'FAQPage' === $schemaTypeOptions->webPage->webPageType ) {
$graph = [
'id' => '#aioseo-faq-page-' . uniqid(),
'slug' => 'faq-page',
'graphName' => 'FAQPage',
'label' => __( 'FAQ Page', 'all-in-one-seo-pack' ),
'properties' => [
'type' => $schemaTypeOptions->webPage->webPageType,
'name' => '#post_title',
'description' => '#post_excerpt',
'questions' => []
]
];
$faqs = $schemaTypeOptions->faq->pages;
if ( ! empty( $faqs ) ) {
foreach ( $faqs as $faqData ) {
$faqData = json_decode( $faqData );
if ( empty( $faqData ) ) {
continue;
}
$graph['properties']['questions'][] = [
'question' => $faqData->question,
'answer' => $faqData->answer
];
}
}
} else {
$graph = [
'id' => '#aioseo-web-page-' . uniqid(),
'slug' => 'web-page',
'graphName' => 'WebPage',
'label' => __( 'Web Page', 'all-in-one-seo-pack' ),
'properties' => [
'type' => $schemaTypeOptions->webPage->webPageType,
'name' => '',
'description' => ''
]
];
}
break;
case 'default':
$dynamicOptions = aioseo()->dynamicOptions->noConflict();
if ( ! empty( $post->post_type ) && $dynamicOptions->searchAppearance->postTypes->has( $post->post_type ) ) {
$schemaOptions->defaultGraph = $dynamicOptions->searchAppearance->postTypes->{$post->post_type}->schemaType;
}
break;
case 'none':
// If "none', we simply don't have to migrate anything.
default:
break;
}
if ( ! empty( $graph ) ) {
if ( $isDefault ) {
$schemaOptions->default->data->{$schemaType} = $graph;
} else {
$schemaOptions->graphs[] = $graph;
$schemaOptions->default->isEnabled = false;
}
}
$aioseoPost->schema = $schemaOptions;
$aioseoPost->save();
return $aioseoPost;
}
/**
* Updates the dashboardWidgets with the new array format.
*
* @since 4.2.8
*
* @return void
*/
private function migrateDashboardWidgetsOptions() {
$rawOptions = $this->getRawOptions();
if ( empty( $rawOptions ) || ! is_bool( $rawOptions['advanced']['dashboardWidgets'] ) ) {
return;
}
$widgets = [ 'seoNews' ];
// If the dashboardWidgets was activated, let's turn on the other widgets.
if ( ! empty( $rawOptions['advanced']['dashboardWidgets'] ) ) {
$widgets[] = 'seoOverview';
$widgets[] = 'seoSetup';
}
aioseo()->options->advanced->dashboardWidgets = $widgets;
}
/**
* Adds the primary_term column to the aioseo_posts table.
*
* @since 4.3.6
*
* @return void
*/
private function addPrimaryTermColumn() {
if ( ! aioseo()->core->db->columnExists( 'aioseo_posts', 'primary_term' ) ) {
$tableName = aioseo()->core->db->db->prefix . 'aioseo_posts';
aioseo()->core->db->execute(
"ALTER TABLE {$tableName}
ADD `primary_term` longtext DEFAULT NULL AFTER `page_analysis`"
);
}
}
/**
* Schedules the revision records removal.
*
* @since 4.3.1
*
* @return void
*/
private function scheduleRemoveRevisionsRecords() {
aioseo()->actionScheduler->scheduleSingle( 'aioseo_v419_remove_revision_records', 10, [], true );
}
/**
* Casts the priority column to a float.
*
* @since 4.3.9
*
* @return void
*/
private function migratePriorityColumn() {
if ( ! aioseo()->core->db->columnExists( 'aioseo_posts', 'priority' ) ) {
return;
}
$prefix = aioseo()->core->db->prefix;
$aioseoPostsTableName = $prefix . 'aioseo_posts';
// First, cast the default value to NULL since it's a string.
aioseo()->core->db->execute( "UPDATE {$aioseoPostsTableName} SET priority = NULL WHERE priority = 'default'" );
// Then, alter the column to a float.
aioseo()->core->db->execute( "ALTER TABLE {$aioseoPostsTableName} MODIFY priority float" );
}
/**
* Update the custom robots.txt rules to the new format,
* by replacing `rule` and `directoryPath` with `directive` and `fieldValue`, respectively.
*
* @since 4.4.2
*
* @return void
*/
private function updateRobotsTxtRules() {
$rawOptions = $this->getRawOptions();
$currentRules = $rawOptions && ! empty( $rawOptions['tools']['robots']['rules'] )
? $rawOptions['tools']['robots']['rules']
: [];
if ( empty( $currentRules ) || ! is_array( $currentRules ) ) {
return;
}
$newRules = [];
foreach ( $currentRules as $oldRule ) {
$parsedRule = json_decode( $oldRule, true );
if ( empty( $parsedRule['rule'] ) && empty( $parsedRule['directoryPath'] ) ) {
continue;
}
$newRule = [
'userAgent' => array_key_exists( 'userAgent', $parsedRule ) ? $parsedRule['userAgent'] : '',
'directive' => array_key_exists( 'rule', $parsedRule ) ? $parsedRule['rule'] : '',
'fieldValue' => array_key_exists( 'directoryPath', $parsedRule ) ? $parsedRule['directoryPath'] : '',
];
$newRules[] = wp_json_encode( $newRule );
}
if ( $newRules ) {
aioseo()->options->tools->robots->rules = $newRules;
}
}
/**
* Checks if the user is currently using the old GA Analytics v3 integration and create a notification.
*
* @since 4.5.1
*
* @return void
*/
private function checkForGaAnalyticsV3() {
// If either MonsterInsights or ExactMetrics is active, let's return early.
$pluginData = aioseo()->helpers->getPluginData();
if (
$pluginData['miPro']['activated'] ||
$pluginData['miLite']['activated'] ||
$pluginData['emPro']['activated'] ||
$pluginData['emLite']['activated']
) {
return;
}
$rawOptions = $this->getRawOptions();
if ( empty( $rawOptions['deprecated']['webmasterTools']['googleAnalytics']['id'] ) ) {
return;
}
// Let's clear the notification if the search is working again.
$notification = Models\Notification::getNotificationByName( 'google-analytics-v3-deprecation' );
if ( $notification->exists() ) {
$notification->dismissed = false;
$notification->save();
return;
}
// Determine which plugin name to use.
$pluginName = 'MonsterInsights';
if (
(
$pluginData['emPro']['installed'] ||
$pluginData['emLite']['installed']
) &&
! $pluginData['miPro']['installed'] &&
! $pluginData['miLite']['installed']
) {
$pluginName = 'ExactMetrics';
}
Models\Notification::addNotification( [
'slug' => uniqid(),
'notification_name' => 'google-analytics-v3-deprecation',
'title' => __( 'Universal Analytics V3 Deprecation Notice', 'all-in-one-seo-pack' ),
'content' => sprintf(
// Translators: 1 - Line break HTML tags, 2 - Plugin short name ("AIOSEO"), Analytics plugin name (e.g. "MonsterInsights").
__( 'You have been using the %2$s Google Analytics V3 (Universal Analytics) integration which has been deprecated by Google and is no longer supported. This may affect your website\'s data accuracy and performance.%1$sTo ensure a seamless analytics experience, we recommend migrating to %3$s, a powerful analytics solution.%1$s%3$s offers advanced features such as real-time tracking, enhanced e-commerce analytics, and easy-to-understand reports, helping you make informed decisions to grow your online presence effectively.%1$sClick the button below to be redirected to the %3$s setup process, where you can start benefiting from its robust analytics capabilities immediately.', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'
',
AIOSEO_PLUGIN_SHORT_NAME,
$pluginName
),
'type' => 'error',
'level' => [ 'all' ],
'button1_label' => __( 'Fix Now', 'all-in-one-seo-pack' ),
'button1_action' => admin_url( 'admin.php?page=aioseo-monsterinsights' ),
'start' => gmdate( 'Y-m-d H:i:s' )
] );
}
/**
* Adds our custom tables for the query arg monitor.
*
* @since 4.5.8
*
* @return void
*/
public function addQueryArgMonitorTables() {
$db = aioseo()->core->db->db;
$charsetCollate = '';
if ( ! empty( $db->charset ) ) {
$charsetCollate .= "DEFAULT CHARACTER SET {$db->charset}";
}
if ( ! empty( $db->collate ) ) {
$charsetCollate .= " COLLATE {$db->collate}";
}
// Check for crawl cleanup logs table.
if ( ! aioseo()->core->db->tableExists( 'aioseo_crawl_cleanup_logs' ) ) {
$tableName = $db->prefix . 'aioseo_crawl_cleanup_logs';
aioseo()->core->db->execute(
"CREATE TABLE {$tableName} (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`slug` text NOT NULL,
`key` text NOT NULL,
`value` text,
`hash` varchar(40) NOT NULL,
`hits` int(20) NOT NULL DEFAULT 1,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY ndx_aioseo_crawl_cleanup_logs_hash (hash)
) {$charsetCollate};"
);
}
// Check for crawl cleanup blocked table.
if ( ! aioseo()->core->db->tableExists( 'aioseo_crawl_cleanup_blocked_args' ) ) {
$tableName = $db->prefix . 'aioseo_crawl_cleanup_blocked_args';
aioseo()->core->db->execute(
"CREATE TABLE {$tableName} (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`key` text,
`value` text,
`key_value_hash` varchar(40),
`regex` varchar(150),
`hits` int(20) NOT NULL DEFAULT 0,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY ndx_aioseo_crawl_cleanup_blocked_args_key_value_hash (key_value_hash),
UNIQUE KEY ndx_aioseo_crawl_cleanup_blocked_args_regex (regex)
) {$charsetCollate};"
);
}
}
/**
* Adds a notification for the query arg monitor.
*
* @since 4.5.8
*
* @return void
*/
private function addQueryArgMonitorNotification() {
$options = $this->getRawOptions();
if (
empty( $options['searchAppearance']['advanced']['crawlCleanup']['enable'] ) ||
empty( $options['searchAppearance']['advanced']['crawlCleanup']['removeUnrecognizedQueryArgs'] )
) {
return;
}
$notification = Models\Notification::getNotificationByName( 'crawl-cleanup-updated' );
if ( $notification->exists() ) {
return;
}
Models\Notification::addNotification( [
'slug' => uniqid(),
'notification_name' => 'crawl-cleanup-updated',
'title' => __( 'Crawl Cleanup changes you should know about', 'all-in-one-seo-pack' ),
'content' => __( 'We\'ve made some significant changes to how we monitor Query Args for our Crawl Cleanup feature. Instead of DISABLING all query args and requiring you to add individual exceptions, we\'ve now changed it to ALLOW all query args by default with the option to easily block unrecognized ones through our new log table.', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'type' => 'info',
'level' => [ 'all' ],
'button1_label' => __( 'Learn More', 'all-in-one-seo-pack' ),
'button1_action' => 'http://route#aioseo-search-appearance&aioseo-scroll=aioseo-query-arg-monitoring&aioseo-highlight=aioseo-query-arg-monitoring:advanced',
'start' => gmdate( 'Y-m-d H:i:s' )
] );
}
/**
* Deprecates the "No Pagination for Canonical URLs" setting.
*
* @since 4.5.9
*
* @return void
*/
public function deprecateNoPaginationForCanonicalUrlsSetting() {
$options = $this->getRawOptions();
if ( empty( $options['searchAppearance']['advanced']['noPaginationForCanonical'] ) ) {
return;
}
$deprecatedOptions = aioseo()->internalOptions->deprecatedOptions;
if ( ! in_array( 'noPaginationForCanonical', $deprecatedOptions, true ) ) {
$deprecatedOptions[] = 'noPaginationForCanonical';
aioseo()->internalOptions->deprecatedOptions = $deprecatedOptions;
}
aioseo()->options->deprecated->searchAppearance->advanced->noPaginationForCanonical = true;
}
/**
* Deprecates the "Breadcrumbs enabled" setting.
*
* @since 4.6.5
*
* @return void
*/
public function deprecateBreadcrumbsEnabledSetting() {
$options = $this->getRawOptions();
if ( ! isset( $options['breadcrumbs']['enable'] ) || 1 === intval( $options['breadcrumbs']['enable'] ) ) {
return;
}
$deprecatedOptions = aioseo()->internalOptions->deprecatedOptions;
if ( ! in_array( 'breadcrumbsEnable', $deprecatedOptions, true ) ) {
$deprecatedOptions[] = 'breadcrumbsEnable';
aioseo()->internalOptions->deprecatedOptions = $deprecatedOptions;
}
aioseo()->options->deprecated->breadcrumbs->enable = false;
}
}