PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.0
Jetpack – WP Security, Backup, Speed, & Growth v16.0
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / scan / class-admin-sidebar-link.php
class-admin-sidebar-link.php
263 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * A class that adds a scan and backup link to the admin sidebar.
4 *
5 * @package automattic/jetpack
6 */
7
8 namespace Automattic\Jetpack\Scan;
9
10 use Automattic\Jetpack\Admin_UI\Admin_Menu;
11 use Automattic\Jetpack\My_Jetpack\Products\Backup;
12 use Automattic\Jetpack\Redirect;
13 use Automattic\Jetpack\Status\Host;
14 use Jetpack_Core_Json_Api_Endpoints;
15
16 /**
17 * Class Main
18 *
19 * Responsible for showing the link if available.
20 *
21 * @package Automattic\Jetpack\Scan
22 */
23 class Admin_Sidebar_Link {
24
25 const SCHEDULE_ACTION_HOOK = 'jetpack_scan_refresh_states_event';
26
27 /**
28 * The singleton instance of this class.
29 *
30 * @var Admin_Sidebar_Link
31 */
32 protected static $instance;
33
34 /**
35 * Used to check if we need to schedule the refresh or we need to do it.
36 *
37 * @var boolean | null
38 */
39 private $schedule_refresh_checked;
40
41 /**
42 * Get the singleton instance of the class.
43 *
44 * @return Admin_Sidebar_Link
45 */
46 public static function instance() {
47 if ( ! isset( self::$instance ) ) {
48 self::$instance = new Admin_Sidebar_Link();
49 self::$instance->init_hooks();
50 }
51
52 return self::$instance;
53 }
54
55 /**
56 * Adds action hooks.
57 */
58 public function init_hooks() {
59 add_action( 'jetpack_admin_menu', array( $this, 'maybe_add_admin_link' ), 99 );
60 add_action( self::SCHEDULE_ACTION_HOOK, array( $this, 'refresh_state_cache' ) );
61 }
62
63 /**
64 * Adds a link to the Scan and Backup page.
65 */
66 public function maybe_add_admin_link() {
67 if ( ! $this->should_show_link() ) {
68 return;
69 }
70
71 if ( $this->should_show_scan() ) {
72 Admin_Menu::add_menu(
73 /** "Scan" is a product name, do not translate. */
74 'Scan',
75 'Scan <span aria-hidden="true">↗</span>',
76 'manage_options',
77 esc_url( Redirect::get_url( 'cloud-scan-history-wp-menu' ) ),
78 null,
79 $this->get_link_offset()
80 );
81 }
82
83 // Add scan item which shows history page only. This is mutally exclusive from the scan item above and is only shown for Atomic sitse.
84 if ( $this->should_show_scan_history_only() ) {
85 Admin_Menu::add_menu(
86 /** "Scan" is a product name, do not translate. */
87 'Scan',
88 'Scan <span aria-hidden="true">↗</span>',
89 'manage_options',
90 esc_url( Redirect::get_url( 'cloud-scan-history-wp-menu' ) ),
91 null,
92 $this->get_link_offset()
93 );
94 }
95
96 if ( $this->should_show_backup() ) {
97 Admin_Menu::add_menu(
98 /** "VaultPress Backup" is a product name, do not translate. */
99 'VaultPress Backup',
100 'VaultPress Backup <span aria-hidden="true">↗</span>',
101 'manage_options',
102 esc_url( Redirect::get_url( 'calypso-backups' ) ),
103 null,
104 $this->get_link_offset()
105 );
106 }
107 }
108
109 /**
110 * We create a menu offset by counting all the pages that have a jetpack_admin_page set as the capability.
111 *
112 * This makes it so that the highlight of the pages works as expected. When you click on the Setting or Dashboard.
113 *
114 * @return int Menu offset.
115 */
116 private function get_link_offset() {
117 global $submenu;
118 $offset = 17;
119
120 if ( ! array_key_exists( 'jetpack', $submenu ) ) {
121 return $offset;
122 }
123
124 foreach ( $submenu['jetpack'] as $link ) {
125 if ( 'jetpack_admin_page' !== $link[1] ) {
126 break;
127 }
128 ++$offset;
129 }
130
131 return $offset;
132 }
133
134 /**
135 * Refreshes the state cache via API call. Called via cron.
136 */
137 public function refresh_state_cache() {
138 Jetpack_Core_Json_Api_Endpoints::get_scan_state();
139 Jetpack_Core_Json_Api_Endpoints::get_rewind_data();
140 }
141
142 /**
143 * Returns true if the link should appear.
144 *
145 * @return boolean
146 */
147 private function should_show_link() {
148 // Jetpack Scan/Backup is currently not supported on multisite.
149 if ( is_multisite() ) {
150 return false;
151 }
152
153 // Check if VaultPress is active, the assumption there is that VaultPress is working.
154 // It has its link the adminbar.
155 if ( class_exists( 'VaultPress' ) ) {
156 return false;
157 }
158
159 return $this->should_show_scan() || $this->should_show_backup() || $this->should_show_scan_history_only();
160 }
161
162 /**
163 * Check if we should display the Scan menu item.
164 *
165 * It will only be displayed if site has Scan enabled, is not an Atomic site, and the stand-alone Protect plugin is not active, because it will have a menu item of its own.
166 *
167 * @return boolean
168 */
169 private function should_show_scan() {
170 return $this->has_scan() && ! $this->has_protect_plugin() && ! ( new Host() )->is_woa_site();
171 }
172
173 /**
174 * Check if we should display the Scan menu item history.
175 *
176 * It will only be displayed if site has Scan enabled, is an Atomic site.
177 *
178 * @return boolean
179 */
180 private function should_show_scan_history_only() {
181 return $this->has_scan() && ( new Host() )->is_woa_site() && get_option( 'wpcom_admin_interface' ) === 'wp-admin';
182 }
183
184 /**
185 * Check if we should display the Backup menu item.
186 *
187 * It will only be displayed if site has Backup enabled and the stand-alone Backup plugin is not active, because it will have a menu item of its own.
188 *
189 * @return boolean
190 */
191 private function should_show_backup() {
192 return $this->has_backup() && ! $this->has_backup_plugin();
193 }
194
195 /**
196 * Detects if Scan is enabled.
197 *
198 * @return boolean
199 */
200 private function has_scan() {
201 $this->maybe_refresh_transient_cache();
202 $scan_state = get_transient( 'jetpack_scan_state' );
203 if ( ! $scan_state ) {
204 return false;
205 }
206
207 return isset( $scan_state->state ) && 'unavailable' !== $scan_state->state;
208 }
209
210 /**
211 * Detects if Protect plugin is active.
212 *
213 * @return boolean
214 */
215 private function has_protect_plugin() {
216 return class_exists( 'Jetpack_Protect' );
217 }
218
219 /**
220 * Detects if Backup is enabled.
221 *
222 * @return boolean
223 */
224 private function has_backup() {
225 $this->maybe_refresh_transient_cache();
226 $rewind_state = get_transient( 'jetpack_rewind_state' );
227 if ( ! $rewind_state ) {
228 return false;
229 }
230
231 return isset( $rewind_state->state ) && 'unavailable' !== $rewind_state->state;
232 }
233
234 /**
235 * Detects if Backup plugin is active.
236 *
237 * @return boolean
238 */
239 private function has_backup_plugin() {
240 return Backup::is_standalone_plugin_active();
241 }
242
243 /**
244 * Triggers a cron job to refresh the Scan and Rewind state cache.
245 */
246 private function maybe_refresh_transient_cache() {
247 if ( $this->schedule_refresh_checked ) {
248 return;
249 }
250
251 // Do we have a jetpack_scan and jetpack_rewind state set?
252 if ( get_transient( 'jetpack_scan_state' ) && get_transient( 'jetpack_rewind_state' ) ) {
253 return;
254 }
255
256 if ( false === wp_next_scheduled( self::SCHEDULE_ACTION_HOOK ) ) {
257 wp_schedule_single_event( time(), self::SCHEDULE_ACTION_HOOK );
258 }
259
260 $this->schedule_refresh_checked = true;
261 }
262 }
263