Analytics
2 years ago
Rest
4 months ago
Privacy.php
1 year ago
Settings_Page.php
3 years ago
Sync_Page.php
6 months ago
Sync_Page.php
411 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\Admin; |
| 25 | |
| 26 | defined( 'ABSPATH' ) || exit; |
| 27 | |
| 28 | use WooCommerce\Square\Handlers\Product; |
| 29 | use WooCommerce\Square\Sync\Records; |
| 30 | |
| 31 | /** |
| 32 | * Handles HTML output for the "Update" section of the Settings page with sync status handling and UI. |
| 33 | * |
| 34 | * @since 2.0.0 |
| 35 | */ |
| 36 | class Sync_Page { |
| 37 | |
| 38 | |
| 39 | /** |
| 40 | * Outputs the page HTML. |
| 41 | * |
| 42 | * @since 2.0.0 |
| 43 | */ |
| 44 | public static function output() { |
| 45 | |
| 46 | ?> |
| 47 | <div id="wc-square-sync-page"> |
| 48 | |
| 49 | <h2><?php esc_html_e( 'Update', 'woocommerce-square' ); ?></h2> |
| 50 | <?php self::output_system_record_of_data_info(); ?> |
| 51 | <?php self::output_sync_status(); ?> |
| 52 | |
| 53 | <h2><?php esc_html_e( 'Sync records', 'woocommerce-square' ); ?></h2> |
| 54 | <?php self::output_sync_records(); ?> |
| 55 | <?php self::output_sync_with_square_modal_template(); ?> |
| 56 | |
| 57 | </div> |
| 58 | <?php |
| 59 | } |
| 60 | |
| 61 | |
| 62 | /** |
| 63 | * Outputs notice-like tabular HTML with information on the current Sync setting handling. |
| 64 | * |
| 65 | * @since 2.0.0 |
| 66 | */ |
| 67 | private static function output_system_record_of_data_info() { |
| 68 | |
| 69 | ?> |
| 70 | <table class="wc_square_table sor widefat" cellspacing="0"> |
| 71 | <tbody> |
| 72 | <?php if ( wc_square()->get_settings_handler()->is_system_of_record_square() ) : ?> |
| 73 | |
| 74 | <tr> |
| 75 | <td> |
| 76 | <?php |
| 77 | printf( |
| 78 | /* translators: Placeholders: %1$s, %3$s - opening <strong> HTML tag, %2$s, $4%s - closing </strong> HTML tag */ |
| 79 | esc_html__( '%1$sSquare%2$s is the system of record set in the sync settings. The following data from Square will overwrite WooCommerce data for synced products: %3$sname, price, description, category, inventory%4$s.', 'woocommerce-square' ), |
| 80 | '<strong>', |
| 81 | '</strong>', |
| 82 | '<strong>', |
| 83 | '</strong>' |
| 84 | ); |
| 85 | ?> |
| 86 | </td> |
| 87 | </tr> |
| 88 | <tr> |
| 89 | <td> |
| 90 | <?php |
| 91 | printf( |
| 92 | /* translators: Placeholders: %1$s - opening <strong> HTML tag, %2$s closing </strong> HTML tag */ |
| 93 | esc_html__( '%1$sProduct images%2$s will be imported from Square if no featured image is set in WooCommerce.', 'woocommerce-square' ), |
| 94 | '<strong>', |
| 95 | '</strong>' |
| 96 | ); |
| 97 | ?> |
| 98 | </td> |
| 99 | </tr> |
| 100 | |
| 101 | <?php elseif ( wc_square()->get_settings_handler()->is_system_of_record_woocommerce() ) : ?> |
| 102 | |
| 103 | <tr> |
| 104 | <td> |
| 105 | <?php |
| 106 | printf( |
| 107 | /* translators: Placeholders: %1$s, %3$s - opening <strong> HTML tag, %2$s, %4$s - closing </strong> HTML tag */ |
| 108 | esc_html__( '%1$sWooCommerce%2$s is the system of record set in the sync settings. The following data from WooCommerce will overwrite Square data for synced products: %3$sname, price, inventory, category, image%4$s.', 'woocommerce-square' ), |
| 109 | '<strong>', |
| 110 | '</strong>', |
| 111 | '<strong>', |
| 112 | '</strong>' |
| 113 | ); |
| 114 | ?> |
| 115 | </td> |
| 116 | </tr> |
| 117 | |
| 118 | <?php else : ?> |
| 119 | |
| 120 | <tr> |
| 121 | <td> |
| 122 | <?php |
| 123 | printf( |
| 124 | /* translators: Placeholders: %1$s - opening <strong> HTML tag, %2$s closing </strong> HTML tag*/ |
| 125 | esc_html__( '%1$sSync setting not chosen.%2$s Products will not be synced between Square and WooCommerce.', 'woocommerce-square' ), |
| 126 | '<strong>', |
| 127 | '</strong>' |
| 128 | ); |
| 129 | ?> |
| 130 | </td> |
| 131 | </tr> |
| 132 | |
| 133 | <?php endif; ?> |
| 134 | </tbody> |
| 135 | </table> |
| 136 | <?php |
| 137 | } |
| 138 | |
| 139 | |
| 140 | /** |
| 141 | * Outputs tabular HTML with information on sync status and a button to trigger a manual sync. |
| 142 | * |
| 143 | * @since 2.0.0 |
| 144 | */ |
| 145 | private static function output_sync_status() { |
| 146 | |
| 147 | $is_connected = wc_square()->get_settings_handler()->is_connected(); |
| 148 | $sync_in_progress = $is_connected ? wc_square()->get_sync_handler()->is_sync_in_progress() : false; |
| 149 | $synced_products = wc_square()->get_settings_handler()->is_product_sync_enabled() ? Product::get_products_synced_with_square() : array(); |
| 150 | $synced_count = count( $synced_products ); |
| 151 | $is_product_import = false; |
| 152 | |
| 153 | if ( $sync_in_progress ) { |
| 154 | |
| 155 | $current_job = wc_square()->get_sync_handler()->get_job_in_progress(); |
| 156 | $is_product_import = isset( $current_job->action ) && 'product_import' === $current_job->action; |
| 157 | } |
| 158 | |
| 159 | if ( ! $is_connected ) { |
| 160 | $disabled_reason = esc_html__( 'Please connect to Square to enable product sync.', 'woocommerce-square' ); |
| 161 | } elseif ( ! wc_square()->get_settings_handler()->get_location_id() ) { |
| 162 | $disabled_reason = esc_html__( 'Please set the business location to enable product sync.', 'woocommerce-square' ); |
| 163 | } elseif ( 0 === $synced_count ) { |
| 164 | $disabled_reason = esc_html__( 'There are currently no products marked to be synced with Square.', 'woocommerce-square' ); |
| 165 | } elseif ( $sync_in_progress ) { |
| 166 | $disabled_reason = esc_html__( 'A sync is currently in progress. Please try again later.', 'woocommerce-square' ); |
| 167 | } |
| 168 | |
| 169 | if ( ! empty( $disabled_reason ) ) { |
| 170 | /* translators: Placeholder: %s - reason text */ |
| 171 | $disabled_reason = sprintf( esc_html__( 'Product sync between WooCommerce and Square is currently unavailable. %s', 'woocommerce-square' ), $disabled_reason ); |
| 172 | } |
| 173 | |
| 174 | ?> |
| 175 | <table class="wc_square_table sync widefat" cellspacing="0"> |
| 176 | <thead> |
| 177 | <tr> |
| 178 | <th class="synced-products"><?php esc_html_e( 'Synced products', 'woocommerce-square' ); ?></th> |
| 179 | <th class="latest-sync"><?php esc_html_e( 'Latest sync', 'woocommerce-square' ); ?></th> |
| 180 | <th class="next-sync"><?php esc_html_e( 'Next sync', 'woocommerce-square' ); ?></th> |
| 181 | <th class="actions"><?php esc_html_e( 'Actions', 'woocommerce-square' ); ?></th> |
| 182 | </tr> |
| 183 | </thead> |
| 184 | <tbody> |
| 185 | <tr> |
| 186 | <td class="synced-products"> |
| 187 | <a href="<?php echo esc_url( admin_url( 'edit.php?s&post_status=all&post_type=product&product_type=synced-with-square&stock_status&paged=1' ) ); ?>"> |
| 188 | <?php |
| 189 | printf( |
| 190 | /* translators: Placeholder: %d number of products synced with Square */ |
| 191 | esc_html( _n( '%d product', '%d products', $synced_count, 'woocommerce-square' ) ), |
| 192 | esc_html( $synced_count ) |
| 193 | ); |
| 194 | ?> |
| 195 | </a> |
| 196 | <input |
| 197 | type="hidden" |
| 198 | id="wc-square-sync-products-count" |
| 199 | value="<?php echo esc_attr( $synced_count ); ?>" |
| 200 | /> |
| 201 | </td> |
| 202 | |
| 203 | <?php $date_time_format = wc_date_format() . ' ' . wc_time_format(); ?> |
| 204 | |
| 205 | <td class="latest-sync"> |
| 206 | <p class="sync-result"> |
| 207 | <?php if ( $sync_in_progress ) : ?> |
| 208 | <?php if ( $is_product_import ) : ?> |
| 209 | <em><?php esc_html_e( 'Importing now…', 'woocommerce-square' ); ?></em> |
| 210 | <?php else : ?> |
| 211 | <em><?php esc_html_e( 'Syncing now…', 'woocommerce-square' ); ?></em> |
| 212 | <?php endif; ?> |
| 213 | <?php else : ?> |
| 214 | <?php $last_synced_at = wc_square()->get_sync_handler()->get_last_synced_at(); ?> |
| 215 | <?php if ( $last_synced_at ) : ?> |
| 216 | <?php |
| 217 | $last_synced_date = new \DateTime(); |
| 218 | $last_synced_date->setTimestamp( $last_synced_at ); |
| 219 | $last_synced_date->setTimezone( new \DateTimeZone( wc_timezone_string() ) ); |
| 220 | echo esc_html( $last_synced_date->format( $date_time_format ) ); |
| 221 | ?> |
| 222 | <?php else : ?> |
| 223 | <em><?php esc_html_e( 'Not synced yet.', 'woocommerce-square' ); ?></em> |
| 224 | <?php endif; ?> |
| 225 | <?php endif; ?> |
| 226 | </p> |
| 227 | </td> |
| 228 | <td class="next-sync"> |
| 229 | <p> |
| 230 | <?php if ( $sync_in_progress ) : ?> |
| 231 | — |
| 232 | <?php else : ?> |
| 233 | <?php $next_sync_at = wc_square()->get_sync_handler()->get_next_sync_at(); ?> |
| 234 | <?php if ( $next_sync_at ) : ?> |
| 235 | <?php |
| 236 | $next_sync_date = new \DateTime(); |
| 237 | $next_sync_date->setTimestamp( $next_sync_at ); |
| 238 | $next_sync_date->setTimezone( new \DateTimeZone( wc_timezone_string() ) ); |
| 239 | |
| 240 | echo esc_html( $next_sync_date->format( $date_time_format ) ); |
| 241 | ?> |
| 242 | <?php else : ?> |
| 243 | — |
| 244 | <?php endif; ?> |
| 245 | <?php endif; ?> |
| 246 | </p> |
| 247 | </td> |
| 248 | <td class="actions"> |
| 249 | <button |
| 250 | id="wc-square-sync" |
| 251 | class="button button-large" |
| 252 | <?php echo ! empty( $disabled_reason ) ? sprintf( 'disabled="disabled" title="%s"', esc_attr( $disabled_reason ) ) : ''; ?> |
| 253 | ><?php esc_html_e( 'Sync now', 'woocommerce-square' ); ?></button> |
| 254 | <div id="wc-square-sync-progress-spinner" class="spinner" style="float:none; <?php echo $sync_in_progress ? 'visibility:visible;' : ''; ?>"></div> |
| 255 | <?php if ( wc_square()->get_settings_handler()->is_system_of_record_square() ) : ?> |
| 256 | <p class="description" style="margin-top: 8px; font-style: italic; color: #646970;"> |
| 257 | <?php esc_html_e( 'Updates existing synced products only. Does not import new products from Square.', 'woocommerce-square' ); ?> |
| 258 | </p> |
| 259 | <?php endif; ?> |
| 260 | </td> |
| 261 | </tr> |
| 262 | </tbody> |
| 263 | </table> |
| 264 | <?php |
| 265 | } |
| 266 | |
| 267 | /** |
| 268 | * Outputs tabular HTML with sync record logs and UI. |
| 269 | * |
| 270 | * @since 2.0.0 |
| 271 | */ |
| 272 | private static function output_sync_records() { |
| 273 | |
| 274 | $records = Records::get_records(); |
| 275 | ?> |
| 276 | |
| 277 | <button |
| 278 | id="wc-square_clear-sync-records" |
| 279 | class="button button-large" |
| 280 | <?php |
| 281 | if ( empty( $records ) ) { |
| 282 | echo 'disabled="disabled"'; |
| 283 | } |
| 284 | ?> |
| 285 | ><?php echo esc_html_x( 'Clear history', 'Delete all records', 'woocommerce-square' ); ?></button> |
| 286 | |
| 287 | <table class="wc_square_table records widefat" cellspacing="0"> |
| 288 | <thead> |
| 289 | <tr> |
| 290 | <th class="date-time"><?php echo esc_html_x( 'Time', 'Date - Time', 'woocommerce-square' ); ?></th> |
| 291 | <th class="type"><?php esc_html_e( 'Status', 'woocommerce-square' ); ?></th> |
| 292 | <th class="message"><?php esc_html_e( 'Message', 'woocommerce-square' ); ?></th> |
| 293 | <th class="actions"><?php esc_html_e( 'Actions', 'woocommerce-square' ); ?></th> |
| 294 | </tr> |
| 295 | </thead> |
| 296 | <tbody> |
| 297 | <?php if ( ! empty( $records ) ) : ?> |
| 298 | |
| 299 | <?php foreach ( $records as $record ) : ?> |
| 300 | |
| 301 | <tr id="record-<?php echo esc_attr( $record->get_id() ); ?>"> |
| 302 | <td class="date-time"><?php echo esc_html( $record->get_local_date() ); ?></td> |
| 303 | <td class="type"><mark class="<?php echo esc_attr( sanitize_html_class( $record->get_type() ) ); ?>"><span><?php echo esc_html( $record->get_label() ); ?></span></mark></td> |
| 304 | <td class="message"><?php echo wp_kses_post( $record->get_message() ); ?></td> |
| 305 | <td class="actions"> |
| 306 | <?php foreach ( $record->get_actions() as $action ) : ?> |
| 307 | <button |
| 308 | class="button action <?php echo sanitize_html_class( $action->name ); ?> tips" |
| 309 | data-id="<?php echo esc_attr( $record->get_id() ); ?>" |
| 310 | data-action="<?php echo esc_attr( $action->name ); ?>" |
| 311 | data-tip="<?php echo esc_attr( $action->label ); ?>" |
| 312 | ><?php echo wp_kses_post( $action->icon ); ?></button> |
| 313 | <?php endforeach; ?> |
| 314 | </td> |
| 315 | </tr> |
| 316 | |
| 317 | <?php endforeach; ?> |
| 318 | |
| 319 | <?php else : ?> |
| 320 | |
| 321 | <tr> |
| 322 | <td colspan="4"> |
| 323 | <em><?php esc_html_e( 'No records found.', 'woocommerce-square' ); ?></em> |
| 324 | </td> |
| 325 | </tr> |
| 326 | |
| 327 | <?php endif; ?> |
| 328 | </tbody> |
| 329 | <tfoot> |
| 330 | <tr> |
| 331 | <th class="date-time"><?php echo esc_html_x( 'Time', 'Date - Time', 'woocommerce-square' ); ?></th> |
| 332 | <th class="type"><?php esc_html_e( 'Status', 'woocommerce-square' ); ?></th> |
| 333 | <th class="message"><?php esc_html_e( 'Message', 'woocommerce-square' ); ?></th> |
| 334 | <th class="actions"><?php esc_html_e( 'Actions', 'woocommerce-square' ); ?></th> |
| 335 | </tr> |
| 336 | </tfoot> |
| 337 | </table> |
| 338 | <?php |
| 339 | } |
| 340 | |
| 341 | |
| 342 | /** |
| 343 | * Outputs a backbone modal template for starting a manual sync process. |
| 344 | * |
| 345 | * @since 2.0.0 |
| 346 | */ |
| 347 | private static function output_sync_with_square_modal_template() { |
| 348 | |
| 349 | ?> |
| 350 | <script type="text/template" id="tmpl-wc-square-sync"> |
| 351 | <div class="wc-backbone-modal"> |
| 352 | <div class="wc-backbone-modal-content"> |
| 353 | <section class="wc-backbone-modal-main" role="main"> |
| 354 | <header class="wc-backbone-modal-header"> |
| 355 | <h1><?php esc_html_e( 'Sync products with Square', 'woocommerce-square' ); ?></h1> |
| 356 | <button class="modal-close modal-close-link dashicons dashicons-no-alt"> |
| 357 | <span class="screen-reader-text"><?php esc_html_e( 'Close modal window', 'woocommerce-square' ); ?></span> |
| 358 | </button> |
| 359 | </header> |
| 360 | <article> |
| 361 | <?php $square_settings = wc_square()->get_settings_handler(); ?> |
| 362 | <?php if ( $square_settings->is_system_of_record_square() ) : ?> |
| 363 | <p style="background: #fcf9e8; border-left: 4px solid #dba617; padding: 10px 12px; margin-bottom: 16px;"> |
| 364 | <strong><?php esc_html_e( 'Note:', 'woocommerce-square' ); ?></strong> |
| 365 | <?php esc_html_e( 'This will only update products that are already synced with Square. New products in Square will not be imported. To import new products, use "Import all Products from Square" on the Settings tab.', 'woocommerce-square' ); ?> |
| 366 | </p> |
| 367 | <?php endif; ?> |
| 368 | <?php ob_start(); ?> |
| 369 | <ul> |
| 370 | <?php if ( $square_settings->is_system_of_record_square() ) : ?> |
| 371 | <li><?php esc_html_e( 'If a match is found in Square, product data in WooCommerce will be overwritten with Square data.', 'woocommerce-square' ); ?></li> |
| 372 | <?php elseif ( $square_settings->is_system_of_record_woocommerce() ) : ?> |
| 373 | <li><?php esc_html_e( 'If a match is found in WooCommerce, product data in Square will be overwritten with WooCommerce data.', 'woocommerce-square' ); ?></li> |
| 374 | <?php endif; ?> |
| 375 | <?php if ( $square_settings->is_system_of_record_square() ) : ?> |
| 376 | <?php if ( $square_settings->hide_missing_square_products() ) : ?> |
| 377 | <li><?php esc_html_e( 'If a match is not found in Square, the product will be hidden from the catalog in WooCommerce.', 'woocommerce-square' ); ?></li> |
| 378 | <?php else : ?> |
| 379 | <li><?php esc_html_e( 'If a match is not found in Square, the product will be skipped in the sync.', 'woocommerce-square' ); ?></li> |
| 380 | <?php endif; ?> |
| 381 | <?php else : ?> |
| 382 | <li><?php esc_html_e( 'If a match is not found, a new product will be created in Square.', 'woocommerce-square' ); ?></li> |
| 383 | <?php endif; ?> |
| 384 | </ul> |
| 385 | <?php $additional_info = ob_get_clean(); ?> |
| 386 | <?php |
| 387 | printf( |
| 388 | /* translators: Placeholders: %1$s - the name of the system of record set in the sync settings (e.g. Square or WooCommerce), %3%s - unordered HTML list of additional information item(s) */ |
| 389 | esc_html__( 'You are about to sync products with Square. %1$s is your system of record set in the sync settings. For all products synced with Square: %2$s', 'woocommerce-square' ), |
| 390 | esc_html( $square_settings->get_system_of_record_name() ), |
| 391 | $additional_info // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- The contents of $additional_info is already escaped above. |
| 392 | ); |
| 393 | ?> |
| 394 | </article> |
| 395 | <footer> |
| 396 | <div class="inner"> |
| 397 | <button id="btn-close" class="button button-large"><?php esc_html_e( 'Cancel', 'woocommerce-square' ); ?></button> |
| 398 | <button id="btn-ok" class="button button-large button-primary"><?php esc_html_e( 'Start sync', 'woocommerce-square' ); ?></button> |
| 399 | </div> |
| 400 | </footer> |
| 401 | </section> |
| 402 | </div> |
| 403 | </div> |
| 404 | <div class="wc-backbone-modal-backdrop modal-close"></div> |
| 405 | </script> |
| 406 | <?php |
| 407 | } |
| 408 | |
| 409 | |
| 410 | } |
| 411 |