class-upgrade.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\Internal
  6. */
  7. /**
  8. * This code handles the option upgrades
  9. */
  10. class WPSEO_Upgrade {
  11. /**
  12. * Class constructor
  13. */
  14. public function __construct() {
  15. $version = WPSEO_Options::get( 'version' );
  16. WPSEO_Options::maybe_set_multisite_defaults( false );
  17. if ( version_compare( $version, '1.5.0', '<' ) ) {
  18. $this->upgrade_15( $version );
  19. }
  20. if ( version_compare( $version, '2.0', '<' ) ) {
  21. $this->upgrade_20();
  22. }
  23. if ( version_compare( $version, '2.1', '<' ) ) {
  24. $this->upgrade_21();
  25. }
  26. if ( version_compare( $version, '2.2', '<' ) ) {
  27. $this->upgrade_22();
  28. }
  29. if ( version_compare( $version, '2.3', '<' ) ) {
  30. $this->upgrade_23();
  31. }
  32. if ( version_compare( $version, '3.0', '<' ) ) {
  33. $this->upgrade_30();
  34. }
  35. if ( version_compare( $version, '3.3', '<' ) ) {
  36. $this->upgrade_33();
  37. }
  38. if ( version_compare( $version, '3.6', '<' ) ) {
  39. $this->upgrade_36();
  40. }
  41. if ( version_compare( $version, '4.0', '<' ) ) {
  42. $this->upgrade_40();
  43. }
  44. if ( version_compare( $version, '4.4', '<' ) ) {
  45. $this->upgrade_44();
  46. }
  47. if ( version_compare( $version, '4.7', '<' ) ) {
  48. $this->upgrade_47();
  49. }
  50. if ( version_compare( $version, '4.9', '<' ) ) {
  51. $this->upgrade_49();
  52. }
  53. if ( version_compare( $version, '5.0', '<' ) ) {
  54. $this->upgrade_50();
  55. }
  56. if ( version_compare( $version, '5.0', '>=' )
  57. && version_compare( $version, '5.1', '<' )
  58. ) {
  59. $this->upgrade_50_51();
  60. }
  61. if ( version_compare( $version, '5.5', '<' ) ) {
  62. $this->upgrade_55();
  63. }
  64. if ( version_compare( $version, '5.6', '<' ) ) {
  65. $this->upgrade_56();
  66. }
  67. if ( version_compare( $version, '6.1', '<' ) ) {
  68. $this->upgrade_61();
  69. }
  70. if ( version_compare( $version, '6.3', '<' ) ) {
  71. $this->upgrade_63();
  72. }
  73. if ( version_compare( $version, '7.0-RC0', '<' ) ) {
  74. $this->upgrade_70();
  75. }
  76. if ( version_compare( $version, '7.1-RC0', '<' ) ) {
  77. $this->upgrade_71();
  78. }
  79. if ( version_compare( $version, '7.3-RC0', '<' ) ) {
  80. $this->upgrade_73();
  81. }
  82. if ( version_compare( $version, '7.4-RC0', '<' ) ) {
  83. $this->upgrade_74();
  84. }
  85. if ( version_compare( $version, '7.5.3', '<' ) ) {
  86. $this->upgrade_753();
  87. }
  88. if ( version_compare( $version, '7.7-RC0', '<' ) ) {
  89. $this->upgrade_77();
  90. }
  91. if ( version_compare( $version, '7.7.2-RC0', '<' ) ) {
  92. $this->upgrade_772();
  93. }
  94. // Since 3.7.
  95. $upsell_notice = new WPSEO_Product_Upsell_Notice();
  96. $upsell_notice->set_upgrade_notice();
  97. /**
  98. * Filter: 'wpseo_run_upgrade' - Runs the upgrade hook which are dependent on Yoast SEO
  99. *
  100. * @api string - The current version of Yoast SEO
  101. */
  102. do_action( 'wpseo_run_upgrade', $version );
  103. $this->finish_up();
  104. }
  105. /**
  106. * Runs the needed cleanup after an update, setting the DB version to latest version, flushing caches etc.
  107. */
  108. protected function finish_up() {
  109. WPSEO_Options::set( 'version', WPSEO_VERSION );
  110. add_action( 'shutdown', 'flush_rewrite_rules' ); // Just flush rewrites, always, to at least make them work after an upgrade.
  111. WPSEO_Sitemaps_Cache::clear(); // Flush the sitemap cache.
  112. WPSEO_Options::ensure_options_exist(); // Make sure all our options always exist - issue #1245.
  113. }
  114. /**
  115. * Run the Yoast SEO 1.5 upgrade routine
  116. *
  117. * @param string $version Current plugin version.
  118. */
  119. private function upgrade_15( $version ) {
  120. // Clean up options and meta.
  121. WPSEO_Options::clean_up( null, $version );
  122. WPSEO_Meta::clean_up();
  123. }
  124. /**
  125. * Moves options that moved position in WPSEO 2.0
  126. */
  127. private function upgrade_20() {
  128. /**
  129. * Clean up stray wpseo_ms options from the options table, option should only exist in the sitemeta table.
  130. * This could have been caused in many version of Yoast SEO, so deleting it for everything below 2.0
  131. */
  132. delete_option( 'wpseo_ms' );
  133. $wpseo = $this->get_option_from_database( 'wpseo' );
  134. $this->save_option_setting( $wpseo, 'pinterestverify' );
  135. // Re-save option to trigger sanitization.
  136. $this->cleanup_option_data( 'wpseo' );
  137. }
  138. /**
  139. * Detects if taxonomy terms were split and updates the corresponding taxonomy meta's accordingly.
  140. */
  141. private function upgrade_21() {
  142. $taxonomies = get_option( 'wpseo_taxonomy_meta', array() );
  143. if ( ! empty( $taxonomies ) ) {
  144. foreach ( $taxonomies as $taxonomy => $tax_metas ) {
  145. foreach ( $tax_metas as $term_id => $tax_meta ) {
  146. if ( function_exists( 'wp_get_split_term' ) ) {
  147. $new_term_id = wp_get_split_term( $term_id, $taxonomy );
  148. if ( $new_term_id !== false ) {
  149. $taxonomies[ $taxonomy ][ $new_term_id ] = $taxonomies[ $taxonomy ][ $term_id ];
  150. unset( $taxonomies[ $taxonomy ][ $term_id ] );
  151. }
  152. }
  153. }
  154. }
  155. update_option( 'wpseo_taxonomy_meta', $taxonomies );
  156. }
  157. }
  158. /**
  159. * Performs upgrade functions to Yoast SEO 2.2
  160. */
  161. private function upgrade_22() {
  162. // Unschedule our tracking.
  163. wp_clear_scheduled_hook( 'yoast_tracking' );
  164. $this->cleanup_option_data( 'wpseo' );
  165. }
  166. /**
  167. * Schedules upgrade function to Yoast SEO 2.3
  168. */
  169. private function upgrade_23() {
  170. add_action( 'wp', array( $this, 'upgrade_23_query' ), 90 );
  171. add_action( 'admin_head', array( $this, 'upgrade_23_query' ), 90 );
  172. }
  173. /**
  174. * Performs upgrade query to Yoast SEO 2.3
  175. */
  176. public function upgrade_23_query() {
  177. $wp_query = new WP_Query( 'post_type=any&meta_key=_yoast_wpseo_sitemap-include&meta_value=never&order=ASC' );
  178. if ( ! empty( $wp_query->posts ) ) {
  179. $options = get_option( 'wpseo_xml' );
  180. $excluded_posts = array();
  181. if ( $options['excluded-posts'] !== '' ) {
  182. $excluded_posts = explode( ',', $options['excluded-posts'] );
  183. }
  184. foreach ( $wp_query->posts as $post ) {
  185. if ( ! in_array( $post->ID, $excluded_posts ) ) {
  186. $excluded_posts[] = $post->ID;
  187. }
  188. }
  189. // Updates the meta value.
  190. $options['excluded-posts'] = implode( ',', $excluded_posts );
  191. // Update the option.
  192. update_option( 'wpseo_xml', $options );
  193. }
  194. // Remove the meta fields.
  195. delete_post_meta_by_key( '_yoast_wpseo_sitemap-include' );
  196. }
  197. /**
  198. * Performs upgrade functions to Yoast SEO 3.0.
  199. */
  200. private function upgrade_30() {
  201. // Remove the meta fields for sitemap prio.
  202. delete_post_meta_by_key( '_yoast_wpseo_sitemap-prio' );
  203. }
  204. /**
  205. * Performs upgrade functions to Yoast SEO 3.3.
  206. */
  207. private function upgrade_33() {
  208. // Notification dismissals have been moved to User Meta instead of global option.
  209. delete_option( Yoast_Notification_Center::STORAGE_KEY );
  210. }
  211. /**
  212. * Performs upgrade functions to Yoast SEO 3.6.
  213. */
  214. private function upgrade_36() {
  215. global $wpdb;
  216. // Between 3.2 and 3.4 the sitemap options were saved with autoloading enabled.
  217. $wpdb->query( 'DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE "wpseo_sitemap_%" AND autoload = "yes"' );
  218. }
  219. /**
  220. * Removes the about notice when its still in the database.
  221. */
  222. private function upgrade_40() {
  223. $center = Yoast_Notification_Center::get();
  224. $center->remove_notification_by_id( 'wpseo-dismiss-about' );
  225. }
  226. /**
  227. * Moves the content-analysis-active and keyword-analysis-acive options from wpseo-titles to wpseo.
  228. */
  229. private function upgrade_44() {
  230. $wpseo_titles = $this->get_option_from_database( 'wpseo_titles' );
  231. $this->save_option_setting( $wpseo_titles, 'content-analysis-active', 'content_analysis_active' );
  232. $this->save_option_setting( $wpseo_titles, 'keyword-analysis-active', 'keyword_analysis_active' );
  233. // Remove irrelevant content from the option.
  234. $this->cleanup_option_data( 'wpseo_titles' );
  235. }
  236. /**
  237. * Renames the meta name for the cornerstone content. It was a public meta field and it has to be private.
  238. */
  239. private function upgrade_47() {
  240. global $wpdb;
  241. // The meta key has to be private, so prefix it.
  242. $wpdb->query(
  243. $wpdb->prepare(
  244. 'UPDATE ' . $wpdb->postmeta . ' SET meta_key = %s WHERE meta_key = "yst_is_cornerstone"',
  245. WPSEO_Cornerstone::META_NAME
  246. )
  247. );
  248. }
  249. /**
  250. * Removes the 'wpseo-dismiss-about' notice for every user that still has it.
  251. */
  252. private function upgrade_49() {
  253. global $wpdb;
  254. /*
  255. * Using a filter to remove the notification for the current logged in user. The notification center is
  256. * initializing the notifications before the upgrade routine has been executedd and is saving the stored
  257. * notifications on shutdown. This causes the returning notification. By adding this filter the shutdown
  258. * routine on the notification center will remove the notification.
  259. */
  260. add_filter( 'yoast_notifications_before_storage', array( $this, 'remove_about_notice' ) );
  261. $meta_key = $wpdb->get_blog_prefix() . Yoast_Notification_Center::STORAGE_KEY;
  262. $usermetas = $wpdb->get_results(
  263. $wpdb->prepare( '
  264. SELECT user_id, meta_value
  265. FROM ' . $wpdb->usermeta . '
  266. WHERE meta_key = %s AND meta_value LIKE %s
  267. ',
  268. $meta_key,
  269. '%wpseo-dismiss-about%'
  270. ),
  271. ARRAY_A
  272. );
  273. if ( empty( $usermetas ) ) {
  274. return;
  275. }
  276. foreach ( $usermetas as $usermeta ) {
  277. $notifications = maybe_unserialize( $usermeta['meta_value'] );
  278. foreach ( $notifications as $notification_key => $notification ) {
  279. if ( ! empty( $notification['options']['id'] ) && $notification['options']['id'] === 'wpseo-dismiss-about' ) {
  280. unset( $notifications[ $notification_key ] );
  281. }
  282. }
  283. update_user_option( $usermeta['user_id'], Yoast_Notification_Center::STORAGE_KEY, array_values( $notifications ) );
  284. }
  285. }
  286. /**
  287. * Removes the wpseo-dismiss-about notice from a list of notifications.
  288. *
  289. * @param Yoast_Notification[] $notifications The notifications to filter.
  290. *
  291. * @return Yoast_Notification[] The filtered list of notifications. Excluding the wpseo-dismiss-about notification.
  292. */
  293. public function remove_about_notice( $notifications ) {
  294. foreach ( $notifications as $notification_key => $notification ) {
  295. if ( $notification->get_id() === 'wpseo-dismiss-about' ) {
  296. unset( $notifications[ $notification_key ] );
  297. }
  298. }
  299. return $notifications;
  300. }
  301. /**
  302. * Adds the yoast_seo_links table to the database.
  303. */
  304. private function upgrade_50() {
  305. global $wpdb;
  306. $link_installer = new WPSEO_Link_Installer();
  307. $link_installer->install();
  308. // Trigger reindex notification.
  309. $notifier = new WPSEO_Link_Notifier();
  310. $notifier->manage_notification();
  311. // Deletes the post meta value, which might created in the RC.
  312. $wpdb->query( 'DELETE FROM ' . $wpdb->postmeta . ' WHERE meta_key = "_yst_content_links_processed"' );
  313. }
  314. /**
  315. * Updates the internal_link_count column to support improved functionality.
  316. */
  317. private function upgrade_50_51() {
  318. global $wpdb;
  319. $count_storage = new WPSEO_Meta_Storage();
  320. $wpdb->query( 'ALTER TABLE ' . $count_storage->get_table_name() . ' MODIFY internal_link_count int(10) UNSIGNED NULL DEFAULT NULL' );
  321. }
  322. /**
  323. * Register new capabilities and roles.
  324. */
  325. private function upgrade_55() {
  326. // Register roles.
  327. do_action( 'wpseo_register_roles' );
  328. WPSEO_Role_Manager_Factory::get()->add();
  329. // Register capabilities.
  330. do_action( 'wpseo_register_capabilities' );
  331. WPSEO_Capability_Manager_Factory::get()->add();
  332. }
  333. /**
  334. * Updates legacy license page options to the latest version.
  335. */
  336. private function upgrade_56() {
  337. global $wpdb;
  338. // Make sure License Server checks are on the latest server version by default.
  339. update_option( 'wpseo_license_server_version', WPSEO_License_Page_Manager::VERSION_BACKWARDS_COMPATIBILITY );
  340. // Make sure incoming link count entries are at least 0, not NULL.
  341. $count_storage = new WPSEO_Meta_Storage();
  342. $wpdb->query( 'UPDATE ' . $count_storage->get_table_name() . ' SET incoming_link_count = 0 WHERE incoming_link_count IS NULL' );
  343. }
  344. /**
  345. * Updates the links for the link count when there is a difference between the site and home url. We've used the
  346. * site url instead of the home url.
  347. *
  348. * @return void
  349. */
  350. private function upgrade_61() {
  351. // When the home url is the same as the site url, just do nothing.
  352. if ( home_url() === site_url() ) {
  353. return;
  354. }
  355. global $wpdb;
  356. $link_storage = new WPSEO_Link_Storage();
  357. $wpdb->query( 'DELETE FROM ' . $link_storage->get_table_name() );
  358. $meta_storage = new WPSEO_Meta_Storage();
  359. $wpdb->query( 'DELETE FROM ' . $meta_storage->get_table_name() );
  360. }
  361. /**
  362. * Removes some no longer used options for noindexing subpages and for meta keywords and its associated templates.
  363. *
  364. * @return void
  365. */
  366. private function upgrade_63() {
  367. $this->cleanup_option_data( 'wpseo_titles' );
  368. }
  369. /**
  370. * Perform the 7.0 upgrade, moves settings around, deletes several options.
  371. *
  372. * @return void
  373. */
  374. private function upgrade_70() {
  375. $wpseo_permalinks = $this->get_option_from_database( 'wpseo_permalinks' );
  376. $wpseo_xml = $this->get_option_from_database( 'wpseo_xml' );
  377. $wpseo_rss = $this->get_option_from_database( 'wpseo_rss' );
  378. $wpseo = $this->get_option_from_database( 'wpseo' );
  379. $wpseo_internallinks = $this->get_option_from_database( 'wpseo_internallinks' );
  380. // Move some permalink settings, then delete the option.
  381. $this->save_option_setting( $wpseo_permalinks, 'redirectattachment', 'disable-attachment' );
  382. $this->save_option_setting( $wpseo_permalinks, 'stripcategorybase' );
  383. // Move one XML sitemap setting, then delete the option.
  384. $this->save_option_setting( $wpseo_xml, 'enablexmlsitemap', 'enable_xml_sitemap' );
  385. // Move the RSS settings to the search appearance settings, then delete the RSS option.
  386. $this->save_option_setting( $wpseo_rss, 'rssbefore' );
  387. $this->save_option_setting( $wpseo_rss, 'rssafter' );
  388. $this->save_option_setting( $wpseo, 'company_logo' );
  389. $this->save_option_setting( $wpseo, 'company_name' );
  390. $this->save_option_setting( $wpseo, 'company_or_person' );
  391. $this->save_option_setting( $wpseo, 'person_name' );
  392. // Remove the website name and altername name as we no longer need them.
  393. $this->cleanup_option_data( 'wpseo' );
  394. // All the breadcrumbs settings have moved to the search appearance settings.
  395. foreach ( array_keys( $wpseo_internallinks ) as $key ) {
  396. $this->save_option_setting( $wpseo_internallinks, $key );
  397. }
  398. // Convert hidden metabox options to display metabox options.
  399. $title_options = get_option( 'wpseo_titles' );
  400. foreach ( $title_options as $key => $value ) {
  401. if ( strpos( $key, 'hideeditbox-tax-' ) === 0 ) {
  402. $taxonomy = substr( $key, strlen( 'hideeditbox-tax-' ) );
  403. WPSEO_Options::set( 'display-metabox-tax-' . $taxonomy, ! $value );
  404. continue;
  405. }
  406. if ( strpos( $key, 'hideeditbox-' ) === 0 ) {
  407. $post_type = substr( $key, strlen( 'hideeditbox-' ) );
  408. WPSEO_Options::set( 'display-metabox-pt-' . $post_type, ! $value );
  409. continue;
  410. }
  411. }
  412. // Cleanup removed options.
  413. delete_option( 'wpseo_xml' );
  414. delete_option( 'wpseo_permalinks' );
  415. delete_option( 'wpseo_rss' );
  416. delete_option( 'wpseo_internallinks' );
  417. // Remove possibly present plugin conflict notice for plugin that was removed from the list of conflicting plugins.
  418. $yoast_plugin_conflict = WPSEO_Plugin_Conflict::get_instance();
  419. $yoast_plugin_conflict->clear_error( 'header-footer/plugin.php' );
  420. // Moves the user meta for excluding from the XML sitemap to a noindex.
  421. global $wpdb;
  422. $wpdb->query( "UPDATE $wpdb->usermeta SET meta_key = 'wpseo_noindex_author' WHERE meta_key = 'wpseo_excludeauthorsitemap'" );
  423. }
  424. /**
  425. * Perform the 7.1 upgrade.
  426. *
  427. * @return void
  428. */
  429. private function upgrade_71() {
  430. $this->cleanup_option_data( 'wpseo_social' );
  431. // Move the breadcrumbs setting and invert it.
  432. $title_options = $this->get_option_from_database( 'wpseo_titles' );
  433. if ( array_key_exists( 'breadcrumbs-blog-remove', $title_options ) ) {
  434. WPSEO_Options::set( 'breadcrumbs-display-blog-page', ! $title_options['breadcrumbs-blog-remove'] );
  435. $this->cleanup_option_data( 'wpseo_titles' );
  436. }
  437. }
  438. /**
  439. * Perform the 7.3 upgrade.
  440. *
  441. * @return void
  442. */
  443. private function upgrade_73() {
  444. global $wpdb;
  445. // We've moved the cornerstone checkbox to our proper namespace.
  446. $wpdb->query( "UPDATE $wpdb->postmeta SET meta_key = '_yoast_wpseo_is_cornerstone' WHERE meta_key = '_yst_is_cornerstone'" );
  447. // Remove the previous Whip dismissed message, as this is a new one regarding PHP 5.2.
  448. delete_option( 'whip_dismiss_timestamp' );
  449. }
  450. /**
  451. * Performs the 7.4 upgrade.
  452. *
  453. * @return void
  454. */
  455. private function upgrade_74() {
  456. $this->remove_sitemap_validators();
  457. }
  458. /**
  459. * Performs the 7.5.3 upgrade.
  460. *
  461. * When upgrading purging media is potentially relevant.
  462. *
  463. * @return void
  464. */
  465. private function upgrade_753() {
  466. // Only when attachments are not disabled.
  467. if ( WPSEO_Options::get( 'disable-attachment' ) === true ) {
  468. return;
  469. }
  470. // Only when attachments are not no-indexed.
  471. if ( WPSEO_Options::get( 'noindex-attachment' ) === true ) {
  472. return;
  473. }
  474. // Set purging relevancy.
  475. WPSEO_Options::set( 'is-media-purge-relevant', true );
  476. }
  477. /**
  478. * Performs the 7.7 upgrade.
  479. *
  480. * @return void
  481. */
  482. private function upgrade_77() {
  483. // Remove all OpenGraph content image cache.
  484. $this->delete_post_meta( '_yoast_wpseo_post_image_cache' );
  485. }
  486. /**
  487. * Performs the 7.7.2 upgrade.
  488. *
  489. * @return void
  490. */
  491. private function upgrade_772() {
  492. if ( WPSEO_Utils::is_woocommerce_active() ) {
  493. $this->migrate_woocommerce_archive_setting_to_shop_page();
  494. }
  495. }
  496. /**
  497. * Removes the post meta fields for a given meta key.
  498. *
  499. * @param string $meta_key The meta key.
  500. *
  501. * @return void
  502. */
  503. private function delete_post_meta( $meta_key ) {
  504. global $wpdb;
  505. $deleted = $wpdb->delete( $wpdb->postmeta, array( 'meta_key' => $meta_key ), array( '%s' ) );
  506. if ( $deleted ) {
  507. wp_cache_set( 'last_changed', microtime(), 'posts' );
  508. }
  509. }
  510. /**
  511. * Removes all sitemap validators.
  512. *
  513. * This should be executed on every upgrade routine until we have removed the sitemap caching in the database.
  514. *
  515. * @return void
  516. */
  517. private function remove_sitemap_validators() {
  518. global $wpdb;
  519. // Remove all sitemap validators.
  520. $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'wpseo_sitemap%validator%'" );
  521. }
  522. /**
  523. * Retrieves the option value directly from the database.
  524. *
  525. * @param string $option_name Option to retrieve.
  526. *
  527. * @return array|mixed The content of the option if exists, otherwise an empty array.
  528. */
  529. protected function get_option_from_database( $option_name ) {
  530. global $wpdb;
  531. // Load option directly from the database, to avoid filtering and sanitization.
  532. $sql = $wpdb->prepare( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = %s', $option_name );
  533. $results = $wpdb->get_results( $sql, ARRAY_A );
  534. if ( ! empty( $results ) ) {
  535. return maybe_unserialize( $results[0]['option_value'] );
  536. }
  537. return array();
  538. }
  539. /**
  540. * Cleans the option to make sure only relevant settings are there.
  541. *
  542. * @param string $option_name Option name save.
  543. *
  544. * @return void
  545. */
  546. protected function cleanup_option_data( $option_name ) {
  547. $data = get_option( $option_name, array() );
  548. if ( ! is_array( $data ) || $data === array() ) {
  549. return;
  550. }
  551. /*
  552. * Clean up the option by re-saving it.
  553. *
  554. * The option framework will remove any settings that are not configured
  555. * for this option, removing any migrated settings.
  556. */
  557. update_option( $option_name, $data );
  558. }
  559. /**
  560. * Saves an option setting to where it should be stored.
  561. *
  562. * @param array $source_data The option containing the value to be migrated.
  563. * @param string $source_setting Name of the key in the "from" option.
  564. * @param string|null $target_setting Name of the key in the "to" option.
  565. *
  566. * @return void
  567. */
  568. protected function save_option_setting( $source_data, $source_setting, $target_setting = null ) {
  569. if ( $target_setting === null ) {
  570. $target_setting = $source_setting;
  571. }
  572. if ( isset( $source_data[ $source_setting ] ) ) {
  573. WPSEO_Options::set( $target_setting, $source_data[ $source_setting ] );
  574. }
  575. }
  576. /**
  577. * Migrates WooCommerce archive settings to the WooCommerce Shop page meta-data settings.
  578. *
  579. * If no Shop page is defined, nothing will be migrated.
  580. *
  581. * @return void
  582. */
  583. private function migrate_woocommerce_archive_setting_to_shop_page() {
  584. $shop_page_id = wc_get_page_id( 'shop' );
  585. if ( $shop_page_id === -1 ) {
  586. return;
  587. }
  588. $title = WPSEO_Meta::get_value( 'title', $shop_page_id );
  589. if ( empty( $title ) ) {
  590. $option_title = WPSEO_Options::get( 'title-ptarchive-product' );
  591. WPSEO_Meta::set_value(
  592. 'title',
  593. $option_title,
  594. $shop_page_id
  595. );
  596. WPSEO_Options::set( 'title-ptarchive-product', '' );
  597. }
  598. $meta_description = WPSEO_Meta::get_value( 'metadesc', $shop_page_id );
  599. if ( empty( $meta_description ) ) {
  600. $option_metadesc = WPSEO_Options::get( 'metadesc-ptarchive-product' );
  601. WPSEO_Meta::set_value(
  602. 'metadesc',
  603. $option_metadesc,
  604. $shop_page_id
  605. );
  606. WPSEO_Options::set( 'metadesc-ptarchive-product', '' );
  607. }
  608. $bc_title = WPSEO_Meta::get_value( 'bctitle', $shop_page_id );
  609. if ( empty( $bc_title ) ) {
  610. $option_bctitle = WPSEO_Options::get( 'bctitle-ptarchive-product' );
  611. WPSEO_Meta::set_value(
  612. 'bctitle',
  613. $option_bctitle,
  614. $shop_page_id
  615. );
  616. WPSEO_Options::set( 'bctitle-ptarchive-product', '' );
  617. }
  618. $noindex = WPSEO_Meta::get_value( 'meta-robots-noindex', $shop_page_id );
  619. if ( $noindex === '0' ) {
  620. $option_noindex = WPSEO_Options::get( 'noindex-ptarchive-product' );
  621. WPSEO_Meta::set_value(
  622. 'meta-robots-noindex',
  623. $option_noindex,
  624. $shop_page_id
  625. );
  626. WPSEO_Options::set( 'noindex-ptarchive-product', false );
  627. }
  628. }
  629. }