diff --git a/composer.json b/composer.json index 3e0112c14ab..83dce1fda06 100644 --- a/composer.json +++ b/composer.json @@ -7,14 +7,15 @@ "prefer-stable": true, "minimum-stability": "dev", "require": { - "automattic/jetpack-autoloader": "^1.2.0", "php": ">=5.6|>=7.0", + "automattic/jetpack-autoloader": "^1.2.0", "composer/installers": "1.7.0", - "woocommerce/woocommerce-blocks": "2.5.7", - "woocommerce/woocommerce-rest-api": "1.0.5" + "maxmind-db/reader": "1.6.0", + "woocommerce/woocommerce-blocks": "2.5.10", + "woocommerce/woocommerce-rest-api": "1.0.6" }, "require-dev": { - "phpunit/phpunit": "7.5.18", + "phpunit/phpunit": "7.5.20", "woocommerce/woocommerce-sniffs": "0.0.9" }, "config": { diff --git a/composer.lock b/composer.lock index 8426538364e..1af8da387da 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "95355370e5e250e500f8114896d52f7a", + "content-hash": "316f960abc40df62fbc75b77930323fc", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -165,17 +165,77 @@ "time": "2019-08-12T15:00:31+00:00" }, { - "name": "woocommerce/woocommerce-blocks", - "version": "v2.5.7", + "name": "maxmind-db/reader", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "24b6552d38204fbbdd87ec5ba76f3ec391b042d0" + "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", + "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/24b6552d38204fbbdd87ec5ba76f3ec391b042d0", - "reference": "24b6552d38204fbbdd87ec5ba76f3ec391b042d0", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/febd4920bf17c1da84cef58e56a8227dfb37fbe4", + "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "conflict": { + "ext-maxminddb": "<1.6.0,>=2.0.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "2.*", + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpcov": "^3.0", + "phpunit/phpunit": "5.*", + "squizlabs/php_codesniffer": "3.*" + }, + "suggest": { + "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", + "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", + "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups" + }, + "type": "library", + "autoload": { + "psr-4": { + "MaxMind\\Db\\": "src/MaxMind/Db" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory J. Oschwald", + "email": "goschwald@maxmind.com", + "homepage": "https://www.maxmind.com/" + } + ], + "description": "MaxMind DB Reader API", + "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", + "keywords": [ + "database", + "geoip", + "geoip2", + "geolocation", + "maxmind" + ], + "time": "2019-12-19T22:59:03+00:00" + }, + { + "name": "woocommerce/woocommerce-blocks", + "version": "v2.5.10", + "source": { + "type": "git", + "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", + "reference": "4a6d993c1df7ccd8581873ee56269efa00d49ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/4a6d993c1df7ccd8581873ee56269efa00d49ddc", + "reference": "4a6d993c1df7ccd8581873ee56269efa00d49ddc", "shasum": "" }, "require": { @@ -209,20 +269,20 @@ "gutenberg", "woocommerce" ], - "time": "2019-12-20T16:26:08+00:00" + "time": "2020-01-09T15:29:03+00:00" }, { "name": "woocommerce/woocommerce-rest-api", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-rest-api.git", - "reference": "3be425631faefa61ab8b81011ae8a422b9bfca35" + "reference": "78ccf4d4c6bafbc841182b68aa863e7b0caa37c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/3be425631faefa61ab8b81011ae8a422b9bfca35", - "reference": "3be425631faefa61ab8b81011ae8a422b9bfca35", + "url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/78ccf4d4c6bafbc841182b68aa863e7b0caa37c8", + "reference": "78ccf4d4c6bafbc841182b68aa863e7b0caa37c8", "shasum": "" }, "require": { @@ -249,7 +309,7 @@ ], "description": "The WooCommerce core REST API.", "homepage": "https://github.com/woocommerce/woocommerce-rest-api", - "time": "2019-12-18T22:20:59+00:00" + "time": "2020-01-15T23:29:39+00:00" } ], "packages-dev": [ @@ -527,16 +587,16 @@ }, { "name": "phpcompatibility/php-compatibility", - "version": "9.3.4", + "version": "9.3.5", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "1f37659196e4f3113ea506a7efba201c52303bf1" + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/1f37659196e4f3113ea506a7efba201c52303bf1", - "reference": "1f37659196e4f3113ea506a7efba201c52303bf1", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", "shasum": "" }, "require": { @@ -581,7 +641,7 @@ "phpcs", "standards" ], - "time": "2019-11-15T04:12:02+00:00" + "time": "2019-12-27T09:44:58+00:00" }, { "name": "phpcompatibility/phpcompatibility-paragonie", @@ -739,16 +799,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.2", + "version": "4.3.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", "shasum": "" }, "require": { @@ -760,6 +820,7 @@ "require-dev": { "doctrine/instantiator": "^1.0.5", "mockery/mockery": "^1.0", + "phpdocumentor/type-resolver": "0.4.*", "phpunit/phpunit": "^6.4" }, "type": "library", @@ -786,7 +847,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-09-12T14:27:41+00:00" + "time": "2019-12-28T18:55:12+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -837,16 +898,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.10.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "d638ebbb58daba25a6a0dc7969e1358a0e3c6682" + "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d638ebbb58daba25a6a0dc7969e1358a0e3c6682", - "reference": "d638ebbb58daba25a6a0dc7969e1358a0e3c6682", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/cbe1df668b3fe136bcc909126a0f529a78d4cbbc", + "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc", "shasum": "" }, "require": { @@ -896,7 +957,7 @@ "spy", "stub" ], - "time": "2019-12-17T16:54:23+00:00" + "time": "2019-12-22T21:05:45+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1152,16 +1213,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.5.18", + "version": "7.5.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fcf6c4bfafaadc07785528b06385cce88935474d" + "reference": "9467db479d1b0487c99733bb1e7944d32deded2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fcf6c4bfafaadc07785528b06385cce88935474d", - "reference": "fcf6c4bfafaadc07785528b06385cce88935474d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c", + "reference": "9467db479d1b0487c99733bb1e7944d32deded2c", "shasum": "" }, "require": { @@ -1232,7 +1293,7 @@ "testing", "xunit" ], - "time": "2019-12-06T05:14:37+00:00" + "time": "2020-01-08T08:45:45+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index 13a5cc05658..76ba356bd6c 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -36,6 +36,7 @@ class WC_Admin_Notices { 'no_secure_connection' => 'secure_connection_notice', 'wc_admin' => 'wc_admin_feature_plugin_notice', WC_PHP_MIN_REQUIREMENTS_NOTICE => 'wp_php_min_requirements_notice', + 'maxmind_license_key' => 'maxmind_missing_license_key_notice', ); /** @@ -87,6 +88,7 @@ class WC_Admin_Notices { self::add_wc_admin_feature_plugin_notice(); self::add_notice( 'template_files' ); self::add_min_version_notice(); + self::add_maxmind_missing_license_key_notice(); } /** @@ -428,6 +430,41 @@ class WC_Admin_Notices { include dirname( __FILE__ ) . '/views/html-notice-wp-php-minimum-requirements.php'; } + /** + * Add MaxMind missing license key notice. + * + * @since 3.9.0 + */ + public static function add_maxmind_missing_license_key_notice() { + $default_address = get_option( 'woocommerce_default_customer_address' ); + + if ( ! in_array( $default_address, array( 'geolocation', 'geolocation_ajax' ), true ) ) { + return; + } + + $integration_options = get_option( 'woocommerce_maxmind_geolocation_settings' ); + if ( empty( $integration_options['license_key'] ) ) { + self::add_notice( 'maxmind_license_key' ); + } + } + + /** + * Display MaxMind missing license key notice. + * + * @since 3.9.0 + */ + public static function maxmind_missing_license_key_notice() { + $user_dismissed_notice = get_user_meta( get_current_user_id(), 'dismissed_maxmind_license_key_notice', true ); + $filter_dismissed_notice = ! apply_filters( 'woocommerce_maxmind_geolocation_display_notices', true ); + + if ( $user_dismissed_notice || $filter_dismissed_notice ) { + self::remove_notice( 'maxmind_license_key' ); + return; + } + + include dirname( __FILE__ ) . '/views/html-notice-maxmind-license-key.php'; + } + /** * Determine if the store is running SSL. * diff --git a/includes/admin/settings/class-wc-settings-general.php b/includes/admin/settings/class-wc-settings-general.php index 44c4dc7b51b..6e0126b00da 100644 --- a/includes/admin/settings/class-wc-settings-general.php +++ b/includes/admin/settings/class-wc-settings-general.php @@ -39,17 +39,6 @@ class WC_Settings_General extends WC_Settings_Page { $currency_code_options[ $code ] = $name . ' (' . get_woocommerce_currency_symbol( $code ) . ')'; } - $woocommerce_default_customer_address_options = array( - '' => __( 'No location by default', 'woocommerce' ), - 'base' => __( 'Shop base address', 'woocommerce' ), - 'geolocation' => __( 'Geolocate', 'woocommerce' ), - 'geolocation_ajax' => __( 'Geolocate (with page caching support)', 'woocommerce' ), - ); - - if ( version_compare( PHP_VERSION, '5.4', '<' ) ) { - unset( $woocommerce_default_customer_address_options['geolocation'], $woocommerce_default_customer_address_options['geolocation_ajax'] ); - } - $settings = apply_filters( 'woocommerce_general_settings', array( @@ -182,10 +171,15 @@ class WC_Settings_General extends WC_Settings_Page { 'title' => __( 'Default customer location', 'woocommerce' ), 'id' => 'woocommerce_default_customer_address', 'desc_tip' => __( 'This option determines a customers default location. The MaxMind GeoLite Database will be periodically downloaded to your wp-content directory if using geolocation.', 'woocommerce' ), - 'default' => 'geolocation', + 'default' => 'base', 'type' => 'select', 'class' => 'wc-enhanced-select', - 'options' => $woocommerce_default_customer_address_options, + 'options' => array( + '' => __( 'No location by default', 'woocommerce' ), + 'base' => __( 'Shop base address', 'woocommerce' ), + 'geolocation' => __( 'Geolocate', 'woocommerce' ), + 'geolocation_ajax' => __( 'Geolocate (with page caching support)', 'woocommerce' ), + ), ), array( diff --git a/includes/admin/views/html-admin-page-status-report.php b/includes/admin/views/html-admin-page-status-report.php index 337aca7cd45..729882eab2f 100644 --- a/includes/admin/views/html-admin-page-status-report.php +++ b/includes/admin/views/html-admin-page-status-report.php @@ -435,25 +435,6 @@ $untested_plugins = $plugin_updates->get_untested_plugins( WC()->version, 'min - -
' . esc_html( $database['maxmind_geoip_database'] ) . '
';
- } else {
- /* Translators: %1$s: Library url, %2$s: install path. */
- printf( ' ' . sprintf( esc_html__( 'The MaxMind GeoIP Database does not exist - Geolocation will not function. You can download and install it manually from %1$s to the path: %2$s. Scroll down to "Downloads" and download the "MaxMind DB binary, gzipped" file next to "GeoLite2 Country". Please remember to uncompress GeoLite2-Country_xxxxxxxx.tar.gz and upload the GeoLite2-Country.mmdb file only.', 'woocommerce' ), 'https://dev.maxmind.com/geoip/geoip2/geolite2/', '' . esc_html( $database['maxmind_geoip_database'] ) . '
' ) . '', esc_html( WC_LOG_DIR ) );
- }
- ?>
- + + | ++ + | +
---|
address
in the MaxMind DB.
- *
- * @param string $ipAddress
- * the IP address to look up
- *
- * @throws \BadMethodCallException if this method is called on a closed database
- * @throws \InvalidArgumentException if something other than a single IP address is passed to the method
- * @throws InvalidDatabaseException
- * if the database is invalid or there is an error reading
- * from it
- *
- * @return array the record for the IP address
- */
- public function get($ipAddress)
- {
- if (func_num_args() !== 1) {
- throw new \InvalidArgumentException(
- 'Method takes exactly one argument.'
- );
- }
-
- if (!is_resource($this->fileHandle)) {
- throw new \BadMethodCallException(
- 'Attempt to read from a closed MaxMind DB.'
- );
- }
-
- if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
- throw new \InvalidArgumentException(
- "The value \"$ipAddress\" is not a valid IP address."
- );
- }
-
- if ($this->metadata->ipVersion === 4 && strrpos($ipAddress, ':')) {
- throw new \InvalidArgumentException(
- "Error looking up $ipAddress. You attempted to look up an"
- . ' IPv6 address in an IPv4-only database.'
- );
- }
- $pointer = $this->findAddressInTree($ipAddress);
- if ($pointer === 0) {
- return null;
- }
-
- return $this->resolveDataPointer($pointer);
- }
-
- private function findAddressInTree($ipAddress)
- {
- // XXX - could simplify. Done as a byte array to ease porting
- $rawAddress = array_merge(unpack('C*', inet_pton($ipAddress)));
-
- $bitCount = count($rawAddress) * 8;
-
- // The first node of the tree is always node 0, at the beginning of the
- // value
- $node = $this->startNode($bitCount);
-
- for ($i = 0; $i < $bitCount; $i++) {
- if ($node >= $this->metadata->nodeCount) {
- break;
- }
- $tempBit = 0xFF & $rawAddress[$i >> 3];
- $bit = 1 & ($tempBit >> 7 - ($i % 8));
-
- $node = $this->readNode($node, $bit);
- }
- if ($node === $this->metadata->nodeCount) {
- // Record is empty
- return 0;
- } elseif ($node > $this->metadata->nodeCount) {
- // Record is a data pointer
- return $node;
- }
- throw new InvalidDatabaseException('Something bad happened');
- }
-
- private function startNode($length)
- {
- // Check if we are looking up an IPv4 address in an IPv6 tree. If this
- // is the case, we can skip over the first 96 nodes.
- if ($this->metadata->ipVersion === 6 && $length === 32) {
- return $this->ipV4StartNode();
- }
- // The first node of the tree is always node 0, at the beginning of the
- // value
- return 0;
- }
-
- private function ipV4StartNode()
- {
- // This is a defensive check. There is no reason to call this when you
- // have an IPv4 tree.
- if ($this->metadata->ipVersion === 4) {
- return 0;
- }
-
- if ($this->ipV4Start) {
- return $this->ipV4Start;
- }
- $node = 0;
-
- for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; $i++) {
- $node = $this->readNode($node, 0);
- }
- $this->ipV4Start = $node;
-
- return $node;
- }
-
- private function readNode($nodeNumber, $index)
- {
- $baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
-
- // XXX - probably could condense this.
- switch ($this->metadata->recordSize) {
- case 24:
- $bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
- list(, $node) = unpack('N', "\x00" . $bytes);
-
- return $node;
- case 28:
- $middleByte = Util::read($this->fileHandle, $baseOffset + 3, 1);
- list(, $middle) = unpack('C', $middleByte);
- if ($index === 0) {
- $middle = (0xF0 & $middle) >> 4;
- } else {
- $middle = 0x0F & $middle;
- }
- $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 3);
- list(, $node) = unpack('N', chr($middle) . $bytes);
-
- return $node;
- case 32:
- $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
- list(, $node) = unpack('N', $bytes);
-
- return $node;
- default:
- throw new InvalidDatabaseException(
- 'Unknown record size: '
- . $this->metadata->recordSize
- );
- }
- }
-
- private function resolveDataPointer($pointer)
- {
- $resolved = $pointer - $this->metadata->nodeCount
- + $this->metadata->searchTreeSize;
- if ($resolved > $this->fileSize) {
- throw new InvalidDatabaseException(
- "The MaxMind DB file's search tree is corrupt"
- );
- }
-
- list($data) = $this->decoder->decode($resolved);
-
- return $data;
- }
-
- /*
- * This is an extremely naive but reasonably readable implementation. There
- * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
- * an issue, but I suspect it won't be.
- */
- private function findMetadataStart($filename)
- {
- $handle = $this->fileHandle;
- $fstat = fstat($handle);
- $fileSize = $fstat['size'];
- $marker = self::$METADATA_START_MARKER;
- $markerLength = self::$METADATA_START_MARKER_LENGTH;
- $metadataMaxLengthExcludingMarker
- = min(self::$METADATA_MAX_SIZE, $fileSize) - $markerLength;
-
- for ($i = 0; $i <= $metadataMaxLengthExcludingMarker; $i++) {
- for ($j = 0; $j < $markerLength; $j++) {
- fseek($handle, $fileSize - $i - $j - 1);
- $matchBit = fgetc($handle);
- if ($matchBit !== $marker[$markerLength - $j - 1]) {
- continue 2;
- }
- }
-
- return $fileSize - $i;
- }
- throw new InvalidDatabaseException(
- "Error opening database file ($filename). " .
- 'Is this a valid MaxMind DB file?'
- );
- }
-
- /**
- * @throws \InvalidArgumentException if arguments are passed to the method
- * @throws \BadMethodCallException if the database has been closed
- *
- * @return Metadata object for the database
- */
- public function metadata()
- {
- if (func_num_args()) {
- throw new \InvalidArgumentException(
- 'Method takes no arguments.'
- );
- }
-
- // Not technically required, but this makes it consistent with
- // C extension and it allows us to change our implementation later.
- if (!is_resource($this->fileHandle)) {
- throw new \BadMethodCallException(
- 'Attempt to read from a closed MaxMind DB.'
- );
- }
-
- return $this->metadata;
- }
-
- /**
- * Closes the MaxMind DB and returns resources to the system.
- *
- * @throws \Exception
- * if an I/O error occurs
- */
- public function close()
- {
- if (!is_resource($this->fileHandle)) {
- throw new \BadMethodCallException(
- 'Attempt to close a closed MaxMind DB.'
- );
- }
- fclose($this->fileHandle);
- }
-}
diff --git a/includes/libraries/geolite2/Reader/Decoder.php b/includes/libraries/geolite2/Reader/Decoder.php
deleted file mode 100644
index 40ae27e049e..00000000000
--- a/includes/libraries/geolite2/Reader/Decoder.php
+++ /dev/null
@@ -1,311 +0,0 @@
- 'extended',
- 1 => 'pointer',
- 2 => 'utf8_string',
- 3 => 'double',
- 4 => 'bytes',
- 5 => 'uint16',
- 6 => 'uint32',
- 7 => 'map',
- 8 => 'int32',
- 9 => 'uint64',
- 10 => 'uint128',
- 11 => 'array',
- 12 => 'container',
- 13 => 'end_marker',
- 14 => 'boolean',
- 15 => 'float',
- ];
-
- public function __construct(
- $fileStream,
- $pointerBase = 0,
- $pointerTestHack = false
- ) {
- $this->fileStream = $fileStream;
- $this->pointerBase = $pointerBase;
- $this->pointerTestHack = $pointerTestHack;
-
- $this->switchByteOrder = $this->isPlatformLittleEndian();
- }
-
- public function decode($offset)
- {
- list(, $ctrlByte) = unpack(
- 'C',
- Util::read($this->fileStream, $offset, 1)
- );
- $offset++;
-
- $type = $this->types[$ctrlByte >> 5];
-
- // Pointers are a special case, we don't read the next $size bytes, we
- // use the size to determine the length of the pointer and then follow
- // it.
- if ($type === 'pointer') {
- list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset);
-
- // for unit testing
- if ($this->pointerTestHack) {
- return [$pointer];
- }
-
- list($result) = $this->decode($pointer);
-
- return [$result, $offset];
- }
-
- if ($type === 'extended') {
- list(, $nextByte) = unpack(
- 'C',
- Util::read($this->fileStream, $offset, 1)
- );
-
- $typeNum = $nextByte + 7;
-
- if ($typeNum < 8) {
- throw new InvalidDatabaseException(
- 'Something went horribly wrong in the decoder. An extended type '
- . 'resolved to a type number < 8 ('
- . $this->types[$typeNum]
- . ')'
- );
- }
-
- $type = $this->types[$typeNum];
- $offset++;
- }
-
- list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset);
-
- return $this->decodeByType($type, $offset, $size);
- }
-
- private function decodeByType($type, $offset, $size)
- {
- switch ($type) {
- case 'map':
- return $this->decodeMap($size, $offset);
- case 'array':
- return $this->decodeArray($size, $offset);
- case 'boolean':
- return [$this->decodeBoolean($size), $offset];
- }
-
- $newOffset = $offset + $size;
- $bytes = Util::read($this->fileStream, $offset, $size);
- switch ($type) {
- case 'utf8_string':
- return [$this->decodeString($bytes), $newOffset];
- case 'double':
- $this->verifySize(8, $size);
-
- return [$this->decodeDouble($bytes), $newOffset];
- case 'float':
- $this->verifySize(4, $size);
-
- return [$this->decodeFloat($bytes), $newOffset];
- case 'bytes':
- return [$bytes, $newOffset];
- case 'uint16':
- case 'uint32':
- return [$this->decodeUint($bytes), $newOffset];
- case 'int32':
- return [$this->decodeInt32($bytes), $newOffset];
- case 'uint64':
- case 'uint128':
- return [$this->decodeBigUint($bytes, $size), $newOffset];
- default:
- throw new InvalidDatabaseException(
- 'Unknown or unexpected type: ' . $type
- );
- }
- }
-
- private function verifySize($expected, $actual)
- {
- if ($expected !== $actual) {
- throw new InvalidDatabaseException(
- "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
- );
- }
- }
-
- private function decodeArray($size, $offset)
- {
- $array = [];
-
- for ($i = 0; $i < $size; $i++) {
- list($value, $offset) = $this->decode($offset);
- array_push($array, $value);
- }
-
- return [$array, $offset];
- }
-
- private function decodeBoolean($size)
- {
- return $size === 0 ? false : true;
- }
-
- private function decodeDouble($bits)
- {
- // XXX - Assumes IEEE 754 double on platform
- list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits));
-
- return $double;
- }
-
- private function decodeFloat($bits)
- {
- // XXX - Assumes IEEE 754 floats on platform
- list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits));
-
- return $float;
- }
-
- private function decodeInt32($bytes)
- {
- $bytes = $this->zeroPadLeft($bytes, 4);
- list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes));
-
- return $int;
- }
-
- private function decodeMap($size, $offset)
- {
- $map = [];
-
- for ($i = 0; $i < $size; $i++) {
- list($key, $offset) = $this->decode($offset);
- list($value, $offset) = $this->decode($offset);
- $map[$key] = $value;
- }
-
- return [$map, $offset];
- }
-
- private $pointerValueOffset = [
- 1 => 0,
- 2 => 2048,
- 3 => 526336,
- 4 => 0,
- ];
-
- private function decodePointer($ctrlByte, $offset)
- {
- $pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
-
- $buffer = Util::read($this->fileStream, $offset, $pointerSize);
- $offset = $offset + $pointerSize;
-
- $packed = $pointerSize === 4
- ? $buffer
- : (pack('C', $ctrlByte & 0x7)) . $buffer;
-
- $unpacked = $this->decodeUint($packed);
- $pointer = $unpacked + $this->pointerBase
- + $this->pointerValueOffset[$pointerSize];
-
- return [$pointer, $offset];
- }
-
- private function decodeUint($bytes)
- {
- list(, $int) = unpack('N', $this->zeroPadLeft($bytes, 4));
-
- return $int;
- }
-
- private function decodeBigUint($bytes, $byteLength)
- {
- $maxUintBytes = log(PHP_INT_MAX, 2) / 8;
-
- if ($byteLength === 0) {
- return 0;
- }
-
- $numberOfLongs = ceil($byteLength / 4);
- $paddedLength = $numberOfLongs * 4;
- $paddedBytes = $this->zeroPadLeft($bytes, $paddedLength);
- $unpacked = array_merge(unpack("N$numberOfLongs", $paddedBytes));
-
- $integer = 0;
-
- // 2^32
- $twoTo32 = '4294967296';
-
- foreach ($unpacked as $part) {
- // We only use gmp or bcmath if the final value is too big
- if ($byteLength <= $maxUintBytes) {
- $integer = ($integer << 32) + $part;
- } elseif (extension_loaded('gmp')) {
- $integer = gmp_strval(gmp_add(gmp_mul($integer, $twoTo32), $part));
- } elseif (extension_loaded('bcmath')) {
- $integer = bcadd(bcmul($integer, $twoTo32), $part);
- } else {
- throw new \RuntimeException(
- 'The gmp or bcmath extension must be installed to read this database.'
- );
- }
- }
-
- return $integer;
- }
-
- private function decodeString($bytes)
- {
- // XXX - NOOP. As far as I know, the end user has to explicitly set the
- // encoding in PHP. Strings are just bytes.
- return $bytes;
- }
-
- private function sizeFromCtrlByte($ctrlByte, $offset)
- {
- $size = $ctrlByte & 0x1f;
- $bytesToRead = $size < 29 ? 0 : $size - 28;
- $bytes = Util::read($this->fileStream, $offset, $bytesToRead);
- $decoded = $this->decodeUint($bytes);
-
- if ($size === 29) {
- $size = 29 + $decoded;
- } elseif ($size === 30) {
- $size = 285 + $decoded;
- } elseif ($size > 30) {
- $size = ($decoded & (0x0FFFFFFF >> (32 - (8 * $bytesToRead))))
- + 65821;
- }
-
- return [$size, $offset + $bytesToRead];
- }
-
- private function zeroPadLeft($content, $desiredLength)
- {
- return str_pad($content, $desiredLength, "\x00", STR_PAD_LEFT);
- }
-
- private function maybeSwitchByteOrder($bytes)
- {
- return $this->switchByteOrder ? strrev($bytes) : $bytes;
- }
-
- private function isPlatformLittleEndian()
- {
- $testint = 0x00FF;
- $packed = pack('S', $testint);
-
- return $testint === current(unpack('v', $packed));
- }
-}
diff --git a/includes/libraries/geolite2/Reader/InvalidDatabaseException.php b/includes/libraries/geolite2/Reader/InvalidDatabaseException.php
deleted file mode 100644
index d2a9a775f28..00000000000
--- a/includes/libraries/geolite2/Reader/InvalidDatabaseException.php
+++ /dev/null
@@ -1,10 +0,0 @@
-binaryFormatMajorVersion =
- $metadata['binary_format_major_version'];
- $this->binaryFormatMinorVersion =
- $metadata['binary_format_minor_version'];
- $this->buildEpoch = $metadata['build_epoch'];
- $this->databaseType = $metadata['database_type'];
- $this->languages = $metadata['languages'];
- $this->description = $metadata['description'];
- $this->ipVersion = $metadata['ip_version'];
- $this->nodeCount = $metadata['node_count'];
- $this->recordSize = $metadata['record_size'];
- $this->nodeByteSize = $this->recordSize / 4;
- $this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
- }
-
- public function __get($var)
- {
- return $this->$var;
- }
-}
diff --git a/includes/libraries/geolite2/Reader/Util.php b/includes/libraries/geolite2/Reader/Util.php
deleted file mode 100644
index 87ebbf133f3..00000000000
--- a/includes/libraries/geolite2/Reader/Util.php
+++ /dev/null
@@ -1,26 +0,0 @@
-query( "ALTER TABLE {$wpdb->prefix}wc_download_log DROP FOREIGN KEY {$fk->CONSTRAINT_NAME}" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_download_log DROP FOREIGN KEY {$fk->CONSTRAINT_NAME}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
}
}
@@ -2046,3 +2046,38 @@ function wc_update_370_mro_std_currency() {
function wc_update_370_db_version() {
WC_Install::update_db_version( '3.7.0' );
}
+
+/**
+ * We've moved the MaxMind database to a new location, as per the TOS' requirement that the database not
+ * be publicly accessible.
+ */
+function wc_update_390_move_maxmind_database() {
+ // Make sure to use all of the correct filters to pull the local database path.
+ $old_path = apply_filters( 'woocommerce_geolocation_local_database_path', WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb', 2 );
+
+ // Generate a prefix for the old file and store it in the integration as it would expect it.
+ $prefix = wp_generate_password( 32, false );
+ update_option( 'woocommerce_maxmind_geolocation_settings', array( 'database_prefix' => $prefix ) );
+
+ // Generate the new path in the same way that the integration will.
+ $uploads_dir = wp_upload_dir();
+ $new_path = trailingslashit( $uploads_dir['basedir'] ) . 'woocommerce_uploads/' . $prefix . '-GeoLite2-Country.mmdb';
+ $new_path = apply_filters( 'woocommerce_geolocation_local_database_path', $new_path, 2 );
+
+ @rename( $old_path, $new_path ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
+}
+
+/**
+ * So that we can best meet MaxMind's TOS, the geolocation database update cron should run once per 15 days.
+ */
+function wc_update_390_change_geolocation_database_update_cron() {
+ wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
+ wp_schedule_event( time() + ( DAY_IN_SECONDS * 15 ), 'fifteendays', 'woocommerce_geoip_updater' );
+}
+
+/**
+ * Update DB version.
+ */
+function wc_update_390_db_version() {
+ WC_Install::update_db_version( '3.9.0' );
+}
diff --git a/package-lock.json b/package-lock.json
index 35cdfbd2219..a34bb63a837 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3591,9 +3591,9 @@
}
},
"@types/json-schema": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
- "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
+ "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==",
"dev": true
},
"@types/minimatch": {
@@ -3608,12 +3608,6 @@
"integrity": "sha512-Jrb/x3HT4PTJp6a4avhmJCDEVrPdqLfl3e8GGMbpkGGdwAV5UGlIs4vVEfsHHfylZVOKZWpOqmqFH8CbfOZ6kg==",
"dev": true
},
- "@types/normalize-package-data": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
- "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
- "dev": true
- },
"@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
@@ -3666,27 +3660,27 @@
"integrity": "sha512-wBlsw+8n21e6eTd4yVv8YD/E3xq0O6nNnJIquutAsFGE7EyMKz7W6RNT6BRu1SmdgmlCZ9tb0X+j+D6HGr8pZw=="
},
"@typescript-eslint/experimental-utils": {
- "version": "2.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.12.0.tgz",
- "integrity": "sha512-jv4gYpw5N5BrWF3ntROvCuLe1IjRenLy5+U57J24NbPGwZFAjhnM45qpq0nDH1y/AZMb3Br25YiNVwyPbz6RkA==",
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.16.0.tgz",
+ "integrity": "sha512-bXTmAztXpqxliDKZgvWkl+5dHeRN+jqXVZ16peKKFzSXVzT6mz8kgBpHiVzEKO2NZ8OCU7dG61K9sRS/SkUUFQ==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
- "@typescript-eslint/typescript-estree": "2.12.0",
+ "@typescript-eslint/typescript-estree": "2.16.0",
"eslint-scope": "^5.0.0"
}
},
"@typescript-eslint/typescript-estree": {
- "version": "2.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.12.0.tgz",
- "integrity": "sha512-rGehVfjHEn8Frh9UW02ZZIfJs6SIIxIu/K1bbci8rFfDE/1lQ8krIJy5OXOV3DVnNdDPtoiPOdEANkLMrwXbiQ==",
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.16.0.tgz",
+ "integrity": "sha512-hyrCYjFHISos68Bk5KjUAXw0pP/455qq9nxqB1KkT67Pxjcfw+r6Yhcmqnp8etFL45UexCHUMrADHH7dI/m2WQ==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"eslint-visitor-keys": "^1.1.0",
"glob": "^7.1.6",
"is-glob": "^4.0.1",
- "lodash.unescape": "4.0.1",
+ "lodash": "^4.17.15",
"semver": "^6.3.0",
"tsutils": "^3.17.1"
},
@@ -3714,6 +3708,12 @@
"path-is-absolute": "^1.0.0"
}
},
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -5622,9 +5622,9 @@
}
},
"commander": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz",
- "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz",
+ "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==",
"dev": true
},
"commondir": {
@@ -6252,9 +6252,9 @@
},
"dependencies": {
"commander": {
- "version": "2.20.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
- "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"lru-cache": {
@@ -6516,12 +6516,13 @@
}
},
"eslint-plugin-jest": {
- "version": "23.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.1.1.tgz",
- "integrity": "sha512-2oPxHKNh4j1zmJ6GaCBuGcb8FVZU7YjFUOJzGOPnl9ic7VA/MGAskArLJiRIlnFUmi1EUxY+UiATAy8dv8s5JA==",
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.6.0.tgz",
+ "integrity": "sha512-GH8AhcFXspOLqak7fqnddLXEJsrFyvgO8Bm60SexvKSn1+3rWYESnCiWUOCUcBTprNSDSE4CtAZdM4EyV6gPPw==",
"dev": true,
"requires": {
- "@typescript-eslint/experimental-utils": "^2.5.0"
+ "@typescript-eslint/experimental-utils": "^2.5.0",
+ "micromatch": "^4.0.2"
}
},
"eslint-plugin-react-hooks": {
@@ -6876,9 +6877,9 @@
}
},
"fault": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.2.tgz",
- "integrity": "sha512-o2eo/X2syzzERAtN5LcGbiVQ0WwZSlN3qLtadwAz3X8Bu+XWD16dja/KMsjZLiQr+BLGPDnHGkc4yUJf1Xpkpw==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.3.tgz",
+ "integrity": "sha512-sfFuP4X0hzrbGKjAUNXYvNqsZ5F6ohx/dZ9I0KQud/aiZNwg263r5L9yGB0clvXHCkzXh5W3t7RSHchggYIFmA==",
"dev": true,
"requires": {
"format": "^0.2.2"
@@ -7126,9 +7127,9 @@
"dev": true
},
"flatten": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
- "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
+ "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==",
"dev": true
},
"flow-parser": {
@@ -8679,9 +8680,9 @@
}
},
"handlebars": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
- "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
+ "version": "4.5.3",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+ "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
"dev": true,
"requires": {
"neo-async": "^2.6.0",
@@ -8922,28 +8923,73 @@
}
},
"husky": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz",
- "integrity": "sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ==",
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-4.0.10.tgz",
+ "integrity": "sha512-Ptm4k2DqOwxeK/kzu5RaJmNRoGvESrgDXObFcZ8aJZcyXyMBHhM2FqZj6zYKdetadmP3wCwxEHCBuB9xGlRp8A==",
"dev": true,
"requires": {
- "chalk": "^2.4.2",
+ "chalk": "^3.0.0",
"ci-info": "^2.0.0",
- "cosmiconfig": "^5.2.1",
- "execa": "^1.0.0",
- "get-stdin": "^7.0.0",
+ "cosmiconfig": "^6.0.0",
"opencollective-postinstall": "^2.0.2",
"pkg-dir": "^4.2.0",
"please-upgrade-node": "^3.2.0",
- "read-pkg": "^5.2.0",
- "run-node": "^1.0.0",
- "slash": "^3.0.0"
+ "slash": "^3.0.0",
+ "which-pm-runs": "^1.0.0"
},
"dependencies": {
- "get-stdin": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz",
- "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==",
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "cosmiconfig": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+ "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+ "dev": true,
+ "requires": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.1.0",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.7.2"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"parse-json": {
@@ -8958,23 +9004,20 @@
"lines-and-columns": "^1.1.6"
}
},
- "read-pkg": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
- "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
- "@types/normalize-package-data": "^2.4.0",
- "normalize-package-data": "^2.5.0",
- "parse-json": "^5.0.0",
- "type-fest": "^0.6.0"
+ "has-flag": "^4.0.0"
}
- },
- "type-fest": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
- "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
- "dev": true
}
}
},
@@ -11425,6 +11468,24 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
},
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=",
+ "dev": true
+ },
+ "lodash.isregexp": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isregexp/-/lodash.isregexp-4.0.1.tgz",
+ "integrity": "sha1-4T5kezDNVZdSoEzZEghvr32hwws=",
+ "dev": true
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
+ "dev": true
+ },
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -11662,6 +11723,15 @@
"unist-util-visit": "^1.1.0"
}
},
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
"memize": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/memize/-/memize-1.0.5.tgz",
@@ -11826,13 +11896,14 @@
}
},
"mocha": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz",
- "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.0.tgz",
+ "integrity": "sha512-CirsOPbO3jU86YKjjMzFLcXIb5YiGLUrjrXFHoJ3e2z9vWiaZVCZQ2+gtRGMPWF+nFhN6AWwLM/juzAQ6KRkbA==",
"dev": true,
"requires": {
"ansi-colors": "3.2.3",
"browser-stdout": "1.3.1",
+ "chokidar": "3.3.0",
"debug": "3.2.6",
"diff": "3.5.0",
"escape-string-regexp": "1.0.5",
@@ -11845,7 +11916,7 @@
"minimatch": "3.0.4",
"mkdirp": "0.5.1",
"ms": "2.1.1",
- "node-environment-flags": "1.0.5",
+ "node-environment-flags": "1.0.6",
"object.assign": "4.1.0",
"strip-json-comments": "2.0.1",
"supports-color": "6.0.0",
@@ -11856,6 +11927,38 @@
"yargs-unparser": "1.6.0"
},
"dependencies": {
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "binary-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz",
+ "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.1",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.2.0"
+ }
+ },
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
@@ -11874,6 +11977,22 @@
"locate-path": "^3.0.0"
}
},
+ "fsevents": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+ "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
+ "dev": true,
+ "optional": true
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
"log-symbols": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
@@ -11889,6 +12008,21 @@
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
+ "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.0.4"
+ }
+ },
"supports-color": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
@@ -11968,9 +12102,9 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
},
"node-environment-flags": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
- "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
+ "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==",
"dev": true,
"requires": {
"object.getownpropertydescriptors": "^2.0.3",
@@ -13122,15 +13256,6 @@
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
"dev": true
},
- "mem": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
- "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
- "dev": true,
- "requires": {
- "mimic-fn": "^1.0.0"
- }
- },
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
@@ -13180,14 +13305,6 @@
"requires": {
"ansi-regex": "^3.0.0",
"ansi-styles": "^3.2.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
- "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
- "dev": true
- }
}
},
"private": {
@@ -13994,12 +14111,6 @@
"is-promise": "^2.1.0"
}
},
- "run-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz",
- "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==",
- "dev": true
- },
"run-parallel": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
@@ -15694,44 +15805,40 @@
"dev": true
},
"stylelint-config-recommended-scss": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-4.0.0.tgz",
- "integrity": "sha512-aEy0ENUrH4ASgFCu2mMcqBUAX0l4CPXg0XucJXdW+I7mdqJ7ICddkxP1eamBNBZ1QToc/wsuLmTQcalk3qYpsw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-4.1.0.tgz",
+ "integrity": "sha512-4012ca0weVi92epm3RRBRZcRJIyl5vJjJ/tJAKng+Qat5+cnmuCwyOI2vXkKdjNfGd0gvzyKCKEkvTMDcbtd7Q==",
"dev": true,
"requires": {
"stylelint-config-recommended": "^3.0.0"
}
},
"stylelint-config-wordpress": {
- "version": "15.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-wordpress/-/stylelint-config-wordpress-15.0.0.tgz",
- "integrity": "sha512-53wJuCaS35MiO942ML3//lJ3sIvq9LC2Aw8y7DB9yIuO0Eqx2duWUFyxVQQDmEqDvcEg9gVXHKVca/YI+vMKIg==",
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-wordpress/-/stylelint-config-wordpress-16.0.0.tgz",
+ "integrity": "sha512-fu8F2a3DTHjo7Id4rUbua2FprieKBDQ+jQ67XVBMsys8YyBjOd/CdcCRiWQug4sA1/A41lq0JlD2gOlR0dWmpw==",
"dev": true,
"requires": {
"stylelint-config-recommended": "^3.0.0",
- "stylelint-config-recommended-scss": "^4.0.0",
- "stylelint-scss": "^3.11.1"
+ "stylelint-config-recommended-scss": "^4.1.0",
+ "stylelint-scss": "^3.13.0"
}
},
"stylelint-scss": {
- "version": "3.11.1",
- "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.11.1.tgz",
- "integrity": "sha512-0FZNSfy5X2Or4VRA3Abwfrw1NHrI6jHT8ji9xSwP8Re2Kno0i90qbHwm8ohPO0kRB1RP9x1vCYBh4Tij+SZjIg==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.13.0.tgz",
+ "integrity": "sha512-SaLnvQyndaPcsgVJsMh6zJ1uKVzkRZJx+Wg/stzoB1mTBdEmGketbHrGbMQNymzH/0mJ06zDSpeCDvNxqIJE5A==",
"dev": true,
"requires": {
- "lodash": "^4.17.15",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isregexp": "^4.0.1",
+ "lodash.isstring": "^4.0.1",
"postcss-media-query-parser": "^0.2.3",
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-selector-parser": "^6.0.2",
"postcss-value-parser": "^4.0.2"
},
"dependencies": {
- "lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
- "dev": true
- },
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
@@ -16628,6 +16735,12 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
+ "which-pm-runs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
+ "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
+ "dev": true
+ },
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
diff --git a/package.json b/package.json
index 555451ec7dc..bc417f16af7 100644
--- a/package.json
+++ b/package.json
@@ -29,8 +29,8 @@
"babel-eslint": "10.0.3",
"chai": "4.2.0",
"chai-as-promised": "7.1.1",
- "commander": "3.0.2",
- "eslint-plugin-jest": "23.1.1",
+ "commander": "4.1.0",
+ "eslint-plugin-jest": "23.6.0",
"config": "3.2.4",
"cross-env": "6.0.3",
"eslint": "6.8.0",
@@ -53,17 +53,17 @@
"grunt-shell": "3.0.1",
"grunt-stylelint": "0.13.0",
"grunt-wp-i18n": "1.0.3",
- "husky": "3.1.0",
+ "husky": "4.0.10",
"istanbul": "1.0.0-alpha.2",
"jest": "24.9.0",
"jest-puppeteer": "4.4.0",
"lint-staged": "9.5.0",
- "mocha": "6.2.2",
+ "mocha": "7.0.0",
"node-sass": "4.13.0",
"prettier": "github:automattic/calypso-prettier#c56b4251",
"puppeteer": "2.0.0",
"stylelint": "12.0.1",
- "stylelint-config-wordpress": "15.0.0"
+ "stylelint-config-wordpress": "16.0.0"
},
"engines": {
"node": ">=10.15.0",
diff --git a/readme.txt b/readme.txt
index 94a074c3613..bd0350e4727 100644
--- a/readme.txt
+++ b/readme.txt
@@ -201,6 +201,7 @@ INTERESTED IN DEVELOPMENT?
* Tweak - Include processing orders in tracker data when opted in. #25071
* Tweak - Centralize check for default themes to fix Storefront appearance in the Setup Wizard. #25216
* Tweak - Adds a WordPress version check before recommending the WooCommerce Admin plugin during setup. #25260
+* Fix - Added license key support recent changes from MaxMind GeoLite2. #25378
* Fix - Honor tax rounding preference in edit item and refund flows. #24208
* Fix - Prevent incorrect number of decimal points in prices. #24281
* Fix - Fixed initial support for Gutenberg's Experimental Legacy Widget block. #24292
diff --git a/tests/data/GeoLite2-Country.tar.gz b/tests/data/GeoLite2-Country.tar.gz
new file mode 100644
index 00000000000..f1aef5d4290
Binary files /dev/null and b/tests/data/GeoLite2-Country.tar.gz differ
diff --git a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php
deleted file mode 100644
index 08a277503f2..00000000000
--- a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php
+++ /dev/null
@@ -1,40 +0,0 @@
-assertEquals( 'US', $geolite->get_country_iso( $ipv4 ) );
-
- // Check for IPv6.
- $this->assertEquals( 'US', $geolite->get_country_iso( $ipv6 ) );
-
- // Check for non-valid IP.
- $this->assertEquals( '', $geolite->get_country_iso( 'foobar' ) );
- }
-}
diff --git a/tests/unit-tests/integrations/class-wc-tests-integrations.php b/tests/unit-tests/integrations/class-wc-tests-integrations.php
index 083a873f11f..1adc9aff493 100644
--- a/tests/unit-tests/integrations/class-wc-tests-integrations.php
+++ b/tests/unit-tests/integrations/class-wc-tests-integrations.php
@@ -30,8 +30,8 @@ class WC_Tests_Integrations extends WC_Unit_Test_Case {
*/
public function test_filter() {
$integrations = new WC_Integrations();
- $this->assertEquals( array(), $integrations->integrations );
- $this->assertEquals( array(), $integrations->get_integrations() );
+ $this->assertArrayHasKey( 'maxmind_geolocation', $integrations->integrations );
+ $this->assertArrayHasKey( 'maxmind_geolocation', $integrations->get_integrations() );
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'class-dummy-integration.php';
diff --git a/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php b/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php
new file mode 100644
index 00000000000..aba5a35a1af
--- /dev/null
+++ b/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php
@@ -0,0 +1,146 @@
+http_responder = array( $this, 'mock_http_responses' );
+ }
+
+ /**
+ * Tests that the database path filters work as intended.
+ *
+ * @expectedDeprecated woocommerce_geolocation_local_database_path
+ */
+ public function test_database_path_filters() {
+ $database_service = new WC_Integration_MaxMind_Database_Service( '' );
+
+ $path = $database_service->get_database_path();
+ $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/' . WC_Integration_MaxMind_Database_Service::DATABASE . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $path );
+
+ add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path_deprecated' ), 1, 2 );
+ $path = $database_service->get_database_path();
+ remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path_deprecated' ), 1 );
+
+ $this->assertEquals( '/deprecated_filter', $path );
+
+ add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) );
+ $path = $database_service->get_database_path();
+ remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) );
+
+ $this->assertEquals( '/filter', $path );
+
+ // Now perform any tests with a database file prefix.
+ $database_service = new WC_Integration_MaxMind_Database_Service( 'testing' );
+
+ $path = $database_service->get_database_path();
+ $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/testing-' . WC_Integration_MaxMind_Database_Service::DATABASE . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $path );
+ }
+
+ /**
+ * Tests that the database download works as expected.
+ */
+ public function test_download_database_works() {
+ $database_service = new WC_Integration_MaxMind_Database_Service( '' );
+ $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb';
+
+ $result = $database_service->download_database( 'testing_license' );
+
+ $this->assertEquals( $expected_database, $result );
+
+ // Remove the downloaded file and folder.
+ unlink( $expected_database );
+ rmdir( dirname( $expected_database ) );
+ }
+
+ /**
+ * Tests the that database download wraps the download and extraction errors.
+ */
+ public function test_download_database_wraps_errors() {
+ $database_service = new WC_Integration_MaxMind_Database_Service( '' );
+
+ $result = $database_service->download_database( 'invalid_license' );
+
+ $this->assertWPError( $result );
+ $this->assertEquals( 'woocommerce_maxmind_geolocation_database_license_key', $result->get_error_code() );
+
+ $result = $database_service->download_database( 'generic_error' );
+
+ $this->assertWPError( $result );
+ $this->assertEquals( 'woocommerce_maxmind_geolocation_database_download', $result->get_error_code() );
+
+ $result = $database_service->download_database( 'archive_error' );
+
+ $this->assertWPError( $result );
+ $this->assertEquals( 'woocommerce_maxmind_geolocation_database_archive', $result->get_error_code() );
+ }
+
+ /**
+ * Hook for the deprecated database path filter.
+ *
+ * @param string $database_path The path to the database file.
+ * @param string $deprecated Deprecated since 3.4.0.
+ * @return string
+ */
+ public function filter_database_path_deprecated( $database_path, $deprecated ) {
+ return '/deprecated_filter';
+ }
+
+ /**
+ * Hook for the database path filter.
+ *
+ * @param string $database_path The path to the database file.
+ * @return string
+ */
+ public function filter_database_path( $database_path ) {
+ return '/filter';
+ }
+
+ /**
+ * Helper method to define mocked HTTP responses using WP_HTTP_TestCase.
+ * Thanks to WP_HTTP_TestCase, it is not necessary to perform a regular request
+ * to an external server which would significantly slow down the tests.
+ *
+ * This function is called by WP_HTTP_TestCase::http_request_listner().
+ *
+ * @param array $request Request arguments.
+ * @param string $url URL of the request.
+ *
+ * @return array|WP_Error|false mocked response, error, or false to let WP perform a regular request.
+ */
+ protected function mock_http_responses( $request, $url ) {
+ $mocked_response = false;
+
+ if ( 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=testing_license&suffix=tar.gz' === $url ) {
+ // We need to copy the file to where the request is supposed to have streamed it.
+ copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/GeoLite2-Country.tar.gz', $request['filename'] );
+
+ $mocked_response = array(
+ 'response' => array( 'code' => 200 ),
+ );
+ } elseif ( 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=invalid_license&suffix=tar.gz' === $url ) {
+ return new WP_Error( 'http_404', 'Unauthorized', array( 'code' => 401 ) );
+ } elseif ( 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=generic_error&suffix=tar.gz' === $url ) {
+ return new WP_Error( 'http_404', 'Unauthorized', array( 'code' => 500 ) );
+ } elseif ( 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=archive_error&suffix=tar.gz' === $url ) {
+ $mocked_response = array(
+ 'response' => array( 'code' => 200 ),
+ );
+ }
+
+ return $mocked_response;
+ }
+}
diff --git a/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php b/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php
new file mode 100644
index 00000000000..e7bbbd3e517
--- /dev/null
+++ b/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php
@@ -0,0 +1,125 @@
+database_service = $this->getMockBuilder( 'WC_Integration_maxMind_Database_Service' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ add_filter( 'woocommerce_maxmind_geolocation_database_service', array( $this, 'override_integration_service' ) );
+ }
+
+ /**
+ * Make sure that the database is not updated if no target database path is given.
+ */
+ public function test_update_database_does_nothing_without_database_path() {
+ $this->database_service->expects( $this->once() )
+ ->method( 'get_database_path' )
+ ->willReturn( '' );
+
+ ( new WC_Integration_MaxMind_Geolocation() )->update_database();
+ }
+
+ /**
+ * Makes sure that the database can be updated to a given database.
+ */
+ public function test_update_database_to_parameter_file() {
+ $this->database_service->expects( $this->once() )
+ ->method( 'get_database_path' )
+ ->willReturn( '/testing' );
+
+ ( new WC_Integration_MaxMind_Geolocation() )->update_database( '/tmp/noop.mmdb' );
+ }
+
+ /**
+ * Makes sure that the integration uses the license key correctly.
+ */
+ public function test_update_database_uses_license_key() {
+ $this->database_service->expects( $this->once() )
+ ->method( 'get_database_path' )
+ ->willReturn( '/testing' );
+ $this->database_service->expects( $this->once() )
+ ->method( 'download_database' )
+ ->with( 'test_license' )
+ ->willReturn( '/tmp/' . WC_Integration_MaxMind_Database_Service::DATABASE . '.' . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION );
+
+ $integration = new WC_Integration_MaxMind_Geolocation();
+ $integration->update_option( 'license_key', 'test_license' );
+
+ $integration->update_database();
+ }
+
+ /**
+ * Make sure that the geolocate_ip method does not squash existing country codes.
+ */
+ public function test_geolocate_ip_returns_existing_country_code() {
+ $data = ( new WC_Integration_MaxMind_Geolocation() )->get_geolocation( array( 'country' => 'US' ), '192.168.1.1' );
+
+ $this->assertEquals( 'US', $data['country'] );
+ }
+
+ /**
+ * Make sure that the geolocate_ip method does nothing if IP is not set.
+ */
+ public function test_geolocate_ip_returns_empty_without_ip_address() {
+ $data = ( new WC_Integration_MaxMind_Geolocation() )->get_geolocation( array(), '' );
+
+ $this->assertEmpty( $data );
+ }
+
+ /**
+ * Make sure that the geolocate_ip method uses the appropriate service methods..
+ */
+ public function test_geolocate_ip_uses_service() {
+ $this->database_service->expects( $this->once() )
+ ->method( 'get_iso_country_code_for_ip' )
+ ->with( '192.168.1.1' )
+ ->willReturn( 'US' );
+
+ $data = ( new WC_Integration_MaxMind_Geolocation() )->get_geolocation( array(), '192.168.1.1' );
+
+ $this->assertEquals( 'US', $data['country'] );
+ }
+
+ /**
+ * Overrides the filesystem method.
+ *
+ * @return string
+ */
+ public function override_filesystem_method() {
+ return 'Base';
+ }
+
+ /**
+ * Overrides the database service used by the integration.
+ *
+ * @return mixed
+ */
+ public function override_integration_service() {
+ return $this->database_service;
+ }
+}
diff --git a/tests/unit-tests/shipping/shipping.php b/tests/unit-tests/shipping/shipping.php
index f922899afd7..87c2d6b7569 100644
--- a/tests/unit-tests/shipping/shipping.php
+++ b/tests/unit-tests/shipping/shipping.php
@@ -60,19 +60,6 @@ class WC_Tests_Shipping extends WC_Unit_Test_Case {
);
$this->assertFalse( $result );
- // Failure for invalid postcode.
- $result = $shipping->is_package_shippable(
- array(
- 'destination' => array(
- 'country' => 'US',
- 'state' => 'CA',
- 'postcode' => 'test',
- 'address' => '',
- ),
- )
- );
- $this->assertFalse( $result );
-
// Success for correct address.
$result = $shipping->is_package_shippable(
array(
diff --git a/tests/unit-tests/util/api-functions.php b/tests/unit-tests/util/api-functions.php
index 9379a4d2198..bdd1ebf7653 100644
--- a/tests/unit-tests/util/api-functions.php
+++ b/tests/unit-tests/util/api-functions.php
@@ -82,8 +82,12 @@ class WC_Tests_API_Functions extends WC_Unit_Test_Case {
*/
public function test_wc_rest_upload_image_from_url_should_return_error_when_invalid_image_is_passed() {
// empty file.
- $expected_error_message = 'Invalid image: File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.';
- $result = wc_rest_upload_image_from_url( 'http://somedomain.com/invalid-image-1.png' );
+ if ( version_compare( get_bloginfo( 'version' ), '5.4-alpha', '>=' ) ) {
+ $expected_error_message = 'Invalid image: File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini file or by post_max_size being defined as smaller than upload_max_filesize in php.ini.';
+ } else {
+ $expected_error_message = 'Invalid image: File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.';
+ }
+ $result = wc_rest_upload_image_from_url( 'http://somedomain.com/invalid-image-1.png' );
$this->assertWPError( $result );
$this->assertEquals( $expected_error_message, $result->get_error_message() );
diff --git a/woocommerce.php b/woocommerce.php
index 1e0e98c5d38..567a96036f1 100644
--- a/woocommerce.php
+++ b/woocommerce.php
@@ -3,7 +3,7 @@
* Plugin Name: WooCommerce
* Plugin URI: https://woocommerce.com/
* Description: An eCommerce toolkit that helps you sell anything. Beautifully.
- * Version: 3.9.0-rc.2
+ * Version: 3.9.0-rc.3
* Author: Automattic
* Author URI: https://woocommerce.com
* Text Domain: woocommerce