MS_Model_Upgrade

Upgrade DB model.

Defined (1)

The class is defined in the following location(s).

/app/model/class-ms-model-upgrade.php  
  1. class MS_Model_Upgrade extends MS_Model { 
  2.  
  3. /** 
  4. * Initialize upgrading check. 
  5. * @since 1.0.0 
  6. */ 
  7. public static function init() { 
  8. self::update(); 
  9.  
  10. MS_Factory::load( 'MS_Model_Upgrade' ); 
  11.  
  12. // This function is intended for development/testing only! 
  13. self::maybe_restore(); 
  14.  
  15. // This is a hidden feature available in the Settings > General page. 
  16. add_action( 'init', array( __CLASS__, 'maybe_reset' ) ); 
  17.  
  18. // Prevent WordPress from updating the Membership plugin when the 
  19. // WPMU DEV Dashboard is disabled. 
  20. if ( ! class_exists( 'WPMUDEV_Dashboard' ) ) { 
  21. add_filter( 
  22. 'plugins_api',  
  23. array( __CLASS__, 'no_dash_plugins_api' ),  
  24. 101, 3 
  25. ); 
  26. add_filter( 
  27. 'site_transient_update_plugins',  
  28. array( __CLASS__, 'no_dash_update_plugins' ) 
  29. ); 
  30.  
  31. do_action( 'ms_model_upgrade_init' ); 
  32.  
  33. /** 
  34. * Upgrade database. 
  35. * @since 1.0.0 
  36. * @param bool $force Also execute update logic when version did not change. 
  37. */ 
  38. public static function update( $force = false ) { 
  39. static $Done = false; 
  40.  
  41. if ( $Done && ! $force ) { return; } 
  42.  
  43. // Migration handler has its own valid_user check. 
  44. self::check_migration_handler(); 
  45.  
  46. // Updates are only triggered from Admin-Side by an Admin user. 
  47. if ( ! self::valid_user() ) { return; } 
  48.  
  49. // Check for correct network-wide protection setup. 
  50. self::check_settings(); 
  51.  
  52. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  53. $old_version = $settings->version; // Old: The version in DB. 
  54. $new_version = MS_Plugin::instance()->version; // New: Version in file. 
  55.  
  56. $is_new_setup = empty( $old_version ); 
  57.  
  58. // Compare current src version to DB version: 
  59. // We only do UP-grades but no DOWN-grades! 
  60. if ( $old_version ) { 
  61. $version_changed = version_compare( $old_version, $new_version, 'lt' ); 
  62. } else { 
  63. $version_changed = true; 
  64.  
  65. if ( $force || $version_changed ) { 
  66. $Done = true; 
  67. $msg = array(); 
  68.  
  69. /** 
  70. * ----- General update logic, executed on every update ------------ 
  71. */ 
  72.  
  73. do_action( 
  74. 'ms_model_upgrade_before_update',  
  75. $settings,  
  76. $old_version,  
  77. $new_version,  
  78. $force 
  79. ); 
  80.  
  81. // Prepare the Update message. 
  82. if ( ! $version_changed ) { 
  83. $msg[] = sprintf( 
  84. __( '<strong>Membership 2</strong> is set up for version %1$s!' , 'membership2' ),  
  85. $new_version 
  86. ); 
  87. } else { 
  88. $msg[] = sprintf( 
  89. __( '<strong>Membership 2</strong> was updated to version %1$s!' , 'membership2' ),  
  90. $new_version 
  91. ); 
  92.  
  93. // Every time the plugin is updated we clear the cache. 
  94. MS_Factory::clear(); 
  95.  
  96. // Create missing Membership pages. 
  97. $new_pages = MS_Model_Pages::create_missing_pages(); 
  98.  
  99. if ( ! empty( $new_pages ) ) { 
  100. $msg[] = sprintf( 
  101. __( 'New Membership pages created: "%1$s".', 'membership2' ),  
  102. implode( '", "', $new_pages ) 
  103. ); 
  104.  
  105. // Remove an old version of Protected Content 
  106. // TODO: REMOVE THIS BLOCK/FUNCTION END OF 2015 
  107. if ( $version_changed ) { 
  108. self::remove_old_copy(); 
  109.  
  110. // Note: We do not create menu items on upgrade! Users might have 
  111. // intentionally removed the items from the menu... 
  112.  
  113. /** 
  114. * ----- Version-Specific update logic ----------------------------- 
  115. */ 
  116.  
  117. // Upgrade from a 1.0.0.x version to 1.0.1.0 or higher 
  118. if ( version_compare( $old_version, '1.0.1.0', 'lt' ) ) { 
  119. self::_upgrade_1_0_1_0(); 
  120.  
  121. // Upgrade from 1.0.1.0 version to 1.0.1.1 or higher 
  122. if ( version_compare( $old_version, '1.0.1.1', 'lt' ) ) { 
  123. self::_upgrade_1_0_1_1(); 
  124.  
  125. // Upgrade from 1.0.1.x version to 1.0.2.0 or higher 
  126. if ( version_compare( $old_version, '1.0.2.0', 'lt' ) ) { 
  127. self::_upgrade_1_0_2_0(); 
  128.  
  129. // Upgrade from 1.0.2.x version to 1.0.2.4 or higher 
  130. if ( version_compare( $old_version, '1.0.2.4', 'lt' ) ) { 
  131. self::_upgrade_1_0_2_4(); 
  132.  
  133. /** 
  134. * ----- General update logic, executed on every update ------------ 
  135. */ 
  136.  
  137. $settings->version = $new_version; 
  138. $settings->save(); 
  139.  
  140. // Display a message after the page is reloaded. 
  141. if ( ! $is_new_setup ) { 
  142. lib3()->ui->admin_message( implode( '<br>', $msg ), '', '', 'ms-update' ); 
  143.  
  144. do_action( 
  145. 'ms_model_upgrade_after_update',  
  146. $settings,  
  147. $old_version,  
  148. $new_version,  
  149. $force 
  150. ); 
  151.  
  152. $addons = MS_Factory::load( 'MS_Model_Addon' ); 
  153. $addons->flush_list(); 
  154.  
  155. // This will reload the current page. 
  156. MS_Plugin::flush_rewrite_rules(); 
  157.  
  158. /** 
  159. * When WPMU DEV Dashboard is disabled this function will tell WordPress 
  160. * to not update Membership 2. 
  161. * PRO ONLY! 
  162. * @since 1.0.1.2 
  163. * @param mixed $res False: Update plugin / True: WP ignores plugin. 
  164. * @param string $action 
  165. * @param object $args 
  166. * @return mixed 
  167. */ 
  168. static public function no_dash_plugins_api( $res, $action, $args ) { 
  169. if ( ! empty( $args ) && is_object( $args ) ) { 
  170. if ( 'wpmudev_install-1003656' == $args->slug ) { 
  171. $res = true; 
  172. } elseif ( 'wpmudev_install-130' == $args->slug ) { 
  173. $res = true; 
  174. } elseif ( 'membership' == $args->slug ) { 
  175. $res = true; 
  176.  
  177. return $res; 
  178.  
  179. /** 
  180. * Filter the site transient value right before it is returned by the 
  181. * get_site_transient function. 
  182. * We mark the Membership2 plugin for "no update". 
  183. * PRO ONLY! 
  184. * @since 1.0.1.2 
  185. * @param object $data 
  186. * @return object 
  187. */ 
  188. static public function no_dash_update_plugins( $data ) { 
  189. if ( ! empty( $data ) && is_object( $data ) && ! empty( $data->response ) ) { 
  190. if ( isset( $data->response['membership/membership2.php'] ) ) { 
  191. $data->no_update['membership/membership2.php'] = $data->response['membership/membership2.php']; 
  192. unset( $data->response['membership/membership2.php'] ); 
  193.  
  194. return $data; 
  195.  
  196.  
  197. # ########################################################################## 
  198. # ########################################################################## 
  199.  
  200. /** 
  201. * Upgrade from any 1.0.0.x version to a higher version. 
  202. */ 
  203. static private function _upgrade_1_0_1_0() { 
  204. lib3()->updates->clear(); 
  205.  
  206. /** 
  207. * The "is_member" flag of users was not correctly saved when a 
  208. * subscription was added via the M2 > Members page. 
  209. * Fix this now. 
  210. */ 
  211. global $wpdb; 
  212. $sql = " 
  213. SELECT DISTINCT usr.user_id 
  214. FROM 
  215. {$wpdb->posts} post 
  216. LEFT JOIN {$wpdb->usermeta} usr 
  217. ON usr.user_id = post.post_author 
  218. AND usr.meta_key = 'ms_is_member' 
  219. WHERE 
  220. post_type = 'ms_relationship' 
  221. AND (usr.meta_value IS NULL OR usr.meta_value != 1); 
  222. "; 
  223. $result = $wpdb->get_col( $sql ); 
  224. foreach ( $result as $user_id ) { 
  225. lib3()->updates->add( 'update_user_meta', $user_id, 'ms_is_member', true ); 
  226.  
  227. // Execute all queued actions! 
  228. lib3()->updates->plugin( 'membership2' ); 
  229. lib3()->updates->execute(); 
  230.  
  231. /** 
  232. * Upgrade from 1.0.1.0 version to a higher version. 
  233. */ 
  234. static private function _upgrade_1_0_1_1() { 
  235. lib3()->updates->clear(); 
  236.  
  237. /** 
  238. * A bug in 1.0.1 created multiple copies of email templates. 
  239. * This update block will delete the duplicates again. 
  240. */ 
  241. global $wpdb; 
  242. $sql = " 
  243. SELECT ID 
  244. FROM {$wpdb->posts} 
  245. WHERE 
  246. post_type = 'ms_communication' 
  247. AND ID NOT IN ( 
  248. SELECT 
  249. MIN( p.ID ) ID 
  250. FROM 
  251. {$wpdb->posts} p 
  252. INNER JOIN {$wpdb->postmeta} m1 
  253. ON m1.post_id = p.ID AND m1.meta_key = 'type' 
  254. WHERE 
  255. p.post_type = 'ms_communication' 
  256. AND LENGTH( m1.meta_value ) > 0 
  257. GROUP BY 
  258. m1.meta_value,  
  259. p.post_parent 
  260. ); 
  261. "; 
  262. $ids = $wpdb->get_col( $sql ); 
  263.  
  264. foreach ( $ids as $id ) { 
  265. lib3()->updates->add( 'wp_delete_post', $id, true ); 
  266.  
  267. // Execute all queued actions! 
  268. lib3()->updates->plugin( 'membership2' ); 
  269. lib3()->updates->execute(); 
  270.  
  271. /** 
  272. * Upgrade from 1.0.1.1 version to a higher version. 
  273. */ 
  274. static private function _upgrade_1_0_2_0() { 
  275. lib3()->updates->clear(); 
  276.  
  277. /** 
  278. * Transaction logs are a bit messed up because some meta-keys have an 
  279. * underscore as prefix while other do not have it. This query removes 
  280. * the underscore from all transaction-log meta key names. 
  281. */ 
  282. global $wpdb; 
  283. $sql = " 
  284. UPDATE {$wpdb->postmeta} 
  285. INNER JOIN {$wpdb->posts} ON {$wpdb->postmeta}.post_id={$wpdb->posts}.ID 
  286. SET meta_key = SUBSTR(meta_key, 2) 
  287. WHERE 
  288. {$wpdb->posts}.post_type = 'ms_transaction_log' 
  289. AND SUBSTR({$wpdb->postmeta}.meta_key, 1, 1) = '_' 
  290. "; 
  291. $ids = $wpdb->query( $sql ); 
  292.  
  293. /** 
  294. * Upgrade from 1.0.2.x version to 1.0.2.4 version. 
  295. */ 
  296. static private function _upgrade_1_0_2_4() { 
  297. lib3()->updates->clear(); 
  298.  
  299. /** 
  300. * Transaction matching of M1 payments with M2 memberships has improved 
  301. * so a single M2 membership can be matched with multiple transaction 
  302. * types. 
  303. */ 
  304. $memberships = MS_Model_Membership::get_memberships(); 
  305. foreach ( $memberships as $item ) { 
  306. $source_id = $membership->source_id; 
  307. if ( empty( $source_id ) ) { continue; } 
  308.  
  309. $data = lib3()->array->get( 
  310. $membership->get_custom_data( 'matching' ) 
  311. ); 
  312.  
  313. if ( ! isset( $data['m1'] ) ) { $data['m1'] = array(); } 
  314. $data['m1'] = lib3()->array->get( $data['m1'] ); 
  315. $data['m1'][] = $source_id; 
  316. $membership->set_custom_data( 'matching', $data ); 
  317. $membership->save(); 
  318.  
  319. # ########################################################################## 
  320.  
  321. /** 
  322. * Used when upgrading from Membership to M2. If both Membership and 
  323. * Protected Content are installed when upgrading then the old 
  324. * "protected-content" folder may survive the upgrade and needs to be 
  325. * manually removed. 
  326. * @since 1.0.0 
  327. */ 
  328. static private function remove_old_copy() { 
  329. $new_dir = WP_PLUGIN_DIR . '/membership'; 
  330. $old_dir = WP_PLUGIN_DIR . '/protected-content'; 
  331. $old_plugins = array( 
  332. 'protected-content/protected-content.php',  
  333. 'membership/membershippremium.php',  
  334. ); 
  335. $new_plugin = plugin_basename( MS_Plugin::instance()->file ); 
  336.  
  337. // Make sure that the current plugin is the official M2 one. 
  338. if ( false === strpos( MS_Plugin::instance()->dir, $new_dir ) ) { 
  339. // Cancel: This plugin is not the official plugin (maybe a backup or beta version) 
  340.  
  341. if ( false !== strpos( MS_Plugin::instance()->dir, $old_dir ) ) { 
  342. lib3()->ui->admin_message( 
  343. __( '<b>Upgrade warning</b>:<br>The Membership 2 plugin is installed in an deprecated folder. Some users did report issues when the plugin is installed in this directory.<br>To fix this issue please follow these steps:<br><br>1. Delete* the old Membership Premium plugin if it is still installed.<br>2. Delete* the Membership 2 plugin.<br>3. Re-install Membership 2 from the WPMU Dashboard - your existing data is not affected by this.<br><br>*) <em>Only deactivating the plugins does not work, you have to delete them.</em>', 'membership2' ),  
  344. 'error' 
  345. ); 
  346.  
  347. return; 
  348.  
  349. // 1. See if there is a old copy of the plugin directory. Delete it. 
  350. if ( is_dir( $old_dir ) && is_file( $old_dir . '/protected-content.php' ) ) { 
  351. // Looks like the old version of this plugin is still installed. Remove it. 
  352. try { 
  353. unlink( $old_dir . '/protected-content.php' ); 
  354. array_map( 'unlink', glob( "$old_dir/*.*" ) ); 
  355. rmdir( $old_dir ); 
  356. } catch( Exception $e ) { 
  357. // Something went wrong when removing the old plugin. 
  358.   
  359. // 2. See if WordPress uses an old plugin in the DB. Update it. 
  360. if ( is_multisite() ) { 
  361. $global_plugins = (array) get_site_option( 'active_sitewide_plugins', array() ); 
  362. foreach ( $global_plugins as $key => $the_path ) { 
  363. if ( in_array( $the_path, $old_plugins ) ) { 
  364. $global_plugins[$key] = $new_plugin; 
  365. update_site_option( 'active_sitewide_plugins', $global_plugins ); 
  366.   
  367. $site_plugins = (array) get_option( 'active_plugins', array() ); 
  368. foreach ( $site_plugins as $key => $the_path ) { 
  369. if ( in_array( $the_path, $old_plugins ) ) { 
  370. $site_plugins[$key] = $new_plugin; 
  371. update_option( 'active_plugins', $site_plugins ); 
  372.   
  373. # ########################################################################## 
  374. # ########################################################################## 
  375.   
  376.   
  377. /** 
  378. * Completely whipe all Membership data from Database. 
  379. * Note: This function is not used currently... 
  380. * @since 1.0.0 
  381. */ 
  382. static private function cleanup_db() { 
  383. global $wpdb; 
  384. $sql = array(); 
  385. $trash_ids = array(); 
  386.  
  387. // Delete membership meta-data from users. 
  388. $users = MS_Model_Member::get_members(); 
  389. foreach ( $users as $user ) { 
  390. $user->delete_all_membership_usermeta(); 
  391. $user->save(); 
  392.  
  393. // Determine IDs of Membership Pages. 
  394. $page_types = MS_Model_Pages::get_page_types(); 
  395. foreach ( $page_types as $type => $name ) { 
  396. $page_id = MS_Model_Pages::get_setting( $type ); 
  397. $trash_ids[] = $page_id; 
  398.  
  399. /** 
  400. * Delete all plugin settings. 
  401. * Settings are saved by classes that extend MS_Model_option 
  402. */ 
  403. foreach ( MS_Model_Gateway::get_gateways() as $option ) { 
  404. $option->delete(); 
  405. MS_Factory::load( 'MS_Model_Addon' )->delete(); 
  406. MS_Factory::load( 'MS_Model_Pages' )->delete(); 
  407. MS_Factory::load( 'MS_Model_Settings' )->delete(); 
  408.  
  409. /** 
  410. * Delete transient data 
  411. * Transient data is saved by classed that extend MS_Model_Transient 
  412. */ 
  413. MS_Factory::load( 'MS_Model_Simulate' )->delete(); 
  414.  
  415. /** 
  416. * Delete all plugin content. 
  417. * Content is saved by classes that extend MS_Model_CustomPostType 
  418. */ 
  419. $ms_posttypes = array( 
  420. MS_Model_Communication::get_post_type(),  
  421. MS_Model_Event::get_post_type(),  
  422. MS_Model_Invoice::get_post_type(),  
  423. MS_Model_Transactionlog::get_post_type(),  
  424. MS_Model_Membership::get_post_type(),  
  425. MS_Model_Relationship::get_post_type(),  
  426. MS_Addon_Coupon_Model::get_post_type(),  
  427. MS_Addon_Invitation_Model::get_post_type(),  
  428. ); 
  429.  
  430. foreach ( $ms_posttypes as $type ) { 
  431. $sql[] = $wpdb->prepare( 
  432. "DELETE FROM $wpdb->posts WHERE post_type = %s;",  
  433. $type 
  434. ); 
  435.  
  436. // Remove orphaned post-metadata. 
  437. $sql[] = " 
  438. DELETE FROM $wpdb->postmeta 
  439. WHERE NOT EXISTS ( 
  440. SELECT 1 FROM $wpdb->posts tmp WHERE tmp.ID = post_id 
  441. ); 
  442. "; 
  443.  
  444. // Clear all WP transient cache. 
  445. $sql[] = " 
  446. DELETE FROM $wpdb->options 
  447. WHERE option_name LIKE '_transient_%'; 
  448. "; 
  449.  
  450. foreach ( $sql as $s ) { 
  451. $wpdb->query( $s ); 
  452.  
  453. // Move Membership pages to trash. 
  454. foreach ( $trash_ids as $id ) { 
  455. wp_delete_post( $id, true ); 
  456.  
  457. // Clear all data from WP Object cache. 
  458. wp_cache_flush(); 
  459.  
  460. // Redirect to the main page. 
  461. wp_safe_redirect( MS_Controller_Plugin::get_admin_url() ); 
  462. exit; 
  463.  
  464. /** 
  465. * Checks several settings to make sure that M2 is fully working. 
  466. * A) Makes sure that network-wide protection works by ensuring that the 
  467. * plugin is also network-activated. 
  468. * B) Checks if the permalink structure uses the post-name 
  469. * @since 1.0.0 
  470. */ 
  471. static private function check_settings() { 
  472. static $Setting_Check_Done = false; 
  473.  
  474. if ( ! $Setting_Check_Done ) { 
  475. $Setting_Check_Done = true; 
  476.  
  477. // A) Check plugin activation in network-wide mode. 
  478. if ( is_multisite() ) { 
  479.  
  480. if ( MS_Plugin::is_network_wide() ) { 
  481. // This function does not exist in network admin 
  482. if ( ! function_exists( 'is_plugin_active_for_network' ) ) { 
  483. require_once ABSPATH . '/wp-admin/includes/plugin.php'; 
  484.  
  485. if ( ! is_plugin_active_for_network( MS_PLUGIN ) ) { 
  486. activate_plugin( MS_PLUGIN, null, true ); 
  487. lib3()->ui->admin_message( 
  488. __( 'Info: Membership2 is not activated network-wide', 'membership2' ) 
  489. ); 
  490.  
  491. // B) Check the Permalink settings. 
  492. if ( false === strpos( get_option( 'permalink_structure' ), '%postname%' ) ) { 
  493. lib3()->ui->admin_message( 
  494. sprintf( 
  495. __( 'Your %sPermalink structure%s should include the %sPost name%s to ensure Membership 2 is working correctly.', 'membership2' ),  
  496. '<a href="' . admin_url( 'options-permalink.php' ) . '">',  
  497. '</a>',  
  498. '<strong>',  
  499. '</strong>' 
  500. ),  
  501. 'err' 
  502. ); 
  503.  
  504. return; 
  505.  
  506. /** 
  507. * This function checks if we arrive here after a migration, i.e. after the 
  508. * user updated Membership Premium or Protected Content to M2 
  509. * @since 1.0.0 
  510. */ 
  511. static private function check_migration_handler() { 
  512. $migrate = ''; 
  513. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  514.  
  515. // Check Migration from old Membership plugin. 
  516. $option_m1 = '_wpmudev_update_to_m2'; 
  517. $option_m1_free = '_wporg_update_to_m2'; 
  518. $from_m1 = get_site_option( $option_m1 ); 
  519. $from_m1_free = get_site_option( $option_m1_free ); 
  520.  
  521. if ( $from_m1 || $from_m1_free ) { 
  522. $migrate = 'm1'; 
  523.  
  524. delete_site_option( $option_m1 ); 
  525. delete_site_option( $option_m1_free ); 
  526. $settings->set_special_view( 'MS_View_MigrationM1' ); 
  527.  
  528. $view = $settings->get_special_view(); 
  529.  
  530. if ( $migrate || 'MS_View_MigrationM1' == $view ) { 
  531. if ( ! empty( $_REQUEST['skip_import'] ) ) { 
  532. $settings->reset_special_view(); 
  533. wp_safe_redirect( 
  534. esc_url_raw( remove_query_arg( array( 'skip_import' ) ) ) 
  535. ); 
  536. exit; 
  537. } else { 
  538. $settings->set_special_view( 'MS_View_MigrationM1' ); 
  539.  
  540. // Complete the migration when the import is done. 
  541. add_action( 
  542. 'ms_import_action_done',  
  543. array( 'MS_Model_Settings', 'reset_special_view' ) 
  544. ); 
  545.  
  546. /** 
  547. * Returns a secure token to trigger advanced admin actions like db-reset 
  548. * or restoring a snapshot. 
  549. * - Only one token is valid at any given time. 
  550. * - Each token has a timeout of max. 120 seconds. 
  551. * - Each token can be used once only. 
  552. * @since 1.0.0 
  553. * @internal 
  554. * @param string $action Like a nonce, this is the action to execute. 
  555. * @return array Intended usage: add_query_param( $token, $url ) 
  556. */ 
  557. static public function get_token( $action ) { 
  558. if ( ! is_user_logged_in() ) { return array(); } 
  559. if ( ! is_admin() ) { return array(); } 
  560.  
  561. $one_time_key = uniqid(); 
  562. MS_Factory::set_transient( 'ms_one_time_key-' . $action, $one_time_key, 120 ); 
  563.  
  564. // Token is valid for 86 seconds because of usage of date('B') 
  565. $plain = $action . '-' . date( 'B' ) . ':' . get_current_user_id() . '-' . $one_time_key; 
  566. $token = array( 'ms_token' => wp_create_nonce( $plain ) ); 
  567. return $token; 
  568.  
  569. /** 
  570. * Verfies the admin token in the $_GET collection 
  571. * $_GET['ms_token'] must match the current ms_token 
  572. * $_POST['confirm'] must have value 'yes' 
  573. * @since 1.0.0 
  574. * @internal 
  575. * @param string $action Like a nonce, this is the action to execute. 
  576. * @return bool 
  577. */ 
  578. static private function verify_token( $action ) { 
  579. if ( ! self::valid_user() ) { return false; } 
  580.  
  581. if ( empty( $_GET['ms_token'] ) ) { return false; } 
  582. $get_token = $_GET['ms_token']; 
  583.  
  584. if ( empty( $_POST['confirm'] ) ) { return false; } 
  585. if ( 'yes' != $_POST['confirm'] ) { return false; } 
  586.  
  587. $one_time_key = MS_Factory::get_transient( 'ms_one_time_key-' . $action ); 
  588. MS_Factory::delete_transient( 'ms_one_time_key-' . $action ); 
  589. if ( empty( $one_time_key ) ) { return false; } 
  590.  
  591. // We verify the current and the previous beat 
  592. $plain_token_1 = $action . '-' . date( 'B' ) . ':' . get_current_user_id() . '-' . $one_time_key; 
  593. $plain_token_2 = $action . '-' . ( date( 'B' ) - 1 ) . ':' . get_current_user_id() . '-' . $one_time_key; 
  594.  
  595. if ( wp_verify_nonce( $get_token, $plain_token_1 ) ) { return true; } 
  596. if ( wp_verify_nonce( $get_token, $plain_token_2 ) ) { return true; } 
  597.  
  598. return false; 
  599.  
  600. /** 
  601. * Verifies the following conditions: 
  602. * - Current user is logged in and has admin permissions 
  603. * - The request is an wp-admin request 
  604. * - The request is not an Ajax call 
  605. * @since 1.0.0 
  606. * @return bool True if all conditions are true 
  607. */ 
  608. static private function valid_user() { 
  609. /** 
  610. * Determine user_id from request cookies. 
  611. * @see wp-includes/pluggable.php wp_currentuserinfo() 
  612. */ 
  613. $user_id = apply_filters( 'determine_current_user', false ); 
  614.  
  615. if ( ! $user_id ) { return false; } 
  616. if ( ! is_admin() ) { return false; } 
  617. if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { return false; } 
  618. if ( defined( 'DOING_CRON' ) && DOING_CRON ) { return false; } 
  619. if ( ! current_user_can( 'manage_options' ) ) { return false; } 
  620.  
  621. return true; 
  622.  
  623. /** 
  624. * Checks if valid reset-instructions are present. If yes, then whipe the 
  625. * plugin settings. 
  626. * @since 1.0.0 
  627. */ 
  628. static public function maybe_reset() { 
  629. static $Reset_Done = false; 
  630.  
  631. if ( ! $Reset_Done ) { 
  632. $Reset_Done = true; 
  633. if ( ! self::verify_token( 'reset' ) ) { return false; } 
  634.  
  635. self::cleanup_db(); 
  636. $msg = __( 'Membership 2 successfully reset!', 'membership2' ); 
  637. lib3()->ui->admin_message( $msg ); 
  638.  
  639. wp_safe_redirect( MS_Controller_Plugin::get_admin_url( 'MENU_SLUG' ) ); 
  640. exit; 
  641.  
  642. /** 
  643. * Checks if valid restore-options are specified. If they are, the snapshot 
  644. * will be restored. 
  645. * @since 1.0.0 
  646. * @internal This function is intended for development/testing only! 
  647. */ 
  648. static private function maybe_restore() { 
  649. static $Restore_Done = false; 
  650.  
  651. if ( ! $Restore_Done ) { 
  652. $Restore_Done = true; 
  653. if ( empty( $_POST['restore_snapshot'] ) ) { return false; } 
  654. $snapshot = $_POST['restore_snapshot']; 
  655.  
  656. if ( ! self::verify_token( 'restore' ) ) { return false; } 
  657.  
  658. lib3()->updates->plugin( 'membership2' ); 
  659. if ( lib3()->updates->restore( $snapshot ) ) { 
  660. printf( 
  661. '<p>' . 
  662. __( 'The Membership2 Snapshot "%s" was restored!', 'membership2' ) . 
  663. '</p>',  
  664. $snapshot 
  665. ); 
  666.  
  667. printf( 
  668. '<p><b>' . 
  669. __( 'To prevent auto-updating the DB again we stop here!', 'membership2' ) . 
  670. '</b></p>' 
  671. ); 
  672.  
  673. printf( 
  674. '<p>' . 
  675. __( 'You now have the option to <br />(A) downgrade the plugin to an earlier version via FTP or <br />(B) to %sre-run the upgrade process%s.', 'membership2' ) . 
  676. '</p>',  
  677. '<a href="' . MS_Controller_Plugin::get_admin_url( 'MENU_SLUG' ) . '">',  
  678. '</a>' 
  679. ); 
  680.  
  681. wp_die( '', 'Snapshot Restored' ); 
  682.  
  683. };