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 / Lifecycle.php
woocommerce-square / includes Last commit date
API 3 years ago Admin 2 years ago Emails 2 years ago Framework 2 years ago Gateway 2 years ago Handlers 2 years ago Sync 2 years ago Utilities 3 years ago AJAX.php 3 years ago API.php 3 years ago Admin.php 3 years ago Functions.php 3 years ago Gateway.php 2 years ago Lifecycle.php 3 years ago Plugin.php 2 years ago Settings.php 2 years ago WC_Order_Square.php 2 years ago
Lifecycle.php
591 lines
1 <?php
2 /**
3 * WooCommerce Square
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@woocommerce.com so we can send you a copy immediately.
12 *
13 * DISCLAIMER
14 *
15 * Do not edit or add to this file if you wish to upgrade WooCommerce Square to newer
16 * versions in the future. If you wish to customize WooCommerce Square for your
17 * needs please refer to https://docs.woocommerce.com/document/woocommerce-square/
18 *
19 * @author WooCommerce
20 * @copyright Copyright: (c) 2019, Automattic, Inc.
21 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
22 */
23
24 namespace WooCommerce\Square;
25
26 defined( 'ABSPATH' ) || exit;
27
28 use WooCommerce\Square\Handlers\Product;
29
30 /**
31 * The plugin lifecycle handler.
32 *
33 * @since 2.0.0
34 *
35 * @method Plugin get_plugin()
36 */
37 class Lifecycle extends \WooCommerce\Square\Framework\Lifecycle {
38
39 /**
40 * Lifecycle constructor.
41 *
42 * @since 2.0.0
43 *
44 * @param Plugin $plugin main instance.
45 */
46 public function __construct( Plugin $plugin ) {
47
48 parent::__construct( $plugin );
49
50 // plugin upgrade path: maps automatically each semver to upgrade_to_x_y_z() protected method.
51 $this->upgrade_versions = array(
52 '2.0.0',
53 '2.0.4',
54 '2.1.5',
55 '2.2.0',
56 '2.3.0',
57 '3.0.2',
58 '3.2.0',
59 '3.7.1',
60 '3.8.3',
61 );
62 }
63
64
65 /**
66 * Performs plugin installation.
67 *
68 * @since 2.0.0
69 */
70 protected function install() {
71
72 // create the db table for the customer index.
73 Gateway\Customer_Helper::create_table();
74
75 /**
76 * Fires upon plugin installed.
77 *
78 * @since 2.0.0
79 *
80 * @param string $version plugin version (available from v2.0.0)
81 */
82 do_action( 'wc_square_installed', Plugin::VERSION );
83 }
84
85
86 /**
87 * Performs upgrade tasks.
88 *
89 * @since 2.0.0
90 *
91 * @param string $installed_version semver.
92 */
93 protected function upgrade( $installed_version ) {
94
95 parent::upgrade( $installed_version );
96
97 /**
98 * Fires upon plugin upgraded (legacy hook).
99 *
100 * @since 1.0.0
101 *
102 * @param string $version version updating to (available from v2.0.0)
103 * @param string $version version updating from (available from v2.0.0)
104 */
105 do_action( 'wc_square_updated', Plugin::VERSION, $installed_version );
106 }
107
108
109 /**
110 * Upgrades to version 2.0.0
111 *
112 * @since 2.0.0
113 */
114 protected function upgrade_to_2_0_0() {
115
116 // create the db table for the customer index.
117 Gateway\Customer_Helper::create_table();
118
119 wc_set_time_limit( 300 );
120
121 // migrate all the things!
122 $syncing_products = $this->migrate_plugin_settings();
123
124 $this->migrate_gateway_settings();
125 $this->migrate_orders();
126
127 // only set the products "sync" status if v2 is now configured to sync products.
128 if ( $syncing_products ) {
129
130 $this->migrate_products();
131
132 // assume a last sync occurred before upgrading.
133 $this->get_plugin()->get_sync_handler()->set_last_synced_at();
134 $this->get_plugin()->get_sync_handler()->set_inventory_last_synced_at();
135 }
136
137 $this->migrate_customers();
138
139 // mark upgrade complete.
140 update_option( 'wc_square_updated_to_2_0_0', true );
141 }
142
143
144 /**
145 * Upgrades to version 2.0.4.
146 *
147 * @since 2.0.4
148 */
149 protected function upgrade_to_2_0_4() {
150
151 $v1_settings = get_option( 'woocommerce_squareconnect_settings', array() );
152 $v2_settings = get_option( 'wc_square_settings', array() );
153
154 $v2_settings = $this->get_migrated_system_of_record( $v1_settings, $v2_settings );
155
156 update_option( 'wc_square_settings', $v2_settings );
157 }
158
159 /**
160 * Upgrades to version 2.1.5
161 *
162 * 2.1.5 updated the woocommerce_square_customers database schema.
163 *
164 * @see https://github.com/woocommerce/woocommerce-square/issues/359
165 * @since 2.1.5
166 */
167 protected function upgrade_to_2_1_5() {
168 Gateway\Customer_Helper::create_table();
169 }
170
171 /**
172 * Adds the missing Square customer table.
173 *
174 * @see https://github.com/woocommerce/woocommerce-square/issues/825
175 * @since 3.2.0
176 */
177 protected function upgrade_to_3_2_0() {
178 Gateway\Customer_Helper::create_table();
179 }
180
181 /**
182 * Deletes all transient data related to payment tokens.
183 *
184 * @see https://github.com/woocommerce/woocommerce-square/issues/1050
185 * @since 3.8.3
186 */
187 protected function upgrade_to_3_8_3() {
188 wc_square()->get_gateway()->get_payment_tokens_handler()->clear_all_transients();
189 }
190
191 /**
192 * Upgrades to version 3.7.1
193 *
194 * This upgrade disables gift cards, and shows a notice to inform the merchant.
195 * Gift Cards are in beta status and not recommended for production.
196 *
197 * @see https://github.com/woocommerce/woocommerce-square/issues/1003
198 * @see https://github.com/woocommerce/woocommerce-square/issues/1009
199 * @since 3.7.1.
200 */
201 protected function upgrade_to_3_7_1() {
202 // Early return if Gift Cards are already disabled.
203 $gateway_settings = get_option( 'woocommerce_square_credit_card_settings', array() );
204 if ( ! isset( $gateway_settings['enable_gift_cards'] ) || 'no' === $gateway_settings['enable_gift_cards'] ) {
205 return;
206 }
207
208 // Force-disable Gift Cards (only if store has it enabled).
209 $gateway_settings['enable_gift_cards'] = 'no';
210 update_option( 'woocommerce_square_credit_card_settings', $gateway_settings );
211
212 // Store an option to inform the merchant that Gift Cards has been force-disabled.
213 // Using version number in the option name so it's easy to remove in the future.
214 update_option( 'woocommerce_square_3_7_1_gift_cards_force_disable_notice', 'yes' );
215 }
216
217 /**
218 * Generates a milestone notice message.
219 *
220 * @since 2.1.7
221 *
222 * @param string $custom_message Custom text that notes what milestone was completed.
223 * @return string
224 */
225 protected function generate_milestone_notice_message( $custom_message ) {
226
227 $message = '';
228
229 if ( $this->get_plugin()->get_reviews_url() ) {
230
231 // to be prepended at random to each milestone notice.
232 $exclamations = array(
233 __( 'Awesome', 'woocommerce-square' ),
234 __( 'Congratulations', 'woocommerce-square' ),
235 __( 'Great', 'woocommerce-square' ),
236 __( 'Fantastic', 'woocommerce-square' ),
237 );
238
239 $message = $exclamations[ array_rand( $exclamations ) ] . ', ' . esc_html( $custom_message ) . ' ';
240
241 $message .= sprintf(
242 /* translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a> tag, %4$s - <a> tag, %5$s - </a> tag */
243 __( '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' ),
244 '<strong>' . esc_html( $this->get_plugin()->get_plugin_name() ) . '</strong>',
245 '<a href="' . esc_url( $this->get_plugin()->get_reviews_url() ) . '">',
246 '</a>',
247 '<a href="' . esc_url( $this->get_plugin()->get_support_url() ) . '">',
248 '</a>'
249 );
250 }
251
252 return $message;
253 }
254
255 /**
256 * Upgrades to version 2.2.0.
257 *
258 * @since 2.2.0
259 */
260 protected function upgrade_to_2_2_0() {
261
262 $v1_settings = get_option( 'wc_square_settings', array() );
263
264 $v2_settings = $this->set_environment_location_id( $v1_settings );
265
266 update_option( 'wc_square_settings', $v2_settings );
267 }
268
269 /**
270 * Upgrades to version 2.3.0.
271 *
272 * @since 2.3.0
273 */
274 protected function upgrade_to_2_3_0() {
275 // Set `enable_digital_wallets` default to no for existing stores
276 $gateway_settings = get_option( 'woocommerce_square_credit_card_settings', array() );
277
278 if ( ! isset( $gateway_settings['enable_digital_wallets'] ) ) {
279 $gateway_settings['enable_digital_wallets'] = 'no';
280 }
281
282 update_option( 'woocommerce_square_credit_card_settings', $gateway_settings );
283 }
284
285 /**
286 * Deletes the transient that holds locations data.
287 *
288 * @see https://github.com/woocommerce/woocommerce-square/issues/786#issuecomment-1121388650
289 *
290 * @since 3.0.2
291 */
292 protected function upgrade_to_3_0_2() {
293 delete_transient( 'wc_square_locations' );
294 }
295
296 /**
297 * Migrates plugin settings from v1 to v2.
298 *
299 * @see Lifecycle::upgrade_to_2_0_0()
300 *
301 * @since 2.0.0
302 *
303 * @return bool whether a Sync setting was enabled from migration
304 */
305 private function migrate_plugin_settings() {
306
307 $this->get_plugin()->log( 'Migrating plugin settings...' );
308
309 // get legacy and new default settings.
310 $new_settings = get_option( 'wc_square_settings', array() );
311 $legacy_settings = get_option( 'woocommerce_squareconnect_settings', array() );
312 $email_settings = get_option( 'woocommerce_wc_square_sync_completed_settings', array() );
313
314 // bail if they already have v2 settings present.
315 if ( ! empty( $new_settings ) ) {
316 return;
317 }
318
319 // handle access token first.
320 $legacy_access_token = get_option( 'woocommerce_square_merchant_access_token' );
321 if ( $legacy_access_token ) {
322
323 // the access token was previously stored unencrypted.
324 if ( ! empty( $legacy_access_token ) && Utilities\Encryption_Utility::is_encryption_supported() ) {
325
326 $encryption = new Utilities\Encryption_Utility();
327
328 try {
329 $legacy_access_token = $encryption->encrypt_data( $legacy_access_token );
330 } catch ( \Exception $exception ) {
331 // log the event, but don't halt the process.
332 $this->get_plugin()->log( 'Could not encrypt access token during upgrade. ' . $exception->getMessage() );
333 }
334 }
335
336 // previously only 'production' environment was assumed.
337 $access_tokens = get_option( 'wc_square_access_tokens', array() );
338 $access_tokens['production'] = is_string( $legacy_access_token ) ? $legacy_access_token : '';
339
340 update_option( 'wc_square_access_tokens', $access_tokens );
341 }
342
343 // migrate store location.
344 if ( ! empty( $legacy_settings['location'] ) ) {
345 $new_settings['location_id'] = $legacy_settings['location'];
346 }
347
348 // toggle debug logging.
349 $new_settings['debug_logging_enabled'] = isset( $legacy_settings['logging'] ) && in_array( $legacy_settings['logging'], array( 'yes', 'no' ), true ) ? $legacy_settings['logging'] : 'no';
350
351 // set the SOR and inventory sync values.
352 $new_settings = $this->get_migrated_system_of_record( $legacy_settings, $new_settings );
353
354 // migrate email notification settings: if there's a recipient, we enable email and pass recipient(s) to email setting.
355 if ( isset( $legacy_settings['sync_email'] ) && is_string( $legacy_settings['sync_email'] ) && '' !== trim( $legacy_settings['sync_email'] ) ) {
356 $email_settings['enabled'] = 'yes';
357 $email_settings['recipient'] = $legacy_settings['sync_email'];
358 } else {
359 $email_settings['enabled'] = 'no';
360 $email_settings['recipient'] = '';
361 }
362
363 // save email settings.
364 update_option( 'woocommerce_wc_square_sync_completed_settings', $email_settings );
365 // save plugin settings.
366 update_option( 'wc_square_settings', $new_settings );
367
368 $this->get_plugin()->log( 'Plugin settings migration complete.' );
369
370 return isset( $new_settings['system_of_record'] ) && Settings::SYSTEM_OF_RECORD_DISABLED !== $new_settings['system_of_record'];
371 }
372
373
374 /**
375 * Migrates gateway settings from v1 to v2.
376 *
377 * @see Lifecycle::upgrade_to_2_0_0()
378 *
379 * @since 2.0.0
380 */
381 private function migrate_gateway_settings() {
382
383 $this->get_plugin()->log( 'Migrating gateway settings...' );
384
385 $legacy_settings = get_option( 'woocommerce_square_settings', array() );
386 $new_settings = get_option( 'woocommerce_square_credit_card_settings', array() );
387
388 // bail if they already have v2 settings present.
389 if ( ! empty( $new_settings ) ) {
390 return;
391 }
392
393 if ( isset( $legacy_settings['enabled'] ) ) {
394 $new_settings['enabled'] = 'yes' === $legacy_settings['enabled'] ? 'yes' : 'no';
395 }
396
397 if ( isset( $legacy_settings['title'] ) && is_string( $legacy_settings['title'] ) ) {
398 $new_settings['title'] = $legacy_settings['title'];
399 }
400
401 if ( isset( $legacy_settings['description'] ) && is_string( $legacy_settings['description'] ) ) {
402 $new_settings['description'] = $legacy_settings['description'];
403 }
404
405 // note: the following is not an error, the setting on v1 intends "delayed" capture, hence authorization only, if set.
406 if ( isset( $legacy_settings['capture'] ) ) {
407 $new_settings['transaction_type'] = 'yes' === $legacy_settings['capture'] ? Gateway::TRANSACTION_TYPE_AUTHORIZATION : Gateway::TRANSACTION_TYPE_CHARGE;
408 }
409
410 // not quite the same, since tokenization is a new thing, but we could presume the intention to let customers save their payment details.
411 if ( isset( $legacy_settings['create_customer'] ) ) {
412 $new_settings['tokenization'] = 'yes' === $legacy_settings['create_customer'] ? 'yes' : 'no';
413 }
414
415 if ( isset( $legacy_settings['logging'] ) ) {
416 $new_settings['debug_mode'] = 'yes' === $legacy_settings['logging'] ? 'log' : 'off';
417 }
418
419 // there was no card types setting in v1.
420 $new_settings['card_types'] = array(
421 'VISA',
422 'MC',
423 'AMEX',
424 'JCB',
425 // purposefully omit dinersclub & discover.
426 );
427
428 // save migrated settings.
429 update_option( 'woocommerce_square_credit_card_settings', $new_settings );
430
431 $this->get_plugin()->log( 'Gateway settings migration complete.' );
432 }
433
434
435 /**
436 * Migrates order data from v1 to v2.
437 *
438 * @see Lifecycle::upgrade_to_2_0_0()
439 *
440 * @since 2.0.0
441 */
442 private function migrate_orders() {
443 global $wpdb;
444
445 $this->get_plugin()->log( 'Migrating orders data...' );
446
447 $wpdb->update( $wpdb->postmeta, array( 'meta_key' => '_wc_square_credit_card_charge_captured' ), array( 'meta_key' => '_square_charge_captured' ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
448
449 // move payment ID to new gateway ID meta key value.
450 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
451 $wpdb->postmeta,
452 array(
453 'meta_value' => 'square_credit_card', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
454 ),
455 array(
456 'meta_key' => '_payment_method', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
457 'meta_value' => 'square', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
458 )
459 );
460 $this->get_plugin()->log( 'Orders migration complete.' );
461 }
462
463
464 /**
465 * Migrates product data from v1 to v2.
466 *
467 * @see Lifecycle::upgrade_to_2_0_0()
468 *
469 * @since 2.0.0
470 */
471 private function migrate_products() {
472 global $wpdb;
473
474 $this->get_plugin()->log( 'Migrating products data...' );
475
476 // the handling in v1 was reversed, so we want products where sync wasn't disabled.
477 $legacy_product_ids = get_posts(
478 array(
479 'nopaging' => true,
480 'post_type' => 'product',
481 'post_status' => 'all',
482 'fields' => 'ids',
483 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
484
485 'relation' => 'OR',
486 array(
487 'key' => '_wcsquare_disable_sync',
488 'value' => 'no',
489 ),
490 array(
491 'key' => '_wcsquare_disable_sync',
492 'compare' => 'NOT EXISTS',
493 ),
494 ),
495 )
496 );
497
498 // in v2 we turn those products as flagged to be sync-enabled instead.
499 if ( ! empty( $legacy_product_ids ) ) {
500
501 $failed_products = array();
502
503 // ensure taxonomy is registered at this stage.
504 if ( ! taxonomy_exists( Product::SYNCED_WITH_SQUARE_TAXONOMY ) ) {
505 Product::init_taxonomies();
506 }
507
508 // will not create the term if already exists.
509 wp_create_term( 'yes', Product::SYNCED_WITH_SQUARE_TAXONOMY );
510
511 // set Square sync status via taxonomy term.
512 foreach ( $legacy_product_ids as $i => $product_id ) {
513
514 $set_term = wp_set_object_terms( $product_id, array( 'yes' ), Product::SYNCED_WITH_SQUARE_TAXONOMY );
515
516 if ( ! is_array( $set_term ) ) {
517
518 unset( $legacy_product_ids[ $i ] );
519
520 $failed_products[] = $product_id;
521 }
522 }
523
524 // log any errors.
525 if ( ! empty( $failed_products ) ) {
526 $this->get_plugin()->log( 'Could not update sync with Square status for products with ID: ' . implode( ', ', array_unique( $failed_products ) ) . '.' );
527 }
528 }
529
530 $this->get_plugin()->log( 'Products migration complete.' );
531 }
532
533
534 /**
535 * Migrates customer data.
536 *
537 * @since 2.0.0
538 */
539 private function migrate_customers() {
540 global $wpdb;
541
542 $this->get_plugin()->log( 'Migrating customer data.' );
543
544 $rows = (int) $wpdb->update( $wpdb->usermeta, array( 'meta_key' => 'wc_square_customer_id' ), array( 'meta_key' => '_square_customer_id' ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
545
546 $this->get_plugin()->log( sprintf( '%d customers migrated', $rows ) );
547 }
548
549
550 /**
551 * Adds the Sync setting setting to the v2 plugin settings depending on v1 setting values.
552 *
553 * @since 2.0.2
554 *
555 * @param array $v1_settings v1 plugin settings.
556 * @param array $v2_settings v2 plugin settings.
557 * @return array
558 */
559 private function get_migrated_system_of_record( $v1_settings, $v2_settings ) {
560
561 $sync_products = isset( $v1_settings['sync_products'] ) && 'yes' === $v1_settings['sync_products'];
562 $sync_inventory = $sync_products && isset( $v1_settings['sync_inventory'] ) && 'yes' === $v1_settings['sync_inventory'];
563 $inventory_polling = isset( $v1_settings['inventory_polling'] ) && 'yes' === $v1_settings['inventory_polling'];
564
565 $v2_settings['system_of_record'] = $sync_products && $inventory_polling ? Settings::SYSTEM_OF_RECORD_SQUARE : Settings::SYSTEM_OF_RECORD_DISABLED;
566 $v2_settings['enable_inventory_sync'] = $inventory_polling || $sync_inventory ? 'yes' : 'no';
567
568 return $v2_settings;
569 }
570
571 /**
572 * Adds environment specific location_id to, and removes general location_id from v1 setting array.
573 *
574 * @since 2.2.0
575 *
576 * @param array $v1_settings v1 plugin settings.
577 * @return array
578 */
579 private function set_environment_location_id( $v1_settings ) {
580
581 $environment = isset( $v1_settings['enable_sandbox'] ) && 'yes' === $v1_settings['enable_sandbox'] ? 'sandbox' : 'production';
582
583 if ( ! isset( $v1_settings[ $environment . '_location_id' ] ) ) {
584 $v1_location_id = isset( $v1_settings['location_id'] ) ? $v1_settings['location_id'] : '';
585 $v1_settings[ $environment . '_location_id' ] = $v1_location_id;
586 }
587
588 return $v1_settings;
589 }
590 }
591