PluginProbe ʕ •ᴥ•ʔ
WooCommerce Square / 4.5.0
WooCommerce Square v4.5.0
5.5.0 5.4.3 5.4.2 5.4.1 5.4.0 trunk 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.7.0 2.8.0 2.9.0 2.9.1 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.2.0 3.3.0 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.7.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 4.0.0 4.1.0 4.2.0 4.2.1 4.2.2 4.2.3 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5 4.8.6 4.8.7 4.8.8 4.9.0 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 4.9.8 4.9.9 5.0.0 5.0.1 5.1.0 5.1.1 5.1.2 5.2.0 5.3.0 5.3.1 5.3.2 5.3.3
woocommerce-square / includes / Framework / Lifecycle.php
woocommerce-square / includes / Framework Last commit date
Addresses 3 years ago Api 3 years ago Compatibility 2 years ago PaymentGateway 2 years ago Utilities 3 years ago Admin_Message_Handler.php 3 years ago Admin_Notice_Handler.php 3 years ago Lifecycle.php 3 years ago Plugin.php 3 years ago Plugin_Compatibility.php 3 years ago Plugin_Dependencies.php 3 years ago Square_Helper.php 3 years ago
Lifecycle.php
571 lines
1 <?php
2 /**
3 * WooCommerce Plugin Framework
4 *
5 * This source file is subject to the GNU General Public License v3.0
6 * that is bundled with this package in the file license.txt.
7 * It is also available through the world-wide-web at this URL:
8 * http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
9 * If you did not receive a copy of the license and are unable to
10 * obtain it through the world-wide-web, please send an email
11 * to license@skyverge.com so we can send you a copy immediately.
12 *
13 * @since 3.0.0
14 * @author WooCommerce / SkyVerge
15 * @copyright Copyright (c) 2013-2019, SkyVerge, Inc.
16 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
17 *
18 * Modified by WooCommerce on 15 December 2021.
19 */
20
21 namespace WooCommerce\Square\Framework;
22
23 use WooCommerce;
24
25 defined( 'ABSPATH' ) or exit;
26
27 /**
28 * Plugin lifecycle handler.
29 *
30 * Registers and displays milestone notice prompts and eventually the plugin
31 * install, upgrade, activation, and deactivation routines.
32 *
33 * @since 3.0.0
34 */
35 class Lifecycle {
36
37
38 /** @var array the version numbers that have an upgrade routine */
39 protected $upgrade_versions = array();
40
41 /** @var string minimum milestone version */
42 private $milestone_version;
43
44 /** @var Plugin plugin instance */
45 private $plugin;
46
47
48 /**
49 * Constructs the class.
50 *
51 * @since 3.0.0
52 *
53 * @param Plugin $plugin plugin instance
54 */
55 public function __construct( WooCommerce\Square\Framework\Plugin $plugin ) {
56
57 $this->plugin = $plugin;
58
59 $this->add_hooks();
60 }
61
62
63 /**
64 * Adds the action & filter hooks.
65 *
66 * @since 3.0.0
67 */
68 protected function add_hooks() {
69
70 // handle activation
71 add_action( 'admin_init', array( $this, 'handle_activation' ) );
72
73 // handle deactivation
74 add_action( 'deactivate_' . $this->get_plugin()->get_plugin_file(), array( $this, 'handle_deactivation' ) );
75
76 if ( is_admin() && ! wp_doing_ajax() ) {
77
78 // initialize the plugin lifecycle
79 add_action( 'wp_loaded', array( $this, 'init' ) );
80
81 // add the admin notices
82 add_action( 'init', array( $this, 'add_admin_notices' ) );
83 }
84
85 // catch any milestones triggered by action
86 add_action( 'wc_square_milestone_reached', array( $this, 'trigger_milestone' ), 10, 3 );
87 }
88
89
90 /**
91 * Initializes the plugin lifecycle.
92 *
93 * @since 3.0.0
94 */
95 public function init() {
96
97 // potentially handle a new activation
98 $this->handle_activation();
99
100 $installed_version = $this->get_installed_version();
101 $plugin_version = $this->get_plugin()->get_version();
102
103 // installed version lower than plugin version?
104 if ( version_compare( $installed_version, $plugin_version, '<' ) ) {
105
106 if ( ! $installed_version ) {
107
108 $this->install();
109
110 // store the upgrade event regardless if there was a routine for it
111 $this->store_event( 'install' );
112
113 /**
114 * Fires after the plugin has been installed.
115 *
116 * @since 3.0.0
117 */
118 do_action( 'wc_square_installed' );
119
120 } else {
121
122 $this->upgrade( $installed_version );
123
124 // store the upgrade event regardless if there was a routine for it
125 $this->add_upgrade_event( $installed_version );
126
127 // if the plugin never had any previous milestones, consider them all reached so their notices aren't displayed
128 if ( ! $this->get_milestone_version() ) {
129 $this->set_milestone_version( $plugin_version );
130 }
131
132 /**
133 * Fires after the plugin has been updated.
134 *
135 * @since 3.0.0
136 *
137 * @param string $installed_version previously installed version
138 */
139 do_action( 'wc_square_updated', $installed_version );
140 }
141
142 // new version number
143 $this->set_installed_version( $plugin_version );
144 }
145 }
146
147
148 /**
149 * Triggers plugin activation.
150 *
151 * We don't use register_activation_hook() as that can't be called inside
152 * the 'plugins_loaded' action. Instead, we rely on setting to track the
153 * plugin's activation status.
154 *
155 * @internal
156 *
157 * @link https://developer.wordpress.org/reference/functions/register_activation_hook/#comment-2100
158 *
159 * @since 3.0.0
160 */
161 public function handle_activation() {
162
163 if ( ! get_option( 'wc_square_is_active', false ) ) {
164
165 /**
166 * Fires when the plugin is activated.
167 *
168 * @since 3.0.0
169 */
170 do_action( 'wc_square_activated' );
171
172 update_option( 'wc_square_is_active', 'yes' );
173 }
174 }
175
176
177 /**
178 * Triggers plugin deactivation.
179 *
180 * @internal
181 *
182 * @since 3.0.0
183 */
184 public function handle_deactivation() {
185
186 /**
187 * Fires when the plugin is deactivated.
188 *
189 * @since 3.0.0
190 */
191 do_action( 'wc_square_deactivated' );
192
193 delete_option( 'wc_square_is_active' );
194 }
195
196 /**
197 * Helper method to install default settings for a plugin.
198 *
199 * @since 3.0.0
200 *
201 * @param array $settings settings in format required by WC_Admin_Settings
202 */
203 public function install_default_settings( array $settings ) {
204
205 foreach ( $settings as $setting ) {
206
207 if ( isset( $setting['id'], $setting['default'] ) ) {
208 update_option( $setting['id'], $setting['default'] );
209 }
210 }
211 }
212
213 /**
214 * Performs any upgrade tasks based on the provided installed version.
215 *
216 * @since 3.0.0
217 *
218 * @param string $installed_version installed version
219 */
220 protected function upgrade( $installed_version ) {
221
222 foreach ( $this->upgrade_versions as $upgrade_version ) {
223
224 $upgrade_method = 'upgrade_to_' . str_replace( array( '.', '-' ), '_', $upgrade_version );
225
226 if ( version_compare( $installed_version, $upgrade_version, '<' ) && is_callable( array( $this, $upgrade_method ) ) ) {
227
228 $this->get_plugin()->log( sprintf( "Starting upgrade to v%s", $upgrade_version ) );
229
230 $this->$upgrade_method( $installed_version );
231
232 $this->get_plugin()->log( sprintf( "Upgrade to v%s complete.", $upgrade_version ) );
233 }
234 }
235 }
236
237
238 /**
239 * Adds any lifecycle admin notices.
240 *
241 * @since 3.0.0
242 */
243 public function add_admin_notices() {
244
245 // display any milestone notices
246 foreach ( $this->get_milestone_messages() as $id => $message ) {
247
248 // bail if this notice was already dismissed
249 if ( ! $this->get_plugin()->get_admin_notice_handler()->should_display_notice( $id ) ) {
250 continue;
251 }
252
253 /**
254 * Filters a milestone notice message.
255 *
256 * @since 3.0.0
257 *
258 * @param string $message message text to be used for the milestone notice
259 * @param string $id milestone ID
260 */
261 $message = apply_filters( 'wc_square_milestone_message', $this->generate_milestone_notice_message( $message ), $id );
262
263 if ( $message ) {
264
265 $this->get_plugin()->get_admin_notice_handler()->add_admin_notice( $message, $id, array(
266 'always_show_on_settings' => false,
267 ) );
268
269 // only display one notice at a time
270 break;
271 }
272 }
273 }
274
275
276 /** Milestone Methods *****************************************************/
277
278
279 /**
280 * Triggers a milestone.
281 *
282 * This will only be triggered if the install's "milestone version" is lower
283 * than $since. Plugins can specify $since as the version at which a
284 * milestone's feature was added. This prevents existing installs from
285 * triggering notices for milestones that have long passed, like a payment
286 * gateway's first successful payment. Omitting $since will assume the
287 * milestone has always existed and should only trigger for fresh installs.
288 *
289 * @since 3.0.0
290 *
291 * @param string $id milestone ID
292 * @param string $message message to display to the user
293 * @param string $since the version since this milestone has existed in the plugin
294 * @return bool
295 */
296 public function trigger_milestone( $id, $message, $since = '1.0.0' ) {
297
298 // if the plugin was had milestones before this milestone was added, don't trigger it
299 if ( version_compare( $this->get_milestone_version(), $since, '>' ) ) {
300 return false;
301 }
302
303 return $this->register_milestone_message( $id, $message );
304 }
305
306
307 /**
308 * Generates a milestone notice message.
309 *
310 * @since 3.0.0
311 *
312 * @param string $custom_message custom text that notes what milestone was completed.
313 * @return string
314 */
315 protected function generate_milestone_notice_message( $custom_message ) {
316
317 $message = '';
318
319 if ( $this->get_plugin()->get_reviews_url() ) {
320
321 // to be prepended at random to each milestone notice
322 $exclamations = array(
323 __( 'Awesome', 'woocommerce-square' ),
324 __( 'Fantastic', 'woocommerce-square' ),
325 __( 'Cowabunga', 'woocommerce-square' ),
326 __( 'Congratulations', 'woocommerce-square' ),
327 __( 'Hot dog', 'woocommerce-square' ),
328 );
329
330 $message = $exclamations[ array_rand( $exclamations ) ] . ', ' . esc_html( $custom_message ) . ' ';
331
332 $message .= sprintf(
333 /* translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a> tag, %4$s - <a> tag, %5$s - </a> tag */
334 __( 'Are you having a great experience with %1$s so far? Please consider %2$sleaving a review%3$s! If things aren\'t going quite as expected, we\'re happy to help -- please %4$sreach out to our support team%5$s.', 'woocommerce-square' ),
335 '<strong>' . esc_html( $this->get_plugin()->get_plugin_name() ) . '</strong>',
336 '<a href="' . esc_url( $this->get_plugin()->get_reviews_url() ) . '">', '</a>',
337 '<a href="' . esc_url( $this->get_plugin()->get_support_url() ) . '">', '</a>'
338 );
339 }
340
341 return $message;
342 }
343
344
345 /**
346 * Registers a milestone message to be displayed in the admin.
347 *
348 * @since 3.0.0
349 * @see Lifecycle::generate_milestone_notice_message()
350 *
351 * @param string $id milestone ID
352 * @param string $message message to display to the user
353 * @return bool whether the message was successfully registered
354 */
355 public function register_milestone_message( $id, $message ) {
356
357 $milestone_messages = $this->get_milestone_messages();
358 $dismissed_notices = array_keys( $this->get_plugin()->get_admin_notice_handler()->get_dismissed_notices() );
359
360 // get the total number of dismissed milestone messages
361 $dismissed_milestone_messages = array_intersect( array_keys( $milestone_messages ), $dismissed_notices );
362
363 // if the user has dismissed more than three milestone messages already, don't add any more
364 if ( count( $dismissed_milestone_messages ) > 3 ) {
365 return false;
366 }
367
368 $milestone_messages[ $id ] = $message;
369
370 return update_option( 'wc_square_milestone_messages', $milestone_messages );
371 }
372
373
374 /** Event history methods *****************************************************************************************/
375
376
377 /**
378 * Adds an upgrade lifecycle event.
379 *
380 * @since 3.0.0
381 *
382 * @param string $from_version version upgrading from
383 * @param array $data extra data to add
384 * @return false|int
385 */
386 public function add_upgrade_event( $from_version, array $data = array() ) {
387
388 $data = array_merge( array(
389 'from_version' => $from_version,
390 ), $data );
391
392 return $this->store_event( 'upgrade', $data );
393 }
394
395 /**
396 * Stores a lifecycle event.
397 *
398 * This can be used to log installs, upgrades, etc...
399 *
400 * Uses a direct database query to avoid cache issues.
401 *
402 * @since 3.0.0
403 *
404 * @param string $name lifecycle event name
405 * @param array $data any extra data to store
406 * @return false|int
407 */
408 public function store_event( $name, array $data = array() ) {
409 global $wpdb;
410
411 $history = $this->get_event_history();
412
413 $event = array(
414 'name' => wc_clean( $name ),
415 'time' => (int) current_time( 'timestamp' ),
416 'version' => wc_clean( $this->get_plugin()->get_version() ),
417 );
418
419 if ( ! empty( $data ) ) {
420 $event['data'] = wc_clean( $data );
421 }
422
423 array_unshift( $history, $event );
424
425 // limit to the last 30 events
426 $history = array_slice( $history, 0, 29 );
427
428 return $wpdb->replace(
429 $wpdb->options,
430 array(
431 'option_name' => $this->get_event_history_option_name(),
432 'option_value' => wp_json_encode( $history ),
433 'autoload' => 'no',
434 ),
435 array(
436 '%s',
437 '%s',
438 )
439 );
440 }
441
442
443 /**
444 * Gets the lifecycle event history.
445 *
446 * The last 30 events are stored, with the latest first.
447 *
448 * @since 3.0.0
449 *
450 * @return array
451 */
452 public function get_event_history() {
453 global $wpdb;
454
455 $history = array();
456
457 $results = $wpdb->get_var( $wpdb->prepare( "
458 SELECT option_value
459 FROM {$wpdb->options}
460 WHERE option_name = %s
461 ", $this->get_event_history_option_name() ) );
462
463 if ( $results ) {
464 $history = json_decode( $results, true );
465 }
466
467 return is_array( $history ) ? $history : array();
468 }
469
470
471 /**
472 * Gets the event history option name.
473 *
474 * @since 3.0.0
475 *
476 * @return string
477 */
478 protected function get_event_history_option_name() {
479
480 return 'wc_square_lifecycle_events';
481 }
482
483
484 /** Utility Methods *******************************************************/
485
486
487 /**
488 * Gets the registered milestone messages.
489 *
490 * @since 3.0.0
491 *
492 * @return array
493 */
494 protected function get_milestone_messages() {
495
496 return get_option( 'wc_square_milestone_messages', array() );
497 }
498
499
500 /**
501 * Sets the milestone version.
502 *
503 * @since 3.0.0
504 *
505 * @param string $version plugin version
506 * @return bool
507 */
508 public function set_milestone_version( $version ) {
509
510 $this->milestone_version = $version;
511
512 return update_option( 'wc_square_milestone_version', $version );
513 }
514
515
516 /**
517 * Gets the milestone version.
518 *
519 * @since 3.0.0
520 *
521 * @return string
522 */
523 public function get_milestone_version() {
524
525 if ( ! $this->milestone_version ) {
526 $this->milestone_version = get_option( 'wc_square_milestone_version', '' );
527 }
528
529 return $this->milestone_version;
530 }
531
532
533 /**
534 * Gets the currently installed plugin version.
535 *
536 * @since 3.0.0
537 *
538 * @return string
539 */
540 protected function get_installed_version() {
541
542 return get_option( $this->get_plugin()->get_plugin_version_name() );
543 }
544
545
546 /**
547 * Sets the installed plugin version.
548 *
549 * @since 3.0.0
550 *
551 * @param string $version version to set
552 */
553 protected function set_installed_version( $version ) {
554
555 update_option( $this->get_plugin()->get_plugin_version_name(), $version );
556 }
557
558
559 /**
560 * Gets the plugin instance.
561 *
562 * @since 3.0.0
563 *
564 * @return Plugin
565 */
566 protected function get_plugin() {
567
568 return $this->plugin;
569 }
570 }
571