PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 12.2.3
Jetpack – WP Security, Backup, Speed, & Growth v12.2.3
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 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / _inc / lib / class-jetpack-recommendations.php
jetpack / _inc / lib Last commit date
admin-pages 3 years ago core-api 3 years ago debugger 3 years ago markdown 4 years ago class-jetpack-ai-helper.php 3 years ago class-jetpack-currencies.php 5 years ago class-jetpack-google-drive-helper.php 3 years ago class-jetpack-instagram-gallery-helper.php 3 years ago class-jetpack-mapbox-helper.php 3 years ago class-jetpack-podcast-feed-locator.php 5 years ago class-jetpack-podcast-helper.php 3 years ago class-jetpack-recommendations.php 3 years ago class-jetpack-tweetstorm-helper.php 3 years ago class-jetpack-wizard.php 5 years ago class.color.php 4 years ago class.core-rest-api-endpoints.php 3 years ago class.jetpack-automatic-install-skin.php 4 years ago class.jetpack-iframe-embed.php 4 years ago class.jetpack-keyring-service-helper.php 3 years ago class.jetpack-password-checker.php 3 years ago class.jetpack-search-performance-logger.php 4 years ago class.media-extractor.php 3 years ago class.media-summary.php 3 years ago class.media.php 3 years ago components.php 3 years ago debugger.php 4 years ago functions.wp-notify.php 3 years ago icalendar-reader.php 3 years ago markdown.php 3 years ago plans.php 4 years ago plugins.php 4 years ago tonesque.php 3 years ago widgets.php 4 years ago
class-jetpack-recommendations.php
493 lines
1 <?php
2 /**
3 * Utilities related to the Jetpack Recommendations
4 *
5 * @package automattic/jetpack
6 */
7
8 use Automattic\Jetpack\Connection\Client;
9 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
10 use Automattic\Jetpack\Plugins_Installer;
11 use Automattic\Jetpack\Status;
12 use Automattic\Jetpack\Status\Host;
13
14 /**
15 * Contains utilities related to the Jetpack Recommendations.
16 *
17 * @package automattic/jetpack
18 */
19
20 /**
21 * Jetpack_Recommendations class
22 */
23 class Jetpack_Recommendations {
24 const PUBLICIZE_RECOMMENDATION = 'publicize';
25 const PROTECT_RECOMMENDATION = 'protect';
26 const ANTI_SPAM_RECOMMENDATION = 'anti-spam';
27 const VIDEOPRESS_RECOMMENDATION = 'videopress';
28 const BACKUP_PLAN_RECOMMENDATION = 'backup-plan';
29 const BOOST_RECOMMENDATION = 'boost';
30
31 const CONDITIONAL_RECOMMENDATIONS_OPTION = 'recommendations_conditional';
32 const CONDITIONAL_RECOMMENDATIONS = array(
33 self::PUBLICIZE_RECOMMENDATION,
34 self::PROTECT_RECOMMENDATION,
35 self::ANTI_SPAM_RECOMMENDATION,
36 self::VIDEOPRESS_RECOMMENDATION,
37 self::BACKUP_PLAN_RECOMMENDATION,
38 self::BOOST_RECOMMENDATION,
39 );
40
41 const VIDEOPRESS_TIMED_ACTION = 'jetpack_recommend_videopress';
42
43 /**
44 * Returns a boolean indicating if the Jetpack Recommendations are enabled.
45 *
46 * @since 9.3.0
47 *
48 * @return bool
49 */
50 public static function is_enabled() {
51 // Shortcircuit early if Jetpack is not active or we are in offline mode.
52 if ( ! Jetpack::is_connection_ready() || ( new Status() )->is_offline_mode() ) {
53 return false;
54 }
55
56 // No recommendations for Atomic sites, they already get onboarded in Calypso.
57 if ( ( new Host() )->is_woa_site() ) {
58 return false;
59 }
60
61 self::initialize_jetpack_recommendations();
62
63 return true;
64 }
65
66 /**
67 * Returns a boolean indicating if the Jetpack Banner is enabled.
68 *
69 * @since 9.3.0
70 *
71 * @return bool
72 */
73 public static function is_banner_enabled() {
74 // Shortcircuit early if the recommendations are not enabled at all.
75 if ( ! self::is_enabled() ) {
76 return false;
77 }
78
79 $recommendations_banner_enabled = Jetpack_Options::get_option( 'recommendations_banner_enabled', null );
80
81 // If the option is already set, just return the cached value.
82 // Otherwise calculate it and store it before returning it.
83 if ( null !== $recommendations_banner_enabled ) {
84 return $recommendations_banner_enabled;
85 }
86
87 if ( ! Jetpack::connection()->is_connected() ) {
88 return new WP_Error( 'site_not_connected', esc_html__( 'Site not connected.', 'jetpack' ) );
89 }
90
91 $blog_id = Jetpack_Options::get_option( 'id' );
92
93 $request_path = sprintf( '/sites/%s/jetpack-recommendations/site-registered-date', $blog_id );
94 $result = Client::wpcom_json_api_request_as_blog(
95 $request_path,
96 2,
97 array(
98 'headers' => array( 'content-type' => 'application/json' ),
99 ),
100 null,
101 'wpcom'
102 );
103
104 $body = json_decode( wp_remote_retrieve_body( $result ) );
105 if ( 200 === wp_remote_retrieve_response_code( $result ) ) {
106 $site_registered_date = $body->site_registered_date;
107 } else {
108 $connection = new Connection_Manager( 'jetpack' );
109 $site_registered_date = $connection->get_assumed_site_creation_date();
110 }
111
112 $recommendations_start_date = gmdate( 'Y-m-d H:i:s', strtotime( '2020-12-01 00:00:00' ) );
113 $recommendations_banner_enabled = $site_registered_date > $recommendations_start_date;
114
115 Jetpack_Options::update_option( 'recommendations_banner_enabled', $recommendations_banner_enabled );
116
117 return $recommendations_banner_enabled;
118 }
119
120 /**
121 * Set up actions to monitor for things that trigger a recommendation.
122 *
123 * @return false|void
124 */
125 public static function init_conditional_recommendation_actions() {
126 // Check to make sure that recommendations are enabled.
127 if ( ! self::is_enabled() ) {
128 return false;
129 }
130
131 // Monitor for the publishing of a new post.
132 add_action( 'transition_post_status', array( get_called_class(), 'post_transition' ), 10, 3 );
133 add_action( 'jetpack_activate_module', array( get_called_class(), 'jetpack_module_activated' ), 10, 2 );
134
135 // Monitor for activating a new plugin.
136 add_action( 'activated_plugin', array( get_called_class(), 'plugin_activated' ), 10 );
137
138 // Monitor for the addition of a new comment.
139 add_action( 'comment_post', array( get_called_class(), 'comment_added' ), 10, 3 );
140
141 // Monitor for Jetpack connection success.
142 add_action( 'jetpack_authorize_ending_authorized', array( get_called_class(), 'jetpack_connected' ) );
143 add_action( self::VIDEOPRESS_TIMED_ACTION, array( get_called_class(), 'recommend_videopress' ) );
144
145 // Monitor for changes in plugins that have auto-updates enabled
146 add_action( 'update_site_option_auto_update_plugins', array( get_called_class(), 'plugin_auto_update_settings_changed' ), 10, 3 );
147 }
148
149 /**
150 * Check when Jetpack modules are activated if some recommendations should be skipped.
151 *
152 * @param string $module Name of the module activated.
153 * @param bool $success Whether the module activation was successful.
154 */
155 public static function jetpack_module_activated( $module, $success ) {
156 if ( 'publicize' === $module && $success ) {
157 self::disable_conditional_recommendation( self::PUBLICIZE_RECOMMENDATION );
158 } elseif ( 'videopress' === $module && $success ) {
159 // If VideoPress is enabled and a recommendation for it is scheduled, cancel that recommendation.
160 $recommendation_timestamp = wp_next_scheduled( self::VIDEOPRESS_TIMED_ACTION );
161 if ( false !== $recommendation_timestamp ) {
162 wp_unschedule_event( $recommendation_timestamp, self::VIDEOPRESS_TIMED_ACTION );
163 }
164 }
165 }
166
167 /**
168 * Hook for transition_post_status that checks for the publishing of a new post or page.
169 * Used to enable the publicize and boost recommendations.
170 *
171 * @param string $new_status new status of post.
172 * @param string $old_status old status of post.
173 * @param WP_Post $post the post object being updated.
174 */
175 public static function post_transition( $new_status, $old_status, $post ) {
176 // Check for condition when post has been published.
177 if ( 'post' === $post->post_type && 'publish' === $new_status && 'publish' !== $old_status && ! Jetpack::is_module_active( 'publicize' ) ) {
178 // Set the publicize recommendation to have met criteria to be shown.
179 self::enable_conditional_recommendation( self::PUBLICIZE_RECOMMENDATION );
180 return;
181 }
182 // A new page has been published
183 // Check to see if the boost plugin is active
184 if (
185 'page' === $post->post_type &&
186 'publish' === $new_status &&
187 'publish' !== $old_status &&
188 ! Plugins_Installer::is_plugin_active( 'boost/jetpack-boost.php' ) &&
189 ! Plugins_Installer::is_plugin_active( 'jetpack-boost/jetpack-boost.php' )
190 ) {
191 self::enable_conditional_recommendation( self::BOOST_RECOMMENDATION );
192 }
193 }
194
195 /**
196 * Runs when a plugin gets activated
197 *
198 * @param string $plugin Path to the plugins file relative to the plugins directory.
199 */
200 public static function plugin_activated( $plugin ) {
201 // If the plugin is in this list, don't enable the recommendation.
202 $plugin_whitelist = array(
203 'jetpack.php',
204 'akismet.php',
205 'creative-mail.php',
206 'jetpack-backup.php',
207 'jetpack-boost.php',
208 'jetpack-protect.php',
209 'crowdsignal.php',
210 'vaultpress.php',
211 'woocommerce.php',
212 );
213
214 $path_parts = explode( '/', $plugin );
215 $plugin_file = $path_parts ? array_pop( $path_parts ) : $plugin;
216
217 if ( ! in_array( $plugin_file, $plugin_whitelist, true ) ) {
218 $products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
219
220 // Check for a plan or product that enables scan.
221 $plan_supports_scan = Jetpack_Plan::supports( 'scan' );
222 $has_scan_product = count( array_intersect( array( 'jetpack_scan', 'jetpack_scan_monthly' ), $products ) ) > 0;
223 $has_scan = $plan_supports_scan || $has_scan_product;
224
225 // Check if Jetpack Protect plugin is already active.
226 $has_protect = Plugins_Installer::is_plugin_active( 'jetpack-protect/jetpack-protect.php' ) || Plugins_Installer::is_plugin_active( 'protect/jetpack-protect.php' );
227
228 if ( ! $has_scan && ! $has_protect ) {
229 self::enable_conditional_recommendation( self::PROTECT_RECOMMENDATION );
230 }
231 }
232 }
233
234 /**
235 * Runs when the auto_update_plugins option has been changed
236 *
237 * @param string $option_name - the name of the option updated ( always auto_update_plugins ).
238 * @param array $new_auto_update_plugins - plugins that have auto update enabled following the change.
239 * @param array $old_auto_update_plugins - plugins that had auto update enabled before the most recent change.
240 * @return void
241 */
242 public static function plugin_auto_update_settings_changed( $option_name, $new_auto_update_plugins, $old_auto_update_plugins ) {
243 if (
244 is_multisite() ||
245 self::is_conditional_recommendation_enabled( self::BACKUP_PLAN_RECOMMENDATION )
246 ) {
247 return;
248 }
249
250 // Look for plugins that have had auto-update enabled in this most recent update.
251 $enabled_auto_updates = array_diff( $new_auto_update_plugins, $old_auto_update_plugins );
252 if ( ! empty( $enabled_auto_updates ) ) {
253 // Check the backup state.
254 $rewind_state = get_transient( 'jetpack_rewind_state' );
255 $has_backup = $rewind_state && in_array( $rewind_state->state, array( 'awaiting_credentials', 'provisioning', 'active' ), true );
256
257 if ( ! $has_backup ) {
258 self::enable_conditional_recommendation( self::BACKUP_PLAN_RECOMMENDATION );
259 }
260 }
261 }
262
263 /**
264 * Runs when a new comment is added.
265 *
266 * @param integer $comment_id The ID of the comment that was added.
267 * @param bool $comment_approved Whether or not the comment is approved.
268 * @param array $commentdata Comment data.
269 */
270 public static function comment_added( $comment_id, $comment_approved, $commentdata ) {
271 if ( self::is_conditional_recommendation_enabled( self::ANTI_SPAM_RECOMMENDATION ) ) {
272 return;
273 }
274
275 if ( Plugins_Installer::is_plugin_active( 'akismet/akismet.php' ) ) {
276 return;
277 }
278
279 // The site has anti-spam features already.
280 $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
281 $has_anti_spam_product = count( array_intersect( array( 'jetpack_anti_spam', 'jetpack_anti_spam_monthly' ), $site_products ) ) > 0;
282
283 if ( Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) {
284 return;
285 }
286
287 if ( isset( $commentdata['comment_post_ID'] ) ) {
288 $post_id = $commentdata['comment_post_ID'];
289 } else {
290 $comment = get_comment( $comment_id );
291 $post_id = $comment->comment_post_ID;
292 }
293 $comment_count = get_comments_number( $post_id );
294
295 if ( intval( $comment_count ) >= 5 ) {
296 self::enable_conditional_recommendation( self::ANTI_SPAM_RECOMMENDATION );
297 }
298 }
299
300 /**
301 * Runs after a successful connection is made.
302 */
303 public static function jetpack_connected() {
304 // Schedule a recommendation for VideoPress in 2 weeks.
305 if ( false === wp_next_scheduled( self::VIDEOPRESS_TIMED_ACTION ) ) {
306 $date = new DateTime();
307 $date->add( new DateInterval( 'P14D' ) );
308 wp_schedule_single_event( $date->getTimestamp(), self::VIDEOPRESS_TIMED_ACTION );
309 }
310 }
311
312 /**
313 * Enable a recommendation for VideoPress.
314 */
315 public static function recommend_videopress() {
316 // Check to see if the VideoPress recommendation is already enabled.
317 if ( self::is_conditional_recommendation_enabled( self::VIDEOPRESS_RECOMMENDATION ) ) {
318 return;
319 }
320
321 $site_plan = Jetpack_Plan::get();
322 $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
323
324 if ( self::should_recommend_videopress( $site_plan, $site_products ) ) {
325 self::enable_conditional_recommendation( self::VIDEOPRESS_RECOMMENDATION );
326 }
327 }
328
329 /**
330 * Should we provide a recommendation for videopress?
331 * This method exists to facilitate unit testing
332 *
333 * @param array $site_plan A representation of the site's plan.
334 * @param array $site_products An array of product slugs.
335 * @return boolean
336 */
337 public static function should_recommend_videopress( $site_plan, $site_products ) {
338 // Does the site have the VideoPress module enabled?
339 if ( Jetpack::is_module_active( 'videopress' ) ) {
340 return false;
341 }
342
343 // Does the site plan have upgraded videopress features?
344 // For now, this just checks to see if the site has a free plan.
345 // Jetpack_Plan::supports('videopress') returns true for all plans, since there is a free tier.
346 $is_free_plan = 'free' === $site_plan['class'];
347 if ( ! $is_free_plan ) {
348 return false;
349 }
350
351 // Does this site already have a VideoPress product?
352 $has_videopress_product = count( array_intersect( array( 'jetpack_videopress', 'jetpack_videopress_monthly' ), $site_products ) ) > 0;
353 if ( $has_videopress_product ) {
354 return false;
355 }
356
357 return true;
358 }
359
360 /**
361 * Enable a recommendation.
362 *
363 * @param string $recommendation_name The name of the recommendation to enable.
364 * @return false|void
365 */
366 public static function enable_conditional_recommendation( $recommendation_name ) {
367 if ( ! in_array( $recommendation_name, self::CONDITIONAL_RECOMMENDATIONS, true ) ) {
368 return false;
369 }
370
371 $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
372 if ( ! in_array( $recommendation_name, $conditional_recommendations, true ) ) {
373 $conditional_recommendations[] = $recommendation_name;
374 Jetpack_Options::update_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, $conditional_recommendations );
375 }
376 }
377
378 /**
379 * Disable a recommendation.
380 *
381 * @param string $recommendation_name The name of the recommendation to disable.
382 * @return false|void
383 */
384 public static function disable_conditional_recommendation( $recommendation_name ) {
385 if ( ! in_array( $recommendation_name, self::CONDITIONAL_RECOMMENDATIONS, true ) ) {
386 return false;
387 }
388
389 $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
390 $recommendation_index = array_search( $recommendation_name, $conditional_recommendations, true );
391
392 if ( false !== $recommendation_index ) {
393 array_splice( $conditional_recommendations, $recommendation_index, 1 );
394 Jetpack_Options::update_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, $conditional_recommendations );
395 }
396 }
397
398 /**
399 * Check to see if a recommendation is enabled or not.
400 *
401 * @param string $recommendation_name The name of the recommendation to check for.
402 * @return bool
403 */
404 public static function is_conditional_recommendation_enabled( $recommendation_name ) {
405 $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
406 return in_array( $recommendation_name, $conditional_recommendations, true );
407 }
408
409 /**
410 * Gets data for all conditional recommendations.
411 *
412 * @return mixed
413 */
414 public static function get_conditional_recommendations() {
415 return Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
416 }
417
418 /**
419 * Get an array of new conditional recommendations that have not been viewed.
420 *
421 * @return array
422 */
423 public static function get_new_conditional_recommendations() {
424 $conditional_recommendations = self::get_conditional_recommendations();
425 $recommendations_data = Jetpack_Options::get_option( 'recommendations_data', array() );
426 $viewed_recommendations = isset( $recommendations_data['viewedRecommendations'] ) ? $recommendations_data['viewedRecommendations'] : array();
427
428 // array_diff returns a keyed array - reduce to unique values.
429 return array_unique( array_values( array_diff( $conditional_recommendations, $viewed_recommendations ) ) );
430 }
431
432 /**
433 * Initializes the Recommendations step according to the Setup Wizard state.
434 */
435 private static function initialize_jetpack_recommendations() {
436 if ( Jetpack_Options::get_option( 'recommendations_step' ) ) {
437 return;
438 }
439
440 $setup_wizard_status = Jetpack_Options::get_option( 'setup_wizard_status' );
441 if ( 'completed' === $setup_wizard_status ) {
442 Jetpack_Options::update_option( 'recommendations_banner_enabled', false );
443 Jetpack_Options::update_option( 'recommendations_step', 'setup-wizard-completed' );
444 }
445 }
446
447 /**
448 * Get the data for the recommendations
449 *
450 * @return array Recommendations data
451 */
452 public static function get_recommendations_data() {
453 self::initialize_jetpack_recommendations();
454
455 return Jetpack_Options::get_option( 'recommendations_data', array() );
456 }
457
458 /**
459 * Update the data for the recommendations
460 *
461 * @param WP_REST_Request $data The data.
462 */
463 public static function update_recommendations_data( $data ) {
464 if ( ! empty( $data ) ) {
465 Jetpack_Options::update_option( 'recommendations_data', $data );
466 }
467 }
468
469 /**
470 * Get the data for the recommendations
471 *
472 * @return array Recommendations data
473 */
474 public static function get_recommendations_step() {
475 self::initialize_jetpack_recommendations();
476
477 return array(
478 'step' => Jetpack_Options::get_option( 'recommendations_step', 'not-started' ),
479 );
480 }
481
482 /**
483 * Update the step for the recommendations
484 *
485 * @param WP_REST_Request $step The step.
486 */
487 public static function update_recommendations_step( $step ) {
488 if ( ! empty( $step ) ) {
489 Jetpack_Options::update_option( 'recommendations_step', $step );
490 }
491 }
492 }
493