Changeset 3053833 for woocommerce-pos
- Timestamp:
- 03/18/2024 06:27:15 PM (13 months ago)
- Location:
- woocommerce-pos
- Files:
-
- 24 edited
- 1 copied
-
tags/1.4.12 (copied) (copied from woocommerce-pos/trunk)
-
tags/1.4.12/includes/API/Settings.php (modified) (2 diffs)
-
tags/1.4.12/includes/Admin/Menu.php (modified) (4 diffs)
-
tags/1.4.12/includes/Admin/Updaters/Pro_Plugin_Updater.php (modified) (21 diffs)
-
tags/1.4.12/includes/Admin/templates/upgrade.php (modified) (1 diff)
-
tags/1.4.12/includes/Form_Handler.php (modified) (3 diffs)
-
tags/1.4.12/includes/Services/Settings.php (modified) (2 diffs)
-
tags/1.4.12/readme.txt (modified) (2 diffs)
-
tags/1.4.12/vendor/autoload.php (modified) (1 diff)
-
tags/1.4.12/vendor/composer/autoload_real.php (modified) (2 diffs)
-
tags/1.4.12/vendor/composer/autoload_static.php (modified) (2 diffs)
-
tags/1.4.12/vendor/composer/installed.php (modified) (2 diffs)
-
tags/1.4.12/woocommerce-pos.php (modified) (3 diffs)
-
trunk/includes/API/Settings.php (modified) (2 diffs)
-
trunk/includes/Admin/Menu.php (modified) (4 diffs)
-
trunk/includes/Admin/Updaters/Pro_Plugin_Updater.php (modified) (21 diffs)
-
trunk/includes/Admin/templates/upgrade.php (modified) (1 diff)
-
trunk/includes/Form_Handler.php (modified) (3 diffs)
-
trunk/includes/Services/Settings.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/vendor/autoload.php (modified) (1 diff)
-
trunk/vendor/composer/autoload_real.php (modified) (2 diffs)
-
trunk/vendor/composer/autoload_static.php (modified) (2 diffs)
-
trunk/vendor/composer/installed.php (modified) (2 diffs)
-
trunk/woocommerce-pos.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
woocommerce-pos/tags/1.4.12/includes/API/Settings.php
r3020668 r3053833 35 35 public function __construct() { 36 36 add_filter( 'option_woocommerce_pos_settings_payment_gateways', array( $this, 'payment_gateways_settings' ) ); 37 38 // remove this once Pro settings have been moved to the new settings service. 39 add_filter( 'pre_update_option_woocommerce_pos_pro_settings_license', array( $this, 'remove_license_transient' ) ); 37 40 } 38 41 … … 544 547 return $options; 545 548 } 549 550 /** 551 * Temporary fix for stale license status transient. Remove when possible. 552 */ 553 public function remove_license_transient( $value ) { 554 delete_transient( 'woocommerce_pos_pro_license_status' ); 555 return $value; 556 } 546 557 } -
woocommerce-pos/tags/1.4.12/includes/Admin/Menu.php
r3048280 r3053833 13 13 use const HOUR_IN_SECONDS; 14 14 use const WCPOS\WooCommercePOS\PLUGIN_NAME; 15 use const WCPOS\WooCommercePOS\VERSION as PLUGIN_VERSION; 15 16 16 17 /** … … 40 41 add_filter( 'custom_menu_order', '__return_true' ); 41 42 add_filter( 'menu_order', array( $this, 'menu_order' ), 9, 1 ); 43 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_landing_scripts_and_styles' ) ); 42 44 } 43 45 … … 80 82 */ 81 83 public function display_upgrade_page(): void { 82 $upgrade = get_transient( 'remote_pro_page' );83 84 // Check for transient, if none, grab remote HTML file85 if ( false === $upgrade ) {86 // Get remote HTML file87 $response = wp_remote_get( 'http://wcpos.com/pro/?wp-admin=woocommerce-pos' );88 // Check for error89 if ( is_wp_error( $response ) ) {90 return;91 }92 // Parse remote HTML file93 $upgrade = wp_remote_retrieve_body( $response );94 // Check for error95 if ( is_wp_error( $upgrade ) ) {96 return;97 }98 // Store remote HTML file in transient, expire after 24 hours99 set_transient( 'remote_pro_page', $upgrade, 24 * HOUR_IN_SECONDS );100 }101 84 include_once 'templates/upgrade.php'; 102 85 } … … 193 176 ); 194 177 } 178 179 /** 180 * Enqueue landing page scripts and styles. 181 */ 182 public function enqueue_landing_scripts_and_styles( $hook_suffix ): void { 183 if ( $hook_suffix === $this->toplevel_screen_id ) { 184 $is_development = isset( $_ENV['DEVELOPMENT'] ) && $_ENV['DEVELOPMENT']; 185 $url = $is_development ? 'http://localhost:9000/' : 'https://cdn.jsdelivr.net/gh/wcpos/wp-admin-landing/assets/'; 186 187 // Enqueue the landing page CSS from CDN 188 wp_enqueue_style( 189 'wcpos-landing', 190 $url . 'css/landing.css', 191 array(), 192 PLUGIN_VERSION 193 ); 194 195 // Ensure WordPress bundled React and lodash are loaded as dependencies 196 wp_enqueue_script( 'react' ); 197 wp_enqueue_script( 'lodash' ); 198 199 // Enqueue the landing page JS from CDN, with React and lodash as dependencies 200 wp_enqueue_script( 201 'wcpos-landing', 202 $url . 'js/landing.js', 203 array( 204 'react', 205 'react-dom', 206 'wp-element', 207 'lodash', 208 ), 209 PLUGIN_VERSION, 210 true 211 ); 212 } 213 } 195 214 } -
woocommerce-pos/tags/1.4.12/includes/Admin/Updaters/Pro_Plugin_Updater.php
r3021613 r3053833 27 27 28 28 /** 29 * The path to the Pro plugin30 *31 * @var string $pro_plugin_path32 */33 private $pro_plugin_path = 'woocommerce-pos-pro/woocommerce-pos-pro.php';34 35 /**36 29 * The update server URL 37 30 * … … 45 38 * @var string $update_data_transient_key 46 39 */ 47 private $update_data_transient_key = 'woocommerce_pos_pro_update_data'; 48 40 public static $update_data_transient_key = 'woocommerce_pos_pro_update_data'; 41 42 /** 43 * Transient key for the update data 44 * 45 * @var string $license_status_transient_key 46 */ 47 public static $license_status_transient_key = 'woocommerce_pos_pro_license_status'; 48 49 /** 50 * Installed Pro plugins 51 * Note: Generally this would be an array of 1 installed Pro plugins but 52 * it's possible an older version of the plugin is installed in a different directory. 53 * 54 * @var array $installed_pro_plugins 55 */ 56 private $installed_pro_plugins = array(); 57 58 /** 59 * Constructor. 60 */ 61 public function __construct() { 49 62 /** 50 * Transient key for the update data 51 * 52 * @var string $update_data_transient_key 63 * First we need to check if the Pro plugin is installed (one or more versions) 53 64 */ 54 private $license_status_transient_key = 'woocommerce_pos_pro_license_status';55 56 /**57 * Whether the Pro plugin is installed58 *59 * @var bool $installed60 */61 private $installed;62 63 /**64 * Whether the Pro plugin is active65 *66 * @var bool $active67 */68 private $active;69 70 /**71 * The current version of the Pro plugin72 *73 * @var string $current_version74 */75 private $current_version;76 77 /**78 * Constructor.79 */80 public function __construct() {81 // Ensure the necessary functions are available82 65 include_once ABSPATH . 'wp-admin/includes/plugin.php'; 83 84 $status = $this->check_pro_plugin_status(); 85 $this->installed = $status['installed']; 86 $this->active = $status['active']; 87 $this->current_version = $status['version']; 66 $all_plugins = get_plugins(); 67 foreach ( $all_plugins as $plugin_path => $plugin_data ) { 68 $plugin_dir = dirname( $plugin_path ); 69 if ( strpos( $plugin_dir, $this->pro_plugin_slug ) === 0 ) { 70 if ( isset( $plugin_data['UpdateURI'] ) && $plugin_data['UpdateURI'] == $this->update_server ) { 71 $this->installed_pro_plugins[ $plugin_path ] = $plugin_data; 72 } 73 } 74 } 88 75 89 76 // Allow the update server to be overridden for development. … … 92 79 } 93 80 94 if ( $this->installed) {81 if ( count( $this->installed_pro_plugins ) > 0 ) { 95 82 add_filter( 'update_plugins_updates.wcpos.com', array( $this, 'update_plugins' ), 10, 4 ); 96 83 add_action( 'upgrader_process_complete', array( $this, 'after_plugin_update' ), 10, 2 ); 97 84 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 4 ); 98 add_action( 'in_plugin_update_message-' . $this->pro_plugin_path, array( $this, 'plugin_update_message' ), 10, 2 );99 85 add_action( 'install_plugins_pre_plugin-information', array( $this, 'plugin_information' ), 5 ); 100 } 101 } 102 103 /** 104 * Check the status of the Pro plugin 105 * 106 * @return array( 107 * 'installed' => bool, 108 * 'active' => bool, 109 * 'version' => string|null, 110 * ) 111 */ 112 public function check_pro_plugin_status() { 113 $status = array( 114 'installed' => false, 115 'active' => false, 116 'version' => null, 117 ); 118 119 // Check if the Pro plugin file exists. 120 if ( file_exists( WP_PLUGIN_DIR . '/' . $this->pro_plugin_path ) ) { 121 $status['installed'] = true; 122 $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $this->pro_plugin_path ); 123 $status['version'] = $plugin_data['Version']; 124 125 // Check if the Pro plugin is active. 126 if ( is_plugin_active( $this->pro_plugin_path ) ) { 127 $status['active'] = true; 128 } 129 } 130 131 /** 132 * This is a hack to manually trigger Pro update for version < 1.4.0 133 * TODO: remove this after 1.4.0 is released for a while 134 */ 135 if ( $status['version'] && version_compare( $status['version'], '1.4.0', '<' ) ) { 136 // Manually the update_plugins transient 137 $update_plugins = get_site_transient( 'update_plugins' ); 138 if ( ! is_object( $update_plugins ) ) { 139 $update_plugins = new stdClass(); 140 } 141 142 $license_settings = $this->get_license_settings(); 143 $key = isset( $license_settings['key'] ) ? $license_settings['key'] : ''; 144 $instance = isset( $license_settings['instance'] ) ? $license_settings['instance'] : ''; 145 146 // Construct the download URL, taking into account the environment 147 $package_url = add_query_arg( 148 array( 149 'key' => urlencode( $key ), 150 'instance' => urlencode( $instance ), 151 ), 152 'https://updates.wcpos.com/pro/download/1.4.1' 153 ); 154 155 $update = array( 156 'id' => 'https://updates.wcpos.com', 157 'slug' => 'woocommerce-pos-pro', 158 'plugin' => $this->pro_plugin_path, 159 'new_version' => '1.4.1', 160 'url' => 'https://wcpos.com/pro', 161 'package' => $package_url, 162 'requires' => '5.6', 163 'tested' => '6.5', 164 'requires_php' => '7.4', 165 'icons' => array( 166 '1x' => 'https://wcpos.com/wp-content/uploads/2014/06/woopos-pro.png', 167 ), 168 'upgrade_notice' => $this->maybe_add_upgrade_notice(), 169 ); 170 171 $update_plugins->response[ $this->pro_plugin_path ] = (object) $update; 172 173 set_site_transient( 'update_plugins', $update_plugins ); 174 } 175 176 return $status; 86 add_action( 'admin_enqueue_scripts', array( $this, 'license_status_styles' ) ); 87 88 // loop through the installed Pro plugins. 89 foreach ( $this->installed_pro_plugins as $plugin_path => $plugin_data ) { 90 add_action( 'in_plugin_update_message-' . $plugin_path, array( $this, 'plugin_update_message' ), 10, 2 ); 91 add_action( 'after_plugin_row_' . $plugin_path, array( $this, 'license_status_notice' ), 99 ); 92 93 /** 94 * This is a hack to manually trigger Pro update for version < 1.4.0 95 * TODO: remove this after 1.4.0 is released for a while 96 */ 97 if ( isset( $plugin_data['Version'] ) && version_compare( $plugin_data['Version'], '1.4.0', '<' ) ) { 98 $this->remove_this_hack_for_older_versions( $plugin_path ); 99 } 100 } 101 } 177 102 } 178 103 … … 212 137 */ 213 138 public function update_plugins( $update, $plugin_data, $plugin_file, $locales ) { 214 $update_data = $this->check_pro_plugin_updates(); 139 $current_version = isset( $plugin_data['Version'] ) ? $plugin_data['Version'] : '1'; 140 $update_data = $this->check_pro_plugin_updates( $current_version ); 215 141 $is_development = isset( $_ENV['DEVELOPMENT'] ) && $_ENV['DEVELOPMENT']; 216 142 217 143 // Check if update data is valid and if a new version is available. 218 if ( ! is_wp_error( $update_data ) && is_object( $update_data ) && isset( $update_data->version ) ) { 219 $latest_version = $update_data->version; 220 221 // No update needed if the current version is greater than the latest version. 222 if ( version_compare( $this->current_version, $latest_version, '>' ) ) { 223 return $update; 224 } 225 144 if ( isset( $update_data['version'] ) && version_compare( $current_version, $update_data['version'], '<' ) ) { 226 145 $license_settings = $this->get_license_settings(); 227 146 $key = isset( $license_settings['key'] ) ? $license_settings['key'] : ''; … … 244 163 'id' => 'https://updates.wcpos.com', 245 164 'slug' => 'woocommerce-pos-pro', 246 'plugin' => $ this->pro_plugin_path,247 'version' => $ latest_version,165 'plugin' => $plugin_file, 166 'version' => $update_data['version'], 248 167 'url' => 'https://wcpos.com/pro', 249 168 'package' => $package_url, … … 264 183 * Check for updates to the Pro plugin 265 184 * 266 * @param bool $force Force an update check. 267 */ 268 public function check_pro_plugin_updates( $force = false ) { 269 $update_data = get_transient( $this->update_data_transient_key ); 185 * @param string $version The current plugin version. 186 * @param bool $force Force an update check. 187 */ 188 public function check_pro_plugin_updates( $version = '1', $force = false ) { 189 $update_data = get_transient( self::$update_data_transient_key ); 270 190 271 191 if ( empty( $update_data ) || $force ) { 272 192 $expiration = 60 * 60 * 12; // 12 hours. 273 $url = $this->update_server . '/update/' . $ this->current_version;193 $url = $this->update_server . '/update/' . $version; 274 194 275 195 // make the api call. … … 277 197 $url, 278 198 array( 279 'timeout' => wp_doing_cron() ? 10 : 3,199 'timeout' => wp_doing_cron() ? 10 : 5, 280 200 'headers' => array( 281 201 'Accept' => 'application/json', … … 285 205 286 206 $data = $this->validate_api_response( $response ); 287 288 // Ensure $data has version, download_url and notes. 289 if ( ! is_wp_error( $data ) ) { 207 $error = isset( $data['is_error'] ) && $data['is_error'] ? $data : false; 208 209 // Ensure $data is an associative array and has version, download_url, and notes. 210 if ( ! $error && is_array( $data ) ) { 290 211 $expected_properties = array( 'version', 'download_url', 'notes' ); 291 212 foreach ( $expected_properties as $property ) { 292 if ( ! property_exists( $data, $property) ) {213 if ( ! array_key_exists( $property, $data ) ) { 293 214 $data = new WP_Error( 'invalid_response_structure', "Missing expected property: $property" ); 294 215 break; 295 216 } 296 217 } 297 } 298 299 if ( is_wp_error( $data ) ) { 218 } else { 300 219 Logger::log( $data ); 301 220 $expiration = 60 * 60 * 1; // try again in an hour if error. 302 221 } 303 222 304 set_transient( $this->update_data_transient_key, $data, $expiration ); 223 $success = set_transient( self::$update_data_transient_key, $data, $expiration ); 224 if ( ! $success ) { 225 Logger::log( 'Failed to set update data transient' ); 226 } 227 228 return $data; 305 229 } 306 230 … … 314 238 */ 315 239 private function check_license_status( $force = false ) { 316 $license_status = get_transient( $this->license_status_transient_key );240 $license_status = get_transient( self::$license_status_transient_key ); 317 241 $expiration = 60 * 60 * 12; // 12 hours. 318 242 … … 320 244 * TODO: How to allow for multisite? 321 245 */ 322 if ( is_multisite() ) { 323 $error = new WP_Error( 'multisite_update', 'Please go to http://wcpos.com/my-account to download update.' ); 324 set_transient( $this->license_status_transient_key, $error, $expiration ); 325 return $error; 326 } 246 // if ( is_multisite() ) { 247 // $error = array( 248 // 'code' => 'multisite_update', 249 // 'message' => 'Please go to http://wcpos.com/my-account to download update.', 250 // ); 251 // set_transient( $this->license_status_transient_key, $error, $expiration ); 252 // return $error; 253 // } 327 254 328 255 $license_settings = $this->get_license_settings(); … … 335 262 if ( empty( $key ) || empty( $instance ) ) { 336 263 // set the transient to an error. 337 $error = new WP_Error( 'missing_license_key', 'License key is not activated.' ); 338 set_transient( $this->license_status_transient_key, $error, $expiration ); 264 $error = array( 265 'is_error' => true, 266 'code' => 'missing_license_key', 267 'message' => 'License key is not activated.', 268 ); 269 set_transient( self::$license_status_transient_key, $error, $expiration ); 339 270 return $error; 340 271 } … … 354 285 $url, 355 286 array( 356 'timeout' => wp_doing_cron() ? 10 : 3,287 'timeout' => wp_doing_cron() ? 10 : 5, 357 288 'headers' => array( 358 289 'Accept' => 'application/json', … … 362 293 363 294 $data = $this->validate_api_response( $response ); 364 365 if ( is_wp_error( $data ) ) { 366 Logger::log( $data ); 367 $expiration = 60 * 60 * 1; // try again in an hour if error. 368 } 369 370 set_transient( $this->license_status_transient_key, $data, $expiration ); 295 $error = isset( $data['is_error'] ) && $data['is_error'] ? $data : false; 296 297 if ( $error ) { 298 Logger::log( $error ); 299 } 300 301 $success = set_transient( self::$license_status_transient_key, $data, $expiration ); 302 if ( ! $success ) { 303 Logger::log( 'Failed to set license status transient' ); 304 } 305 306 return $data; 371 307 } 372 308 … … 383 319 public function validate_api_response( $response ) { 384 320 if ( is_wp_error( $response ) ) { 385 return $response; 386 } 387 388 $decoded_response = json_decode( $response['body'] ); 321 return array( 322 'is_error' => true, 323 'code' => $response->get_error_code(), 324 'message' => $response->get_error_message(), 325 ); 326 } 327 328 $decoded_response = json_decode( $response['body'], true ); // Decode as associative array. 389 329 if ( null === $decoded_response ) { 390 return new WP_Error( 'invalid_json', 'Invalid JSON in response', $response['body'] ); 330 return array( 331 'is_error' => true, 332 'code' => 'invalid_json', 333 'message' => 'Invalid JSON in response', 334 'data' => $response['body'], 335 ); 336 } 337 338 if ( $response['response']['code'] === 403 ) { 339 return array( 340 'is_error' => true, 341 'expired' => true, 342 'code' => 'license_expired', 343 'message' => isset( $decoded_response['error'] ) ? $decoded_response['error'] : 'License expired.', 344 ); 391 345 } 392 346 393 347 if ( $response['response']['code'] !== 200 ) { 394 $error = isset( $decoded_response->error ) ? $decoded_response->error : 'No error message returned from server'; 395 return new WP_Error( 'invalid_response_code', $error ); 348 return array( 349 'is_error' => true, 350 'code' => 'invalid_response_code', 351 'message' => isset( $decoded_response['error'] ) ? $decoded_response['error'] : 'No error message returned from server.', 352 ); 396 353 } 397 354 398 355 // Ensure $decoded_response has the expected structure. 399 if ( ! isset( $decoded_response->data ) ) { 400 return new WP_Error( 'invalid_response_structure', 'Missing expected property: data' ); 401 } 402 403 return $decoded_response->data; 404 } 405 406 407 /** 408 * Create an update response object for the WordPress transient 409 * NOTE: this transient is different to the one we use to store the update data 410 * 411 * @param array $args { 412 * Arguments for creating the update data object. 413 * 414 * @type string $new_version New plugin version. 415 * @type string $package Plugin update package URL. 416 * } 417 * @return object { 418 * An object of metadata about the available plugin update. 419 * 420 * @type string $id Plugin ID, e.g. `w.org/plugins/[plugin-name]`. 421 * @type string $slug Plugin slug. 422 * @type string $plugin Plugin basename. 423 * @type string $new_version New plugin version. 424 * @type string $url Plugin URL. 425 * @type string $package Plugin update package URL. 426 * @type string[] $icons An array of plugin icon URLs. 427 * @type string[] $banners An array of plugin banner URLs. 428 * @type string[] $banners_rtl An array of plugin RTL banner URLs. 429 * @type string $requires The version of WordPress which the plugin requires. 430 * @type string $tested The version of WordPress the plugin is tested against. 431 * @type string $requires_php The version of PHP which the plugin requires. 432 * } 433 */ 434 private function create_update_response_object( $args = array() ) { 435 $defaults = array( 436 'id' => '0', 437 'slug' => 'woocommerce-pos-pro', 438 'plugin' => $this->pro_plugin_path, 439 'url' => 'https://wcpos.com/pro', 440 'requires' => '5.6', 441 'tested' => '6.5', 442 'requires_php' => '7.4', 443 'icons' => array( 444 '1x' => 'https://wcpos.com/wp-content/uploads/2014/06/woopos-pro.png', 445 ), 446 ); 447 448 $parsed_args = wp_parse_args( $args, $defaults ); 449 450 $update_obj = new \stdClass(); 451 foreach ( $parsed_args as $key => $value ) { 452 $update_obj->$key = $value; 453 } 454 455 return $update_obj; 356 if ( ! isset( $decoded_response['data'] ) ) { 357 return array( 358 'is_error' => true, 359 'code' => 'invalid_response_structure', 360 'message' => 'Missing expected property: data', 361 ); 362 } 363 364 return $decoded_response['data']; 456 365 } 457 366 … … 465 374 if ( $options['action'] == 'update' && $options['type'] == 'plugin' ) { 466 375 if ( isset( $options['plugins'] ) && in_array( 'woocommerce-pos/woocommerce-pos.php', $options['plugins'] ) ) { 467 delete_transient( $this->update_data_transient_key ); 468 $this->check_pro_plugin_updates(); 376 delete_transient( self::$update_data_transient_key ); 469 377 } 470 378 } … … 520 428 */ 521 429 public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $status ) { 522 if ( $plugin_file !== $this->pro_plugin_path ) {523 return $plugin_meta;524 }525 526 430 // $license_status = 'Your license status here'; // Fetch or generate your license status message 527 431 // $plugin_meta[] = '<span style="color: #d63638;">' . esc_html( $license_status ) . '</span>'; … … 560 464 */ 561 465 public function plugin_update_message( $plugin_data, $response ) { 562 if ( $response->plugin !== $this->pro_plugin_path ) { 563 return; 564 } 565 566 $license_status = $this->check_license_status(); 567 if ( ! is_wp_error( $license_status ) ) { 568 return; 569 } 570 571 $message = 'Your license has expired. <a href="http://wcpos.com/my-account/">Please renew</> to update.'; 572 573 if ( $license_status->get_error_code() === 'missing_license_key' ) { 574 $message = $license_status->get_error_message(); 575 } 576 577 echo '<br /><span style="color: #d63638;">' . wp_kses_post( $message ) . '</span>'; 466 // Nothing at the moment. 467 468 // $message = 'Your license has expired. <a href="http://wcpos.com/my-account/">Please renew</> to update.'; 469 470 // if ( $license_status->get_error_code() === 'missing_license_key' ) { 471 // $message = $license_status->get_error_message(); 472 // } 473 474 // echo '<br /><span style="color: #d63638;">' . wp_kses_post( $message ) . '</span>'; 578 475 } 579 476 … … 588 485 } 589 486 590 $update_data = get_transient( $this->update_data_transient_key );591 $message = 'Something went wrong. Please try again later.';487 $update_data = get_transient( self::$update_data_transient_key ); 488 $message = esc_html__( 'Something went wrong. Please try again later.', 'woocommerce-pos' ); 592 489 593 490 if ( is_wp_error( $update_data ) ) { … … 600 497 } 601 498 499 /* translators: WordPress */ 602 500 iframe_header( __( 'Plugin Installation' ) ); 603 501 … … 640 538 private function maybe_add_upgrade_notice() { 641 539 $license_status = $this->check_license_status(); 642 if ( ! is_wp_error( $license_status ) ) { 540 $active = isset( $license_status['activated'] ) && $license_status['activated']; 541 $inactive = isset( $license_status['activated'] ) && ! $license_status['activated']; 542 $expired = isset( $license_status['expired'] ) && $license_status['expired']; 543 544 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 545 $inactive = isset( $license_status['code'] ) && 546 in_array( 547 $license_status['code'], 548 array( 549 'missing_license_key', // no license key is set. 550 'invalid_response_code', // usually the key or instance is wrong length. 551 ) 552 ); 553 } 554 555 if ( $inactive ) { 556 return esc_html__( 'Your WooCommerce Pro license is inactive', 'woocommerce-pos' ); 557 } 558 559 if ( $expired ) { 560 return esc_html__( 'Your WooCommerce Pro license has expired', 'woocommerce-pos' ); 561 } 562 563 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 564 return $license_status['message']; 565 } 566 } 567 568 /** 569 * Add a notice to the plugin update table on Dashboard > Updates 570 */ 571 public function license_status_notice() { 572 $license_status = $this->check_license_status(); 573 $active = isset( $license_status['activated'] ) && $license_status['activated']; 574 $inactive = isset( $license_status['activated'] ) && ! $license_status['activated']; 575 $expired = isset( $license_status['expired'] ) && $license_status['expired']; 576 577 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 578 $inactive = isset( $license_status['code'] ) && 579 in_array( 580 $license_status['code'], 581 array( 582 'missing_license_key', // no license key is set. 583 'invalid_response_code', // usually the key or instance is wrong length. 584 ) 585 ); 586 } 587 588 if ( $active ) { 589 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 590 <td colspan="4" class="plugin-update colspanchange"> 591 <div class="update-message notice inline wcpos-active" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #5D9B5C;background-color:#F8FFF1;"> 592 <p class="installer-q-icon">' . 593 esc_html__( 'Your WooCommerce Pro license is valid and active.', 'woocommerce-pos' ) . 594 ' ' . 595 esc_html__( 'You are receiving plugin updates.', 'woocommerce-pos' ) 596 . '</p> 597 </div> 598 </td> 599 </tr>'; 643 600 return; 644 601 } 645 602 646 if ( $license_status->get_error_code() === 'missing_license_key' ) { 647 return $license_status->get_error_message(); 648 } 649 650 return 'Your license has expired. Please renew to update.'; 603 if ( $inactive ) { 604 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 605 <td colspan="4" class="plugin-update colspanchange"> 606 <div class="update-message notice inline wcpos-inactive" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #BD5858;background-color:#FFF8E1;"> 607 <p class="installer-q-icon">' . 608 esc_html__( 'Your WooCommerce Pro license is inactive.', 'woocommerce-pos' ) . 609 ' ' . 610 sprintf( 611 wp_kses( 612 __( '<a href="%s">Click here</a> to activate your license key.', 'woocommerce-pos' ), 613 array( 'a' => array( 'href' => array() ) ) 614 ), 615 esc_url( admin_url( 'admin.php?page=woocommerce-pos-settings#license' ) ) 616 ) 617 . '</p> 618 </div> 619 </td> 620 </tr>'; 621 return; 622 } 623 624 if ( $expired ) { 625 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 626 <td colspan="4" class="plugin-update colspanchange"> 627 <div class="update-message notice inline wcpos-expired" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #D63638;background-color:#FFF7F7;"> 628 <p class="installer-q-icon">' . 629 esc_html__( 'Your WooCommerce Pro license has expired.', 'woocommerce-pos' ) . 630 ' ' . 631 sprintf( 632 wp_kses( 633 __( '<a href="%s">Please renew</a> to receive updates.', 'woocommerce-pos' ), 634 array( 'a' => array( 'href' => array() ) ) 635 ), 636 'https://wcpos.com/my-account/' 637 ) 638 . '</p> 639 </div> 640 </td> 641 </tr>'; 642 return; 643 } 644 645 $message = esc_html__( 'Something went wrong. Please try again later.', 'woocommerce-pos' ); 646 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 647 $message = $license_status['message']; 648 } 649 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 650 <td colspan="4" class="plugin-update colspanchange"> 651 <div class="update-message notice inline wcpos-expired" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #D63638;background-color:#FFF7F7;"> 652 <p class="installer-q-icon">' . $message . '</p> 653 </div> 654 </td> 655 </tr>'; 656 } 657 658 /** 659 * Add some styles for the license status notice 660 * 661 * @param string $hook The current admin page. 662 */ 663 public function license_status_styles( $hook ) { 664 if ( 'plugins.php' === $hook ) { 665 wp_register_style( 'woocommerce-pos-styles', false ); 666 wp_enqueue_style( 'woocommerce-pos-styles' ); 667 668 $css = ' 669 .woocommerce-pos-pro-license .wcpos-active p::before { 670 content: "\f12a"; 671 color: #4d7d4c; 672 width: 25px; 673 } 674 .woocommerce-pos-pro-license .wcpos-inactive p::before { 675 content: "\f112"; 676 color: #bd5858; 677 width: 25px; 678 } 679 .woocommerce-pos-pro-license .wcpos-expired p::before { 680 width: 25px; 681 } 682 '; 683 wp_add_inline_style( 'woocommerce-pos-styles', $css ); 684 } 651 685 } 652 686 … … 657 691 */ 658 692 private function get_license_settings() { 659 if ( ! $this->active ) { 660 if ( file_exists( WP_PLUGIN_DIR . '/woocommerce-pos-pro/includes/Services/Settings.php' ) ) { 661 include_once WP_PLUGIN_DIR . '/woocommerce-pos-pro/includes/Services/Settings.php'; 662 if ( method_exists( '\WCPOS\WooCommercePOSPro\Services\Settings', '_get_inactive_license_settings' ) ) { 663 return \WCPOS\WooCommercePOSPro\Services\Settings::_get_inactive_license_settings(); 664 } 665 } 666 } 667 return woocommerce_pos_get_settings( 'license' ); 693 // first check if any Pro plugins are active. 694 foreach ( $this->installed_pro_plugins as $plugin_path => $plugin_data ) { 695 if ( is_plugin_active( $plugin_path ) ) { 696 return woocommerce_pos_get_settings( 'license' ); 697 } 698 } 699 700 // else, try and get the settings from the first Pro plugin. 701 $first_folder = dirname( array_key_first( $this->installed_pro_plugins ) ); 702 if ( file_exists( WP_PLUGIN_DIR . '/' . $first_folder . '/includes/Services/Settings.php' ) ) { 703 include_once WP_PLUGIN_DIR . '/' . $first_folder . '/includes/Services/Settings.php'; 704 if ( method_exists( '\WCPOS\WooCommercePOSPro\Services\Settings', '_get_inactive_license_settings' ) ) { 705 return \WCPOS\WooCommercePOSPro\Services\Settings::_get_inactive_license_settings(); 706 } 707 } 708 } 709 710 /** 711 * Temporary fix for older versions of the Pro plugin 712 * 713 * @param string $plugin_path The plugin path. 714 */ 715 private function remove_this_hack_for_older_versions( $plugin_path ) { 716 // Manually the update_plugins transient 717 $update_plugins = get_site_transient( 'update_plugins' ); 718 if ( ! is_object( $update_plugins ) ) { 719 $update_plugins = new stdClass(); 720 $update_plugins->response = array(); 721 } 722 723 $license_settings = $this->get_license_settings(); 724 $key = isset( $license_settings['key'] ) ? $license_settings['key'] : ''; 725 $instance = isset( $license_settings['instance'] ) ? $license_settings['instance'] : ''; 726 727 // Construct the download URL, taking into account the environment. 728 $package_url = add_query_arg( 729 array( 730 'key' => urlencode( $key ), 731 'instance' => urlencode( $instance ), 732 ), 733 'https://updates.wcpos.com/pro/download/1.4.5' 734 ); 735 736 $update = array( 737 'id' => 'https://updates.wcpos.com', 738 'slug' => 'woocommerce-pos-pro', 739 'plugin' => $plugin_path, 740 'new_version' => '1.4.5', 741 'url' => 'https://wcpos.com/pro', 742 'package' => $package_url, 743 'requires' => '5.6', 744 'tested' => '6.5', 745 'requires_php' => '7.4', 746 'icons' => array( 747 '1x' => 'https://wcpos.com/wp-content/uploads/2014/06/woopos-pro.png', 748 ), 749 'upgrade_notice' => $this->maybe_add_upgrade_notice(), 750 ); 751 752 $update_plugins->response[ $plugin_path ] = (object) $update; 753 754 set_site_transient( 'update_plugins', $update_plugins ); 668 755 } 669 756 } -
woocommerce-pos/tags/1.4.12/includes/Admin/templates/upgrade.php
r2845568 r3053833 5 5 * @author Paul Kilmurray <paul@kilbot.com.au> 6 6 * 7 * @see http://www.kilbot.com .au7 * @see http://www.kilbot.com 8 8 */ 9 9 ?> 10 10 11 <!-- temporary inline css, todo: remove this --> 12 <style type="text/css"> 13 .web-title { 14 display: none; 15 } 11 <div class="wrap clear"> 16 12 17 .blurb { 18 font-size: 14px; 19 line-height: 1.6em; 20 } 21 22 .widget-area { 23 float: right; 24 width: 33%; 25 margin-left: 20px; 26 text-align: center; 27 margin-bottom: 20px; 28 } 29 30 .widget-area .btn { 31 display: inline-block; 32 margin-bottom: 0; 33 font-weight: 400; 34 text-align: center; 35 vertical-align: middle; 36 cursor: pointer; 37 background-image: none; 38 border: 1px solid transparent; 39 white-space: nowrap; 40 text-decoration: none; 41 margin: 20px 0; 42 } 43 44 .widget-area .btn-primary { 45 color: #fff; 46 background-color: #cd2f19; 47 border-color: #b62a16; 48 } 49 50 .widget-area .btn-lg { 51 padding: 10px 16px; 52 font-size: 18px; 53 line-height: 1.33; 54 border-radius: 6px; 55 } 56 57 .comparison-table { 58 width: 100%; 59 border-spacing: 0; 60 border-collapse: collapse; 61 border: 1px solid #e5e5e5; 62 box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); 63 background-color: #f5f5f5; 64 } 65 66 .comparison-table thead { 67 font-size: 18px; 68 } 69 70 .comparison-table thead tr { 71 border-bottom: 1px solid #e5e5e5; 72 } 73 74 .comparison-table thead th { 75 width: 33%; 76 font-weight: normal; 77 } 78 79 .comparison-table thead th:first-of-type { 80 background-color: #B0B0B0; 81 color: #f5f5f5; 82 } 83 84 .comparison-table thead th:last-of-type { 85 background-color: #d54e21; 86 color: #f5f5f5; 87 } 88 89 .comparison-table th, td { 90 padding: 1% 2%; 91 } 92 93 .comparison-table tbody th { 94 font-weight: normal; 95 text-align: right; 96 } 97 98 .comparison-table tbody tr { 99 border-bottom: 1px solid #e5e5e5; 100 } 101 102 .comparison-table tbody tr td:first-of-type { 103 background-color: #fafafa; 104 } 105 106 .comparison-table tbody tr td:last-of-type { 107 background-color: #fef7f1; 108 } 109 110 .comparison-table .fa { 111 font-family: Dashicons !important;; 112 speak: none; 113 font-style: normal; 114 font-weight: normal; 115 font-variant: normal; 116 text-transform: none; 117 -webkit-font-smoothing: antialiased; 118 -moz-osx-font-smoothing: grayscale; 119 } 120 121 .comparison-table .fa-check:before { 122 content: "\f147"; 123 color: #3c763d; 124 font-size: 24px; 125 } 126 127 .comparison-table .fa-times:before { 128 content: "\f335"; 129 color: #a94442; 130 font-size: 24px; 131 } 132 </style> 133 134 <div class="wrap clear woocommerce-pos-upgrade"> 135 136 <!-- 13 <!-- 137 14 Little trick to get around WP js injection of admin notices 138 15 WP js looks for first h2 in .wrap and appends notices, so we'll make the first one hidden 139 16 https://github.com/WordPress/WordPress/blob/master/wp-admin/js/common.js 140 17 --> 141 <h2 style="display:none"></h2>18 <h2 style="display:none"></h2> 142 19 143 <h2 style="margin:20px 0;">Thank you for using WooCommerce POS!</h2> 144 145 <?php echo $upgrade; ?> 20 <div id="woocommerce-pos-upgrade"></div> 146 21 147 22 </div> 148 -
woocommerce-pos/tags/1.4.12/includes/Form_Handler.php
r2929317 r3053833 1 1 <?php 2 /** 3 * 4 */ 2 5 3 6 namespace WCPOS\WooCommercePOS; 4 7 8 use WCPOS\WooCommercePOS\Services\Auth as AuthService; 9 10 /** 11 * 12 */ 5 13 class Form_Handler { 6 14 … … 28 36 global $wp; 29 37 30 if ( woocommerce_pos_request() && isset( $_POST['woocommerce_pay'], $_GET['key'] ) ) {38 if ( woocommerce_pos_request() && isset( $_POST['woocommerce_pay'], $_GET['key'], $_GET['token'] ) ) { 31 39 $order_id = absint( $wp->query_vars['order-pay'] ); 32 40 $order = wc_get_order( $order_id ); 33 41 34 // set customer 42 // Ensure the order exists. 43 if ( ! $order ) { 44 wp_die( 45 esc_html__( 'Order does not exist.', 'woocommerce-pos' ), 46 esc_html__( 'Error', 'woocommerce-pos' ), 47 array( 'response' => 403 ) 48 ); 49 } 50 51 // Verify the order key matches the key provided in the URL. 52 $provided_key = sanitize_text_field( wp_unslash( $_GET['key'] ) ); 53 if ( $provided_key !== $order->get_order_key() ) { 54 wp_die( 55 esc_html__( 'Order key mismatch.', 'woocommerce-pos' ), 56 esc_html__( 'Error', 'woocommerce-pos' ), 57 array( 'response' => 403 ) 58 ); 59 } 60 61 // Verify the cashier is authorized to access the order. 62 $provided_token = sanitize_text_field( wp_unslash( $_GET['token'] ) ); 63 $auth = AuthService::instance(); 64 $user = $auth->validate_token( $provided_token ); 65 if ( is_wp_error( $user ) ) { 66 wp_die( 67 esc_html__( 'Cashier token mismatch.', 'woocommerce-pos' ), 68 esc_html__( 'Error', 'woocommerce-pos' ), 69 array( 'response' => 403 ) 70 ); 71 } 72 73 // set customer. 35 74 wp_set_current_user( $order->get_customer_id() ); 36 75 } 37 38 76 } 39 77 … … 71 109 } 72 110 } 73 74 111 } -
woocommerce-pos/tags/1.4.12/includes/Services/Settings.php
r3048280 r3053833 4 4 5 5 use WC_Payment_Gateways; 6 use WP_Error; 6 7 use const WCPOS\WooCommercePOS\VERSION; 7 use WP_Error;8 8 9 9 /** … … 162 162 163 163 /** 164 * @param string $id 165 * @param array $settings 166 * 167 * @return null|array|mixed|WP_Error 164 * Saves settings for a specific section. 165 * 166 * @param string $id The ID of the settings section being saved. 167 * @param array $settings The settings array to be saved. 168 * 169 * @return array|WP_Error Returns the updated settings array on success or WP_Error on failure. 168 170 */ 169 171 public function save_settings( string $id, array $settings ) { 170 $success = update_option( 171 static::$db_prefix . $id, 172 array_merge( 173 $settings, 174 array( 'date_modified_gmt' => current_time( 'mysql', true ) ) 175 ), 176 false 177 ); 172 $settings = array_merge( 173 $settings, 174 array( 'date_modified_gmt' => current_time( 'mysql', true ) ) 175 ); 176 177 /** 178 * Filters the settings before they are saved. 179 * 180 * Allows modification of the settings array for a specific section before it is saved to the database. 181 * 182 * @since 1.4.12 183 * 184 * @param array $settings The settings array about to be saved. 185 * @param string $id The ID of the settings section being saved. 186 */ 187 $settings = apply_filters( "woocommerce_pos_pre_save_{$id}_settings", $settings, $id ); 188 189 $success = update_option( static::$db_prefix . $id, $settings, false ); 178 190 179 191 if ( $success ) { 180 return $this->get_settings( $id ); 192 $saved_settings = $this->get_settings( $id ); 193 194 /** 195 * Fires after settings for a specific section are successfully saved. 196 * 197 * Provides a way to execute additional logic after a specific settings section is updated. 198 * 199 * @since 1.4.12 200 * 201 * @param array $saved_settings The settings array that was just saved. 202 * @param string $id The ID of the settings section that was saved. 203 */ 204 do_action( "woocommerce_pos_saved_{$id}_settings", $saved_settings, $id ); 205 206 return $saved_settings; 181 207 } 182 208 -
woocommerce-pos/tags/1.4.12/readme.txt
r3048280 r3053833 2 2 Contributors: kilbot 3 3 Tags: cart, e-commerce, ecommerce, inventory, point-of-sale, pos, sales, sell, shop, shopify, store, vend, woocommerce, wordpress-ecommerce 4 Requires at least: 5.6 & WooCommerce 5.35 Tested up to: 6. 46 Stable tag: 1.4.1 14 Requires at least: 5.6 5 Tested up to: 6.5 6 Stable tag: 1.4.12 7 7 License: GPL-3.0 8 8 License URI: http://www.gnu.org/licenses/gpl-3.0.html … … 63 63 64 64 == Changelog == 65 66 = 1.4.12 - 2024/03/18 = 67 * Security: Fix Insufficient Verification of Data Authenticity to Authenticated (Customer+) Information Disclosure (reported by Lucio Sá) 68 * Fix: Pro plugin not showing updates for some users 65 69 66 70 = 1.4.11 - 2024/03/09 = -
woocommerce-pos/tags/1.4.12/vendor/autoload.php
r3048280 r3053833 23 23 require_once __DIR__ . '/composer/autoload_real.php'; 24 24 25 return ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d::getLoader();25 return ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98::getLoader(); -
woocommerce-pos/tags/1.4.12/vendor/composer/autoload_real.php
r3048280 r3053833 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d5 class ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98 6 6 { 7 7 private static $loader; … … 23 23 } 24 24 25 spl_autoload_register(array('ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d', 'loadClassLoader'), true, true);25 spl_autoload_register(array('ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98', 'loadClassLoader'), true, true); 26 26 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 27 spl_autoload_unregister(array('ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d', 'loadClassLoader'));27 spl_autoload_unregister(array('ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98', 'loadClassLoader')); 28 28 29 29 require __DIR__ . '/autoload_static.php'; 30 call_user_func(\Composer\Autoload\ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::getInitializer($loader));30 call_user_func(\Composer\Autoload\ComposerStaticInit4381cd7e2816c049c0c912563977ae98::getInitializer($loader)); 31 31 32 32 $loader->register(true); 33 33 34 $filesToLoad = \Composer\Autoload\ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$files;34 $filesToLoad = \Composer\Autoload\ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$files; 35 35 $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { 36 36 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { -
woocommerce-pos/tags/1.4.12/vendor/composer/autoload_static.php
r3048280 r3053833 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d7 class ComposerStaticInit4381cd7e2816c049c0c912563977ae98 8 8 { 9 9 public static $files = array ( … … 330 330 { 331 331 return \Closure::bind(function () use ($loader) { 332 $loader->prefixLengthsPsr4 = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$prefixLengthsPsr4;333 $loader->prefixDirsPsr4 = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$prefixDirsPsr4;334 $loader->prefixesPsr0 = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$prefixesPsr0;335 $loader->classMap = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$classMap;332 $loader->prefixLengthsPsr4 = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$prefixLengthsPsr4; 333 $loader->prefixDirsPsr4 = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$prefixDirsPsr4; 334 $loader->prefixesPsr0 = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$prefixesPsr0; 335 $loader->classMap = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$classMap; 336 336 337 337 }, null, ClassLoader::class); -
woocommerce-pos/tags/1.4.12/vendor/composer/installed.php
r3048280 r3053833 2 2 'root' => array( 3 3 'name' => 'wcpos/woocommerce-pos', 4 'pretty_version' => 'v1.4.1 1',5 'version' => '1.4.1 1.0',6 'reference' => ' 49a47c823e48eb87ba9a51d7253bcf1d7c05a496',4 'pretty_version' => 'v1.4.12', 5 'version' => '1.4.12.0', 6 'reference' => '8e655c54f31968b7da74a7f5a1464c958a0147ed', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 90 90 ), 91 91 'wcpos/woocommerce-pos' => array( 92 'pretty_version' => 'v1.4.1 1',93 'version' => '1.4.1 1.0',94 'reference' => ' 49a47c823e48eb87ba9a51d7253bcf1d7c05a496',92 'pretty_version' => 'v1.4.12', 93 'version' => '1.4.12.0', 94 'reference' => '8e655c54f31968b7da74a7f5a1464c958a0147ed', 95 95 'type' => 'wordpress-plugin', 96 96 'install_path' => __DIR__ . '/../../', -
woocommerce-pos/tags/1.4.12/woocommerce-pos.php
r3048280 r3053833 4 4 * Plugin URI: https://wordpress.org/plugins/woocommerce-pos/ 5 5 * Description: A simple front-end for taking WooCommerce orders at the Point of Sale. Requires <a href="http://wordpress.org/plugins/woocommerce/">WooCommerce</a>. 6 * Version: 1.4.1 16 * Version: 1.4.12 7 7 * Author: kilbot 8 8 * Author URI: http://wcpos.com … … 11 11 * License URI: http://www.gnu.org/licenses/gpl-3.0.txt 12 12 * Domain Path: /languages 13 * Requires at least: 5.6 14 * Requires PHP: 7.4 15 * Requires Plugins: woocommerce 16 * Tested up to: 6.5 13 17 * WC tested up to: 8.6 14 * WC requires at least: 5.3 .18 * WC requires at least: 5.3 15 19 * 16 20 * @author Paul Kilmurray <paul@kilbot.com> … … 23 27 24 28 // Define plugin constants. 25 const VERSION = '1.4.1 1';29 const VERSION = '1.4.12'; 26 30 const PLUGIN_NAME = 'woocommerce-pos'; 27 31 const SHORT_NAME = 'wcpos'; -
woocommerce-pos/trunk/includes/API/Settings.php
r3020668 r3053833 35 35 public function __construct() { 36 36 add_filter( 'option_woocommerce_pos_settings_payment_gateways', array( $this, 'payment_gateways_settings' ) ); 37 38 // remove this once Pro settings have been moved to the new settings service. 39 add_filter( 'pre_update_option_woocommerce_pos_pro_settings_license', array( $this, 'remove_license_transient' ) ); 37 40 } 38 41 … … 544 547 return $options; 545 548 } 549 550 /** 551 * Temporary fix for stale license status transient. Remove when possible. 552 */ 553 public function remove_license_transient( $value ) { 554 delete_transient( 'woocommerce_pos_pro_license_status' ); 555 return $value; 556 } 546 557 } -
woocommerce-pos/trunk/includes/Admin/Menu.php
r3048280 r3053833 13 13 use const HOUR_IN_SECONDS; 14 14 use const WCPOS\WooCommercePOS\PLUGIN_NAME; 15 use const WCPOS\WooCommercePOS\VERSION as PLUGIN_VERSION; 15 16 16 17 /** … … 40 41 add_filter( 'custom_menu_order', '__return_true' ); 41 42 add_filter( 'menu_order', array( $this, 'menu_order' ), 9, 1 ); 43 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_landing_scripts_and_styles' ) ); 42 44 } 43 45 … … 80 82 */ 81 83 public function display_upgrade_page(): void { 82 $upgrade = get_transient( 'remote_pro_page' );83 84 // Check for transient, if none, grab remote HTML file85 if ( false === $upgrade ) {86 // Get remote HTML file87 $response = wp_remote_get( 'http://wcpos.com/pro/?wp-admin=woocommerce-pos' );88 // Check for error89 if ( is_wp_error( $response ) ) {90 return;91 }92 // Parse remote HTML file93 $upgrade = wp_remote_retrieve_body( $response );94 // Check for error95 if ( is_wp_error( $upgrade ) ) {96 return;97 }98 // Store remote HTML file in transient, expire after 24 hours99 set_transient( 'remote_pro_page', $upgrade, 24 * HOUR_IN_SECONDS );100 }101 84 include_once 'templates/upgrade.php'; 102 85 } … … 193 176 ); 194 177 } 178 179 /** 180 * Enqueue landing page scripts and styles. 181 */ 182 public function enqueue_landing_scripts_and_styles( $hook_suffix ): void { 183 if ( $hook_suffix === $this->toplevel_screen_id ) { 184 $is_development = isset( $_ENV['DEVELOPMENT'] ) && $_ENV['DEVELOPMENT']; 185 $url = $is_development ? 'http://localhost:9000/' : 'https://cdn.jsdelivr.net/gh/wcpos/wp-admin-landing/assets/'; 186 187 // Enqueue the landing page CSS from CDN 188 wp_enqueue_style( 189 'wcpos-landing', 190 $url . 'css/landing.css', 191 array(), 192 PLUGIN_VERSION 193 ); 194 195 // Ensure WordPress bundled React and lodash are loaded as dependencies 196 wp_enqueue_script( 'react' ); 197 wp_enqueue_script( 'lodash' ); 198 199 // Enqueue the landing page JS from CDN, with React and lodash as dependencies 200 wp_enqueue_script( 201 'wcpos-landing', 202 $url . 'js/landing.js', 203 array( 204 'react', 205 'react-dom', 206 'wp-element', 207 'lodash', 208 ), 209 PLUGIN_VERSION, 210 true 211 ); 212 } 213 } 195 214 } -
woocommerce-pos/trunk/includes/Admin/Updaters/Pro_Plugin_Updater.php
r3021613 r3053833 27 27 28 28 /** 29 * The path to the Pro plugin30 *31 * @var string $pro_plugin_path32 */33 private $pro_plugin_path = 'woocommerce-pos-pro/woocommerce-pos-pro.php';34 35 /**36 29 * The update server URL 37 30 * … … 45 38 * @var string $update_data_transient_key 46 39 */ 47 private $update_data_transient_key = 'woocommerce_pos_pro_update_data'; 48 40 public static $update_data_transient_key = 'woocommerce_pos_pro_update_data'; 41 42 /** 43 * Transient key for the update data 44 * 45 * @var string $license_status_transient_key 46 */ 47 public static $license_status_transient_key = 'woocommerce_pos_pro_license_status'; 48 49 /** 50 * Installed Pro plugins 51 * Note: Generally this would be an array of 1 installed Pro plugins but 52 * it's possible an older version of the plugin is installed in a different directory. 53 * 54 * @var array $installed_pro_plugins 55 */ 56 private $installed_pro_plugins = array(); 57 58 /** 59 * Constructor. 60 */ 61 public function __construct() { 49 62 /** 50 * Transient key for the update data 51 * 52 * @var string $update_data_transient_key 63 * First we need to check if the Pro plugin is installed (one or more versions) 53 64 */ 54 private $license_status_transient_key = 'woocommerce_pos_pro_license_status';55 56 /**57 * Whether the Pro plugin is installed58 *59 * @var bool $installed60 */61 private $installed;62 63 /**64 * Whether the Pro plugin is active65 *66 * @var bool $active67 */68 private $active;69 70 /**71 * The current version of the Pro plugin72 *73 * @var string $current_version74 */75 private $current_version;76 77 /**78 * Constructor.79 */80 public function __construct() {81 // Ensure the necessary functions are available82 65 include_once ABSPATH . 'wp-admin/includes/plugin.php'; 83 84 $status = $this->check_pro_plugin_status(); 85 $this->installed = $status['installed']; 86 $this->active = $status['active']; 87 $this->current_version = $status['version']; 66 $all_plugins = get_plugins(); 67 foreach ( $all_plugins as $plugin_path => $plugin_data ) { 68 $plugin_dir = dirname( $plugin_path ); 69 if ( strpos( $plugin_dir, $this->pro_plugin_slug ) === 0 ) { 70 if ( isset( $plugin_data['UpdateURI'] ) && $plugin_data['UpdateURI'] == $this->update_server ) { 71 $this->installed_pro_plugins[ $plugin_path ] = $plugin_data; 72 } 73 } 74 } 88 75 89 76 // Allow the update server to be overridden for development. … … 92 79 } 93 80 94 if ( $this->installed) {81 if ( count( $this->installed_pro_plugins ) > 0 ) { 95 82 add_filter( 'update_plugins_updates.wcpos.com', array( $this, 'update_plugins' ), 10, 4 ); 96 83 add_action( 'upgrader_process_complete', array( $this, 'after_plugin_update' ), 10, 2 ); 97 84 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 4 ); 98 add_action( 'in_plugin_update_message-' . $this->pro_plugin_path, array( $this, 'plugin_update_message' ), 10, 2 );99 85 add_action( 'install_plugins_pre_plugin-information', array( $this, 'plugin_information' ), 5 ); 100 } 101 } 102 103 /** 104 * Check the status of the Pro plugin 105 * 106 * @return array( 107 * 'installed' => bool, 108 * 'active' => bool, 109 * 'version' => string|null, 110 * ) 111 */ 112 public function check_pro_plugin_status() { 113 $status = array( 114 'installed' => false, 115 'active' => false, 116 'version' => null, 117 ); 118 119 // Check if the Pro plugin file exists. 120 if ( file_exists( WP_PLUGIN_DIR . '/' . $this->pro_plugin_path ) ) { 121 $status['installed'] = true; 122 $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $this->pro_plugin_path ); 123 $status['version'] = $plugin_data['Version']; 124 125 // Check if the Pro plugin is active. 126 if ( is_plugin_active( $this->pro_plugin_path ) ) { 127 $status['active'] = true; 128 } 129 } 130 131 /** 132 * This is a hack to manually trigger Pro update for version < 1.4.0 133 * TODO: remove this after 1.4.0 is released for a while 134 */ 135 if ( $status['version'] && version_compare( $status['version'], '1.4.0', '<' ) ) { 136 // Manually the update_plugins transient 137 $update_plugins = get_site_transient( 'update_plugins' ); 138 if ( ! is_object( $update_plugins ) ) { 139 $update_plugins = new stdClass(); 140 } 141 142 $license_settings = $this->get_license_settings(); 143 $key = isset( $license_settings['key'] ) ? $license_settings['key'] : ''; 144 $instance = isset( $license_settings['instance'] ) ? $license_settings['instance'] : ''; 145 146 // Construct the download URL, taking into account the environment 147 $package_url = add_query_arg( 148 array( 149 'key' => urlencode( $key ), 150 'instance' => urlencode( $instance ), 151 ), 152 'https://updates.wcpos.com/pro/download/1.4.1' 153 ); 154 155 $update = array( 156 'id' => 'https://updates.wcpos.com', 157 'slug' => 'woocommerce-pos-pro', 158 'plugin' => $this->pro_plugin_path, 159 'new_version' => '1.4.1', 160 'url' => 'https://wcpos.com/pro', 161 'package' => $package_url, 162 'requires' => '5.6', 163 'tested' => '6.5', 164 'requires_php' => '7.4', 165 'icons' => array( 166 '1x' => 'https://wcpos.com/wp-content/uploads/2014/06/woopos-pro.png', 167 ), 168 'upgrade_notice' => $this->maybe_add_upgrade_notice(), 169 ); 170 171 $update_plugins->response[ $this->pro_plugin_path ] = (object) $update; 172 173 set_site_transient( 'update_plugins', $update_plugins ); 174 } 175 176 return $status; 86 add_action( 'admin_enqueue_scripts', array( $this, 'license_status_styles' ) ); 87 88 // loop through the installed Pro plugins. 89 foreach ( $this->installed_pro_plugins as $plugin_path => $plugin_data ) { 90 add_action( 'in_plugin_update_message-' . $plugin_path, array( $this, 'plugin_update_message' ), 10, 2 ); 91 add_action( 'after_plugin_row_' . $plugin_path, array( $this, 'license_status_notice' ), 99 ); 92 93 /** 94 * This is a hack to manually trigger Pro update for version < 1.4.0 95 * TODO: remove this after 1.4.0 is released for a while 96 */ 97 if ( isset( $plugin_data['Version'] ) && version_compare( $plugin_data['Version'], '1.4.0', '<' ) ) { 98 $this->remove_this_hack_for_older_versions( $plugin_path ); 99 } 100 } 101 } 177 102 } 178 103 … … 212 137 */ 213 138 public function update_plugins( $update, $plugin_data, $plugin_file, $locales ) { 214 $update_data = $this->check_pro_plugin_updates(); 139 $current_version = isset( $plugin_data['Version'] ) ? $plugin_data['Version'] : '1'; 140 $update_data = $this->check_pro_plugin_updates( $current_version ); 215 141 $is_development = isset( $_ENV['DEVELOPMENT'] ) && $_ENV['DEVELOPMENT']; 216 142 217 143 // Check if update data is valid and if a new version is available. 218 if ( ! is_wp_error( $update_data ) && is_object( $update_data ) && isset( $update_data->version ) ) { 219 $latest_version = $update_data->version; 220 221 // No update needed if the current version is greater than the latest version. 222 if ( version_compare( $this->current_version, $latest_version, '>' ) ) { 223 return $update; 224 } 225 144 if ( isset( $update_data['version'] ) && version_compare( $current_version, $update_data['version'], '<' ) ) { 226 145 $license_settings = $this->get_license_settings(); 227 146 $key = isset( $license_settings['key'] ) ? $license_settings['key'] : ''; … … 244 163 'id' => 'https://updates.wcpos.com', 245 164 'slug' => 'woocommerce-pos-pro', 246 'plugin' => $ this->pro_plugin_path,247 'version' => $ latest_version,165 'plugin' => $plugin_file, 166 'version' => $update_data['version'], 248 167 'url' => 'https://wcpos.com/pro', 249 168 'package' => $package_url, … … 264 183 * Check for updates to the Pro plugin 265 184 * 266 * @param bool $force Force an update check. 267 */ 268 public function check_pro_plugin_updates( $force = false ) { 269 $update_data = get_transient( $this->update_data_transient_key ); 185 * @param string $version The current plugin version. 186 * @param bool $force Force an update check. 187 */ 188 public function check_pro_plugin_updates( $version = '1', $force = false ) { 189 $update_data = get_transient( self::$update_data_transient_key ); 270 190 271 191 if ( empty( $update_data ) || $force ) { 272 192 $expiration = 60 * 60 * 12; // 12 hours. 273 $url = $this->update_server . '/update/' . $ this->current_version;193 $url = $this->update_server . '/update/' . $version; 274 194 275 195 // make the api call. … … 277 197 $url, 278 198 array( 279 'timeout' => wp_doing_cron() ? 10 : 3,199 'timeout' => wp_doing_cron() ? 10 : 5, 280 200 'headers' => array( 281 201 'Accept' => 'application/json', … … 285 205 286 206 $data = $this->validate_api_response( $response ); 287 288 // Ensure $data has version, download_url and notes. 289 if ( ! is_wp_error( $data ) ) { 207 $error = isset( $data['is_error'] ) && $data['is_error'] ? $data : false; 208 209 // Ensure $data is an associative array and has version, download_url, and notes. 210 if ( ! $error && is_array( $data ) ) { 290 211 $expected_properties = array( 'version', 'download_url', 'notes' ); 291 212 foreach ( $expected_properties as $property ) { 292 if ( ! property_exists( $data, $property) ) {213 if ( ! array_key_exists( $property, $data ) ) { 293 214 $data = new WP_Error( 'invalid_response_structure', "Missing expected property: $property" ); 294 215 break; 295 216 } 296 217 } 297 } 298 299 if ( is_wp_error( $data ) ) { 218 } else { 300 219 Logger::log( $data ); 301 220 $expiration = 60 * 60 * 1; // try again in an hour if error. 302 221 } 303 222 304 set_transient( $this->update_data_transient_key, $data, $expiration ); 223 $success = set_transient( self::$update_data_transient_key, $data, $expiration ); 224 if ( ! $success ) { 225 Logger::log( 'Failed to set update data transient' ); 226 } 227 228 return $data; 305 229 } 306 230 … … 314 238 */ 315 239 private function check_license_status( $force = false ) { 316 $license_status = get_transient( $this->license_status_transient_key );240 $license_status = get_transient( self::$license_status_transient_key ); 317 241 $expiration = 60 * 60 * 12; // 12 hours. 318 242 … … 320 244 * TODO: How to allow for multisite? 321 245 */ 322 if ( is_multisite() ) { 323 $error = new WP_Error( 'multisite_update', 'Please go to http://wcpos.com/my-account to download update.' ); 324 set_transient( $this->license_status_transient_key, $error, $expiration ); 325 return $error; 326 } 246 // if ( is_multisite() ) { 247 // $error = array( 248 // 'code' => 'multisite_update', 249 // 'message' => 'Please go to http://wcpos.com/my-account to download update.', 250 // ); 251 // set_transient( $this->license_status_transient_key, $error, $expiration ); 252 // return $error; 253 // } 327 254 328 255 $license_settings = $this->get_license_settings(); … … 335 262 if ( empty( $key ) || empty( $instance ) ) { 336 263 // set the transient to an error. 337 $error = new WP_Error( 'missing_license_key', 'License key is not activated.' ); 338 set_transient( $this->license_status_transient_key, $error, $expiration ); 264 $error = array( 265 'is_error' => true, 266 'code' => 'missing_license_key', 267 'message' => 'License key is not activated.', 268 ); 269 set_transient( self::$license_status_transient_key, $error, $expiration ); 339 270 return $error; 340 271 } … … 354 285 $url, 355 286 array( 356 'timeout' => wp_doing_cron() ? 10 : 3,287 'timeout' => wp_doing_cron() ? 10 : 5, 357 288 'headers' => array( 358 289 'Accept' => 'application/json', … … 362 293 363 294 $data = $this->validate_api_response( $response ); 364 365 if ( is_wp_error( $data ) ) { 366 Logger::log( $data ); 367 $expiration = 60 * 60 * 1; // try again in an hour if error. 368 } 369 370 set_transient( $this->license_status_transient_key, $data, $expiration ); 295 $error = isset( $data['is_error'] ) && $data['is_error'] ? $data : false; 296 297 if ( $error ) { 298 Logger::log( $error ); 299 } 300 301 $success = set_transient( self::$license_status_transient_key, $data, $expiration ); 302 if ( ! $success ) { 303 Logger::log( 'Failed to set license status transient' ); 304 } 305 306 return $data; 371 307 } 372 308 … … 383 319 public function validate_api_response( $response ) { 384 320 if ( is_wp_error( $response ) ) { 385 return $response; 386 } 387 388 $decoded_response = json_decode( $response['body'] ); 321 return array( 322 'is_error' => true, 323 'code' => $response->get_error_code(), 324 'message' => $response->get_error_message(), 325 ); 326 } 327 328 $decoded_response = json_decode( $response['body'], true ); // Decode as associative array. 389 329 if ( null === $decoded_response ) { 390 return new WP_Error( 'invalid_json', 'Invalid JSON in response', $response['body'] ); 330 return array( 331 'is_error' => true, 332 'code' => 'invalid_json', 333 'message' => 'Invalid JSON in response', 334 'data' => $response['body'], 335 ); 336 } 337 338 if ( $response['response']['code'] === 403 ) { 339 return array( 340 'is_error' => true, 341 'expired' => true, 342 'code' => 'license_expired', 343 'message' => isset( $decoded_response['error'] ) ? $decoded_response['error'] : 'License expired.', 344 ); 391 345 } 392 346 393 347 if ( $response['response']['code'] !== 200 ) { 394 $error = isset( $decoded_response->error ) ? $decoded_response->error : 'No error message returned from server'; 395 return new WP_Error( 'invalid_response_code', $error ); 348 return array( 349 'is_error' => true, 350 'code' => 'invalid_response_code', 351 'message' => isset( $decoded_response['error'] ) ? $decoded_response['error'] : 'No error message returned from server.', 352 ); 396 353 } 397 354 398 355 // Ensure $decoded_response has the expected structure. 399 if ( ! isset( $decoded_response->data ) ) { 400 return new WP_Error( 'invalid_response_structure', 'Missing expected property: data' ); 401 } 402 403 return $decoded_response->data; 404 } 405 406 407 /** 408 * Create an update response object for the WordPress transient 409 * NOTE: this transient is different to the one we use to store the update data 410 * 411 * @param array $args { 412 * Arguments for creating the update data object. 413 * 414 * @type string $new_version New plugin version. 415 * @type string $package Plugin update package URL. 416 * } 417 * @return object { 418 * An object of metadata about the available plugin update. 419 * 420 * @type string $id Plugin ID, e.g. `w.org/plugins/[plugin-name]`. 421 * @type string $slug Plugin slug. 422 * @type string $plugin Plugin basename. 423 * @type string $new_version New plugin version. 424 * @type string $url Plugin URL. 425 * @type string $package Plugin update package URL. 426 * @type string[] $icons An array of plugin icon URLs. 427 * @type string[] $banners An array of plugin banner URLs. 428 * @type string[] $banners_rtl An array of plugin RTL banner URLs. 429 * @type string $requires The version of WordPress which the plugin requires. 430 * @type string $tested The version of WordPress the plugin is tested against. 431 * @type string $requires_php The version of PHP which the plugin requires. 432 * } 433 */ 434 private function create_update_response_object( $args = array() ) { 435 $defaults = array( 436 'id' => '0', 437 'slug' => 'woocommerce-pos-pro', 438 'plugin' => $this->pro_plugin_path, 439 'url' => 'https://wcpos.com/pro', 440 'requires' => '5.6', 441 'tested' => '6.5', 442 'requires_php' => '7.4', 443 'icons' => array( 444 '1x' => 'https://wcpos.com/wp-content/uploads/2014/06/woopos-pro.png', 445 ), 446 ); 447 448 $parsed_args = wp_parse_args( $args, $defaults ); 449 450 $update_obj = new \stdClass(); 451 foreach ( $parsed_args as $key => $value ) { 452 $update_obj->$key = $value; 453 } 454 455 return $update_obj; 356 if ( ! isset( $decoded_response['data'] ) ) { 357 return array( 358 'is_error' => true, 359 'code' => 'invalid_response_structure', 360 'message' => 'Missing expected property: data', 361 ); 362 } 363 364 return $decoded_response['data']; 456 365 } 457 366 … … 465 374 if ( $options['action'] == 'update' && $options['type'] == 'plugin' ) { 466 375 if ( isset( $options['plugins'] ) && in_array( 'woocommerce-pos/woocommerce-pos.php', $options['plugins'] ) ) { 467 delete_transient( $this->update_data_transient_key ); 468 $this->check_pro_plugin_updates(); 376 delete_transient( self::$update_data_transient_key ); 469 377 } 470 378 } … … 520 428 */ 521 429 public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $status ) { 522 if ( $plugin_file !== $this->pro_plugin_path ) {523 return $plugin_meta;524 }525 526 430 // $license_status = 'Your license status here'; // Fetch or generate your license status message 527 431 // $plugin_meta[] = '<span style="color: #d63638;">' . esc_html( $license_status ) . '</span>'; … … 560 464 */ 561 465 public function plugin_update_message( $plugin_data, $response ) { 562 if ( $response->plugin !== $this->pro_plugin_path ) { 563 return; 564 } 565 566 $license_status = $this->check_license_status(); 567 if ( ! is_wp_error( $license_status ) ) { 568 return; 569 } 570 571 $message = 'Your license has expired. <a href="http://wcpos.com/my-account/">Please renew</> to update.'; 572 573 if ( $license_status->get_error_code() === 'missing_license_key' ) { 574 $message = $license_status->get_error_message(); 575 } 576 577 echo '<br /><span style="color: #d63638;">' . wp_kses_post( $message ) . '</span>'; 466 // Nothing at the moment. 467 468 // $message = 'Your license has expired. <a href="http://wcpos.com/my-account/">Please renew</> to update.'; 469 470 // if ( $license_status->get_error_code() === 'missing_license_key' ) { 471 // $message = $license_status->get_error_message(); 472 // } 473 474 // echo '<br /><span style="color: #d63638;">' . wp_kses_post( $message ) . '</span>'; 578 475 } 579 476 … … 588 485 } 589 486 590 $update_data = get_transient( $this->update_data_transient_key );591 $message = 'Something went wrong. Please try again later.';487 $update_data = get_transient( self::$update_data_transient_key ); 488 $message = esc_html__( 'Something went wrong. Please try again later.', 'woocommerce-pos' ); 592 489 593 490 if ( is_wp_error( $update_data ) ) { … … 600 497 } 601 498 499 /* translators: WordPress */ 602 500 iframe_header( __( 'Plugin Installation' ) ); 603 501 … … 640 538 private function maybe_add_upgrade_notice() { 641 539 $license_status = $this->check_license_status(); 642 if ( ! is_wp_error( $license_status ) ) { 540 $active = isset( $license_status['activated'] ) && $license_status['activated']; 541 $inactive = isset( $license_status['activated'] ) && ! $license_status['activated']; 542 $expired = isset( $license_status['expired'] ) && $license_status['expired']; 543 544 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 545 $inactive = isset( $license_status['code'] ) && 546 in_array( 547 $license_status['code'], 548 array( 549 'missing_license_key', // no license key is set. 550 'invalid_response_code', // usually the key or instance is wrong length. 551 ) 552 ); 553 } 554 555 if ( $inactive ) { 556 return esc_html__( 'Your WooCommerce Pro license is inactive', 'woocommerce-pos' ); 557 } 558 559 if ( $expired ) { 560 return esc_html__( 'Your WooCommerce Pro license has expired', 'woocommerce-pos' ); 561 } 562 563 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 564 return $license_status['message']; 565 } 566 } 567 568 /** 569 * Add a notice to the plugin update table on Dashboard > Updates 570 */ 571 public function license_status_notice() { 572 $license_status = $this->check_license_status(); 573 $active = isset( $license_status['activated'] ) && $license_status['activated']; 574 $inactive = isset( $license_status['activated'] ) && ! $license_status['activated']; 575 $expired = isset( $license_status['expired'] ) && $license_status['expired']; 576 577 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 578 $inactive = isset( $license_status['code'] ) && 579 in_array( 580 $license_status['code'], 581 array( 582 'missing_license_key', // no license key is set. 583 'invalid_response_code', // usually the key or instance is wrong length. 584 ) 585 ); 586 } 587 588 if ( $active ) { 589 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 590 <td colspan="4" class="plugin-update colspanchange"> 591 <div class="update-message notice inline wcpos-active" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #5D9B5C;background-color:#F8FFF1;"> 592 <p class="installer-q-icon">' . 593 esc_html__( 'Your WooCommerce Pro license is valid and active.', 'woocommerce-pos' ) . 594 ' ' . 595 esc_html__( 'You are receiving plugin updates.', 'woocommerce-pos' ) 596 . '</p> 597 </div> 598 </td> 599 </tr>'; 643 600 return; 644 601 } 645 602 646 if ( $license_status->get_error_code() === 'missing_license_key' ) { 647 return $license_status->get_error_message(); 648 } 649 650 return 'Your license has expired. Please renew to update.'; 603 if ( $inactive ) { 604 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 605 <td colspan="4" class="plugin-update colspanchange"> 606 <div class="update-message notice inline wcpos-inactive" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #BD5858;background-color:#FFF8E1;"> 607 <p class="installer-q-icon">' . 608 esc_html__( 'Your WooCommerce Pro license is inactive.', 'woocommerce-pos' ) . 609 ' ' . 610 sprintf( 611 wp_kses( 612 __( '<a href="%s">Click here</a> to activate your license key.', 'woocommerce-pos' ), 613 array( 'a' => array( 'href' => array() ) ) 614 ), 615 esc_url( admin_url( 'admin.php?page=woocommerce-pos-settings#license' ) ) 616 ) 617 . '</p> 618 </div> 619 </td> 620 </tr>'; 621 return; 622 } 623 624 if ( $expired ) { 625 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 626 <td colspan="4" class="plugin-update colspanchange"> 627 <div class="update-message notice inline wcpos-expired" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #D63638;background-color:#FFF7F7;"> 628 <p class="installer-q-icon">' . 629 esc_html__( 'Your WooCommerce Pro license has expired.', 'woocommerce-pos' ) . 630 ' ' . 631 sprintf( 632 wp_kses( 633 __( '<a href="%s">Please renew</a> to receive updates.', 'woocommerce-pos' ), 634 array( 'a' => array( 'href' => array() ) ) 635 ), 636 'https://wcpos.com/my-account/' 637 ) 638 . '</p> 639 </div> 640 </td> 641 </tr>'; 642 return; 643 } 644 645 $message = esc_html__( 'Something went wrong. Please try again later.', 'woocommerce-pos' ); 646 if ( isset( $license_status['is_error'] ) && $license_status['is_error'] ) { 647 $message = $license_status['message']; 648 } 649 echo '<tr class="plugin-update-tr installer-plugin-update-tr woocommerce-pos-pro-license"> 650 <td colspan="4" class="plugin-update colspanchange"> 651 <div class="update-message notice inline wcpos-expired" style="margin:0;border:0;border-bottom:1px solid #DCDCDE;border-left:4px solid #D63638;background-color:#FFF7F7;"> 652 <p class="installer-q-icon">' . $message . '</p> 653 </div> 654 </td> 655 </tr>'; 656 } 657 658 /** 659 * Add some styles for the license status notice 660 * 661 * @param string $hook The current admin page. 662 */ 663 public function license_status_styles( $hook ) { 664 if ( 'plugins.php' === $hook ) { 665 wp_register_style( 'woocommerce-pos-styles', false ); 666 wp_enqueue_style( 'woocommerce-pos-styles' ); 667 668 $css = ' 669 .woocommerce-pos-pro-license .wcpos-active p::before { 670 content: "\f12a"; 671 color: #4d7d4c; 672 width: 25px; 673 } 674 .woocommerce-pos-pro-license .wcpos-inactive p::before { 675 content: "\f112"; 676 color: #bd5858; 677 width: 25px; 678 } 679 .woocommerce-pos-pro-license .wcpos-expired p::before { 680 width: 25px; 681 } 682 '; 683 wp_add_inline_style( 'woocommerce-pos-styles', $css ); 684 } 651 685 } 652 686 … … 657 691 */ 658 692 private function get_license_settings() { 659 if ( ! $this->active ) { 660 if ( file_exists( WP_PLUGIN_DIR . '/woocommerce-pos-pro/includes/Services/Settings.php' ) ) { 661 include_once WP_PLUGIN_DIR . '/woocommerce-pos-pro/includes/Services/Settings.php'; 662 if ( method_exists( '\WCPOS\WooCommercePOSPro\Services\Settings', '_get_inactive_license_settings' ) ) { 663 return \WCPOS\WooCommercePOSPro\Services\Settings::_get_inactive_license_settings(); 664 } 665 } 666 } 667 return woocommerce_pos_get_settings( 'license' ); 693 // first check if any Pro plugins are active. 694 foreach ( $this->installed_pro_plugins as $plugin_path => $plugin_data ) { 695 if ( is_plugin_active( $plugin_path ) ) { 696 return woocommerce_pos_get_settings( 'license' ); 697 } 698 } 699 700 // else, try and get the settings from the first Pro plugin. 701 $first_folder = dirname( array_key_first( $this->installed_pro_plugins ) ); 702 if ( file_exists( WP_PLUGIN_DIR . '/' . $first_folder . '/includes/Services/Settings.php' ) ) { 703 include_once WP_PLUGIN_DIR . '/' . $first_folder . '/includes/Services/Settings.php'; 704 if ( method_exists( '\WCPOS\WooCommercePOSPro\Services\Settings', '_get_inactive_license_settings' ) ) { 705 return \WCPOS\WooCommercePOSPro\Services\Settings::_get_inactive_license_settings(); 706 } 707 } 708 } 709 710 /** 711 * Temporary fix for older versions of the Pro plugin 712 * 713 * @param string $plugin_path The plugin path. 714 */ 715 private function remove_this_hack_for_older_versions( $plugin_path ) { 716 // Manually the update_plugins transient 717 $update_plugins = get_site_transient( 'update_plugins' ); 718 if ( ! is_object( $update_plugins ) ) { 719 $update_plugins = new stdClass(); 720 $update_plugins->response = array(); 721 } 722 723 $license_settings = $this->get_license_settings(); 724 $key = isset( $license_settings['key'] ) ? $license_settings['key'] : ''; 725 $instance = isset( $license_settings['instance'] ) ? $license_settings['instance'] : ''; 726 727 // Construct the download URL, taking into account the environment. 728 $package_url = add_query_arg( 729 array( 730 'key' => urlencode( $key ), 731 'instance' => urlencode( $instance ), 732 ), 733 'https://updates.wcpos.com/pro/download/1.4.5' 734 ); 735 736 $update = array( 737 'id' => 'https://updates.wcpos.com', 738 'slug' => 'woocommerce-pos-pro', 739 'plugin' => $plugin_path, 740 'new_version' => '1.4.5', 741 'url' => 'https://wcpos.com/pro', 742 'package' => $package_url, 743 'requires' => '5.6', 744 'tested' => '6.5', 745 'requires_php' => '7.4', 746 'icons' => array( 747 '1x' => 'https://wcpos.com/wp-content/uploads/2014/06/woopos-pro.png', 748 ), 749 'upgrade_notice' => $this->maybe_add_upgrade_notice(), 750 ); 751 752 $update_plugins->response[ $plugin_path ] = (object) $update; 753 754 set_site_transient( 'update_plugins', $update_plugins ); 668 755 } 669 756 } -
woocommerce-pos/trunk/includes/Admin/templates/upgrade.php
r2845568 r3053833 5 5 * @author Paul Kilmurray <paul@kilbot.com.au> 6 6 * 7 * @see http://www.kilbot.com .au7 * @see http://www.kilbot.com 8 8 */ 9 9 ?> 10 10 11 <!-- temporary inline css, todo: remove this --> 12 <style type="text/css"> 13 .web-title { 14 display: none; 15 } 11 <div class="wrap clear"> 16 12 17 .blurb { 18 font-size: 14px; 19 line-height: 1.6em; 20 } 21 22 .widget-area { 23 float: right; 24 width: 33%; 25 margin-left: 20px; 26 text-align: center; 27 margin-bottom: 20px; 28 } 29 30 .widget-area .btn { 31 display: inline-block; 32 margin-bottom: 0; 33 font-weight: 400; 34 text-align: center; 35 vertical-align: middle; 36 cursor: pointer; 37 background-image: none; 38 border: 1px solid transparent; 39 white-space: nowrap; 40 text-decoration: none; 41 margin: 20px 0; 42 } 43 44 .widget-area .btn-primary { 45 color: #fff; 46 background-color: #cd2f19; 47 border-color: #b62a16; 48 } 49 50 .widget-area .btn-lg { 51 padding: 10px 16px; 52 font-size: 18px; 53 line-height: 1.33; 54 border-radius: 6px; 55 } 56 57 .comparison-table { 58 width: 100%; 59 border-spacing: 0; 60 border-collapse: collapse; 61 border: 1px solid #e5e5e5; 62 box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); 63 background-color: #f5f5f5; 64 } 65 66 .comparison-table thead { 67 font-size: 18px; 68 } 69 70 .comparison-table thead tr { 71 border-bottom: 1px solid #e5e5e5; 72 } 73 74 .comparison-table thead th { 75 width: 33%; 76 font-weight: normal; 77 } 78 79 .comparison-table thead th:first-of-type { 80 background-color: #B0B0B0; 81 color: #f5f5f5; 82 } 83 84 .comparison-table thead th:last-of-type { 85 background-color: #d54e21; 86 color: #f5f5f5; 87 } 88 89 .comparison-table th, td { 90 padding: 1% 2%; 91 } 92 93 .comparison-table tbody th { 94 font-weight: normal; 95 text-align: right; 96 } 97 98 .comparison-table tbody tr { 99 border-bottom: 1px solid #e5e5e5; 100 } 101 102 .comparison-table tbody tr td:first-of-type { 103 background-color: #fafafa; 104 } 105 106 .comparison-table tbody tr td:last-of-type { 107 background-color: #fef7f1; 108 } 109 110 .comparison-table .fa { 111 font-family: Dashicons !important;; 112 speak: none; 113 font-style: normal; 114 font-weight: normal; 115 font-variant: normal; 116 text-transform: none; 117 -webkit-font-smoothing: antialiased; 118 -moz-osx-font-smoothing: grayscale; 119 } 120 121 .comparison-table .fa-check:before { 122 content: "\f147"; 123 color: #3c763d; 124 font-size: 24px; 125 } 126 127 .comparison-table .fa-times:before { 128 content: "\f335"; 129 color: #a94442; 130 font-size: 24px; 131 } 132 </style> 133 134 <div class="wrap clear woocommerce-pos-upgrade"> 135 136 <!-- 13 <!-- 137 14 Little trick to get around WP js injection of admin notices 138 15 WP js looks for first h2 in .wrap and appends notices, so we'll make the first one hidden 139 16 https://github.com/WordPress/WordPress/blob/master/wp-admin/js/common.js 140 17 --> 141 <h2 style="display:none"></h2>18 <h2 style="display:none"></h2> 142 19 143 <h2 style="margin:20px 0;">Thank you for using WooCommerce POS!</h2> 144 145 <?php echo $upgrade; ?> 20 <div id="woocommerce-pos-upgrade"></div> 146 21 147 22 </div> 148 -
woocommerce-pos/trunk/includes/Form_Handler.php
r2929317 r3053833 1 1 <?php 2 /** 3 * 4 */ 2 5 3 6 namespace WCPOS\WooCommercePOS; 4 7 8 use WCPOS\WooCommercePOS\Services\Auth as AuthService; 9 10 /** 11 * 12 */ 5 13 class Form_Handler { 6 14 … … 28 36 global $wp; 29 37 30 if ( woocommerce_pos_request() && isset( $_POST['woocommerce_pay'], $_GET['key'] ) ) {38 if ( woocommerce_pos_request() && isset( $_POST['woocommerce_pay'], $_GET['key'], $_GET['token'] ) ) { 31 39 $order_id = absint( $wp->query_vars['order-pay'] ); 32 40 $order = wc_get_order( $order_id ); 33 41 34 // set customer 42 // Ensure the order exists. 43 if ( ! $order ) { 44 wp_die( 45 esc_html__( 'Order does not exist.', 'woocommerce-pos' ), 46 esc_html__( 'Error', 'woocommerce-pos' ), 47 array( 'response' => 403 ) 48 ); 49 } 50 51 // Verify the order key matches the key provided in the URL. 52 $provided_key = sanitize_text_field( wp_unslash( $_GET['key'] ) ); 53 if ( $provided_key !== $order->get_order_key() ) { 54 wp_die( 55 esc_html__( 'Order key mismatch.', 'woocommerce-pos' ), 56 esc_html__( 'Error', 'woocommerce-pos' ), 57 array( 'response' => 403 ) 58 ); 59 } 60 61 // Verify the cashier is authorized to access the order. 62 $provided_token = sanitize_text_field( wp_unslash( $_GET['token'] ) ); 63 $auth = AuthService::instance(); 64 $user = $auth->validate_token( $provided_token ); 65 if ( is_wp_error( $user ) ) { 66 wp_die( 67 esc_html__( 'Cashier token mismatch.', 'woocommerce-pos' ), 68 esc_html__( 'Error', 'woocommerce-pos' ), 69 array( 'response' => 403 ) 70 ); 71 } 72 73 // set customer. 35 74 wp_set_current_user( $order->get_customer_id() ); 36 75 } 37 38 76 } 39 77 … … 71 109 } 72 110 } 73 74 111 } -
woocommerce-pos/trunk/includes/Services/Settings.php
r3048280 r3053833 4 4 5 5 use WC_Payment_Gateways; 6 use WP_Error; 6 7 use const WCPOS\WooCommercePOS\VERSION; 7 use WP_Error;8 8 9 9 /** … … 162 162 163 163 /** 164 * @param string $id 165 * @param array $settings 166 * 167 * @return null|array|mixed|WP_Error 164 * Saves settings for a specific section. 165 * 166 * @param string $id The ID of the settings section being saved. 167 * @param array $settings The settings array to be saved. 168 * 169 * @return array|WP_Error Returns the updated settings array on success or WP_Error on failure. 168 170 */ 169 171 public function save_settings( string $id, array $settings ) { 170 $success = update_option( 171 static::$db_prefix . $id, 172 array_merge( 173 $settings, 174 array( 'date_modified_gmt' => current_time( 'mysql', true ) ) 175 ), 176 false 177 ); 172 $settings = array_merge( 173 $settings, 174 array( 'date_modified_gmt' => current_time( 'mysql', true ) ) 175 ); 176 177 /** 178 * Filters the settings before they are saved. 179 * 180 * Allows modification of the settings array for a specific section before it is saved to the database. 181 * 182 * @since 1.4.12 183 * 184 * @param array $settings The settings array about to be saved. 185 * @param string $id The ID of the settings section being saved. 186 */ 187 $settings = apply_filters( "woocommerce_pos_pre_save_{$id}_settings", $settings, $id ); 188 189 $success = update_option( static::$db_prefix . $id, $settings, false ); 178 190 179 191 if ( $success ) { 180 return $this->get_settings( $id ); 192 $saved_settings = $this->get_settings( $id ); 193 194 /** 195 * Fires after settings for a specific section are successfully saved. 196 * 197 * Provides a way to execute additional logic after a specific settings section is updated. 198 * 199 * @since 1.4.12 200 * 201 * @param array $saved_settings The settings array that was just saved. 202 * @param string $id The ID of the settings section that was saved. 203 */ 204 do_action( "woocommerce_pos_saved_{$id}_settings", $saved_settings, $id ); 205 206 return $saved_settings; 181 207 } 182 208 -
woocommerce-pos/trunk/readme.txt
r3048280 r3053833 2 2 Contributors: kilbot 3 3 Tags: cart, e-commerce, ecommerce, inventory, point-of-sale, pos, sales, sell, shop, shopify, store, vend, woocommerce, wordpress-ecommerce 4 Requires at least: 5.6 & WooCommerce 5.35 Tested up to: 6. 46 Stable tag: 1.4.1 14 Requires at least: 5.6 5 Tested up to: 6.5 6 Stable tag: 1.4.12 7 7 License: GPL-3.0 8 8 License URI: http://www.gnu.org/licenses/gpl-3.0.html … … 63 63 64 64 == Changelog == 65 66 = 1.4.12 - 2024/03/18 = 67 * Security: Fix Insufficient Verification of Data Authenticity to Authenticated (Customer+) Information Disclosure (reported by Lucio Sá) 68 * Fix: Pro plugin not showing updates for some users 65 69 66 70 = 1.4.11 - 2024/03/09 = -
woocommerce-pos/trunk/vendor/autoload.php
r3048280 r3053833 23 23 require_once __DIR__ . '/composer/autoload_real.php'; 24 24 25 return ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d::getLoader();25 return ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98::getLoader(); -
woocommerce-pos/trunk/vendor/composer/autoload_real.php
r3048280 r3053833 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d5 class ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98 6 6 { 7 7 private static $loader; … … 23 23 } 24 24 25 spl_autoload_register(array('ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d', 'loadClassLoader'), true, true);25 spl_autoload_register(array('ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98', 'loadClassLoader'), true, true); 26 26 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 27 spl_autoload_unregister(array('ComposerAutoloaderInit d5f742ecdf534f147f5b8e2724165a2d', 'loadClassLoader'));27 spl_autoload_unregister(array('ComposerAutoloaderInit4381cd7e2816c049c0c912563977ae98', 'loadClassLoader')); 28 28 29 29 require __DIR__ . '/autoload_static.php'; 30 call_user_func(\Composer\Autoload\ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::getInitializer($loader));30 call_user_func(\Composer\Autoload\ComposerStaticInit4381cd7e2816c049c0c912563977ae98::getInitializer($loader)); 31 31 32 32 $loader->register(true); 33 33 34 $filesToLoad = \Composer\Autoload\ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$files;34 $filesToLoad = \Composer\Autoload\ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$files; 35 35 $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { 36 36 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { -
woocommerce-pos/trunk/vendor/composer/autoload_static.php
r3048280 r3053833 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d7 class ComposerStaticInit4381cd7e2816c049c0c912563977ae98 8 8 { 9 9 public static $files = array ( … … 330 330 { 331 331 return \Closure::bind(function () use ($loader) { 332 $loader->prefixLengthsPsr4 = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$prefixLengthsPsr4;333 $loader->prefixDirsPsr4 = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$prefixDirsPsr4;334 $loader->prefixesPsr0 = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$prefixesPsr0;335 $loader->classMap = ComposerStaticInit d5f742ecdf534f147f5b8e2724165a2d::$classMap;332 $loader->prefixLengthsPsr4 = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$prefixLengthsPsr4; 333 $loader->prefixDirsPsr4 = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$prefixDirsPsr4; 334 $loader->prefixesPsr0 = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$prefixesPsr0; 335 $loader->classMap = ComposerStaticInit4381cd7e2816c049c0c912563977ae98::$classMap; 336 336 337 337 }, null, ClassLoader::class); -
woocommerce-pos/trunk/vendor/composer/installed.php
r3048280 r3053833 2 2 'root' => array( 3 3 'name' => 'wcpos/woocommerce-pos', 4 'pretty_version' => 'v1.4.1 1',5 'version' => '1.4.1 1.0',6 'reference' => ' 49a47c823e48eb87ba9a51d7253bcf1d7c05a496',4 'pretty_version' => 'v1.4.12', 5 'version' => '1.4.12.0', 6 'reference' => '8e655c54f31968b7da74a7f5a1464c958a0147ed', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 90 90 ), 91 91 'wcpos/woocommerce-pos' => array( 92 'pretty_version' => 'v1.4.1 1',93 'version' => '1.4.1 1.0',94 'reference' => ' 49a47c823e48eb87ba9a51d7253bcf1d7c05a496',92 'pretty_version' => 'v1.4.12', 93 'version' => '1.4.12.0', 94 'reference' => '8e655c54f31968b7da74a7f5a1464c958a0147ed', 95 95 'type' => 'wordpress-plugin', 96 96 'install_path' => __DIR__ . '/../../', -
woocommerce-pos/trunk/woocommerce-pos.php
r3048280 r3053833 4 4 * Plugin URI: https://wordpress.org/plugins/woocommerce-pos/ 5 5 * Description: A simple front-end for taking WooCommerce orders at the Point of Sale. Requires <a href="http://wordpress.org/plugins/woocommerce/">WooCommerce</a>. 6 * Version: 1.4.1 16 * Version: 1.4.12 7 7 * Author: kilbot 8 8 * Author URI: http://wcpos.com … … 11 11 * License URI: http://www.gnu.org/licenses/gpl-3.0.txt 12 12 * Domain Path: /languages 13 * Requires at least: 5.6 14 * Requires PHP: 7.4 15 * Requires Plugins: woocommerce 16 * Tested up to: 6.5 13 17 * WC tested up to: 8.6 14 * WC requires at least: 5.3 .18 * WC requires at least: 5.3 15 19 * 16 20 * @author Paul Kilmurray <paul@kilbot.com> … … 23 27 24 28 // Define plugin constants. 25 const VERSION = '1.4.1 1';29 const VERSION = '1.4.12'; 26 30 const PLUGIN_NAME = 'woocommerce-pos'; 27 31 const SHORT_NAME = 'wcpos';
Note: See TracChangeset
for help on using the changeset viewer.