array of [their_meta_key => our_key] */ private static function maps() { return array( 'yoast' => array( '_yoast_wpseo_title' => 'title', '_yoast_wpseo_metadesc' => 'desc', '_yoast_wpseo_focuskw' => 'focus', '_yoast_wpseo_canonical' => 'canonical', '_yoast_wpseo_opengraph-title' => 'og_title', '_yoast_wpseo_opengraph-description'=> 'og_desc', '_yoast_wpseo_opengraph-image' => 'og_image', ), 'rankmath' => array( 'rank_math_title' => 'title', 'rank_math_description' => 'desc', 'rank_math_focus_keyword' => 'focus', 'rank_math_canonical_url' => 'canonical', ), 'sentrixa-theme' => array( '_sxa_seo_title' => 'title', '_sxa_seo_desc' => 'desc', '_sxa_seo_keywords' => 'keywords', ), 'aioseo' => array( '_aioseo_title' => 'title', '_aioseo_description' => 'desc', '_aioseo_keywords' => 'keywords', ), ); } /** Which other SEO plugins left data behind: [source => number of posts]. */ public static function detect() { global $wpdb; $found = array(); foreach ( self::maps() as $src => $map ) { $keys = array_keys( $map ); $in = implode( ',', array_fill( 0, count( $keys ), '%s' ) ); $n = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key IN ($in) AND meta_value <> ''", $keys ) ); // phpcs:ignore WordPress.DB if ( $n ) { $found[ $src ] = $n; } } return $found; } /** @return array source => number of values copied */ public static function run() { global $wpdb; $done = array(); foreach ( self::maps() as $src => $map ) { $count = 0; foreach ( $map as $theirs => $ours ) { $count += (int) $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) SELECT s.post_id, %s, REPLACE(s.meta_value, CONCAT(CHAR(37), CHAR(37)), CHAR(37)) FROM {$wpdb->postmeta} s WHERE s.meta_key = %s AND s.meta_value <> '' AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} t WHERE t.post_id = s.post_id AND t.meta_key = %s AND t.meta_value <> '')", SXSEO_Fields::PREFIX . $ours, $theirs, SXSEO_Fields::PREFIX . $ours ) ); // phpcs:ignore WordPress.DB } if ( 'yoast' === $src ) { $count += (int) $wpdb->query( "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) SELECT s.post_id, '_sxseo_noindex', '1' FROM {$wpdb->postmeta} s WHERE s.meta_key = '_yoast_wpseo_meta-robots-noindex' AND s.meta_value = '1' AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} t WHERE t.post_id = s.post_id AND t.meta_key = '_sxseo_noindex')" ); // phpcs:ignore WordPress.DB } if ( $count ) { $done[ $src ] = $count; } } // The Sentrixa theme stores its social image as an attachment ID; ours stores the URL. $rows = $wpdb->get_results( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_sxa_seo_og_image' AND meta_value <> ''" ); // phpcs:ignore WordPress.DB foreach ( $rows as $r ) { $url = wp_get_attachment_image_url( (int) $r->meta_value, 'full' ); if ( $url && '' === (string) get_post_meta( $r->post_id, '_sxseo_og_image', true ) ) { update_post_meta( $r->post_id, '_sxseo_og_image', esc_url_raw( $url ) ); $done['sentrixa-theme'] = ( $done['sentrixa-theme'] ?? 0 ) + 1; } } // Rank Math keeps several focus keywords as "a, b, c": keep the first. $rows = $wpdb->get_results( "SELECT meta_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_sxseo_focus' AND meta_value LIKE '%,%'" ); // phpcs:ignore WordPress.DB foreach ( $rows as $r ) { $wpdb->update( $wpdb->postmeta, array( 'meta_value' => trim( explode( ',', $r->meta_value )[0] ) ), array( 'meta_id' => $r->meta_id ) ); } SXSEO_Sitemap::purge(); return $done; } }