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