No Description

class-admin-sidebar-link.php 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. /**
  3. * A class that adds a scan and backup link to the admin sidebar.
  4. *
  5. * @package automattic/jetpack
  6. */
  7. namespace Automattic\Jetpack\Scan;
  8. use Automattic\Jetpack\Redirect;
  9. use Jetpack_Core_Json_Api_Endpoints;
  10. /**
  11. * Class Main
  12. *
  13. * Responsible for showing the link if available.
  14. *
  15. * @package Automattic\Jetpack\Scan
  16. */
  17. class Admin_Sidebar_Link {
  18. const SCHEDULE_ACTION_HOOK = 'jetpack_scan_refresh_states_event';
  19. /**
  20. * The singleton instance of this class.
  21. *
  22. * @var Admin_Sidebar_Link
  23. */
  24. protected static $instance;
  25. /**
  26. * Used to check if we need to schedule the refresh or we need to do it.
  27. *
  28. * @var boolean | null
  29. */
  30. private $schedule_refresh_checked;
  31. /**
  32. * Get the singleton instance of the class.
  33. *
  34. * @return Admin_Sidebar_Link
  35. */
  36. public static function instance() {
  37. if ( ! isset( self::$instance ) ) {
  38. self::$instance = new Admin_Sidebar_Link();
  39. self::$instance->init_hooks();
  40. }
  41. return self::$instance;
  42. }
  43. /**
  44. * Adds action hooks.
  45. */
  46. public function init_hooks() {
  47. add_action( 'jetpack_admin_menu', array( $this, 'maybe_add_admin_link' ), 99 );
  48. add_action( self::SCHEDULE_ACTION_HOOK, array( $this, 'refresh_state_cache' ) );
  49. }
  50. /**
  51. * Adds a link to the Scan and Backup page.
  52. */
  53. public function maybe_add_admin_link() {
  54. if ( ! $this->should_show_link() ) {
  55. return;
  56. }
  57. $has_scan = $this->has_scan();
  58. $has_backup = $this->has_backup();
  59. $url = Redirect::get_url( 'calypso-backups' );
  60. if ( $has_scan && ! $has_backup ) {
  61. $menu_label = __( 'Scan', 'jetpack' );
  62. $url = Redirect::get_url( 'calypso-scanner' );
  63. } elseif ( ! $has_scan && $has_backup ) {
  64. $menu_label = __( 'Backup', 'jetpack' );
  65. } else {
  66. // Will be both, as the code won't get this far if neither is true.
  67. $menu_label = __( 'Backup & Scan', 'jetpack' );
  68. }
  69. add_submenu_page( 'jetpack', $menu_label, esc_html( $menu_label ) . ' <span class="dashicons dashicons-external"></span>', 'manage_options', esc_url( $url ), null, $this->get_link_offset() );
  70. }
  71. /**
  72. * We create a menu offset by counting all the pages that have a jetpack_admin_page set as the capability.
  73. *
  74. * This makes it so that the highlight of the pages works as expected. When you click on the Setting or Dashboard.
  75. *
  76. * @return int Menu offset.
  77. */
  78. private function get_link_offset() {
  79. global $submenu;
  80. $offset = 0;
  81. foreach ( $submenu['jetpack'] as $link ) {
  82. if ( 'jetpack_admin_page' !== $link[1] ) {
  83. break;
  84. }
  85. $offset++;
  86. }
  87. return $offset;
  88. }
  89. /**
  90. * Refreshes the state cache via API call. Called via cron.
  91. */
  92. public function refresh_state_cache() {
  93. Jetpack_Core_Json_Api_Endpoints::get_scan_state();
  94. Jetpack_Core_Json_Api_Endpoints::get_rewind_data();
  95. }
  96. /**
  97. * Returns true if the link should appear.
  98. *
  99. * @return boolean
  100. */
  101. private function should_show_link() {
  102. // Jetpack Scan/Backup is currently not supported on multisite.
  103. if ( is_multisite() ) {
  104. return false;
  105. }
  106. // Check if VaultPress is active, the assumption there is that VaultPress is working.
  107. // It has its link the adminbar.
  108. if ( class_exists( 'VaultPress' ) ) {
  109. return false;
  110. }
  111. return $this->has_backup() || $this->has_scan();
  112. }
  113. /**
  114. * Detects if Scan is enabled.
  115. *
  116. * @return boolean
  117. */
  118. private function has_scan() {
  119. $this->maybe_refresh_transient_cache();
  120. $scan_state = get_transient( 'jetpack_scan_state' );
  121. return ! $scan_state || 'unavailable' !== $scan_state->state;
  122. }
  123. /**
  124. * Detects if Backup is enabled.
  125. *
  126. * @return boolean
  127. */
  128. private function has_backup() {
  129. $this->maybe_refresh_transient_cache();
  130. $rewind_state = get_transient( 'jetpack_rewind_state' );
  131. return ! $rewind_state || 'unavailable' !== $rewind_state->state;
  132. }
  133. /**
  134. * Triggers a cron job to refresh the Scan and Rewind state cache.
  135. */
  136. private function maybe_refresh_transient_cache() {
  137. if ( $this->schedule_refresh_checked ) {
  138. return;
  139. }
  140. // Do we have a jetpack_scan and jetpack_rewind state set?
  141. if ( get_transient( 'jetpack_scan_state' ) && get_transient( 'jetpack_rewind_state' ) ) {
  142. return;
  143. }
  144. if ( false === wp_next_scheduled( self::SCHEDULE_ACTION_HOOK ) ) {
  145. wp_schedule_single_event( time(), self::SCHEDULE_ACTION_HOOK );
  146. }
  147. $this->schedule_refresh_checked = true;
  148. }
  149. }