Ei kuvausta

Upgrades.php 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. <?php
  2. /*******************************************************************************
  3. * Copyright (c) 2019, Code Atlantic LLC
  4. ******************************************************************************/
  5. if ( ! defined( 'ABSPATH' ) ) {
  6. exit;
  7. }
  8. /**
  9. * Handles processing of data migration & upgrade routines.
  10. */
  11. class PUM_Utils_Upgrades {
  12. /**
  13. * @var PUM_Upgrade_Registry
  14. */
  15. protected $registry;
  16. /**
  17. * @var self
  18. */
  19. public static $instance;
  20. /**
  21. * Popup Maker version.
  22. *
  23. * @var string
  24. */
  25. public static $version;
  26. /**
  27. * Popup Maker upgraded from version.
  28. *
  29. * @var string
  30. */
  31. public static $upgraded_from;
  32. /**
  33. * Popup Maker initial version.
  34. *
  35. * @var string
  36. */
  37. public static $initial_version;
  38. /**
  39. * Popup Maker db version.
  40. *
  41. * @var string
  42. */
  43. public static $db_version;
  44. /**
  45. * Popup Maker install date.
  46. *
  47. * @var string
  48. */
  49. public static $installed_on;
  50. /**
  51. * Gets everything going with a singleton instance.
  52. *
  53. * @return self
  54. */
  55. public static function instance() {
  56. if ( ! isset( self::$instance ) ) {
  57. self::$instance = new self();
  58. }
  59. return self::$instance;
  60. }
  61. /**
  62. * Sets up the Upgrades class instance.
  63. */
  64. public function __construct() {
  65. // Update stored plugin version info.
  66. self::update_plugin_version();
  67. // Render upgrade admin notices.
  68. add_filter( 'pum_alert_list', array( $this, 'upgrade_alert' ) );
  69. // Add Upgrade tab to Tools page when upgrades available.
  70. add_filter( 'pum_tools_tabs', array( $this, 'tools_page_tabs' ) );
  71. // Render tools page upgrade tab content.
  72. add_action( 'pum_tools_page_tab_upgrades', array( $this, 'tools_page_tab_content' ) );
  73. // Ajax upgrade handler.
  74. add_action( 'wp_ajax_pum_process_upgrade_request', array( $this, 'process_upgrade_request' ) );
  75. // Register core upgrades.
  76. add_action( 'pum_register_upgrades', array( $this, 'register_processes' ) );
  77. // Initiate the upgrade registry. Must be done after versions update for proper comparisons.
  78. $this->registry = PUM_Upgrade_Registry::instance();
  79. }
  80. /**
  81. * Update version info.
  82. */
  83. public static function update_plugin_version() {
  84. self::$version = get_option( 'pum_ver' );
  85. self::$upgraded_from = get_option( 'pum_ver_upgraded_from' );
  86. self::$initial_version = get_option( 'pum_initial_version' );
  87. self::$db_version = get_option( 'pum_db_ver' );
  88. self::$installed_on = get_option( 'pum_installed_on' );
  89. /**
  90. * If no version set check if a deprecated one exists.
  91. */
  92. if ( empty( self::$version ) ) {
  93. $deprecated_ver = get_site_option( 'popmake_version' );
  94. // set to the deprecated version or last version that didn't have the version option set
  95. self::$version = $deprecated_ver ? $deprecated_ver : Popup_Maker::$VER; // Since we had versioning in v1 if there isn't one stored its a new install.
  96. update_option( 'pum_ver', self::$version );
  97. }
  98. /**
  99. * Back fill the initial version with the oldest version we can detect.
  100. */
  101. if ( ! self::$initial_version ) {
  102. $oldest_known = Popup_Maker::$VER;
  103. if ( self::$version && version_compare( self::$version, $oldest_known, '<' ) ) {
  104. $oldest_known = self::$version;
  105. }
  106. if ( self::$upgraded_from && version_compare( self::$upgraded_from, $oldest_known, '<' ) ) {
  107. $oldest_known = self::$upgraded_from;
  108. }
  109. $deprecated_ver = get_site_option( 'popmake_version' );
  110. if ( $deprecated_ver && version_compare( $deprecated_ver, $oldest_known, '<' ) ) {
  111. $oldest_known = $deprecated_ver;
  112. }
  113. $dep_upgraded_from = get_option( 'popmake_version_upgraded_from' );
  114. if ( $dep_upgraded_from && version_compare( $dep_upgraded_from, $oldest_known, '<' ) ) {
  115. $oldest_known = $dep_upgraded_from;
  116. }
  117. self::$initial_version = $oldest_known;
  118. // Only set this value if it doesn't exist.
  119. update_option( 'pum_initial_version', $oldest_known );
  120. }
  121. if ( version_compare( self::$version, Popup_Maker::$VER, '<' ) ) {
  122. // Allow processing of small core upgrades
  123. do_action( 'pum_update_core_version', self::$version );
  124. // Save Upgraded From option
  125. update_option( 'pum_ver_upgraded_from', self::$version );
  126. update_option( 'pum_ver', Popup_Maker::$VER );
  127. self::$upgraded_from = self::$version;
  128. self::$version = Popup_Maker::$VER;
  129. // Reset JS/CSS assets for regeneration.
  130. pum_reset_assets();
  131. } else if ( ! self::$upgraded_from || self::$upgraded_from === 'false' ) {
  132. // Here to prevent constant extra queries.
  133. self::$upgraded_from = '0.0.0';
  134. update_option( 'pum_ver_upgraded_from', self::$upgraded_from );
  135. }
  136. // If no current db version, but prior install detected, set db version correctly.
  137. // Here for backward compatibility.
  138. if ( ! self::$db_version || self::$db_version < Popup_Maker::$DB_VER ) {
  139. self::$db_version = Popup_Maker::$DB_VER;
  140. update_option( 'pum_db_ver', self::$db_version );
  141. }
  142. /**
  143. * Back fill the initial version with the oldest version we can detect.
  144. */
  145. if ( ! self::$installed_on ) {
  146. $installed_on = current_time( 'mysql' );
  147. $review_installed_on = get_option( 'pum_reviews_installed_on' );
  148. if ( ! empty( $review_installed_on ) ) {
  149. $installed_on = $review_installed_on;
  150. }
  151. self::$installed_on = $installed_on;
  152. update_option( 'pum_installed_on', self::$installed_on );
  153. }
  154. }
  155. /**
  156. * @param PUM_Upgrade_Registry $registry
  157. */
  158. public function register_processes( PUM_Upgrade_Registry $registry ) {
  159. // v1.7 Upgrades
  160. $registry->add_upgrade( 'core-v1_7-popups', array(
  161. 'rules' => array(
  162. version_compare( self::$initial_version, '1.7', '<' ),
  163. ),
  164. 'class' => 'PUM_Upgrade_v1_7_Popups',
  165. 'file' => Popup_Maker::$DIR . 'includes/batch/upgrade/class-upgrade-v1_7-popups.php',
  166. ) );
  167. $registry->add_upgrade( 'core-v1_7-settings', array(
  168. 'rules' => array(
  169. version_compare( self::$initial_version, '1.7', '<' ),
  170. ),
  171. 'class' => 'PUM_Upgrade_v1_7_Settings',
  172. 'file' => Popup_Maker::$DIR . 'includes/batch/upgrade/class-upgrade-v1_7-settings.php',
  173. ) );
  174. $registry->add_upgrade( 'core-v1_8-themes', array(
  175. 'rules' => array(
  176. $this->needs_v1_8_theme_upgrade(),
  177. ),
  178. 'class' => 'PUM_Upgrade_v1_8_Themes',
  179. 'file' => Popup_Maker::$DIR . 'includes/batch/upgrade/class-upgrade-v1_8-themes.php',
  180. ) );
  181. }
  182. /**
  183. * @return bool
  184. */
  185. public function needs_v1_8_theme_upgrade() {
  186. if ( pum_has_completed_upgrade( 'core-v1_8-themes' ) ) {
  187. return false;
  188. }
  189. $needs_upgrade = get_transient( 'pum_needs_1_8_theme_upgrades' );
  190. if ( $needs_upgrade === false ) {
  191. $query = new WP_Query( array(
  192. 'post_type' => 'popup_theme',
  193. 'post_status' => 'any',
  194. 'fields' => 'ids',
  195. 'meta_query' => array(
  196. 'relation' => 'OR',
  197. array(
  198. 'key' => 'popup_theme_data_version',
  199. 'compare' => 'NOT EXISTS',
  200. 'value' => 'deprecated', // Here for WP 3.9 or less.
  201. ),
  202. array(
  203. 'key' => 'popup_theme_data_version',
  204. 'compare' => '<',
  205. 'value' => 3,
  206. ),
  207. ),
  208. ) );
  209. $needs_upgrade = $query->post_count;
  210. }
  211. if ( $needs_upgrade <= 0 ) {
  212. pum_set_upgrade_complete( 'core-v1_8-themes' );
  213. delete_transient( 'pum_needs_1_8_theme_upgrades' );
  214. return false;
  215. }
  216. set_transient( 'pum_needs_1_8_theme_upgrades', $needs_upgrade );
  217. return (bool) $needs_upgrade;
  218. }
  219. /**
  220. * Registers a new upgrade routine.
  221. *
  222. * @param string $upgrade_id Upgrade ID.
  223. * @param array $args {
  224. * Arguments for registering a new upgrade routine.
  225. *
  226. * @type array $rules Array of true/false values.
  227. * @type string $class Batch processor class to use.
  228. * @type string $file File containing the upgrade processor class.
  229. * }
  230. *
  231. * @return bool True if the upgrade routine was added, otherwise false.
  232. */
  233. public function add_routine( $upgrade_id, $args ) {
  234. return $this->registry->add_upgrade( $upgrade_id, $args );
  235. }
  236. /**
  237. * Displays upgrade notices.
  238. */
  239. public function upgrade_notices() {
  240. if ( ! $this->has_uncomplete_upgrades() || ! current_user_can( 'manage_options' ) ) {
  241. return;
  242. }
  243. // Enqueue admin JS for the batch processor.
  244. wp_enqueue_script( 'pum-admin-batch' );
  245. wp_enqueue_style( 'pum-admin-batch' ); ?>
  246. <div class="notice notice-info is-dismissible">
  247. <?php $this->render_upgrade_notice(); ?>
  248. <?php $this->render_form(); ?>
  249. </div>
  250. <?php
  251. }
  252. /**
  253. * @param array $alerts
  254. *
  255. * @return array
  256. */
  257. public function upgrade_alert( $alerts = array() ) {
  258. if ( ! $this->has_uncomplete_upgrades() || ! current_user_can( 'manage_options' ) ) {
  259. return $alerts;
  260. }
  261. // Enqueue admin JS for the batch processor.
  262. wp_enqueue_script( 'pum-admin-batch' );
  263. wp_enqueue_style( 'pum-admin-batch' );
  264. ob_start();
  265. $this->render_upgrade_notice();
  266. $this->render_form();
  267. $html = ob_get_clean();
  268. $alerts[] = array(
  269. 'code' => 'upgrades_required',
  270. 'type' => 'warning',
  271. 'html' => $html,
  272. 'priority' => 1000,
  273. 'dismissible' => false,
  274. 'global' => true,
  275. );
  276. return $alerts;
  277. }
  278. /**
  279. * Renders the upgrade notification message.
  280. *
  281. * Message only, no form.
  282. */
  283. public function render_upgrade_notice() {
  284. $resume_upgrade = $this->maybe_resume_upgrade(); ?>
  285. <p class="pum-upgrade-notice">
  286. <?php
  287. if ( empty( $resume_upgrade ) ) { ?>
  288. <strong><?php _e( 'The latest version of Popup Maker requires changes to the Popup Maker settings saved on your site.', 'popup-maker' ); ?></strong>
  289. <?php
  290. } else {
  291. _e( 'Popup Maker needs to complete a the update of your settings that was previously started.', 'popup-maker' );
  292. } ?>
  293. </p>
  294. <?php
  295. }
  296. /**
  297. * Renders the upgrade processing form for reuse.
  298. */
  299. public function render_form() {
  300. $args = array(
  301. 'upgrade_id' => $this->get_current_upgrade_id(),
  302. 'step' => 1,
  303. );
  304. $resume_upgrade = $this->maybe_resume_upgrade();
  305. if ( $resume_upgrade && is_array( $resume_upgrade ) ) {
  306. $args = wp_parse_args( $resume_upgrade, $args );
  307. } ?>
  308. <form method="post" class="pum-form pum-batch-form pum-upgrade-form" data-ays="<?php _e( 'This can sometimes take a few minutes, are you ready to begin?', 'popup-maker' ); ?>" data-upgrade_id="<?php echo $args['upgrade_id']; ?>" data-step="<?php echo (int) $args['step']; ?>" data-nonce="<?php echo esc_attr( wp_create_nonce( 'pum_upgrade_ajax_nonce' ) ); ?>">
  309. <div class="pum-field pum-field-button pum-field-submit">
  310. <p>
  311. <small><?php _e( 'The button below will process these changes automatically for you.', 'popup-maker' ); ?></small>
  312. </p>
  313. <?php submit_button( ! empty( $resume_upgrade ) ? __( 'Finish Upgrades', 'popup-maker' ) : __( 'Process Changes', 'popup-maker' ), 'secondary', 'submit', false ); ?>
  314. </div>
  315. <div class="pum-batch-progress">
  316. <progress class="pum-overall-progress" max="100">
  317. <div class="progress-bar"><span></span></div>
  318. </progress>
  319. <progress class="pum-task-progress" max="100">
  320. <div class="progress-bar"><span></span></div>
  321. </progress>
  322. <div class="pum-upgrade-messages"></div>
  323. </div>
  324. </form>
  325. <?php
  326. }
  327. /**
  328. * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
  329. *
  330. * @return false|array When nothing to resume returns false, otherwise starts the upgrade where it left off
  331. */
  332. public function maybe_resume_upgrade() {
  333. $doing_upgrade = get_option( 'pum_doing_upgrade', array() );
  334. if ( empty( $doing_upgrade ) ) {
  335. return false;
  336. }
  337. return (array) $doing_upgrade;
  338. }
  339. /**
  340. * Retrieves an upgrade routine from the registry.
  341. *
  342. * @param string $upgrade_id Upgrade ID.
  343. *
  344. * @return array|false Upgrade entry from the registry, otherwise false.
  345. */
  346. public function get_routine( $upgrade_id ) {
  347. return $this->registry->get( $upgrade_id );
  348. }
  349. /**
  350. * Get all upgrade routines.
  351. *
  352. * Note: Unfiltered.
  353. *
  354. * @return array
  355. */
  356. public function get_routines() {
  357. return $this->registry->get_upgrades();
  358. }
  359. /**
  360. * Adds an upgrade action to the completed upgrades array
  361. *
  362. * @param string $upgrade_id The action to add to the competed upgrades array
  363. *
  364. * @return bool If the function was successfully added
  365. */
  366. public function set_upgrade_complete( $upgrade_id = '' ) {
  367. if ( empty( $upgrade_id ) ) {
  368. return false;
  369. }
  370. $completed_upgrades = $this->get_completed_upgrades();
  371. if ( ! in_array( $upgrade_id, $completed_upgrades ) ) {
  372. $completed_upgrades[] = $upgrade_id;
  373. do_action( 'pum_set_upgrade_complete', $upgrade_id );
  374. }
  375. // Remove any blanks, and only show uniques
  376. $completed_upgrades = array_unique( array_values( $completed_upgrades ) );
  377. return update_option( 'pum_completed_upgrades', $completed_upgrades );
  378. }
  379. /**
  380. * Get's the array of completed upgrade actions
  381. *
  382. * @return array The array of completed upgrades
  383. */
  384. public function get_completed_upgrades() {
  385. $completed_upgrades = get_option( 'pum_completed_upgrades' );
  386. if ( $completed_upgrades === false ) {
  387. $completed_upgrades = array();
  388. update_option( 'pum_completed_upgrades', $completed_upgrades );
  389. }
  390. return get_option( 'pum_completed_upgrades', array() );
  391. }
  392. /**
  393. * Check if the upgrade routine has been run for a specific action
  394. *
  395. * @param string $upgrade_id The upgrade action to check completion for
  396. *
  397. * @return bool If the action has been added to the completed actions array
  398. */
  399. public function has_completed_upgrade( $upgrade_id = '' ) {
  400. if ( empty( $upgrade_id ) ) {
  401. return false;
  402. }
  403. $completed_upgrades = $this->get_completed_upgrades();
  404. return in_array( $upgrade_id, $completed_upgrades, true );
  405. }
  406. /**
  407. * Conditional function to see if there are upgrades available.
  408. *
  409. * @return bool
  410. */
  411. public function has_uncomplete_upgrades() {
  412. return (bool) count( $this->get_uncompleted_upgrades() );
  413. }
  414. /**
  415. * Returns array of uncompleted upgrades.
  416. *
  417. * This doesn't return an upgrade if:
  418. * - It was previously complete.
  419. * - If any false values in the upgrades $rules array are found.
  420. *
  421. * @return array
  422. */
  423. public function get_uncompleted_upgrades() {
  424. $required_upgrades = $this->get_routines();
  425. foreach ( $required_upgrades as $upgrade_id => $upgrade ) {
  426. // If the upgrade has already completed or one of the rules failed remove it from the list.
  427. if ( $this->has_completed_upgrade( $upgrade_id ) || in_array( false, $upgrade['rules'], true ) ) {
  428. unset( $required_upgrades[ $upgrade_id ] );
  429. }
  430. }
  431. return $required_upgrades;
  432. }
  433. /**
  434. * Handles Ajax for processing a upgrade upgrade/que request.
  435. */
  436. public function process_upgrade_request() {
  437. $upgrade_id = isset( $_REQUEST['upgrade_id'] ) ? sanitize_key( $_REQUEST['upgrade_id'] ) : false;
  438. if ( ! $upgrade_id && ! $this->has_uncomplete_upgrades() ) {
  439. wp_send_json_error( array(
  440. 'error' => __( 'A batch process ID must be present to continue.', 'popup-maker' ),
  441. ) );
  442. }
  443. // Nonce.
  444. if ( ! check_ajax_referer( 'pum_upgrade_ajax_nonce', 'nonce' ) ) {
  445. wp_send_json_error( array(
  446. 'error' => __( 'You do not have permission to initiate this request. Contact an administrator for more information.', 'popup-maker' ),
  447. ) );
  448. }
  449. if ( ! $upgrade_id ) {
  450. $upgrade_id = $this->get_current_upgrade_id();
  451. }
  452. $step = ! empty( $_REQUEST['step'] ) ? absint( $_REQUEST['step'] ) : 1;
  453. /**
  454. * Instantiate the upgrade class.
  455. *
  456. * @var PUM_Interface_Batch_Process|PUM_Interface_Batch_PrefetchProcess $upgrade
  457. */
  458. $upgrade = $this->get_upgrade( $upgrade_id, $step );
  459. if ( $upgrade === false ) {
  460. wp_send_json_error( array(
  461. 'error' => sprintf( __( '%s is an invalid batch process ID.', 'popup-maker' ), esc_html( $upgrade_id ) ),
  462. ) );
  463. }
  464. /**
  465. * Garbage collect any old temporary data in the case step is 1.
  466. * Here to prevent case ajax passes step 1 without resetting process counts.
  467. */
  468. $first_step = $step < 2;
  469. if ( $first_step ) {
  470. $upgrade->finish();
  471. }
  472. $using_prefetch = ( $upgrade instanceof PUM_Interface_Batch_PrefetchProcess );
  473. // Handle pre-fetching data.
  474. if ( $using_prefetch ) {
  475. // Initialize any data needed to process a step.
  476. $data = isset( $_REQUEST['form'] ) ? $_REQUEST['form'] : array();
  477. $upgrade->init( $data );
  478. $upgrade->pre_fetch();
  479. }
  480. /** @var int|string|WP_Error $step */
  481. $step = $upgrade->process_step();
  482. if ( ! is_wp_error( $step ) ) {
  483. $response_data = array(
  484. 'step' => $step,
  485. 'next' => null,
  486. );
  487. // Finish and set the status flag if done.
  488. if ( 'done' === $step ) {
  489. $response_data['done'] = true;
  490. $response_data['message'] = $upgrade->get_message( 'done' );
  491. // Once all calculations have finished, run cleanup.
  492. $upgrade->finish();
  493. // Set the upgrade complete.
  494. pum_set_upgrade_complete( $upgrade_id );
  495. if ( $this->has_uncomplete_upgrades() ) {
  496. // Since the other was complete return the next (now current) upgrade_id.
  497. $response_data['next'] = $this->get_current_upgrade_id();
  498. }
  499. } else {
  500. $response_data['done'] = false;
  501. $response_data['message'] = $first_step ? $upgrade->get_message( 'start' ) : '';
  502. $response_data['percentage'] = $upgrade->get_percentage_complete();
  503. }
  504. wp_send_json_success( $response_data );
  505. } else {
  506. wp_send_json_error( $step );
  507. }
  508. }
  509. /**
  510. * Returns the first key in the uncompleted upgrades.
  511. *
  512. * @return string|null
  513. */
  514. public function get_current_upgrade_id() {
  515. $upgrades = $this->get_uncompleted_upgrades();
  516. reset( $upgrades );
  517. return key( $upgrades );
  518. }
  519. /**
  520. * Returns the current upgrade.
  521. *
  522. * @return bool|PUM_Interface_Batch_PrefetchProcess|PUM_Interface_Batch_Process
  523. */
  524. public function get_current_upgrade() {
  525. $upgrade_id = $this->get_current_upgrade_id();
  526. return $this->get_upgrade( $upgrade_id );
  527. }
  528. /**
  529. * Gets the upgrade process object.
  530. *
  531. * @param string $upgrade_id
  532. * @param int $step
  533. *
  534. * @return bool|PUM_Interface_Batch_Process|PUM_Interface_Batch_PrefetchProcess
  535. */
  536. public function get_upgrade( $upgrade_id = '', $step = 1 ) {
  537. $upgrade = $this->registry->get( $upgrade_id );
  538. if ( ! $upgrade ) {
  539. return false;
  540. }
  541. $class = isset( $upgrade['class'] ) ? sanitize_text_field( $upgrade['class'] ) : '';
  542. $class_file = isset( $upgrade['file'] ) ? $upgrade['file'] : '';
  543. if ( ! class_exists( $class ) && ! empty( $class_file ) && file_exists( $class_file ) ) {
  544. require_once $class_file;
  545. } else {
  546. wp_send_json_error( array(
  547. 'error' => sprintf( __( 'An invalid file path is registered for the %1$s batch process handler.', 'popup-maker' ), "<code>{$upgrade_id}</code>" ),
  548. ) );
  549. }
  550. if ( empty( $class ) || ! class_exists( $class ) ) {
  551. wp_send_json_error( array(
  552. 'error' => sprintf( __( '%1$s is an invalid handler for the %2$s batch process. Please try again.', 'popup-maker' ), "<code>{$class}</code>", "<code>{$upgrade_id}</code>" ),
  553. ) );
  554. }
  555. /**
  556. * @var PUM_Interface_Batch_Process|PUM_Interface_Batch_PrefetchProcess
  557. */
  558. return new $class( $step );
  559. }
  560. /**
  561. * Add upgrades tab to tools page if there are upgrades available.
  562. *
  563. * @param array $tabs
  564. *
  565. * @return array
  566. */
  567. public function tools_page_tabs( $tabs = array() ) {
  568. if ( $this->has_uncomplete_upgrades() ) {
  569. $tabs['upgrades'] = __( 'Upgrades', 'popup-maker' );
  570. }
  571. return $tabs;
  572. }
  573. /**
  574. * Renders upgrade form on the tools page upgrade tab.
  575. */
  576. public function tools_page_tab_content() {
  577. if ( ! $this->has_uncomplete_upgrades() ) {
  578. _e( 'No upgrades currently required.', 'popup-maker' );
  579. return;
  580. }
  581. // Enqueue admin JS for the batch processor.
  582. wp_enqueue_script( 'pum-admin-batch' );
  583. wp_enqueue_style( 'pum-admin-batch' );
  584. $this->render_upgrade_notice();
  585. $this->render_form();
  586. }
  587. }