PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 12.5.2
Jetpack – WP Security, Backup, Speed, & Growth v12.5.2
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 3 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
494 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\Current_Plan as Jetpack_Plan;
11 use Automattic\Jetpack\Plugins_Installer;
12 use Automattic\Jetpack\Status;
13 use Automattic\Jetpack\Status\Host;
14
15 /**
16 * Contains utilities related to the Jetpack Recommendations.
17 *
18 * @package automattic/jetpack
19 */
20
21 /**
22 * Jetpack_Recommendations class
23 */
24 class Jetpack_Recommendations {
25 const PUBLICIZE_RECOMMENDATION = 'publicize';
26 const PROTECT_RECOMMENDATION = 'protect';
27 const ANTI_SPAM_RECOMMENDATION = 'anti-spam';
28 const VIDEOPRESS_RECOMMENDATION = 'videopress';
29 const BACKUP_PLAN_RECOMMENDATION = 'backup-plan';
30 const BOOST_RECOMMENDATION = 'boost';
31
32 const CONDITIONAL_RECOMMENDATIONS_OPTION = 'recommendations_conditional';
33 const CONDITIONAL_RECOMMENDATIONS = array(
34 self::PUBLICIZE_RECOMMENDATION,
35 self::PROTECT_RECOMMENDATION,
36 self::ANTI_SPAM_RECOMMENDATION,
37 self::VIDEOPRESS_RECOMMENDATION,
38 self::BACKUP_PLAN_RECOMMENDATION,
39 self::BOOST_RECOMMENDATION,
40 );
41
42 const VIDEOPRESS_TIMED_ACTION = 'jetpack_recommend_videopress';
43
44 /**
45 * Returns a boolean indicating if the Jetpack Recommendations are enabled.
46 *
47 * @since 9.3.0
48 *
49 * @return bool
50 */
51 public static function is_enabled() {
52 // Shortcircuit early if Jetpack is not active or we are in offline mode.
53 if ( ! Jetpack::is_connection_ready() || ( new Status() )->is_offline_mode() ) {
54 return false;
55 }
56
57 // No recommendations for Atomic sites, they already get onboarded in Calypso.
58 if ( ( new Host() )->is_woa_site() ) {
59 return false;
60 }
61
62 self::initialize_jetpack_recommendations();
63
64 return true;
65 }
66
67 /**
68 * Returns a boolean indicating if the Jetpack Banner is enabled.
69 *
70 * @since 9.3.0
71 *
72 * @return bool
73 */
74 public static function is_banner_enabled() {
75 // Shortcircuit early if the recommendations are not enabled at all.
76 if ( ! self::is_enabled() ) {
77 return false;
78 }
79
80 $recommendations_banner_enabled = Jetpack_Options::get_option( 'recommendations_banner_enabled', null );
81
82 // If the option is already set, just return the cached value.
83 // Otherwise calculate it and store it before returning it.
84 if ( null !== $recommendations_banner_enabled ) {
85 return $recommendations_banner_enabled;
86 }
87
88 if ( ! Jetpack::connection()->is_connected() ) {
89 return new WP_Error( 'site_not_connected', esc_html__( 'Site not connected.', 'jetpack' ) );
90 }
91
92 $blog_id = Jetpack_Options::get_option( 'id' );
93
94 $request_path = sprintf( '/sites/%s/jetpack-recommendations/site-registered-date', $blog_id );
95 $result = Client::wpcom_json_api_request_as_blog(
96 $request_path,
97 2,
98 array(
99 'headers' => array( 'content-type' => 'application/json' ),
100 ),
101 null,
102 'wpcom'
103 );
104
105 $body = json_decode( wp_remote_retrieve_body( $result ) );
106 if ( 200 === wp_remote_retrieve_response_code( $result ) ) {
107 $site_registered_date = $body->site_registered_date;
108 } else {
109 $connection = new Connection_Manager( 'jetpack' );
110 $site_registered_date = $connection->get_assumed_site_creation_date();
111 }
112
113 $recommendations_start_date = gmdate( 'Y-m-d H:i:s', strtotime( '2020-12-01 00:00:00' ) );
114 $recommendations_banner_enabled = $site_registered_date > $recommendations_start_date;
115
116 Jetpack_Options::update_option( 'recommendations_banner_enabled', $recommendations_banner_enabled );
117
118 return $recommendations_banner_enabled;
119 }
120
121 /**
122 * Set up actions to monitor for things that trigger a recommendation.
123 *
124 * @return false|void
125 */
126 public static function init_conditional_recommendation_actions() {
127 // Check to make sure that recommendations are enabled.
128 if ( ! self::is_enabled() ) {
129 return false;
130 }
131
132 // Monitor for the publishing of a new post.
133 add_action( 'transition_post_status', array( static::class, 'post_transition' ), 10, 3 );
134 add_action( 'jetpack_activate_module', array( static::class, 'jetpack_module_activated' ), 10, 2 );
135
136 // Monitor for activating a new plugin.
137 add_action( 'activated_plugin', array( static::class, 'plugin_activated' ), 10 );
138
139 // Monitor for the addition of a new comment.
140 add_action( 'comment_post', array( static::class, 'comment_added' ), 10, 3 );
141
142 // Monitor for Jetpack connection success.
143 add_action( 'jetpack_authorize_ending_authorized', array( static::class, 'jetpack_connected' ) );
144 add_action( self::VIDEOPRESS_TIMED_ACTION, array( static::class, 'recommend_videopress' ) );
145
146 // Monitor for changes in plugins that have auto-updates enabled
147 add_action( 'update_site_option_auto_update_plugins', array( static::class, 'plugin_auto_update_settings_changed' ), 10, 3 );
148 }
149
150 /**
151 * Check when Jetpack modules are activated if some recommendations should be skipped.
152 *
153 * @param string $module Name of the module activated.
154 * @param bool $success Whether the module activation was successful.
155 */
156 public static function jetpack_module_activated( $module, $success ) {
157 if ( 'publicize' === $module && $success ) {
158 self::disable_conditional_recommendation( self::PUBLICIZE_RECOMMENDATION );
159 } elseif ( 'videopress' === $module && $success ) {
160 // If VideoPress is enabled and a recommendation for it is scheduled, cancel that recommendation.
161 $recommendation_timestamp = wp_next_scheduled( self::VIDEOPRESS_TIMED_ACTION );
162 if ( false !== $recommendation_timestamp ) {
163 wp_unschedule_event( $recommendation_timestamp, self::VIDEOPRESS_TIMED_ACTION );
164 }
165 }
166 }
167
168 /**
169 * Hook for transition_post_status that checks for the publishing of a new post or page.
170 * Used to enable the publicize and boost recommendations.
171 *
172 * @param string $new_status new status of post.
173 * @param string $old_status old status of post.
174 * @param WP_Post $post the post object being updated.
175 */
176 public static function post_transition( $new_status, $old_status, $post ) {
177 // Check for condition when post has been published.
178 if ( 'post' === $post->post_type && 'publish' === $new_status && 'publish' !== $old_status && ! Jetpack::is_module_active( 'publicize' ) ) {
179 // Set the publicize recommendation to have met criteria to be shown.
180 self::enable_conditional_recommendation( self::PUBLICIZE_RECOMMENDATION );
181 return;
182 }
183 // A new page has been published
184 // Check to see if the boost plugin is active
185 if (
186 'page' === $post->post_type &&
187 'publish' === $new_status &&
188 'publish' !== $old_status &&
189 ! Plugins_Installer::is_plugin_active( 'boost/jetpack-boost.php' ) &&
190 ! Plugins_Installer::is_plugin_active( 'jetpack-boost/jetpack-boost.php' )
191 ) {
192 self::enable_conditional_recommendation( self::BOOST_RECOMMENDATION );
193 }
194 }
195
196 /**
197 * Runs when a plugin gets activated
198 *
199 * @param string $plugin Path to the plugins file relative to the plugins directory.
200 */
201 public static function plugin_activated( $plugin ) {
202 // If the plugin is in this list, don't enable the recommendation.
203 $plugin_whitelist = array(
204 'jetpack.php',
205 'akismet.php',
206 'creative-mail.php',
207 'jetpack-backup.php',
208 'jetpack-boost.php',
209 'jetpack-protect.php',
210 'crowdsignal.php',
211 'vaultpress.php',
212 'woocommerce.php',
213 );
214
215 $path_parts = explode( '/', $plugin );
216 $plugin_file = $path_parts ? array_pop( $path_parts ) : $plugin;
217
218 if ( ! in_array( $plugin_file, $plugin_whitelist, true ) ) {
219 $products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
220
221 // Check for a plan or product that enables scan.
222 $plan_supports_scan = Jetpack_Plan::supports( 'scan' );
223 $has_scan_product = count( array_intersect( array( 'jetpack_scan', 'jetpack_scan_monthly' ), $products ) ) > 0;
224 $has_scan = $plan_supports_scan || $has_scan_product;
225
226 // Check if Jetpack Protect plugin is already active.
227 $has_protect = Plugins_Installer::is_plugin_active( 'jetpack-protect/jetpack-protect.php' ) || Plugins_Installer::is_plugin_active( 'protect/jetpack-protect.php' );
228
229 if ( ! $has_scan && ! $has_protect ) {
230 self::enable_conditional_recommendation( self::PROTECT_RECOMMENDATION );
231 }
232 }
233 }
234
235 /**
236 * Runs when the auto_update_plugins option has been changed
237 *
238 * @param string $option_name - the name of the option updated ( always auto_update_plugins ).
239 * @param array $new_auto_update_plugins - plugins that have auto update enabled following the change.
240 * @param array $old_auto_update_plugins - plugins that had auto update enabled before the most recent change.
241 * @return void
242 */
243 public static function plugin_auto_update_settings_changed( $option_name, $new_auto_update_plugins, $old_auto_update_plugins ) {
244 if (
245 is_multisite() ||
246 self::is_conditional_recommendation_enabled( self::BACKUP_PLAN_RECOMMENDATION )
247 ) {
248 return;
249 }
250
251 // Look for plugins that have had auto-update enabled in this most recent update.
252 $enabled_auto_updates = array_diff( $new_auto_update_plugins, $old_auto_update_plugins );
253 if ( ! empty( $enabled_auto_updates ) ) {
254 // Check the backup state.
255 $rewind_state = get_transient( 'jetpack_rewind_state' );
256 $has_backup = $rewind_state && in_array( $rewind_state->state, array( 'awaiting_credentials', 'provisioning', 'active' ), true );
257
258 if ( ! $has_backup ) {
259 self::enable_conditional_recommendation( self::BACKUP_PLAN_RECOMMENDATION );
260 }
261 }
262 }
263
264 /**
265 * Runs when a new comment is added.
266 *
267 * @param integer $comment_id The ID of the comment that was added.
268 * @param bool $comment_approved Whether or not the comment is approved.
269 * @param array $commentdata Comment data.
270 */
271 public static function comment_added( $comment_id, $comment_approved, $commentdata ) {
272 if ( self::is_conditional_recommendation_enabled( self::ANTI_SPAM_RECOMMENDATION ) ) {
273 return;
274 }
275
276 if ( Plugins_Installer::is_plugin_active( 'akismet/akismet.php' ) ) {
277 return;
278 }
279
280 // The site has anti-spam features already.
281 $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
282 $has_anti_spam_product = count( array_intersect( array( 'jetpack_anti_spam', 'jetpack_anti_spam_monthly' ), $site_products ) ) > 0;
283
284 if ( Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) {
285 return;
286 }
287
288 if ( isset( $commentdata['comment_post_ID'] ) ) {
289 $post_id = $commentdata['comment_post_ID'];
290 } else {
291 $comment = get_comment( $comment_id );
292 $post_id = $comment->comment_post_ID;
293 }
294 $comment_count = get_comments_number( $post_id );
295
296 if ( intval( $comment_count ) >= 5 ) {
297 self::enable_conditional_recommendation( self::ANTI_SPAM_RECOMMENDATION );
298 }
299 }
300
301 /**
302 * Runs after a successful connection is made.
303 */
304 public static function jetpack_connected() {
305 // Schedule a recommendation for VideoPress in 2 weeks.
306 if ( false === wp_next_scheduled( self::VIDEOPRESS_TIMED_ACTION ) ) {
307 $date = new DateTime();
308 $date->add( new DateInterval( 'P14D' ) );
309 wp_schedule_single_event( $date->getTimestamp(), self::VIDEOPRESS_TIMED_ACTION );
310 }
311 }
312
313 /**
314 * Enable a recommendation for VideoPress.
315 */
316 public static function recommend_videopress() {
317 // Check to see if the VideoPress recommendation is already enabled.
318 if ( self::is_conditional_recommendation_enabled( self::VIDEOPRESS_RECOMMENDATION ) ) {
319 return;
320 }
321
322 $site_plan = Jetpack_Plan::get();
323 $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
324
325 if ( self::should_recommend_videopress( $site_plan, $site_products ) ) {
326 self::enable_conditional_recommendation( self::VIDEOPRESS_RECOMMENDATION );
327 }
328 }
329
330 /**
331 * Should we provide a recommendation for videopress?
332 * This method exists to facilitate unit testing
333 *
334 * @param array $site_plan A representation of the site's plan.
335 * @param array $site_products An array of product slugs.
336 * @return boolean
337 */
338 public static function should_recommend_videopress( $site_plan, $site_products ) {
339 // Does the site have the VideoPress module enabled?
340 if ( Jetpack::is_module_active( 'videopress' ) ) {
341 return false;
342 }
343
344 // Does the site plan have upgraded videopress features?
345 // For now, this just checks to see if the site has a free plan.
346 // Jetpack_Plan::supports('videopress') returns true for all plans, since there is a free tier.
347 $is_free_plan = 'free' === $site_plan['class'];
348 if ( ! $is_free_plan ) {
349 return false;
350 }
351
352 // Does this site already have a VideoPress product?
353 $has_videopress_product = count( array_intersect( array( 'jetpack_videopress', 'jetpack_videopress_monthly' ), $site_products ) ) > 0;
354 if ( $has_videopress_product ) {
355 return false;
356 }
357
358 return true;
359 }
360
361 /**
362 * Enable a recommendation.
363 *
364 * @param string $recommendation_name The name of the recommendation to enable.
365 * @return false|void
366 */
367 public static function enable_conditional_recommendation( $recommendation_name ) {
368 if ( ! in_array( $recommendation_name, self::CONDITIONAL_RECOMMENDATIONS, true ) ) {
369 return false;
370 }
371
372 $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
373 if ( ! in_array( $recommendation_name, $conditional_recommendations, true ) ) {
374 $conditional_recommendations[] = $recommendation_name;
375 Jetpack_Options::update_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, $conditional_recommendations );
376 }
377 }
378
379 /**
380 * Disable a recommendation.
381 *
382 * @param string $recommendation_name The name of the recommendation to disable.
383 * @return false|void
384 */
385 public static function disable_conditional_recommendation( $recommendation_name ) {
386 if ( ! in_array( $recommendation_name, self::CONDITIONAL_RECOMMENDATIONS, true ) ) {
387 return false;
388 }
389
390 $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
391 $recommendation_index = array_search( $recommendation_name, $conditional_recommendations, true );
392
393 if ( false !== $recommendation_index ) {
394 array_splice( $conditional_recommendations, $recommendation_index, 1 );
395 Jetpack_Options::update_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, $conditional_recommendations );
396 }
397 }
398
399 /**
400 * Check to see if a recommendation is enabled or not.
401 *
402 * @param string $recommendation_name The name of the recommendation to check for.
403 * @return bool
404 */
405 public static function is_conditional_recommendation_enabled( $recommendation_name ) {
406 $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
407 return in_array( $recommendation_name, $conditional_recommendations, true );
408 }
409
410 /**
411 * Gets data for all conditional recommendations.
412 *
413 * @return mixed
414 */
415 public static function get_conditional_recommendations() {
416 return Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
417 }
418
419 /**
420 * Get an array of new conditional recommendations that have not been viewed.
421 *
422 * @return array
423 */
424 public static function get_new_conditional_recommendations() {
425 $conditional_recommendations = self::get_conditional_recommendations();
426 $recommendations_data = Jetpack_Options::get_option( 'recommendations_data', array() );
427 $viewed_recommendations = isset( $recommendations_data['viewedRecommendations'] ) ? $recommendations_data['viewedRecommendations'] : array();
428
429 // array_diff returns a keyed array - reduce to unique values.
430 return array_unique( array_values( array_diff( $conditional_recommendations, $viewed_recommendations ) ) );
431 }
432
433 /**
434 * Initializes the Recommendations step according to the Setup Wizard state.
435 */
436 private static function initialize_jetpack_recommendations() {
437 if ( Jetpack_Options::get_option( 'recommendations_step' ) ) {
438 return;
439 }
440
441 $setup_wizard_status = Jetpack_Options::get_option( 'setup_wizard_status' );
442 if ( 'completed' === $setup_wizard_status ) {
443 Jetpack_Options::update_option( 'recommendations_banner_enabled', false );
444 Jetpack_Options::update_option( 'recommendations_step', 'setup-wizard-completed' );
445 }
446 }
447
448 /**
449 * Get the data for the recommendations
450 *
451 * @return array Recommendations data
452 */
453 public static function get_recommendations_data() {
454 self::initialize_jetpack_recommendations();
455
456 return Jetpack_Options::get_option( 'recommendations_data', array() );
457 }
458
459 /**
460 * Update the data for the recommendations
461 *
462 * @param WP_REST_Request $data The data.
463 */
464 public static function update_recommendations_data( $data ) {
465 if ( ! empty( $data ) ) {
466 Jetpack_Options::update_option( 'recommendations_data', $data );
467 }
468 }
469
470 /**
471 * Get the data for the recommendations
472 *
473 * @return array Recommendations data
474 */
475 public static function get_recommendations_step() {
476 self::initialize_jetpack_recommendations();
477
478 return array(
479 'step' => Jetpack_Options::get_option( 'recommendations_step', 'not-started' ),
480 );
481 }
482
483 /**
484 * Update the step for the recommendations
485 *
486 * @param WP_REST_Request $step The step.
487 */
488 public static function update_recommendations_step( $step ) {
489 if ( ! empty( $step ) ) {
490 Jetpack_Options::update_option( 'recommendations_step', $step );
491 }
492 }
493 }
494