From c933b818e05aa7e08b177e3329061b1cba88756f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Dec 2019 21:14:33 +0000 Subject: [PATCH 01/78] Bump handlebars from 4.1.2 to 4.5.3 Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.1.2 to 4.5.3. - [Release notes](https://github.com/wycats/handlebars.js/releases) - [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md) - [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2...v4.5.3) Signed-off-by: dependabot[bot] --- package-lock.json | 50 ++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index f6a3945d213..6f03d7435e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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": { @@ -6876,9 +6876,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 +7126,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 +8679,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", @@ -11662,6 +11662,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", @@ -13122,15 +13131,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 +13180,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": { From e3d95af13f13fc7b6c7e22770578d948d686fb6c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 4 Jan 2020 19:09:11 +0000 Subject: [PATCH 02/78] Update dependency mocha to v7 --- package-lock.json | 78 ++++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index f6a3945d213..a88052e3b76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11826,13 +11826,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 +11846,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 +11857,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 +11907,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 +11938,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 +12032,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", diff --git a/package.json b/package.json index b92fd426745..8db9a7e1359 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "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", From bb51ec52f43a866b189d335ab0bd820d2e7d8bdf Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 Jan 2020 09:20:28 +0000 Subject: [PATCH 03/78] Update dependency commander to v4 --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f6a3945d213..8a1bc77c2ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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": { diff --git a/package.json b/package.json index b92fd426745..8dfc35d49fd 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "babel-eslint": "10.0.3", "chai": "4.2.0", "chai-as-promised": "7.1.1", - "commander": "3.0.2", + "commander": "4.1.0", "eslint-plugin-jest": "23.1.1", "config": "3.2.4", "cross-env": "6.0.3", From 300064187b96942dcafb039feafb15729c63d709 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 7 Jan 2020 15:25:58 -0800 Subject: [PATCH 04/78] Moved the MaxMind DB Reader library into composer and pinned the latest version --- composer.json | 3 +- composer.lock | 64 +++- includes/class-wc-geolite-integration.php | 15 - includes/libraries/geolite2/Reader.php | 309 ----------------- .../libraries/geolite2/Reader/Decoder.php | 311 ------------------ .../Reader/InvalidDatabaseException.php | 10 - .../libraries/geolite2/Reader/Metadata.php | 69 ---- includes/libraries/geolite2/Reader/Util.php | 26 -- 8 files changed, 64 insertions(+), 743 deletions(-) delete mode 100644 includes/libraries/geolite2/Reader.php delete mode 100644 includes/libraries/geolite2/Reader/Decoder.php delete mode 100644 includes/libraries/geolite2/Reader/InvalidDatabaseException.php delete mode 100644 includes/libraries/geolite2/Reader/Metadata.php delete mode 100644 includes/libraries/geolite2/Reader/Util.php diff --git a/composer.json b/composer.json index 3e0112c14ab..48a0490eea3 100644 --- a/composer.json +++ b/composer.json @@ -7,9 +7,10 @@ "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", + "maxmind-db/reader": "1.6.0", "woocommerce/woocommerce-blocks": "2.5.7", "woocommerce/woocommerce-rest-api": "1.0.5" }, diff --git a/composer.lock b/composer.lock index 8426538364e..58b730a3f76 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": "16f33bdc0f7129c5ec814efd76744356", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -164,6 +164,66 @@ ], "time": "2019-08-12T15:00:31+00:00" }, + { + "name": "maxmind-db/reader", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", + "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4" + }, + "dist": { + "type": "zip", + "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.7", @@ -209,7 +269,7 @@ "gutenberg", "woocommerce" ], - "time": "2019-12-20T16:26:08+00:00" + "time": "2019-12-20T17:36:46+00:00" }, { "name": "woocommerce/woocommerce-rest-api", diff --git a/includes/class-wc-geolite-integration.php b/includes/class-wc-geolite-integration.php index a5a33b8eead..296c8281644 100644 --- a/includes/class-wc-geolite-integration.php +++ b/includes/class-wc-geolite-integration.php @@ -38,10 +38,6 @@ class WC_Geolite_Integration { */ public function __construct( $database ) { $this->database = $database; - - if ( ! class_exists( 'MaxMind\\Db\\Reader', false ) ) { - $this->require_geolite_library(); - } } /** @@ -87,15 +83,4 @@ class WC_Geolite_Integration { $this->log->log( $level, $message, array( 'source' => 'geoip' ) ); } - - /** - * Require geolite library. - */ - private function require_geolite_library() { - require_once WC_ABSPATH . 'includes/libraries/geolite2/Reader/Decoder.php'; - require_once WC_ABSPATH . 'includes/libraries/geolite2/Reader/InvalidDatabaseException.php'; - require_once WC_ABSPATH . 'includes/libraries/geolite2/Reader/Metadata.php'; - require_once WC_ABSPATH . 'includes/libraries/geolite2/Reader/Util.php'; - require_once WC_ABSPATH . 'includes/libraries/geolite2/Reader.php'; - } } diff --git a/includes/libraries/geolite2/Reader.php b/includes/libraries/geolite2/Reader.php deleted file mode 100644 index 4ccab914466..00000000000 --- a/includes/libraries/geolite2/Reader.php +++ /dev/null @@ -1,309 +0,0 @@ -get method. - */ -class Reader -{ - private static $DATA_SECTION_SEPARATOR_SIZE = 16; - private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com"; - private static $METADATA_START_MARKER_LENGTH = 14; - private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KB - - private $decoder; - private $fileHandle; - private $fileSize; - private $ipV4Start; - private $metadata; - - /** - * Constructs a Reader for the MaxMind DB format. The file passed to it must - * be a valid MaxMind DB file such as a GeoIp2 database file. - * - * @param string $database - * the MaxMind DB file to use - * - * @throws \InvalidArgumentException for invalid database path or unknown arguments - * @throws \MaxMind\Db\Reader\InvalidDatabaseException - * if the database is invalid or there is an error reading - * from it - */ - public function __construct($database) - { - if (func_num_args() !== 1) { - throw new \InvalidArgumentException( - 'The constructor takes exactly one argument.' - ); - } - - if (!is_readable($database)) { - throw new \InvalidArgumentException( - "The file \"$database\" does not exist or is not readable." - ); - } - $this->fileHandle = @fopen($database, 'rb'); - if ($this->fileHandle === false) { - throw new \InvalidArgumentException( - "Error opening \"$database\"." - ); - } - $this->fileSize = @filesize($database); - if ($this->fileSize === false) { - throw new \UnexpectedValueException( - "Error determining the size of \"$database\"." - ); - } - - $start = $this->findMetadataStart($database); - $metadataDecoder = new Decoder($this->fileHandle, $start); - list($metadataArray) = $metadataDecoder->decode($start); - $this->metadata = new Metadata($metadataArray); - $this->decoder = new Decoder( - $this->fileHandle, - $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE - ); - } - - /** - * Looks up the 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 @@ - Date: Wed, 8 Jan 2020 21:05:14 -0800 Subject: [PATCH 05/78] Added support for creating default integrations --- includes/class-wc-integrations.php | 12 +++++++++++- .../integrations/class-wc-tests-integrations.php | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/includes/class-wc-integrations.php b/includes/class-wc-integrations.php index 3e89f67a706..94c1589a377 100644 --- a/includes/class-wc-integrations.php +++ b/includes/class-wc-integrations.php @@ -29,7 +29,7 @@ class WC_Integrations { do_action( 'woocommerce_integrations_init' ); - $load_integrations = apply_filters( 'woocommerce_integrations', array() ); + $load_integrations = apply_filters( 'woocommerce_integrations', $this->get_default_integrations() ); // Load integration classes. foreach ( $load_integrations as $integration ) { @@ -48,4 +48,14 @@ class WC_Integrations { public function get_integrations() { return $this->integrations; } + + /** + * Fetches all of the default integrations. + * + * @return array + */ + private function get_default_integrations() { + $default_integrations = array(); + return $default_integrations; + } } diff --git a/tests/unit-tests/integrations/class-wc-tests-integrations.php b/tests/unit-tests/integrations/class-wc-tests-integrations.php index 083a873f11f..238ec833f4f 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( 'woocommerce_maxmind_geolocation', $integrations->integrations ); + $this->assertArrayHasKey( 'woocommerce_maxmind_geolocation', $integrations->get_integrations() ); require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'class-dummy-integration.php'; From 45157ff4e1f08af1e1c3b9d97fa60df446cd5e50 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 8 Jan 2020 21:08:25 -0800 Subject: [PATCH 06/78] Added a default integration settings page for managing MaxMind Geolocation services --- includes/class-wc-integrations.php | 4 ++ ...ass-wc-maxmind-geolocation-integration.php | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php diff --git a/includes/class-wc-integrations.php b/includes/class-wc-integrations.php index 94c1589a377..d66ffd9ee02 100644 --- a/includes/class-wc-integrations.php +++ b/includes/class-wc-integrations.php @@ -56,6 +56,10 @@ class WC_Integrations { */ private function get_default_integrations() { $default_integrations = array(); + + include_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php'; + $default_integrations[] = 'WC_MaxMind_Geolocation_Integration'; + return $default_integrations; } } diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php new file mode 100644 index 00000000000..1262c06f9f4 --- /dev/null +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php @@ -0,0 +1,66 @@ +id = 'woocommerce_maxmind_geolocation'; + $this->method_title = __( 'WooCommerce MaxMind Geolocation', 'woocommerce' ); + $this->method_description = __( 'An integration for utilizing MaxMind to do Geolocation lookups.', 'woocommerce' ); + + $this->init_form_fields(); + $this->init_settings(); + + // Bind to the save action for the settings. + add_action( 'woocommerce_update_options_integration_' . $this->id, array( $this, 'process_admin_options' ) ); + } + + /** + * Initializes the settings fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'license_key' => array( + 'title' => __( 'MaxMind License Key', 'woocommerce' ), + 'type' => 'password', + 'description' => __( 'The key that will be used when dealing with MaxMind Geolocation services. You can generate a key in your account after creating an account on MaxMind\'s website.', 'woocommerce' ), + 'desc_tip' => false, + 'default' => '', + ), + ); + } + + /** + * Checks to make sure that the license key is valid. + * + * @param string $key The key of the field. + * @param mixed $value The value of the field. + * @return mixed + * @throws Exception When the license key is invalid. + */ + public function validate_license_key_field( $key, $value ) { + // Empty license keys have no need to validate the data. + if ( empty( $value ) ) { + return $value; + } + + return $value; + } +} From 46d7f16b195d9b39f9f3463dd9a68a8cda3afc86 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 8 Jan 2020 21:09:35 -0800 Subject: [PATCH 07/78] Added support for downloading and extracting the GeoLite2 database --- .../class-wc-maxmind-geolocation-database.php | 89 +++++++++++++++++ ...ass-wc-maxmind-geolocation-integration.php | 16 ++++ tests/data/GeoLite2-Country.tar.gz | Bin 0 -> 14336 bytes .../class-wc-tests-maxmind-database.php | 90 ++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php create mode 100644 tests/data/GeoLite2-Country.tar.gz create mode 100644 tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php new file mode 100644 index 00000000000..9de920dc8d9 --- /dev/null +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php @@ -0,0 +1,89 @@ +license_key = $license_key; + } + + /** + * Fetches the database from the MaxMind service. + * + * @return string|WP_Error The path to the database file or an error if invalid. + */ + public function download_database() { + $download_uri = 'https://download.maxmind.com/app/geoip_download?'; + $download_uri .= http_build_query( + array( + 'edition_id' => 'GeoLite2-Country', + 'license_key' => $this->license_key, + 'suffix' => 'tar.gz', + ) + ); + + // Needed for the download_url call right below. + require_once ABSPATH . 'wp-admin/includes/file.php'; + + $tmp_archive_path = download_url( $download_uri ); + if ( is_wp_error( $tmp_archive_path ) ) { + // Transform the error into something more informative. + $error_data = $tmp_archive_path->get_error_data(); + if ( isset( $error_data['code'] ) ) { + switch ( $error_data['code'] ) { + case 401: + return new WP_Error( + 'woocommerce_maxmind_geolocation_database_license_key', + __( 'The MaxMind license key is invalid.', 'woocommerce' ) + ); + } + } + + return new WP_Error( 'woocommerce_maxmind_geolocation_database_download', __( 'Failed to download the MaxMind database.', 'woocommerce' ) ); + } + + // Extract the database from the archive. + try { + $file = new PharData( $tmp_archive_path ); + + $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . 'GeoLite2-Country.mmdb'; + + $file->extractTo( + dirname( $tmp_database_path ), + trailingslashit( $file->current()->getFilename() ) . 'GeoLite2-Country.mmdb', + true + ); + } catch ( Exception $exception ) { + return new WP_Error( 'woocommerce_maxmind_geolocation_database_archive', $exception->getMessage() ); + } finally { + // Remove the archive since we only care about a single file in it. + unlink( $tmp_archive_path ); + } + + return $tmp_database_path; + } +} diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php index 1262c06f9f4..37ed2bd5448 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php @@ -61,6 +61,22 @@ class WC_MaxMind_Geolocation_Integration extends WC_Integration { return $value; } + // Check the license key by attempting to download the Geolocation database. + $database = new WC_MaxMind_Geolocation_Database( $value ); + + $file = $database->download_database(); + if ( is_wp_error( $file ) ) { + WC_Admin_Settings::add_error( $file->get_error_message() ); + + // Throw an exception to keep from changing this value. This will prevent + // users from accidentally losing their license key, which cannot + // be viewed again after generating. + throw new Exception( $file->get_error_message() ); + } else { + // We don't need the file that we've downloaded. + unlink( $file ); + } + return $value; } } diff --git a/tests/data/GeoLite2-Country.tar.gz b/tests/data/GeoLite2-Country.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..dec6fbbee8e41e40343f6d06160851abd750eb14 GIT binary patch literal 14336 zcmeHOZExE)5I%1KR-_ovF9Y_G-_`-CM7??$HXv=G3Z(bNWJ`*kEZj}0c2X_<7wc-2>tg!e z=RW5iZ_`~9=e!+7j0}w{%Kfk`qY5dAnHR)7iu^d>0pq?G#U8QAU0-|?{n1d10$o$d zAU#dhXxJA;rt;}kU5FhWU9G%Ou0}E&6uZ#!sM&zCOsARr)r;CcMPV5DffI*3@S;`U zUw+hGx1GBO1RA~Gy$9p93An~$|L6R&|9kB?4v0nf*M(+FU%3A_&;S1U%HV7qyg$&Y zkj*GAY{C4;VHNKe$Nw-2yuif&An;-v{}+OKPmP!3zwi4za8@I)&4VypwekO+P=35- zn*IN-UOyl6V*mF-&ciDHpZmWTgb^`5H}P=X7asosZ0psi=Mg;v`vlq0r3TM8?IvGK zU)43=fVN5-Z)lq~X^RfYxh8EZECLpR$A*CM-EV1~_Gq8p(MA8&G$Fk`P~Bvp5=bFL zw0;5o@OPaSYo6$22Vu5=)E*tsl!l~9QbsQQMv4YB0xwbP(gq2%32<*wmQ<9riV{er zbc(DXJ)}Nl3TP?HVbAC(8iOBz3hI?wo6uLZ10C}=pI%^WMmtBjfYy7|@iKGrz_np# zAp#i3Zat0#IKjquh$94N<}u9Xph2R<%|3320M=}io;4Cq=-&nk)kEgfA!-1Pv7@qZtnj?tDYZNFaJbPKO?oP zzI}e{``Uf*+j{*Rgpd0F?EWY2|5W}TL~&@>|2cvW$2HIY&h~m|_n>p<-5;5I{|oPb z#$I**f4=|oBHy?3|8TQDxBM1cKXt@(KON4tc&?ElIg7ZhasE& zXjliEMp!7=PTG|@OualVq|C5~Tw&vW+U>Kh$XO!UX)4FCA~fr3eKP#nb;skelZi=& zJ*CrCnJaVmSgL{f2Z}341K}($ADT|}W*gKr@2cWN6++9h2fHEz^ZP}6Fp!&CM-|6^ zFqDo9ae{7$L1|{zCs@t!mlq~ZMLH14K(bMef4~3)$<_-gbb1O#W%wJ&kiFEpNRyFH zRn9_(&qnI7LsgE73D(7K`5eSSg~SRPhv|H{-P$gOYRsA*y0z%gO{OkPyLMYW|6N+n LB481Ccm)0d*fe_( literal 0 HcmV?d00001 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..4753ecab0cf --- /dev/null +++ b/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php @@ -0,0 +1,90 @@ +http_responder = array( $this, 'mock_http_responses' ); + } + + /** + * Tests that the database download works as expected. + */ + public function test_download_database_works() { + $service = new WC_MaxMind_Geolocation_Database( 'testing_license' ); + $result = $service->download_database(); + + $this->assertEquals( '/tmp/GeoLite2-Country_20200107/GeoLite2-Country.mmdb', $result ); + } + + /** + * Tests the that database download wraps the download and extraction errors. + */ + public function test_download_database_wraps_errors() { + $service = new WC_MaxMind_Geolocation_Database( 'invalid_license' ); + $result = $service->download_database(); + + $this->assertWPError( $result ); + $this->assertEquals( 'woocommerce_maxmind_geolocation_database_license_key', $result->get_error_code() ); + + $service = new WC_MaxMind_Geolocation_Database( 'generic_error' ); + $result = $service->download_database(); + + $this->assertWPError( $result ); + $this->assertEquals( 'woocommerce_maxmind_geolocation_database_download', $result->get_error_code() ); + + $service = new WC_MaxMind_Geolocation_Database( 'archive_error' ); + $result = $service->download_database(); + + $this->assertWPError( $result ); + $this->assertEquals( 'woocommerce_maxmind_geolocation_database_archive', $result->get_error_code() ); + } + + /** + * 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; + } +} From 1eb49ef8b8c2df6a5dd3a31b74479928bea32439 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 8 Jan 2020 21:48:05 -0800 Subject: [PATCH 08/78] Added filterable support for fetching the database path This replaces the corresponding geolocation class functionality. We are deprecating the woocommerce_geolocation_local_database_path filter in favor of the woocommerce_maxmind_geolocation_databse_path filter. Since we want the option to turn this into a feature plugin, it's wise to make sure nothing is too generic. --- .../class-wc-maxmind-geolocation-database.php | 54 ++++++++++++---- .../class-wc-tests-maxmind-database.php | 64 ++++++++++++++++--- 2 files changed, 96 insertions(+), 22 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php index 9de920dc8d9..bbf2cccae25 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php @@ -16,32 +16,58 @@ defined( 'ABSPATH' ) || exit; class WC_MaxMind_Geolocation_Database { /** - * The license key for interacting with the MaxMind service. - * - * @var string + * The name of the MaxMind database to utilize. */ - private $license_key; + const DATABASE = 'GeoLite2-Country'; /** - * Initialize the database. - * - * @param string $license_key The license key to interact with the MaxMind service. + * The extension for the MaxMind database. */ - public function __construct( $license_key ) { - $this->license_key = $license_key; + const DATABASE_EXTENSION = '.mmdb'; + + /** + * Fetches the path that the database should be stored. + * + * @return string The local database path. + */ + public function get_database_path() { + $database_path = WP_CONTENT_DIR . '/uploads/' . self::DATABASE . self::DATABASE_EXTENSION; + + /** + * Filter the geolocation database storage path. + * + * @param string $database_path The path to the database. + * @param int $version Deprecated since 3.4.0. + * @deprecated 3.9.0 + */ + $database_path = apply_filters_deprecated( + 'woocommerce_geolocation_local_database_path', + array( $database_path, 2 ), + '3.9.0', + 'woocommerce_maxmind_geolocation_database_path' + ); + + /** + * Filter the geolocation database storage path. + * + * @since 3.9.0 + * @param string $database_path The path to the database. + */ + return apply_filters( 'woocommerce_maxmind_geolocation_database_path', $database_path ); } /** * Fetches the database from the MaxMind service. * + * @param string $license_key The license key to be used when downloading the database. * @return string|WP_Error The path to the database file or an error if invalid. */ - public function download_database() { + public function download_database( $license_key ) { $download_uri = 'https://download.maxmind.com/app/geoip_download?'; $download_uri .= http_build_query( array( - 'edition_id' => 'GeoLite2-Country', - 'license_key' => $this->license_key, + 'edition_id' => self::DATABASE, + 'license_key' => $license_key, 'suffix' => 'tar.gz', ) ); @@ -70,11 +96,11 @@ class WC_MaxMind_Geolocation_Database { try { $file = new PharData( $tmp_archive_path ); - $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . 'GeoLite2-Country.mmdb'; + $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION; $file->extractTo( dirname( $tmp_database_path ), - trailingslashit( $file->current()->getFilename() ) . 'GeoLite2-Country.mmdb', + trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION, true ); } catch ( Exception $exception ) { 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 index 4753ecab0cf..2750df61a66 100644 --- 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 @@ -10,6 +10,13 @@ */ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { + /** + * The database used by the tests. + * + * @var WC_MaxMind_Geolocation_Database + */ + private $database_service; + /** * Run setup code for unit tests. */ @@ -18,14 +25,37 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { // Callback used by WP_HTTP_TestCase to decide whether to perform HTTP requests or to provide a mocked response. $this->http_responder = array( $this, 'mock_http_responses' ); + + $this->database_service = new WC_MaxMind_Geolocation_Database(); + } + + /** + * Tests that the database path filters work as intended. + * + * @expectedDeprecated woocommerce_geolocation_local_database_path + */ + public function test_database_path_filters() { + $path = $this->database_service->get_database_path(); + $this->assertEquals( WP_CONTENT_DIR . '/uploads/' . WC_MaxMind_Geolocation_Database::DATABASE . WC_MaxMind_Geolocation_Database::DATABASE_EXTENSION, $path ); + + add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path_deprecated' ), 1, 2 ); + $path = $this->database_service->get_database_path(); + remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); + + $this->assertEquals( '/deprecated_filter', $path ); + + add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); + $path = $this->database_service->get_database_path(); + remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); + + $this->assertEquals( '/filter', $path ); } /** * Tests that the database download works as expected. */ public function test_download_database_works() { - $service = new WC_MaxMind_Geolocation_Database( 'testing_license' ); - $result = $service->download_database(); + $result = $this->database_service->download_database( 'testing_license' ); $this->assertEquals( '/tmp/GeoLite2-Country_20200107/GeoLite2-Country.mmdb', $result ); } @@ -34,25 +64,43 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests the that database download wraps the download and extraction errors. */ public function test_download_database_wraps_errors() { - $service = new WC_MaxMind_Geolocation_Database( 'invalid_license' ); - $result = $service->download_database(); + $result = $this->database_service->download_database( 'invalid_license' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_license_key', $result->get_error_code() ); - $service = new WC_MaxMind_Geolocation_Database( 'generic_error' ); - $result = $service->download_database(); + $result = $this->database_service->download_database( 'generic_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_download', $result->get_error_code() ); - $service = new WC_MaxMind_Geolocation_Database( 'archive_error' ); - $result = $service->download_database(); + $result = $this->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 From 95e59fc777b506ae0ed3818bdeff4a1e6d26a973 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 8 Jan 2020 21:59:04 -0800 Subject: [PATCH 09/78] Made the database service class methods static for convenience \ --- .../class-wc-maxmind-geolocation-database.php | 4 ++-- .../class-wc-tests-maxmind-database.php | 23 ++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php index bbf2cccae25..2fbea8c0c2f 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php @@ -30,7 +30,7 @@ class WC_MaxMind_Geolocation_Database { * * @return string The local database path. */ - public function get_database_path() { + public static function get_database_path() { $database_path = WP_CONTENT_DIR . '/uploads/' . self::DATABASE . self::DATABASE_EXTENSION; /** @@ -62,7 +62,7 @@ class WC_MaxMind_Geolocation_Database { * @param string $license_key The license key to be used when downloading the database. * @return string|WP_Error The path to the database file or an error if invalid. */ - public function download_database( $license_key ) { + public static function download_database( $license_key ) { $download_uri = 'https://download.maxmind.com/app/geoip_download?'; $download_uri .= http_build_query( array( 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 index 2750df61a66..5348bf73a97 100644 --- 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 @@ -10,13 +10,6 @@ */ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { - /** - * The database used by the tests. - * - * @var WC_MaxMind_Geolocation_Database - */ - private $database_service; - /** * Run setup code for unit tests. */ @@ -25,8 +18,6 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { // Callback used by WP_HTTP_TestCase to decide whether to perform HTTP requests or to provide a mocked response. $this->http_responder = array( $this, 'mock_http_responses' ); - - $this->database_service = new WC_MaxMind_Geolocation_Database(); } /** @@ -35,17 +26,17 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * @expectedDeprecated woocommerce_geolocation_local_database_path */ public function test_database_path_filters() { - $path = $this->database_service->get_database_path(); + $path = WC_MaxMind_Geolocation_Database::get_database_path(); $this->assertEquals( WP_CONTENT_DIR . '/uploads/' . WC_MaxMind_Geolocation_Database::DATABASE . WC_MaxMind_Geolocation_Database::DATABASE_EXTENSION, $path ); add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path_deprecated' ), 1, 2 ); - $path = $this->database_service->get_database_path(); + $path = WC_MaxMind_Geolocation_Database::get_database_path(); remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); $this->assertEquals( '/deprecated_filter', $path ); add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); - $path = $this->database_service->get_database_path(); + $path = WC_MaxMind_Geolocation_Database::get_database_path(); remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); $this->assertEquals( '/filter', $path ); @@ -55,7 +46,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests that the database download works as expected. */ public function test_download_database_works() { - $result = $this->database_service->download_database( 'testing_license' ); + $result = WC_MaxMind_Geolocation_Database::download_database( 'testing_license' ); $this->assertEquals( '/tmp/GeoLite2-Country_20200107/GeoLite2-Country.mmdb', $result ); } @@ -64,17 +55,17 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests the that database download wraps the download and extraction errors. */ public function test_download_database_wraps_errors() { - $result = $this->database_service->download_database( 'invalid_license' ); + $result = WC_MaxMind_Geolocation_Database::download_database( 'invalid_license' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_license_key', $result->get_error_code() ); - $result = $this->database_service->download_database( 'generic_error' ); + $result = WC_MaxMind_Geolocation_Database::download_database( 'generic_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_download', $result->get_error_code() ); - $result = $this->database_service->download_database( 'archive_error' ); + $result = WC_MaxMind_Geolocation_Database::download_database( 'archive_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_archive', $result->get_error_code() ); From f23c26a9f956a40922f76dd10bafd9b7e6d2ed10 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 8 Jan 2020 22:56:07 -0800 Subject: [PATCH 10/78] Fixed a permissions conflict caused by the dummy GeoLite2 archive's date The test would fail if the web server had stored the data already! --- tests/data/GeoLite2-Country.tar.gz | Bin 14336 -> 4096 bytes .../class-wc-tests-maxmind-database.php | 8 +++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/data/GeoLite2-Country.tar.gz b/tests/data/GeoLite2-Country.tar.gz index dec6fbbee8e41e40343f6d06160851abd750eb14..f1aef5d4290bdeefb358c743c6fcc65b7edbe5fb 100644 GIT binary patch delta 105 zcmZoDXi%8MBEe*!KXIYgGORCkg j8W=Jt7(fKo#hF2ZdiAWPrf@;1N`rb=G3Z(bNWJ`*kEZj}0c2X_<7wc-2>tg!e z=RW5iZ_`~9=e!+7j0}w{%Kfk`qY5dAnHR)7iu^d>0pq?G#U8QAU0-|?{n1d10$o$d zAU#dhXxJA;rt;}kU5FhWU9G%Ou0}E&6uZ#!sM&zCOsARr)r;CcMPV5DffI*3@S;`U zUw+hGx1GBO1RA~Gy$9p93An~$|L6R&|9kB?4v0nf*M(+FU%3A_&;S1U%HV7qyg$&Y zkj*GAY{C4;VHNKe$Nw-2yuif&An;-v{}+OKPmP!3zwi4za8@I)&4VypwekO+P=35- zn*IN-UOyl6V*mF-&ciDHpZmWTgb^`5H}P=X7asosZ0psi=Mg;v`vlq0r3TM8?IvGK zU)43=fVN5-Z)lq~X^RfYxh8EZECLpR$A*CM-EV1~_Gq8p(MA8&G$Fk`P~Bvp5=bFL zw0;5o@OPaSYo6$22Vu5=)E*tsl!l~9QbsQQMv4YB0xwbP(gq2%32<*wmQ<9riV{er zbc(DXJ)}Nl3TP?HVbAC(8iOBz3hI?wo6uLZ10C}=pI%^WMmtBjfYy7|@iKGrz_np# zAp#i3Zat0#IKjquh$94N<}u9Xph2R<%|3320M=}io;4Cq=-&nk)kEgfA!-1Pv7@qZtnj?tDYZNFaJbPKO?oP zzI}e{``Uf*+j{*Rgpd0F?EWY2|5W}TL~&@>|2cvW$2HIY&h~m|_n>p<-5;5I{|oPb z#$I**f4=|oBHy?3|8TQDxBM1cKXt@(KON4tc&?ElIg7ZhasE& zXjliEMp!7=PTG|@OualVq|C5~Tw&vW+U>Kh$XO!UX)4FCA~fr3eKP#nb;skelZi=& zJ*CrCnJaVmSgL{f2Z}341K}($ADT|}W*gKr@2cWN6++9h2fHEz^ZP}6Fp!&CM-|6^ zFqDo9ae{7$L1|{zCs@t!mlq~ZMLH14K(bMef4~3)$<_-gbb1O#W%wJ&kiFEpNRyFH zRn9_(&qnI7LsgE73D(7K`5eSSg~SRPhv|H{-P$gOYRsA*y0z%gO{OkPyLMYW|6N+n LB481Ccm)0d*fe_( 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 index 5348bf73a97..87061531916 100644 --- 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 @@ -46,9 +46,15 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests that the database download works as expected. */ public function test_download_database_works() { + $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; + $result = WC_MaxMind_Geolocation_Database::download_database( 'testing_license' ); - $this->assertEquals( '/tmp/GeoLite2-Country_20200107/GeoLite2-Country.mmdb', $result ); + $this->assertEquals( $expected_database, $result ); + + // Remove the downloaded file and folder. + unlink( $expected_database ); + rmdir( dirname( $expected_database ) ); } /** From 000a75c23b0ec152079fe9707f91d7c8b99d3e8d Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 8 Jan 2020 22:56:24 -0800 Subject: [PATCH 11/78] Fixed the validation for MaxMind license keys --- .../class-wc-maxmind-geolocation-database.php | 2 +- .../class-wc-maxmind-geolocation-integration.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php index 2fbea8c0c2f..5a4cab21067 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php @@ -99,7 +99,7 @@ class WC_MaxMind_Geolocation_Database { $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION; $file->extractTo( - dirname( $tmp_database_path ), + dirname( $tmp_archive_path ), trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION, true ); diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php index 37ed2bd5448..972d2ecee03 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php +++ b/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php @@ -62,9 +62,7 @@ class WC_MaxMind_Geolocation_Integration extends WC_Integration { } // Check the license key by attempting to download the Geolocation database. - $database = new WC_MaxMind_Geolocation_Database( $value ); - - $file = $database->download_database(); + $file = WC_MaxMind_Geolocation_Database::download_database( $value ); if ( is_wp_error( $file ) ) { WC_Admin_Settings::add_error( $file->get_error_message() ); From 3e597e6f683bf74fc77258df3b168ebe9bd8cf72 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 00:31:51 -0800 Subject: [PATCH 12/78] Replaced the Geolocation database fetching functionality with MaxMind integration --- includes/class-wc-geolocation.php | 74 +++++++------------ .../class-wc-tests-geolite-integration.php | 2 +- 2 files changed, 27 insertions(+), 49 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index efcc86c15c4..2b8a4fca489 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -207,7 +207,7 @@ class WC_Geolocation { $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. } else { $ip_address = $ip_address ? $ip_address : self::get_ip_address(); - $database = self::get_local_database_path(); + $database = WC_MaxMind_Geolocation_Database::get_database_path(); if ( self::supports_geolite2() && file_exists( $database ) ) { $country_code = self::geolocate_via_db( $ip_address, $database ); @@ -230,16 +230,6 @@ class WC_Geolocation { ); } - /** - * Path to our local db. - * - * @param string $deprecated Deprecated since 3.4.0. - * @return string - */ - public static function get_local_database_path( $deprecated = '2' ) { - return apply_filters( 'woocommerce_geolocation_local_database_path', WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb', $deprecated ); - } - /** * Update geoip database. * @@ -253,44 +243,32 @@ class WC_Geolocation { return; } - require_once ABSPATH . 'wp-admin/includes/file.php'; - - $database = 'GeoLite2-Country.mmdb'; - $target_database_path = self::get_local_database_path(); - $tmp_database_path = download_url( self::GEOLITE2_DB ); - - if ( ! is_wp_error( $tmp_database_path ) ) { - WP_Filesystem(); - - global $wp_filesystem; - - try { - // Make sure target dir exists. - $wp_filesystem->mkdir( dirname( $target_database_path ) ); - - // Extract files with PharData. Tool built into PHP since 5.3. - $file = new PharData( $tmp_database_path ); // phpcs:ignore PHPCompatibility.Classes.NewClasses.phardataFound - $file_path = trailingslashit( $file->current()->getFileName() ) . $database; - $file->extractTo( dirname( $tmp_database_path ), $file_path, true ); - - // Move file and delete temp. - $wp_filesystem->move( trailingslashit( dirname( $tmp_database_path ) ) . $file_path, $target_database_path, true ); - $wp_filesystem->delete( trailingslashit( dirname( $tmp_database_path ) ) . $file->current()->getFileName() ); - } catch ( Exception $e ) { - $logger->notice( $e->getMessage(), array( 'source' => 'geolocation' ) ); - - // Reschedule download of DB. - wp_clear_scheduled_hook( 'woocommerce_geoip_updater' ); - wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' ); - } - // Delete temp file regardless of success. - $wp_filesystem->delete( $tmp_database_path ); - } else { - $logger->notice( - 'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message(), - array( 'source' => 'geolocation' ) - ); + // There's no need to update the database with no geolocation configured. + $license_key = ( new WC_MaxMind_Geolocation_Integration() )->get_option( 'license_key' ); + if ( empty( $license_key ) ) { + return; } + + // Allow us to easily interact with the filesystem. + require_once ABSPATH . 'wp-admin/includes/file.php'; + WP_Filesystem(); + global $wp_filesystem; + + // Remove any existing archives to comply with the MaxMind TOS. + $target_database_path = WC_MaxMind_Geolocation_Database::get_database_path(); + if ( $wp_filesystem->exists( $target_database_path ) ) { + $wp_filesystem->delete( $target_database_path ); + } + + $tmp_database_path = WC_MaxMind_Geolocation_Database::download_database( $license_key ); + if ( is_wp_error( $tmp_database_path ) ) { + $logger->notice( $tmp_database_path->get_error_message(), array( 'source' => 'geolocation' ) ); + return; + } + + // Move the new database into position. + $wp_filesystem->move( $tmp_database_path, $target_database_path, true ); + $wp_filesystem->delete( dirname( $tmp_database_path ) ); } /** diff --git a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php index 08a277503f2..461e2155681 100644 --- a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php +++ b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php @@ -26,7 +26,7 @@ class WC_Tests_Geolite_Integration extends WC_Unit_Test_Case { $ipv6 = '2620:0:ccc::2'; // Init GeoLite. - $geolite = new WC_Geolite_Integration( WC_Geolocation::get_local_database_path() ); + $geolite = new WC_Geolite_Integration( WC_MaxMind_Geolocation_Database::get_database_path() ); // Check for IPv4. $this->assertEquals( 'US', $geolite->get_country_iso( $ipv4 ) ); From 98119047bfe6d528c6562c6972854f228db53a45 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 00:56:22 -0800 Subject: [PATCH 13/78] Added back the WC_Geolocation's get_local_database_path method since it was publicly used --- includes/class-wc-geolocation.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 2b8a4fca489..6348ecafa0f 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -230,6 +230,16 @@ class WC_Geolocation { ); } + /** + * Path to our local db. + * + * @param string $deprecated Deprecated since 3.4.0. + * @return string + */ + public static function get_local_database_path( $deprecated = '2' ) { + return WC_MaxMind_Geolocation_Database::get_database_path(); + } + /** * Update geoip database. * From 24b7a9a743da73288843298eeae983c27f81e304 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 9 Jan 2020 14:41:16 +0000 Subject: [PATCH 14/78] Update dependency stylelint-config-wordpress to v16 --- package-lock.json | 50 ++++++++++++++++++++++++++++++----------------- package.json | 2 +- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 35cdfbd2219..cb8f9f9a480 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11425,6 +11425,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", @@ -15694,44 +15712,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", diff --git a/package.json b/package.json index 555451ec7dc..704227008bb 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "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", From bf057927ae9c45e434155952ade0481bb450cf51 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 15:46:01 -0800 Subject: [PATCH 15/78] Moved the loading of integration classes into the WC_Autoloader --- includes/class-wc-autoloader.php | 2 ++ includes/class-wc-geolocation.php | 12 +++++++---- includes/class-wc-integrations.php | 20 +++++-------------- ...egration-maxmind-geolocation-database.php} | 6 +++--- ...ss-wc-integration-maxmind-geolocation.php} | 10 +++++----- .../class-wc-tests-geolite-integration.php | 2 +- .../class-wc-tests-maxmind-database.php | 18 +++++++++-------- 7 files changed, 34 insertions(+), 36 deletions(-) rename includes/integrations/maxmind-geolocation/{class-wc-maxmind-geolocation-database.php => class-wc-integration-maxmind-geolocation-database.php} (95%) rename includes/integrations/maxmind-geolocation/{class-wc-maxmind-geolocation-integration.php => class-wc-integration-maxmind-geolocation.php} (89%) diff --git a/includes/class-wc-autoloader.php b/includes/class-wc-autoloader.php index dd287411089..502a5f63f18 100644 --- a/includes/class-wc-autoloader.php +++ b/includes/class-wc-autoloader.php @@ -88,6 +88,8 @@ class WC_Autoloader { $path = $this->include_path . 'payment-tokens/'; } elseif ( 0 === strpos( $class, 'wc_log_handler_' ) ) { $path = $this->include_path . 'log-handlers/'; + } elseif ( 0 === strpos( $class, 'wc_integration' ) ) { + $path = $this->include_path . 'integrations/' . substr( str_replace( '_', '-', $class ), 15 ) . '/'; } if ( empty( $path ) || ! $this->load_file( $path . $file ) ) { diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 6348ecafa0f..db48a1abe79 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -207,7 +207,7 @@ class WC_Geolocation { $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. } else { $ip_address = $ip_address ? $ip_address : self::get_ip_address(); - $database = WC_MaxMind_Geolocation_Database::get_database_path(); + $database = self::get_local_database_path(); if ( self::supports_geolite2() && file_exists( $database ) ) { $country_code = self::geolocate_via_db( $ip_address, $database ); @@ -238,6 +238,8 @@ class WC_Geolocation { */ public static function get_local_database_path( $deprecated = '2' ) { return WC_MaxMind_Geolocation_Database::get_database_path(); + require_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php'; + return WC_Integration_MaxMind_Geolocation_Database::get_database_path(); } /** @@ -254,7 +256,7 @@ class WC_Geolocation { } // There's no need to update the database with no geolocation configured. - $license_key = ( new WC_MaxMind_Geolocation_Integration() )->get_option( 'license_key' ); + $license_key = ( new WC_Integration_MaxMind_Geolocation() )->get_option( 'license_key' ); if ( empty( $license_key ) ) { return; } @@ -264,13 +266,15 @@ class WC_Geolocation { WP_Filesystem(); global $wp_filesystem; + require_once 'class-wc-integration-maxmind-geolocation-database.php'; + // Remove any existing archives to comply with the MaxMind TOS. - $target_database_path = WC_MaxMind_Geolocation_Database::get_database_path(); + $target_database_path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); if ( $wp_filesystem->exists( $target_database_path ) ) { $wp_filesystem->delete( $target_database_path ); } - $tmp_database_path = WC_MaxMind_Geolocation_Database::download_database( $license_key ); + $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $license_key ); if ( is_wp_error( $tmp_database_path ) ) { $logger->notice( $tmp_database_path->get_error_message(), array( 'source' => 'geolocation' ) ); return; diff --git a/includes/class-wc-integrations.php b/includes/class-wc-integrations.php index d66ffd9ee02..8a5c4ee4c02 100644 --- a/includes/class-wc-integrations.php +++ b/includes/class-wc-integrations.php @@ -29,7 +29,11 @@ class WC_Integrations { do_action( 'woocommerce_integrations_init' ); - $load_integrations = apply_filters( 'woocommerce_integrations', $this->get_default_integrations() ); + $load_integrations = array( + 'WC_Integration_MaxMind_Geolocation', + ); + + $load_integrations = apply_filters( 'woocommerce_integrations', $load_integrations ); // Load integration classes. foreach ( $load_integrations as $integration ) { @@ -48,18 +52,4 @@ class WC_Integrations { public function get_integrations() { return $this->integrations; } - - /** - * Fetches all of the default integrations. - * - * @return array - */ - private function get_default_integrations() { - $default_integrations = array(); - - include_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-integration.php'; - $default_integrations[] = 'WC_MaxMind_Geolocation_Integration'; - - return $default_integrations; - } } diff --git a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php similarity index 95% rename from includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php rename to includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php index 5a4cab21067..5c2d594a11a 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php @@ -1,6 +1,6 @@ get_error_message() ); diff --git a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php index 461e2155681..08a277503f2 100644 --- a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php +++ b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php @@ -26,7 +26,7 @@ class WC_Tests_Geolite_Integration extends WC_Unit_Test_Case { $ipv6 = '2620:0:ccc::2'; // Init GeoLite. - $geolite = new WC_Geolite_Integration( WC_MaxMind_Geolocation_Database::get_database_path() ); + $geolite = new WC_Geolite_Integration( WC_Geolocation::get_local_database_path() ); // Check for IPv4. $this->assertEquals( 'US', $geolite->get_country_iso( $ipv4 ) ); 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 index 87061531916..4d17d4c5dc7 100644 --- 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 @@ -5,6 +5,8 @@ * @package WooCommerce\Tests\Integrations */ +require_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php'; + /** * Class WC_Tests_MaxMind_Database */ @@ -26,17 +28,17 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * @expectedDeprecated woocommerce_geolocation_local_database_path */ public function test_database_path_filters() { - $path = WC_MaxMind_Geolocation_Database::get_database_path(); - $this->assertEquals( WP_CONTENT_DIR . '/uploads/' . WC_MaxMind_Geolocation_Database::DATABASE . WC_MaxMind_Geolocation_Database::DATABASE_EXTENSION, $path ); + $path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); + $this->assertEquals( WP_CONTENT_DIR . '/uploads/' . WC_Integration_MaxMind_Geolocation_Database::DATABASE . WC_Integration_MaxMind_Geolocation_Database::DATABASE_EXTENSION, $path ); add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path_deprecated' ), 1, 2 ); - $path = WC_MaxMind_Geolocation_Database::get_database_path(); + $path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); $this->assertEquals( '/deprecated_filter', $path ); add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); - $path = WC_MaxMind_Geolocation_Database::get_database_path(); + $path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); $this->assertEquals( '/filter', $path ); @@ -48,7 +50,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { public function test_download_database_works() { $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; - $result = WC_MaxMind_Geolocation_Database::download_database( 'testing_license' ); + $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'testing_license' ); $this->assertEquals( $expected_database, $result ); @@ -61,17 +63,17 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests the that database download wraps the download and extraction errors. */ public function test_download_database_wraps_errors() { - $result = WC_MaxMind_Geolocation_Database::download_database( 'invalid_license' ); + $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'invalid_license' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_license_key', $result->get_error_code() ); - $result = WC_MaxMind_Geolocation_Database::download_database( 'generic_error' ); + $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'generic_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_download', $result->get_error_code() ); - $result = WC_MaxMind_Geolocation_Database::download_database( 'archive_error' ); + $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'archive_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_archive', $result->get_error_code() ); From 7cdd19da3feb9b7779f3402067eb982ce7960aa9 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 16:16:34 -0800 Subject: [PATCH 16/78] Fixed the erroneous return in WC_Geolocation::get_local_database_path --- includes/class-wc-geolocation.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index db48a1abe79..ff81bb28367 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -237,7 +237,6 @@ class WC_Geolocation { * @return string */ public static function get_local_database_path( $deprecated = '2' ) { - return WC_MaxMind_Geolocation_Database::get_database_path(); require_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php'; return WC_Integration_MaxMind_Geolocation_Database::get_database_path(); } From 72a84911eae99e5f6776ac8b150b4f8a1bb4494c Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 16:18:20 -0800 Subject: [PATCH 17/78] Simplified the URL generation for geolocation database downloads --- .../class-wc-integration-maxmind-geolocation-database.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php index 5c2d594a11a..d2cbdfe5a46 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php @@ -63,13 +63,13 @@ class WC_Integration_MaxMind_Geolocation_Database { * @return string|WP_Error The path to the database file or an error if invalid. */ public static function download_database( $license_key ) { - $download_uri = 'https://download.maxmind.com/app/geoip_download?'; - $download_uri .= http_build_query( + $download_uri = add_query_arg( array( 'edition_id' => self::DATABASE, 'license_key' => $license_key, 'suffix' => 'tar.gz', - ) + ), + 'https://download.maxmind.com/app/geoip_download' ); // Needed for the download_url call right below. From 6af0edfd9425d8bb48d254259660773da331581d Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 16:21:33 -0800 Subject: [PATCH 18/78] Added a deprecation notice for the GEOLITE2_DB constant --- includes/class-wc-geolocation.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index ff81bb28367..914cae934e1 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -35,6 +35,7 @@ class WC_Geolocation { * GeoLite2 DB. * * @since 3.4.0 + * @deprecated 3.9.0 */ const GEOLITE2_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz'; From 0d4b8f4bd3a8e81039637f12cc6acf0a0517ab6b Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 20:44:13 -0800 Subject: [PATCH 19/78] Added sanitization to the license key in download URLs --- .../class-wc-integration-maxmind-geolocation-database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php index d2cbdfe5a46..04b0f1563af 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php @@ -66,7 +66,7 @@ class WC_Integration_MaxMind_Geolocation_Database { $download_uri = add_query_arg( array( 'edition_id' => self::DATABASE, - 'license_key' => $license_key, + 'license_key' => wc_clean( $license_key ), 'suffix' => 'tar.gz', ), 'https://download.maxmind.com/app/geoip_download' From d45a3541f47ec39e648f883cd2879a90fe8c2aeb Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 20:58:42 -0800 Subject: [PATCH 20/78] Removed the unnecessary GeoLite2 version check --- includes/class-wc-geolocation.php | 33 +++++++------------------------ 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 914cae934e1..cfd88464ae4 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -61,16 +61,6 @@ class WC_Geolocation { 'ip-api.com' => 'http://ip-api.com/json/%s', ); - /** - * Check if server supports MaxMind GeoLite2 Reader. - * - * @since 3.4.0 - * @return bool - */ - private static function supports_geolite2() { - return version_compare( PHP_VERSION, '5.4.0', '>=' ); - } - /** * Check if geolocation is enabled. * @@ -101,17 +91,13 @@ class WC_Geolocation { * Hook in geolocation functionality. */ public static function init() { - if ( self::supports_geolite2() ) { - // Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it. - if ( self::is_geolocation_enabled( get_option( 'woocommerce_default_customer_address' ) ) || apply_filters( 'woocommerce_geolocation_update_database_periodically', false ) ) { - add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); - } - - // Trigger database update when settings are changed to enable geolocation. - add_filter( 'pre_update_option_woocommerce_default_customer_address', array( __CLASS__, 'maybe_update_database' ), 10, 2 ); - } else { - add_filter( 'pre_option_woocommerce_default_customer_address', array( __CLASS__, 'disable_geolocation_on_legacy_php' ) ); + // Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it. + if ( self::is_geolocation_enabled( get_option( 'woocommerce_default_customer_address' ) ) || apply_filters( 'woocommerce_geolocation_update_database_periodically', false ) ) { + add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); } + + // Trigger database update when settings are changed to enable geolocation. + add_filter( 'pre_update_option_woocommerce_default_customer_address', array( __CLASS__, 'maybe_update_database' ), 10, 2 ); } /** @@ -210,7 +196,7 @@ class WC_Geolocation { $ip_address = $ip_address ? $ip_address : self::get_ip_address(); $database = self::get_local_database_path(); - if ( self::supports_geolite2() && file_exists( $database ) ) { + if ( file_exists( $database ) ) { $country_code = self::geolocate_via_db( $ip_address, $database ); } elseif ( $api_fallback ) { $country_code = self::geolocate_via_api( $ip_address ); @@ -250,11 +236,6 @@ class WC_Geolocation { public static function update_database() { $logger = wc_get_logger(); - if ( ! self::supports_geolite2() ) { - $logger->notice( 'Requires PHP 5.4 to be able to download MaxMind GeoLite2 database', array( 'source' => 'geolocation' ) ); - return; - } - // There's no need to update the database with no geolocation configured. $license_key = ( new WC_Integration_MaxMind_Geolocation() )->get_option( 'license_key' ); if ( empty( $license_key ) ) { From f91ff82806f2a8a94b6c1b655253c1f98bc15502 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 21:29:47 -0800 Subject: [PATCH 21/78] Moved the loading of the database class into the integration --- includes/class-wc-geolocation.php | 2 -- .../class-wc-integration-maxmind-geolocation.php | 4 ++-- .../maxmind-geolocation/class-wc-tests-maxmind-database.php | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index cfd88464ae4..694eb2d40b4 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -247,8 +247,6 @@ class WC_Geolocation { WP_Filesystem(); global $wp_filesystem; - require_once 'class-wc-integration-maxmind-geolocation-database.php'; - // Remove any existing archives to comply with the MaxMind TOS. $target_database_path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); if ( $wp_filesystem->exists( $target_database_path ) ) { diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 9d82c90a486..f426af48f9b 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -8,6 +8,8 @@ defined( 'ABSPATH' ) || exit; +require_once 'class-wc-integration-maxmind-geolocation-database.php'; + /** * WC Integration MaxMind Geolocation * @@ -59,8 +61,6 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { return $value; } - require_once 'class-wc-integration-maxmind-geolocation-database.php'; - // Check the license key by attempting to download the Geolocation database. $file = WC_Integration_MaxMind_Geolocation_Database::download_database( $value ); if ( is_wp_error( $file ) ) { 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 index 4d17d4c5dc7..08a0cbf78dc 100644 --- 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 @@ -5,8 +5,6 @@ * @package WooCommerce\Tests\Integrations */ -require_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php'; - /** * Class WC_Tests_MaxMind_Database */ From 2df3af1e635af2b3db2aece35cc98bc742705cb1 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 21:31:12 -0800 Subject: [PATCH 22/78] Deprecated the WC_Geolocation::get_local_database_path method --- includes/class-wc-geolocation.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 694eb2d40b4..3f5a5f84fa6 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -194,7 +194,7 @@ class WC_Geolocation { $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. } else { $ip_address = $ip_address ? $ip_address : self::get_ip_address(); - $database = self::get_local_database_path(); + $database = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); if ( file_exists( $database ) ) { $country_code = self::geolocate_via_db( $ip_address, $database ); @@ -220,11 +220,12 @@ class WC_Geolocation { /** * Path to our local db. * + * @deprecated 3.9.0 * @param string $deprecated Deprecated since 3.4.0. * @return string */ public static function get_local_database_path( $deprecated = '2' ) { - require_once WC_ABSPATH . 'includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php'; + wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0' ); return WC_Integration_MaxMind_Geolocation_Database::get_database_path(); } From 6e41f370a59f0fa64e3fd6994ceb6d8821dcad9d Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 21:39:28 -0800 Subject: [PATCH 23/78] Added a documentation link to the license key setting description --- .../class-wc-integration-maxmind-geolocation.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index f426af48f9b..931c781358b 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -40,7 +40,14 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { 'license_key' => array( 'title' => __( 'MaxMind License Key', 'woocommerce' ), 'type' => 'password', - 'description' => __( 'The key that will be used when dealing with MaxMind Geolocation services. You can generate a key in your account after creating an account on MaxMind\'s website.', 'woocommerce' ), + 'description' => sprintf( + /* translators: %1$s: Documentation URL */ + __( + 'The key that will be used when dealing with MaxMind Geolocation services. You can read how to generate one in MaxMind\'s License Key Documentation.', + 'woocommerce' + ), + 'https://support.maxmind.com/account-faq/account-related/how-do-i-generate-a-license-key/' + ), 'desc_tip' => false, 'default' => '', ), From 02ee3f695e48ad37e16fa06d4ce2f0b994e26d14 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 23:22:42 -0800 Subject: [PATCH 24/78] Moved the database update from the WC_Geolocation class to the MaxMind-specific integration --- includes/class-wc-geolocation.php | 76 +------------------ includes/class-wc-install.php | 2 +- ...ass-wc-integration-maxmind-geolocation.php | 73 ++++++++++++++++-- 3 files changed, 70 insertions(+), 81 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 3f5a5f84fa6..4b6959f73bc 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -72,49 +72,6 @@ class WC_Geolocation { return in_array( $current_settings, array( 'geolocation', 'geolocation_ajax' ), true ); } - /** - * Prevent geolocation via MaxMind when using legacy versions of php. - * - * @since 3.4.0 - * @param string $default_customer_address current value. - * @return string - */ - public static function disable_geolocation_on_legacy_php( $default_customer_address ) { - if ( self::is_geolocation_enabled( $default_customer_address ) ) { - $default_customer_address = 'base'; - } - - return $default_customer_address; - } - - /** - * Hook in geolocation functionality. - */ - public static function init() { - // Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it. - if ( self::is_geolocation_enabled( get_option( 'woocommerce_default_customer_address' ) ) || apply_filters( 'woocommerce_geolocation_update_database_periodically', false ) ) { - add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); - } - - // Trigger database update when settings are changed to enable geolocation. - add_filter( 'pre_update_option_woocommerce_default_customer_address', array( __CLASS__, 'maybe_update_database' ), 10, 2 ); - } - - /** - * Maybe trigger a DB update for the first time. - * - * @param string $new_value New value. - * @param string $old_value Old value. - * @return string - */ - public static function maybe_update_database( $new_value, $old_value ) { - if ( $new_value !== $old_value && self::is_geolocation_enabled( $new_value ) ) { - self::update_database(); - } - - return $new_value; - } - /** * Get current user IP Address. * @@ -232,37 +189,12 @@ class WC_Geolocation { /** * Update geoip database. * + * @deprecated 3.9.0 * Extract files with PharData. Tool built into PHP since 5.3. */ public static function update_database() { - $logger = wc_get_logger(); - - // There's no need to update the database with no geolocation configured. - $license_key = ( new WC_Integration_MaxMind_Geolocation() )->get_option( 'license_key' ); - if ( empty( $license_key ) ) { - return; - } - - // Allow us to easily interact with the filesystem. - require_once ABSPATH . 'wp-admin/includes/file.php'; - WP_Filesystem(); - global $wp_filesystem; - - // Remove any existing archives to comply with the MaxMind TOS. - $target_database_path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); - if ( $wp_filesystem->exists( $target_database_path ) ) { - $wp_filesystem->delete( $target_database_path ); - } - - $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $license_key ); - if ( is_wp_error( $tmp_database_path ) ) { - $logger->notice( $tmp_database_path->get_error_message(), array( 'source' => 'geolocation' ) ); - return; - } - - // Move the new database into position. - $wp_filesystem->move( $tmp_database_path, $target_database_path, true ); - $wp_filesystem->delete( dirname( $tmp_database_path ) ); + wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0' ); + WC_Integration_MaxMind_Geolocation::update_database(); } /** @@ -341,5 +273,3 @@ class WC_Geolocation { return $country_code; } } - -WC_Geolocation::init(); diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 45b9e2b0055..0ef50a3a42b 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -452,7 +452,7 @@ class WC_Install { wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' ); wp_schedule_event( time() + 10, apply_filters( 'woocommerce_tracker_event_recurrence', 'daily' ), 'woocommerce_tracker_send_event' ); - // Trigger GeoLite2 database download after 1 minute. + // Trigger GeoIP updater action after 1 minute. wp_schedule_single_event( time() + ( MINUTE_IN_SECONDS * 1 ), 'woocommerce_geoip_updater' ); } diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 931c781358b..adc27e88d1b 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -30,6 +30,25 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { // Bind to the save action for the settings. add_action( 'woocommerce_update_options_integration_' . $this->id, array( $this, 'process_admin_options' ) ); + + /** + * Allows for the automatic database update to be disabled. + * + * @deprecated 3.9.0 + * @return bool Whether or not the database should be updated periodically. + */ + $bind_updater = apply_filters_deprecated( + 'woocommerce_geolocation_update_database_periodically', + array( true ), + '3.9.0', + false, + 'MaxMind\'s TOS requires that the databases be updated or removed periodically.' + ); + + // Bind to the scheduled updater action. + if ( $bind_updater ) { + add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); + } } /** @@ -69,19 +88,59 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { } // Check the license key by attempting to download the Geolocation database. - $file = WC_Integration_MaxMind_Geolocation_Database::download_database( $value ); - if ( is_wp_error( $file ) ) { - WC_Admin_Settings::add_error( $file->get_error_message() ); + $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $value ); + if ( is_wp_error( $tmp_database_path ) ) { + WC_Admin_Settings::add_error( $tmp_database_path->get_error_message() ); // Throw an exception to keep from changing this value. This will prevent // users from accidentally losing their license key, which cannot // be viewed again after generating. - throw new Exception( $file->get_error_message() ); - } else { - // We don't need the file that we've downloaded. - unlink( $file ); + throw new Exception( $tmp_database_path->get_error_message() ); } + // We may as well put this archive to good use, now that we've downloaded one. + self::update_database( $tmp_database_path ); + return $value; } + + /** + * Updates the database used for geolocation queries. + * + * @param string|null $new_database_path The path to the new database file. Null will fetch a new archive. + */ + public static function update_database( $new_database_path = null ) { + $logger = wc_get_logger(); + + // Allow us to easily interact with the filesystem. + require_once ABSPATH . 'wp-admin/includes/file.php'; + WP_Filesystem(); + global $wp_filesystem; + + // Remove any existing archives to comply with the MaxMind TOS. + $target_database_path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); + if ( $wp_filesystem->exists( $target_database_path ) ) { + $wp_filesystem->delete( $target_database_path ); + } + + if ( isset( $new_database_path ) ) { + $tmp_database_path = $new_database_path; + } else { + // We can't download a database if there's no license key configured. + $license_key = ( new WC_Integration_MaxMind_Geolocation() )->get_option( 'license_key' ); + if ( empty( $license_key ) ) { + return; + } + + $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $license_key ); + if ( is_wp_error( $tmp_database_path ) ) { + $logger->notice( $tmp_database_path->get_error_message(), array( 'source' => 'geolocation' ) ); + return; + } + } + + // Move the new database into position. + $wp_filesystem->move( $tmp_database_path, $target_database_path, true ); + $wp_filesystem->delete( dirname( $tmp_database_path ) ); + } } From bbbfc3bfaba98bc0f5b90bbdf43966ea16942e83 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Thu, 9 Jan 2020 23:46:25 -0800 Subject: [PATCH 25/78] Moved the MaxMind geolocation lookup into the integration class --- includes/class-wc-geolite-integration.php | 1 + includes/class-wc-geolocation.php | 22 +--------- ...tegration-maxmind-geolocation-database.php | 27 ++++++++++++- ...ass-wc-integration-maxmind-geolocation.php | 24 +++++++++-- .../class-wc-tests-geolite-integration.php | 40 ------------------- 5 files changed, 48 insertions(+), 66 deletions(-) delete mode 100644 tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php diff --git a/includes/class-wc-geolite-integration.php b/includes/class-wc-geolite-integration.php index 296c8281644..15b7f054b3a 100644 --- a/includes/class-wc-geolite-integration.php +++ b/includes/class-wc-geolite-integration.php @@ -8,6 +8,7 @@ * * @package WooCommerce\Classes * @since 3.4.0 + * @deprecated 3.9.0 */ defined( 'ABSPATH' ) || exit; diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 4b6959f73bc..680fa6c7c08 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -151,11 +151,8 @@ class WC_Geolocation { $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. } else { $ip_address = $ip_address ? $ip_address : self::get_ip_address(); - $database = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); - if ( file_exists( $database ) ) { - $country_code = self::geolocate_via_db( $ip_address, $database ); - } elseif ( $api_fallback ) { + if ( $api_fallback ) { $country_code = self::geolocate_via_api( $ip_address ); } else { $country_code = ''; @@ -197,23 +194,6 @@ class WC_Geolocation { WC_Integration_MaxMind_Geolocation::update_database(); } - /** - * Use MAXMIND GeoLite database to geolocation the user. - * - * @param string $ip_address IP address. - * @param string $database Database path. - * @return string - */ - private static function geolocate_via_db( $ip_address, $database ) { - if ( ! class_exists( 'WC_Geolite_Integration', false ) ) { - require_once WC_ABSPATH . 'includes/class-wc-geolite-integration.php'; - } - - $geolite = new WC_Geolite_Integration( $database ); - - return $geolite->get_country_iso( $ip_address ); - } - /** * Use APIs to Geolocate the user. * diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php index 04b0f1563af..a6c1eb4aa28 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php @@ -11,7 +11,7 @@ defined( 'ABSPATH' ) || exit; /** * WC Integration MaxMind Geolocation Database * - * @version 3.9.0 + * @since 3.9.0 */ class WC_Integration_MaxMind_Geolocation_Database { @@ -112,4 +112,29 @@ class WC_Integration_MaxMind_Geolocation_Database { return $tmp_database_path; } + + /** + * Fetches the ISO country code associated with an IP address. + * + * @param string $ip_address The IP address to find the country code for. + * @return string|null The country code for the IP address, or null if none was found. + */ + public static function get_iso_country_code_for_ip( $ip_address ) { + $country_code = null; + + try { + $reader = new MaxMind\Db\Reader( self::get_database_path() ); + $data = $reader->get( $ip_address ); + + if ( isset( $data['country']['iso_code'] ) ) { + $country_code = $data['country']['iso_code']; + } + + $reader->close(); + } catch ( Exception $e ) { + wc_get_logger()->notice( $e->getMessage(), array( 'source' => 'maxmind-geolocation' ) ); + } + + return $country_code; + } } diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index adc27e88d1b..7416f02a9ee 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -13,7 +13,7 @@ require_once 'class-wc-integration-maxmind-geolocation-database.php'; /** * WC Integration MaxMind Geolocation * - * @version 3.9.0 + * @since 3.9.0 */ class WC_Integration_MaxMind_Geolocation extends WC_Integration { @@ -49,6 +49,9 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { if ( $bind_updater ) { add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); } + + // Bind to the geolocation filter for MaxMind database lookups. + add_filter( 'woocommerce_geolocate_ip', array( $this, 'geolocate_ip' ), 10, 2 ); } /** @@ -110,8 +113,6 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { * @param string|null $new_database_path The path to the new database file. Null will fetch a new archive. */ public static function update_database( $new_database_path = null ) { - $logger = wc_get_logger(); - // Allow us to easily interact with the filesystem. require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); @@ -134,7 +135,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $license_key ); if ( is_wp_error( $tmp_database_path ) ) { - $logger->notice( $tmp_database_path->get_error_message(), array( 'source' => 'geolocation' ) ); + wc_get_logger()->notice( $tmp_database_path->get_error_message(), array( 'source' => 'maxmind-geolocation' ) ); return; } } @@ -143,4 +144,19 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { $wp_filesystem->move( $tmp_database_path, $target_database_path, true ); $wp_filesystem->delete( dirname( $tmp_database_path ) ); } + + /** + * Performs a geolocation lookup against the MaxMind database for the given IP address. + * + * @param string $country_code The country code for the IP address. + * @param string $ip_address The IP address to geolocate. + * @return string The country code for the IP address. + */ + public function geolocate_ip( $country_code, $ip_address ) { + if ( false !== $country_code ) { + return $country_code; + } + + return WC_Integration_MaxMind_Geolocation_Database::get_iso_country_code_for_ip( $ip_address ); + } } 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' ) ); - } -} From b7521368a79939f2b0148fe0e401edfe46312bbd Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 00:07:55 -0800 Subject: [PATCH 26/78] Fixed the response for the geolocation filter --- .../class-wc-integration-maxmind-geolocation.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 7416f02a9ee..130a39b8011 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -157,6 +157,12 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { return $country_code; } - return WC_Integration_MaxMind_Geolocation_Database::get_iso_country_code_for_ip( $ip_address ); + if ( empty( $ip_address ) ) { + return $country_code; + } + + $country_code = WC_Integration_MaxMind_Geolocation_Database::get_iso_country_code_for_ip( $ip_address ); + + return $country_code ? $country_code : false; } } From 0f6da046a1941bf2e96b0e9707d0a4f2ef47a1a3 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 00:08:24 -0800 Subject: [PATCH 27/78] Refactored the IP geolocation method --- includes/class-wc-geolocation.php | 65 ++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 680fa6c7c08..a49dbab7dfc 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -136,37 +136,35 @@ class WC_Geolocation { * @return array */ public static function geolocate_ip( $ip_address = '', $fallback = false, $api_fallback = true ) { - // Filter to allow custom geolocation of the IP address. - $country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback ); + if ( empty( $ip_address ) ) { + $ip_address = self::get_ip_address(); + } + + $country_code = self::get_country_code_from_headers(); if ( false === $country_code ) { - // If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview). - if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { // WPCS: input var ok, CSRF ok. - $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) ); // WPCS: input var ok, CSRF ok. - } elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. - // WP.com VIP has a variable available. - $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. - } elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. - // VIP Go has a variable available also. - $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. - } else { - $ip_address = $ip_address ? $ip_address : self::get_ip_address(); + // Filter to allow custom geolocation of the IP address. + $country_code = apply_filters( 'woocommerce_geolocate_ip', $country_code, $ip_address, $fallback, $api_fallback ); + } - if ( $api_fallback ) { - $country_code = self::geolocate_via_api( $ip_address ); - } else { - $country_code = ''; - } + // If we still haven't found a country code, let's consider doing an API lookup. + if ( false === $country_code && $api_fallback ) { + $country_code = self::geolocate_via_api( $ip_address ); + } - if ( ! $country_code && $fallback ) { - // May be a local environment - find external IP. - return self::geolocate_ip( self::get_external_ip_address(), false, $api_fallback ); - } + // It's possible that we're in a local environment, in which case the geolocation needs to be done from the + // external address. + if ( false === $country_code && $fallback ) { + $external_ip_address = self::get_external_ip_address(); + + // Only bother with this if the external IP differs. + if ( '0.0.0.0' !== $external_ip_address && $external_ip_address !== $ip_address ) { + return self::geolocate_ip( $external_ip_address, false, $api_fallback ); } } return array( - 'country' => $country_code, + 'country' => $country_code ? $country_code : '', 'state' => '', ); } @@ -194,6 +192,27 @@ class WC_Geolocation { WC_Integration_MaxMind_Geolocation::update_database(); } + /** + * Fetches the country code from the request headers, if one is available. + * + * @return string|false The country code pulled from the headers, or false if one was not found. + */ + private static function get_country_code_from_headers() { + $country_code = false; + + if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { // WPCS: input var ok, CSRF ok. + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) ); // WPCS: input var ok, CSRF ok. + } elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. + // WP.com VIP has a variable available. + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. + } elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. + // VIP Go has a variable available also. + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. + } + + return $country_code; + } + /** * Use APIs to Geolocate the user. * From 26e0b71fce8cc791da68a9357f7dd976c3237e18 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 01:23:06 -0800 Subject: [PATCH 28/78] Added support for mod_maxminddb's MM_COUNTRY_CODE server variable --- includes/class-wc-geolocation.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index a49dbab7dfc..ce1b0168872 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -200,14 +200,20 @@ class WC_Geolocation { private static function get_country_code_from_headers() { $country_code = false; - if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { // WPCS: input var ok, CSRF ok. - $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) ); // WPCS: input var ok, CSRF ok. - } elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. - // WP.com VIP has a variable available. - $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. - } elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. - // VIP Go has a variable available also. - $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. + $headers = array( + 'MM_COUNTRY_CODE', + 'GEOIP_COUNTRY_CODE', + 'HTTP_CF_IPCOUNTRY', + 'HTTP_X_COUNTRY_CODE', + ); + + foreach ( $headers as $header ) { + if ( empty( $_SERVER[ $header ] ) ) { + continue; + } + + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER[ $header ] ) ) ); + break; } return $country_code; From 19ded6609d9fdee767b19da4386987721a27f86d Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 02:09:51 -0800 Subject: [PATCH 29/78] Refactored the MaxMind database class to not use static methods in order to make testing the integration class easier --- includes/class-wc-geolocation.php | 6 ++-- includes/class-wc-integrations.php | 15 ++++++++ ...-integration-maxmind-database-service.php} | 14 ++++---- ...ass-wc-integration-maxmind-geolocation.php | 36 ++++++++++++++----- .../class-wc-tests-maxmind-database.php | 31 +++++++++++----- 5 files changed, 76 insertions(+), 26 deletions(-) rename includes/integrations/maxmind-geolocation/{class-wc-integration-maxmind-geolocation-database.php => class-wc-integration-maxmind-database-service.php} (90%) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index ce1b0168872..6c0208ad851 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -178,7 +178,8 @@ class WC_Geolocation { */ public static function get_local_database_path( $deprecated = '2' ) { wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0' ); - return WC_Integration_MaxMind_Geolocation_Database::get_database_path(); + $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); + return $integration->get_database_path(); } /** @@ -189,7 +190,8 @@ class WC_Geolocation { */ public static function update_database() { wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0' ); - WC_Integration_MaxMind_Geolocation::update_database(); + $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); + $integration->update_database(); } /** diff --git a/includes/class-wc-integrations.php b/includes/class-wc-integrations.php index 8a5c4ee4c02..519aa5b393c 100644 --- a/includes/class-wc-integrations.php +++ b/includes/class-wc-integrations.php @@ -52,4 +52,19 @@ class WC_Integrations { public function get_integrations() { return $this->integrations; } + + /** + * Return a desired integration. + * + * @param string $id The id of the integration to get. + * + * @return mixed|null The integration if one is found, otherwise null. + */ + public function get_integration( $id ) { + if ( isset( $this->integrations[ $id ] ) ) { + return $this->integrations[ $id ]; + } + + return null; + } } diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php similarity index 90% rename from includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php rename to includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index a6c1eb4aa28..1b8a9d90212 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation-database.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -1,6 +1,6 @@ self::DATABASE, @@ -119,11 +119,11 @@ class WC_Integration_MaxMind_Geolocation_Database { * @param string $ip_address The IP address to find the country code for. * @return string|null The country code for the IP address, or null if none was found. */ - public static function get_iso_country_code_for_ip( $ip_address ) { + public function get_iso_country_code_for_ip( $ip_address ) { $country_code = null; try { - $reader = new MaxMind\Db\Reader( self::get_database_path() ); + $reader = new MaxMind\Db\Reader( $this->get_database_path() ); $data = $reader->get( $ip_address ); if ( isset( $data['country']['iso_code'] ) ) { diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 130a39b8011..11c55a5b6cd 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -8,7 +8,7 @@ defined( 'ABSPATH' ) || exit; -require_once 'class-wc-integration-maxmind-geolocation-database.php'; +require_once 'class-wc-integration-maxmind-database-service.php'; /** * WC Integration MaxMind Geolocation @@ -17,6 +17,13 @@ require_once 'class-wc-integration-maxmind-geolocation-database.php'; */ class WC_Integration_MaxMind_Geolocation extends WC_Integration { + /** + * The service responsible for interacting with the MaxMind database. + * + * @var WC_Integration_MaxMind_Database_Service + */ + private $database_service; + /** * Initialize the integration. */ @@ -25,6 +32,19 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { $this->method_title = __( 'WooCommerce MaxMind Geolocation', 'woocommerce' ); $this->method_description = __( 'An integration for utilizing MaxMind to do Geolocation lookups.', 'woocommerce' ); + // We will need a service for interacting with the MaxMind database. + + /** + * Supports overriding the database service to be used. + * + * @since 3.9.0 + * @return mixed|null The geolocation database service. + */ + $this->database_service = apply_filters( 'woocommerce_maxmind_geolocation_database_service', null ); + if ( null === $this->database_service ) { + $this->database_service = new WC_Integration_MaxMind_Database_Service(); + } + $this->init_form_fields(); $this->init_settings(); @@ -47,7 +67,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { // Bind to the scheduled updater action. if ( $bind_updater ) { - add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); + add_action( 'woocommerce_geoip_updater', array( $this, 'update_database' ) ); } // Bind to the geolocation filter for MaxMind database lookups. @@ -91,7 +111,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { } // Check the license key by attempting to download the Geolocation database. - $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $value ); + $tmp_database_path = $this->database_service->download_database( $value ); if ( is_wp_error( $tmp_database_path ) ) { WC_Admin_Settings::add_error( $tmp_database_path->get_error_message() ); @@ -112,14 +132,14 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { * * @param string|null $new_database_path The path to the new database file. Null will fetch a new archive. */ - public static function update_database( $new_database_path = null ) { + public function update_database( $new_database_path = null ) { // Allow us to easily interact with the filesystem. require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); global $wp_filesystem; // Remove any existing archives to comply with the MaxMind TOS. - $target_database_path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); + $target_database_path = $this->database_service->get_database_path(); if ( $wp_filesystem->exists( $target_database_path ) ) { $wp_filesystem->delete( $target_database_path ); } @@ -128,12 +148,12 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { $tmp_database_path = $new_database_path; } else { // We can't download a database if there's no license key configured. - $license_key = ( new WC_Integration_MaxMind_Geolocation() )->get_option( 'license_key' ); + $license_key = $this->get_option( 'license_key' ); if ( empty( $license_key ) ) { return; } - $tmp_database_path = WC_Integration_MaxMind_Geolocation_Database::download_database( $license_key ); + $tmp_database_path = $this->database_service->download_database( $license_key ); if ( is_wp_error( $tmp_database_path ) ) { wc_get_logger()->notice( $tmp_database_path->get_error_message(), array( 'source' => 'maxmind-geolocation' ) ); return; @@ -161,7 +181,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { return $country_code; } - $country_code = WC_Integration_MaxMind_Geolocation_Database::get_iso_country_code_for_ip( $ip_address ); + $country_code = $this->database_service->get_iso_country_code_for_ip( $ip_address ); return $country_code ? $country_code : false; } 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 index 08a0cbf78dc..c3c0dc70c1a 100644 --- 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 @@ -9,7 +9,6 @@ * Class WC_Tests_MaxMind_Database */ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { - /** * Run setup code for unit tests. */ @@ -26,17 +25,22 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * @expectedDeprecated woocommerce_geolocation_local_database_path */ public function test_database_path_filters() { - $path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); - $this->assertEquals( WP_CONTENT_DIR . '/uploads/' . WC_Integration_MaxMind_Geolocation_Database::DATABASE . WC_Integration_MaxMind_Geolocation_Database::DATABASE_EXTENSION, $path ); + $database_service = $this->getMockBuilder( 'WC_Integration_MaxMind_Database_Service' ) + ->setMethods( null ) + ->disableOriginalConstructor() + ->getMock(); + + $path = $database_service->get_database_path(); + $this->assertEquals( WP_CONTENT_DIR . '/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 = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); + $path = $database_service->get_database_path(); remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); $this->assertEquals( '/deprecated_filter', $path ); add_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); - $path = WC_Integration_MaxMind_Geolocation_Database::get_database_path(); + $path = $database_service->get_database_path(); remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path' ) ); $this->assertEquals( '/filter', $path ); @@ -46,9 +50,13 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests that the database download works as expected. */ public function test_download_database_works() { + $database_service = $this->getMockBuilder( 'WC_Integration_MaxMind_Database_Service' ) + ->setMethods( null ) + ->disableOriginalConstructor() + ->getMock(); $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; - $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'testing_license' ); + $result = $database_service->download_database( 'testing_license' ); $this->assertEquals( $expected_database, $result ); @@ -61,17 +69,22 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests the that database download wraps the download and extraction errors. */ public function test_download_database_wraps_errors() { - $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'invalid_license' ); + $database_service = $this->getMockBuilder( 'WC_Integration_MaxMind_Database_Service' ) + ->setMethods( null ) + ->disableOriginalConstructor() + ->getMock(); + + $result = $database_service->download_database( 'invalid_license' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_license_key', $result->get_error_code() ); - $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'generic_error' ); + $result = $database_service->download_database( 'generic_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_download', $result->get_error_code() ); - $result = WC_Integration_MaxMind_Geolocation_Database::download_database( 'archive_error' ); + $result = $database_service->download_database( 'archive_error' ); $this->assertWPError( $result ); $this->assertEquals( 'woocommerce_maxmind_geolocation_database_archive', $result->get_error_code() ); From 93e1d606ed16c76388893cfe826dff46dae6a0fe Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 02:47:23 -0800 Subject: [PATCH 30/78] Fixed a bug where empty database paths might break the update --- .../class-wc-integration-maxmind-geolocation.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 11c55a5b6cd..fdf8a4ec30a 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -140,6 +140,12 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { // Remove any existing archives to comply with the MaxMind TOS. $target_database_path = $this->database_service->get_database_path(); + + // If there's no database path, we can't store the database. + if ( empty( $target_database_path ) ) { + return; + } + if ( $wp_filesystem->exists( $target_database_path ) ) { $wp_filesystem->delete( $target_database_path ); } From f5cbca5bebc7d526b65e9879075a16b22401df2d Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 02:47:43 -0800 Subject: [PATCH 31/78] Added unit tests for the MaxMind integration class --- .../class-wc-tests-maxmind-integration.php | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php 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..5649b5b7a8e --- /dev/null +++ b/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php @@ -0,0 +1,123 @@ +database_service = $this->getMockBuilder( 'WC_Integration_maxMind_Database_Service' )->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() { + $country_code = ( new WC_Integration_MaxMind_Geolocation() )->geolocate_ip( 'US', '192.168.1.1' ); + + $this->assertEquals( 'US', $country_code ); + } + + /** + * Make sure that the geolocate_ip method does nothing if IP is not set. + */ + public function test_geolocate_ip_returns_empty_without_ip_address() { + $country_code = ( new WC_Integration_MaxMind_Geolocation() )->geolocate_ip( false, '' ); + + $this->assertFalse( $country_code ); + } + + /** + * 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' ); + + $country_code = ( new WC_Integration_MaxMind_Geolocation() )->geolocate_ip( false, '192.168.1.1' ); + + $this->assertEquals( 'US', $country_code ); + } + + /** + * 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; + } +} From 0e119cb97a48ea193615ed80b2cf924af7e63633 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 11:58:53 -0300 Subject: [PATCH 32/78] Fixed missing methods, added deprecated notices and @since --- includes/class-wc-geolocation.php | 65 +++++++++++++++++++++++++----- includes/class-wc-integrations.php | 4 +- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 6c0208ad851..74430b3fdbd 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -7,7 +7,7 @@ * This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com. * * @package WooCommerce/Classes - * @version 3.4.0 + * @version 3.9.0 */ defined( 'ABSPATH' ) || exit; @@ -78,14 +78,14 @@ class WC_Geolocation { * @return string */ public static function get_ip_address() { - if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { // WPCS: input var ok, CSRF ok. - return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) ); // WPCS: input var ok, CSRF ok. - } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // WPCS: input var ok, CSRF ok. + if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { + return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) ); + } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2 // Make sure we always only send through the first IP in the list which should always be the client IP. - return (string) rest_is_ip_address( trim( current( preg_split( '/,/', sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ) ) ); // WPCS: input var ok, CSRF ok. - } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { // @codingStandardsIgnoreLine - return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); // @codingStandardsIgnoreLine + return (string) rest_is_ip_address( trim( current( preg_split( '/,/', sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ) ) ); + } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { + return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); } return ''; } @@ -177,7 +177,7 @@ class WC_Geolocation { * @return string */ public static function get_local_database_path( $deprecated = '2' ) { - wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0' ); + wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0', 'WC_Integration_MaxMind_Geolocation::get_database_path' ); $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); return $integration->get_database_path(); } @@ -189,7 +189,7 @@ class WC_Geolocation { * Extract files with PharData. Tool built into PHP since 5.3. */ public static function update_database() { - wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0' ); + wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0', 'WC_Integration_MaxMind_Geolocation::update_database' ); $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); $integration->update_database(); } @@ -197,6 +197,7 @@ class WC_Geolocation { /** * Fetches the country code from the request headers, if one is available. * + * @since 3.9.0 * @return string|false The country code pulled from the headers, or false if one was not found. */ private static function get_country_code_from_headers() { @@ -279,4 +280,50 @@ class WC_Geolocation { return $country_code; } + + /** + * Hook in geolocation functionality. + * + * @deprecated 3.9.0 + * @return null + */ + public static function init() { + wc_deprecated_function( 'WC_Geolocation::init', '3.9.0' ); + return null; + } + + /** + * Prevent geolocation via MaxMind when using legacy versions of php. + * + * @deprecated 3.9.0 + * @since 3.4.0 + * @param string $default_customer_address current value. + * @return string + */ + public static function disable_geolocation_on_legacy_php( $default_customer_address ) { + wc_deprecated_function( 'WC_Geolocation::disable_geolocation_on_legacy_php', '3.9.0' ); + + if ( self::is_geolocation_enabled( $default_customer_address ) ) { + $default_customer_address = 'base'; + } + + return $default_customer_address; + } + + /** + * Maybe trigger a DB update for the first time. + * + * @deprecated 3.9.0 + * @param string $new_value New value. + * @param string $old_value Old value. + * @return string + */ + public static function maybe_update_database( $new_value, $old_value ) { + wc_deprecated_function( 'WC_Geolocation::maybe_update_database', '3.9.0' ); + if ( $new_value !== $old_value && self::is_geolocation_enabled( $new_value ) ) { + self::update_database(); + } + + return $new_value; + } } diff --git a/includes/class-wc-integrations.php b/includes/class-wc-integrations.php index 519aa5b393c..13d906060a2 100644 --- a/includes/class-wc-integrations.php +++ b/includes/class-wc-integrations.php @@ -4,7 +4,7 @@ * * Loads Integrations into WooCommerce. * - * @version 2.3.0 + * @version 3.9.0 * @package WooCommerce/Classes/Integrations */ @@ -56,8 +56,8 @@ class WC_Integrations { /** * Return a desired integration. * + * @since 3.9.0 * @param string $id The id of the integration to get. - * * @return mixed|null The integration if one is found, otherwise null. */ public function get_integration( $id ) { From 2554cbf6e06fd79560361b23c826b839443f97bd Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 12:16:53 -0300 Subject: [PATCH 33/78] Prevent fatal error if MaxMind Reader is not installed --- .../class-wc-integration-maxmind-database-service.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index 1b8a9d90212..39eaa6d7f38 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -122,6 +122,11 @@ class WC_Integration_MaxMind_Database_Service { public function get_iso_country_code_for_ip( $ip_address ) { $country_code = null; + if ( ! class_exists( 'MaxMind\Db\Reader' ) ) { + wc_get_logger()->notice( __( 'Missing MaxMind Reader library!', 'woocommerce' ), array( 'source' => 'maxmind-geolocation' ) ); + return $country_code; + } + try { $reader = new MaxMind\Db\Reader( $this->get_database_path() ); $data = $reader->get( $ip_address ); From 8aa7e62a21e9c05f519b6e17d01f32598a562a74 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 12:22:42 -0300 Subject: [PATCH 34/78] Fixed fatal error in system status page --- includes/class-wc-geolocation.php | 4 ++-- .../class-wc-integration-maxmind-geolocation.php | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 74430b3fdbd..79b9f38a69f 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -177,9 +177,9 @@ class WC_Geolocation { * @return string */ public static function get_local_database_path( $deprecated = '2' ) { - wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0', 'WC_Integration_MaxMind_Geolocation::get_database_path' ); + wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0', 'WC_Integration_MaxMind_Database_Service::get_database_path' ); $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); - return $integration->get_database_path(); + return $integration->get_database_service()->get_database_path(); } /** diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index fdf8a4ec30a..e5f03a59caf 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -96,6 +96,15 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { ); } + /** + * Get database service. + * + * @return WC_Integration_MaxMind_Database_Service|null + */ + public function get_database_service() { + return $this->database_service; + } + /** * Checks to make sure that the license key is valid. * From cfeb07eaf759f0670c5b0caeb4ef0cd6a51776b5 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 13:18:25 -0300 Subject: [PATCH 35/78] Removed legacy code --- .../settings/class-wc-settings-general.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/includes/admin/settings/class-wc-settings-general.php b/includes/admin/settings/class-wc-settings-general.php index 44c4dc7b51b..d928034556f 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( @@ -185,7 +174,12 @@ class WC_Settings_General extends WC_Settings_Page { 'default' => 'geolocation', '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( From 91ec28f16788f6e19b3c2cfd10f7e69df38d6690 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 15:02:11 -0300 Subject: [PATCH 36/78] Updated integration ID and included methods to display notices --- ...ass-wc-integration-maxmind-geolocation.php | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index e5f03a59caf..92e7bba091c 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -28,7 +28,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { * Initialize the integration. */ public function __construct() { - $this->id = 'woocommerce_maxmind_geolocation'; + $this->id = 'maxmind_geolocation'; $this->method_title = __( 'WooCommerce MaxMind Geolocation', 'woocommerce' ); $this->method_description = __( 'An integration for utilizing MaxMind to do Geolocation lookups.', 'woocommerce' ); @@ -51,6 +51,9 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { // Bind to the save action for the settings. add_action( 'woocommerce_update_options_integration_' . $this->id, array( $this, 'process_admin_options' ) ); + // Trigger notice if license key is missing. + add_action( 'update_option_woocommerce_default_customer_address', array( $this, 'display_missing_license_key_notice' ), 1000, 2 ); + /** * Allows for the automatic database update to be disabled. * @@ -200,4 +203,48 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { return $country_code ? $country_code : false; } + + /** + * Add missing license key notice. + */ + private function add_missing_license_key_notice() { + if ( ! class_exists( 'WC_Admin_Notices' ) ) { + include_once WC_ABSPATH . 'includes/admin/class-wc-admin-notices.php'; + } + WC_Admin_Notices::add_notice( 'maxmind_license_key' ); + } + + /** + * Remove missing license key notice. + */ + private function remove_missing_license_key_notice() { + if ( ! class_exists( 'WC_Admin_Notices' ) ) { + include_once WC_ABSPATH . 'includes/admin/class-wc-admin-notices.php'; + } + WC_Admin_Notices::remove_notice( 'maxmind_license_key' ); + } + + /** + * Display notice if license key is missing. + * + * @param mixed $old_value Option old value. + * @param mixed $new_value Current value. + */ + public function display_missing_license_key_notice( $old_value, $new_value ) { + if ( ! apply_filters( 'woocommerce_maxmind_geolocation_display_notices', true ) ) { + return; + } + + if ( ! in_array( $new_value, array( 'geolocation', 'geolocation_ajax' ), true ) ) { + $this->remove_missing_license_key_notice(); + return; + } + + $license_key = $this->get_option( 'license_key' ); + if ( ! empty( $license_key ) ) { + return; + } + + $this->add_missing_license_key_notice(); + } } From 48547143f4d2978e177e0e4b65d0fe5a24091481 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 15:02:56 -0300 Subject: [PATCH 37/78] Fixed integration ID --- includes/class-wc-geolocation.php | 4 ++-- tests/unit-tests/integrations/class-wc-tests-integrations.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 79b9f38a69f..6cb98138021 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -178,7 +178,7 @@ class WC_Geolocation { */ public static function get_local_database_path( $deprecated = '2' ) { wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0', 'WC_Integration_MaxMind_Database_Service::get_database_path' ); - $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); + $integration = wc()->integrations->get_integration( 'maxmind_geolocation' ); return $integration->get_database_service()->get_database_path(); } @@ -190,7 +190,7 @@ class WC_Geolocation { */ public static function update_database() { wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0', 'WC_Integration_MaxMind_Geolocation::update_database' ); - $integration = wc()->integrations->get_integration( 'woocommerce_maxmind_geolocation' ); + $integration = wc()->integrations->get_integration( 'maxmind_geolocation' ); $integration->update_database(); } diff --git a/tests/unit-tests/integrations/class-wc-tests-integrations.php b/tests/unit-tests/integrations/class-wc-tests-integrations.php index 238ec833f4f..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->assertArrayHasKey( 'woocommerce_maxmind_geolocation', $integrations->integrations ); - $this->assertArrayHasKey( 'woocommerce_maxmind_geolocation', $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'; From c3abe8ac65f0add23a0c7b1a128d4b7c291c6d14 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 15:07:05 -0300 Subject: [PATCH 38/78] Added missing license key notice and triggers --- includes/admin/class-wc-admin-notices.php | 34 +++++++++++++++++++ .../views/html-notice-maxmind-license-key.php | 30 ++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 includes/admin/views/html-notice-maxmind-license-key.php diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index a0f86eb7caa..6ebdbfebcbc 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,38 @@ 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() { + if ( get_user_meta( get_current_user_id(), 'dismissed_maxmind_license_key_notice', true ) ) { + 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/views/html-notice-maxmind-license-key.php b/includes/admin/views/html-notice-maxmind-license-key.php new file mode 100644 index 00000000000..30238f40e51 --- /dev/null +++ b/includes/admin/views/html-notice-maxmind-license-key.php @@ -0,0 +1,30 @@ + + +
+ + +

+ +

+ +

+ Entre your License Key in the integration settings.', 'woocommerce' ), + admin_url( 'admin.php?page=wc-settings&tab=integration§ion=maxmind_geolocation' ) + ) + ); + ?> +

+
From 49aed6f6ca5f5e8ba0c837161f9f97923315619d Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 16:31:27 -0300 Subject: [PATCH 39/78] Remove alternatives for deprecated methods --- includes/class-wc-geolocation.php | 4 +- .../class-wc-tests-geolite-integration.php | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 6cb98138021..b770c169f5f 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -177,7 +177,7 @@ class WC_Geolocation { * @return string */ public static function get_local_database_path( $deprecated = '2' ) { - wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0', 'WC_Integration_MaxMind_Database_Service::get_database_path' ); + wc_deprecated_function( 'WC_Geolocation::get_local_database_path', '3.9.0' ); $integration = wc()->integrations->get_integration( 'maxmind_geolocation' ); return $integration->get_database_service()->get_database_path(); } @@ -189,7 +189,7 @@ class WC_Geolocation { * Extract files with PharData. Tool built into PHP since 5.3. */ public static function update_database() { - wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0', 'WC_Integration_MaxMind_Geolocation::update_database' ); + wc_deprecated_function( 'WC_Geolocation::update_database', '3.9.0' ); $integration = wc()->integrations->get_integration( 'maxmind_geolocation' ); $integration->update_database(); } diff --git a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php new file mode 100644 index 00000000000..92a92c32417 --- /dev/null +++ b/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php @@ -0,0 +1,43 @@ +integrations->get_integration( 'maxmind_geolocation' ); + $integration->update_database(); + + // Download GeoLite2 database. + WC_Geolocation::update_database(); + + // OpenDNS IP address. + $ipv4 = '208.67.220.220'; + $ipv6 = '2620:0:ccc::2'; + + // Init GeoLite. + $geolite = new WC_Geolite_Integration( WC_Geolocation::get_local_database_path() ); + + // Check for IPv4. + $this->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' ) ); + } +} From 107720dc08b50fba534cf9735c06fb82784526b9 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 17:05:28 -0300 Subject: [PATCH 40/78] Make is_package_shippable less strict --- includes/class-wc-shipping.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/includes/class-wc-shipping.php b/includes/class-wc-shipping.php index de5cb859603..ef2bfe08ed3 100644 --- a/includes/class-wc-shipping.php +++ b/includes/class-wc-shipping.php @@ -294,12 +294,7 @@ class WC_Shipping { } $states = WC()->countries->get_states( $country ); - if ( is_array( $states ) && ! isset( $states[ $package['destination']['state'] ] ) ) { - return false; - } - - $postcode = wc_format_postcode( $package['destination']['postcode'], $country ); - if ( ! WC_Validation::is_postcode( $postcode, $country ) ) { + if ( is_array( $states ) && ! empty( $states ) && ! isset( $states[ $package['destination']['state'] ] ) ) { return false; } From f253c8709685ba3f61cd56787e6d005bf5e84a42 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 10 Jan 2020 17:14:44 -0300 Subject: [PATCH 41/78] Fixed unit tests --- tests/unit-tests/shipping/shipping.php | 13 ------------- 1 file changed, 13 deletions(-) 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( From f5d07c954c2669e419d7fcd24927dbe820e94b2c Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 10 Jan 2020 13:07:26 -0800 Subject: [PATCH 42/78] Adjusted the MaxMind license key notice to be clearer --- includes/admin/views/html-notice-maxmind-license-key.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/views/html-notice-maxmind-license-key.php b/includes/admin/views/html-notice-maxmind-license-key.php index 30238f40e51..de4d751a78d 100644 --- a/includes/admin/views/html-notice-maxmind-license-key.php +++ b/includes/admin/views/html-notice-maxmind-license-key.php @@ -13,7 +13,7 @@ defined( 'ABSPATH' ) || exit;

- +

@@ -21,7 +21,7 @@ defined( 'ABSPATH' ) || exit; echo wp_kses_post( sprintf( /* translators: %s: integration page */ - __( 'Missing MaxMind License Key to enable proper geolocation. Entre your License Key in the integration settings.', 'woocommerce' ), + __( 'You must enter a valid license key on the MaxMind integration settings page in order to use the geolocation service.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=integration§ion=maxmind_geolocation' ) ) ); From 4f6aec61fdc5703de6f7d37452db170355723ddb Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 08:16:44 -0800 Subject: [PATCH 43/78] Added support for a randomized MaxMind database file prefix --- ...c-integration-maxmind-database-service.php | 22 ++++++++++++++++- ...ass-wc-integration-maxmind-geolocation.php | 19 ++++++++++++--- .../class-wc-tests-maxmind-database.php | 24 +++++++++---------- .../class-wc-tests-maxmind-integration.php | 4 +++- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index 39eaa6d7f38..668cf564fca 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -25,13 +25,33 @@ class WC_Integration_MaxMind_Database_Service { */ const DATABASE_EXTENSION = '.mmdb'; + /** + * A prefix for the MaxMind database filename. + * + * @var string + */ + private $database_prefix; + + /** + * WC_Integration_MaxMind_Database_Service constructor. + * + * @param string|null $database_prefix A prefix for the MaxMind database filename. + */ + public function __construct( $database_prefix ) { + $this->database_prefix = $database_prefix; + } + /** * Fetches the path that the database should be stored. * * @return string The local database path. */ public function get_database_path() { - $database_path = WP_CONTENT_DIR . '/uploads/' . self::DATABASE . self::DATABASE_EXTENSION; + $database_path = WP_CONTENT_DIR . '/uploads/'; + if ( ! empty( $this->database_prefix ) ) { + $database_path .= $this->database_prefix . '-'; + } + $database_path .= self::DATABASE . self::DATABASE_EXTENSION; /** * Filter the geolocation database storage path. diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 92e7bba091c..62dc6059996 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -32,8 +32,6 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { $this->method_title = __( 'WooCommerce MaxMind Geolocation', 'woocommerce' ); $this->method_description = __( 'An integration for utilizing MaxMind to do Geolocation lookups.', 'woocommerce' ); - // We will need a service for interacting with the MaxMind database. - /** * Supports overriding the database service to be used. * @@ -42,7 +40,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { */ $this->database_service = apply_filters( 'woocommerce_maxmind_geolocation_database_service', null ); if ( null === $this->database_service ) { - $this->database_service = new WC_Integration_MaxMind_Database_Service(); + $this->database_service = new WC_Integration_MaxMind_Database_Service( $this->get_database_prefix() ); } $this->init_form_fields(); @@ -204,6 +202,21 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { return $country_code ? $country_code : false; } + /** + * Fetches the prefix for the MaxMind database file. + * + * @return string + */ + private function get_database_prefix() { + $prefix = $this->get_option( 'database_prefix' ); + if ( empty( $prefix ) ) { + $prefix = wp_generate_password( 32, false ); + $this->update_option( 'database_prefix', $prefix ); + } + + return $prefix; + } + /** * Add missing license key notice. */ 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 index c3c0dc70c1a..73f95d19d6b 100644 --- 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 @@ -9,6 +9,7 @@ * Class WC_Tests_MaxMind_Database */ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { + /** * Run setup code for unit tests. */ @@ -25,17 +26,14 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * @expectedDeprecated woocommerce_geolocation_local_database_path */ public function test_database_path_filters() { - $database_service = $this->getMockBuilder( 'WC_Integration_MaxMind_Database_Service' ) - ->setMethods( null ) - ->disableOriginalConstructor() - ->getMock(); + $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $path = $database_service->get_database_path(); $this->assertEquals( WP_CONTENT_DIR . '/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' ) ); + remove_filter( 'woocommerce_geolocation_local_database_path', array( $this, 'filter_database_path_deprecated' ), 1 ); $this->assertEquals( '/deprecated_filter', $path ); @@ -44,16 +42,19 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { 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/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 = $this->getMockBuilder( 'WC_Integration_MaxMind_Database_Service' ) - ->setMethods( null ) - ->disableOriginalConstructor() - ->getMock(); + $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; $result = $database_service->download_database( 'testing_license' ); @@ -69,10 +70,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * Tests the that database download wraps the download and extraction errors. */ public function test_download_database_wraps_errors() { - $database_service = $this->getMockBuilder( 'WC_Integration_MaxMind_Database_Service' ) - ->setMethods( null ) - ->disableOriginalConstructor() - ->getMock(); + $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $result = $database_service->download_database( 'invalid_license' ); 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 index 5649b5b7a8e..53c40bd523a 100644 --- 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 @@ -27,7 +27,9 @@ class WC_Tests_MaxMind_Integration extends WC_Unit_Test_Case { add_filter( 'filesystem_method', array( $this, 'override_filesystem_method' ) ); // Have a mock service be used by all integrations. - $this->database_service = $this->getMockBuilder( 'WC_Integration_maxMind_Database_Service' )->getMock(); + $this->database_service = $this->getMockBuilder( 'WC_Integration_maxMind_Database_Service' ) + ->disableOriginalConstructor() + ->getMock(); add_filter( 'woocommerce_maxmind_geolocation_database_service', array( $this, 'override_integration_service' ) ); } From 645affb7f3005e7b6d72583ae64f3fae38902753 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 08:17:11 -0800 Subject: [PATCH 44/78] Removed permanently failing unit test for deprecated GeoLite2 library integration --- .../class-wc-tests-geolite-integration.php | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php 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 92a92c32417..00000000000 --- a/tests/unit-tests/geolocation/class-wc-tests-geolite-integration.php +++ /dev/null @@ -1,43 +0,0 @@ -integrations->get_integration( 'maxmind_geolocation' ); - $integration->update_database(); - - // Download GeoLite2 database. - WC_Geolocation::update_database(); - - // OpenDNS IP address. - $ipv4 = '208.67.220.220'; - $ipv6 = '2620:0:ccc::2'; - - // Init GeoLite. - $geolite = new WC_Geolite_Integration( WC_Geolocation::get_local_database_path() ); - - // Check for IPv4. - $this->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' ) ); - } -} From 6d3a3053c5206ea6e22a5e28eed79cb69f182c9e Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 08:53:43 -0800 Subject: [PATCH 45/78] Moved the database file into the woocommerce_uploads folder --- .../class-wc-integration-maxmind-database-service.php | 2 +- .../maxmind-geolocation/class-wc-tests-maxmind-database.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index 668cf564fca..98ad8968cdd 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -47,7 +47,7 @@ class WC_Integration_MaxMind_Database_Service { * @return string The local database path. */ public function get_database_path() { - $database_path = WP_CONTENT_DIR . '/uploads/'; + $database_path = WP_CONTENT_DIR . '/uploads/woocommerce_uploads/'; if ( ! empty( $this->database_prefix ) ) { $database_path .= $this->database_prefix . '-'; } 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 index 73f95d19d6b..aba5a35a1af 100644 --- 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 @@ -29,7 +29,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $path = $database_service->get_database_path(); - $this->assertEquals( WP_CONTENT_DIR . '/uploads/' . WC_Integration_MaxMind_Database_Service::DATABASE . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $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(); @@ -47,7 +47,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { $database_service = new WC_Integration_MaxMind_Database_Service( 'testing' ); $path = $database_service->get_database_path(); - $this->assertEquals( WP_CONTENT_DIR . '/uploads/testing-' . WC_Integration_MaxMind_Database_Service::DATABASE . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $path ); + $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/testing-' . WC_Integration_MaxMind_Database_Service::DATABASE . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $path ); } /** From 48d819ebeb7c961e440ae5def38ee11e4e1b4d5a Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 11:00:23 -0800 Subject: [PATCH 46/78] Added support for non-standard upload folder paths --- .../class-wc-integration-maxmind-database-service.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index 98ad8968cdd..e56730372fe 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -47,7 +47,9 @@ class WC_Integration_MaxMind_Database_Service { * @return string The local database path. */ public function get_database_path() { - $database_path = WP_CONTENT_DIR . '/uploads/woocommerce_uploads/'; + $uploads_dir = wp_upload_dir(); + + $database_path = trailingslashit( $uploads_dir['basedir'] ) . 'woocommerce_uploads/'; if ( ! empty( $this->database_prefix ) ) { $database_path .= $this->database_prefix . '-'; } From ef0eccf0ace246e598f9157d92cd3a8fcee0f5c3 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 11:18:14 -0800 Subject: [PATCH 47/78] Added upgrade step for removing the legacy MaxMind database --- includes/class-wc-install.php | 5 ++++- includes/wc-update-functions.php | 11 ++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 0ef50a3a42b..4bc1198b36e 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -135,6 +135,9 @@ class WC_Install { 'wc_update_370_mro_std_currency', 'wc_update_370_db_version', ), + '3.9.0' => array( + 'wc_update_390_remove_maxmind_database', + ), ); /** @@ -970,7 +973,7 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes ( $tables = self::get_tables(); foreach ( $tables as $table ) { - $wpdb->query( "DROP TABLE IF EXISTS {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $wpdb->query( "DROP TABLE IF EXISTS {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared } } diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index 07738c6b3a7..400b297af1c 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -1839,7 +1839,7 @@ function wc_update_343_cleanup_foreign_keys() { if ( $results ) { foreach ( $results as $fk ) { - $wpdb->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,12 @@ function wc_update_370_mro_std_currency() { function wc_update_370_db_version() { WC_Install::update_db_version( '3.7.0' ); } + +/** + * The TOS for MaxMind's databases require that they be deleted. Since we're making significant changes to + * the location and function of the database downloads, let's remove the legacy database altogether. + */ +function wc_update_390_remove_maxmind_database() { + // Make sure to remove the file using the path as it was previously defined in WC_Geolocation! + @unlink( WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb' ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged +} From f9d8b85c04d9a830c95775ad35040b93761d3dbf Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 13 Jan 2020 17:40:10 -0300 Subject: [PATCH 48/78] Remove notice when license key is present --- .../class-wc-integration-maxmind-geolocation.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 62dc6059996..b390fe94106 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -134,6 +134,9 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { // We may as well put this archive to good use, now that we've downloaded one. self::update_database( $tmp_database_path ); + // Remove missing license key notice. + $this->remove_missing_license_key_notice(); + return $value; } From d32c470cea3fe7b89f2e0610b95573f2453a0d25 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 14:10:08 -0800 Subject: [PATCH 49/78] Added a database option to allow for selecting different MaxMind databases --- ...c-integration-maxmind-database-service.php | 34 +++++++++++++------ ...ass-wc-integration-maxmind-geolocation.php | 19 +++++++++-- .../class-wc-tests-maxmind-database.php | 12 +++---- .../class-wc-tests-maxmind-integration.php | 2 +- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index e56730372fe..40e4a5b56d4 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -14,12 +14,6 @@ defined( 'ABSPATH' ) || exit; * @since 3.9.0 */ class WC_Integration_MaxMind_Database_Service { - - /** - * The name of the MaxMind database to utilize. - */ - const DATABASE = 'GeoLite2-Country'; - /** * The extension for the MaxMind database. */ @@ -32,13 +26,31 @@ class WC_Integration_MaxMind_Database_Service { */ private $database_prefix; + /** + * The MaxMind database to download. + * + * @var string + */ + private $database; + /** * WC_Integration_MaxMind_Database_Service constructor. * * @param string|null $database_prefix A prefix for the MaxMind database filename. + * @param string $database The MaxMind database to download. */ - public function __construct( $database_prefix ) { + public function __construct( $database_prefix, $database ) { $this->database_prefix = $database_prefix; + $this->database = $database; + } + + /** + * Changes the MaxMind database to download. + * + * @param string $database The new MaxMind database to download. + */ + public function set_database( $database ) { + $this->database = $database; } /** @@ -53,7 +65,7 @@ class WC_Integration_MaxMind_Database_Service { if ( ! empty( $this->database_prefix ) ) { $database_path .= $this->database_prefix . '-'; } - $database_path .= self::DATABASE . self::DATABASE_EXTENSION; + $database_path .= 'MaxMind-Geolocation-Database' . self::DATABASE_EXTENSION; /** * Filter the geolocation database storage path. @@ -87,7 +99,7 @@ class WC_Integration_MaxMind_Database_Service { public function download_database( $license_key ) { $download_uri = add_query_arg( array( - 'edition_id' => self::DATABASE, + 'edition_id' => $this->database, 'license_key' => wc_clean( $license_key ), 'suffix' => 'tar.gz', ), @@ -118,11 +130,11 @@ class WC_Integration_MaxMind_Database_Service { try { $file = new PharData( $tmp_archive_path ); - $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION; + $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . $this->database . self::DATABASE_EXTENSION; $file->extractTo( dirname( $tmp_archive_path ), - trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION, + trailingslashit( $file->current()->getFilename() ) . $this->database . self::DATABASE_EXTENSION, true ); } catch ( Exception $exception ) { diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index b390fe94106..1cd51f6488c 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -40,7 +40,10 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { */ $this->database_service = apply_filters( 'woocommerce_maxmind_geolocation_database_service', null ); if ( null === $this->database_service ) { - $this->database_service = new WC_Integration_MaxMind_Database_Service( $this->get_database_prefix() ); + $this->database_service = new WC_Integration_MaxMind_Database_Service( + $this->get_database_prefix(), + $this->get_option( 'database' ) + ); } $this->init_form_fields(); @@ -80,11 +83,23 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { */ public function init_form_fields() { $this->form_fields = array( + // Note: The database field MUST be first, as the license_key validation relies on the value of it! + 'database' => array( + 'title' => __( 'Database', 'woocommerce' ), + 'type' => 'select', + 'description' => __( 'The database chosen decides the precision of the geolocation search. You should note that higher precision database are larger in size.', 'woocommerce' ), + 'options' => array( + 'GeoLite2-Country' => __( 'GeoLite2 - Country', 'woocommerce' ), + 'GeoLite2-City' => __( 'GeoLite2 - City', 'woocommerce' ), + ), + 'desc_tip' => false, + 'default' => 'GeoLite2-Country', + ), 'license_key' => array( 'title' => __( 'MaxMind License Key', 'woocommerce' ), 'type' => 'password', 'description' => sprintf( - /* translators: %1$s: Documentation URL */ + /* translators: %1$s: Documentation URL */ __( 'The key that will be used when dealing with MaxMind Geolocation services. You can read how to generate one in MaxMind\'s License Key Documentation.', 'woocommerce' 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 index aba5a35a1af..64a0c83bef1 100644 --- 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 @@ -26,10 +26,10 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * @expectedDeprecated woocommerce_geolocation_local_database_path */ public function test_database_path_filters() { - $database_service = new WC_Integration_MaxMind_Database_Service( '' ); + $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 ); + $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/MaxMind-Geolocation-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(); @@ -44,17 +44,17 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { $this->assertEquals( '/filter', $path ); // Now perform any tests with a database file prefix. - $database_service = new WC_Integration_MaxMind_Database_Service( 'testing' ); + $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 ); + $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/testing-MaxMind-Geolocation-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( '' ); + $database_service = new WC_Integration_MaxMind_Database_Service( '', 'GeoLite2-Country' ); $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; $result = $database_service->download_database( 'testing_license' ); @@ -70,7 +70,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * 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( '' ); + $database_service = new WC_Integration_MaxMind_Database_Service( '', 'GeoLite2-Country' ); $result = $database_service->download_database( 'invalid_license' ); 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 index 53c40bd523a..8da1685c850 100644 --- 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 @@ -65,7 +65,7 @@ class WC_Tests_MaxMind_Integration extends WC_Unit_Test_Case { $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 ); + ->willReturn( '/tmp/MaxMind-Geolocation-Database.' . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION ); $integration = new WC_Integration_MaxMind_Geolocation(); $integration->update_option( 'license_key', 'test_license' ); From 7a5083e47b9ad1d94ed5a00b7a07bd3a09602aac Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 14:41:24 -0800 Subject: [PATCH 50/78] Revert "Added a database option to allow for selecting different MaxMind databases" This reverts commit d32c470cea3fe7b89f2e0610b95573f2453a0d25. --- ...c-integration-maxmind-database-service.php | 34 ++++++------------- ...ass-wc-integration-maxmind-geolocation.php | 19 ++--------- .../class-wc-tests-maxmind-database.php | 12 +++---- .../class-wc-tests-maxmind-integration.php | 2 +- 4 files changed, 20 insertions(+), 47 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php index 40e4a5b56d4..e56730372fe 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-database-service.php @@ -14,6 +14,12 @@ defined( 'ABSPATH' ) || exit; * @since 3.9.0 */ class WC_Integration_MaxMind_Database_Service { + + /** + * The name of the MaxMind database to utilize. + */ + const DATABASE = 'GeoLite2-Country'; + /** * The extension for the MaxMind database. */ @@ -26,31 +32,13 @@ class WC_Integration_MaxMind_Database_Service { */ private $database_prefix; - /** - * The MaxMind database to download. - * - * @var string - */ - private $database; - /** * WC_Integration_MaxMind_Database_Service constructor. * * @param string|null $database_prefix A prefix for the MaxMind database filename. - * @param string $database The MaxMind database to download. */ - public function __construct( $database_prefix, $database ) { + public function __construct( $database_prefix ) { $this->database_prefix = $database_prefix; - $this->database = $database; - } - - /** - * Changes the MaxMind database to download. - * - * @param string $database The new MaxMind database to download. - */ - public function set_database( $database ) { - $this->database = $database; } /** @@ -65,7 +53,7 @@ class WC_Integration_MaxMind_Database_Service { if ( ! empty( $this->database_prefix ) ) { $database_path .= $this->database_prefix . '-'; } - $database_path .= 'MaxMind-Geolocation-Database' . self::DATABASE_EXTENSION; + $database_path .= self::DATABASE . self::DATABASE_EXTENSION; /** * Filter the geolocation database storage path. @@ -99,7 +87,7 @@ class WC_Integration_MaxMind_Database_Service { public function download_database( $license_key ) { $download_uri = add_query_arg( array( - 'edition_id' => $this->database, + 'edition_id' => self::DATABASE, 'license_key' => wc_clean( $license_key ), 'suffix' => 'tar.gz', ), @@ -130,11 +118,11 @@ class WC_Integration_MaxMind_Database_Service { try { $file = new PharData( $tmp_archive_path ); - $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . $this->database . self::DATABASE_EXTENSION; + $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION; $file->extractTo( dirname( $tmp_archive_path ), - trailingslashit( $file->current()->getFilename() ) . $this->database . self::DATABASE_EXTENSION, + trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION, true ); } catch ( Exception $exception ) { diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index 1cd51f6488c..b390fe94106 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -40,10 +40,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { */ $this->database_service = apply_filters( 'woocommerce_maxmind_geolocation_database_service', null ); if ( null === $this->database_service ) { - $this->database_service = new WC_Integration_MaxMind_Database_Service( - $this->get_database_prefix(), - $this->get_option( 'database' ) - ); + $this->database_service = new WC_Integration_MaxMind_Database_Service( $this->get_database_prefix() ); } $this->init_form_fields(); @@ -83,23 +80,11 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { */ public function init_form_fields() { $this->form_fields = array( - // Note: The database field MUST be first, as the license_key validation relies on the value of it! - 'database' => array( - 'title' => __( 'Database', 'woocommerce' ), - 'type' => 'select', - 'description' => __( 'The database chosen decides the precision of the geolocation search. You should note that higher precision database are larger in size.', 'woocommerce' ), - 'options' => array( - 'GeoLite2-Country' => __( 'GeoLite2 - Country', 'woocommerce' ), - 'GeoLite2-City' => __( 'GeoLite2 - City', 'woocommerce' ), - ), - 'desc_tip' => false, - 'default' => 'GeoLite2-Country', - ), 'license_key' => array( 'title' => __( 'MaxMind License Key', 'woocommerce' ), 'type' => 'password', 'description' => sprintf( - /* translators: %1$s: Documentation URL */ + /* translators: %1$s: Documentation URL */ __( 'The key that will be used when dealing with MaxMind Geolocation services. You can read how to generate one in MaxMind\'s License Key Documentation.', 'woocommerce' 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 index 64a0c83bef1..aba5a35a1af 100644 --- 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 @@ -26,10 +26,10 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * @expectedDeprecated woocommerce_geolocation_local_database_path */ public function test_database_path_filters() { - $database_service = new WC_Integration_MaxMind_Database_Service( '', '' ); + $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $path = $database_service->get_database_path(); - $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/MaxMind-Geolocation-Database' . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $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(); @@ -44,17 +44,17 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { $this->assertEquals( '/filter', $path ); // Now perform any tests with a database file prefix. - $database_service = new WC_Integration_MaxMind_Database_Service( 'testing', '' ); + $database_service = new WC_Integration_MaxMind_Database_Service( 'testing' ); $path = $database_service->get_database_path(); - $this->assertEquals( WP_CONTENT_DIR . '/uploads/woocommerce_uploads/testing-MaxMind-Geolocation-Database' . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION, $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( '', 'GeoLite2-Country' ); + $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $expected_database = '/tmp/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; $result = $database_service->download_database( 'testing_license' ); @@ -70,7 +70,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { * 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( '', 'GeoLite2-Country' ); + $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $result = $database_service->download_database( 'invalid_license' ); 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 index 8da1685c850..53c40bd523a 100644 --- 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 @@ -65,7 +65,7 @@ class WC_Tests_MaxMind_Integration extends WC_Unit_Test_Case { $this->database_service->expects( $this->once() ) ->method( 'download_database' ) ->with( 'test_license' ) - ->willReturn( '/tmp/MaxMind-Geolocation-Database.' . WC_Integration_MaxMind_Database_Service::DATABASE_EXTENSION ); + ->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' ); From 25dbc47da9eb4465eefce0dd827ffd0501983a62 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 14:43:00 -0800 Subject: [PATCH 51/78] Added a note that the MaxMind integration will only do country lookups. --- .../class-wc-integration-maxmind-geolocation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index b390fe94106..bdb16ce21eb 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -30,7 +30,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { public function __construct() { $this->id = 'maxmind_geolocation'; $this->method_title = __( 'WooCommerce MaxMind Geolocation', 'woocommerce' ); - $this->method_description = __( 'An integration for utilizing MaxMind to do Geolocation lookups.', 'woocommerce' ); + $this->method_description = __( 'An integration for utilizing MaxMind to do Geolocation lookups. Please note that this integration will only do country lookups.', 'woocommerce' ); /** * Supports overriding the database service to be used. From 1c874264d832756dadd63424d213aa35d85853a4 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 13 Jan 2020 21:48:23 -0300 Subject: [PATCH 52/78] Removed MaxMind from System Status page --- .../views/html-admin-page-status-report.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/includes/admin/views/html-admin-page-status-report.php b/includes/admin/views/html-admin-page-status-report.php index 337aca7cd45..bca9f12d587 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 - - - : - - - ' . wp_kses_post( __( 'MaxMind GeoIP database requires at least PHP 5.4.', 'woocommerce' ) ) . ''; - } elseif ( file_exists( $database['maxmind_geoip_database'] ) ) { - echo ' ' . 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 ) ); - } - ?> - - - - From b577b8a38631d00ef186ee019e7d213b9493dad5 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 17:00:39 -0800 Subject: [PATCH 53/78] Changed the geoip update cron to run every 15 days to better comply with MaxMind's TOS --- includes/class-wc-install.php | 10 ++++++---- includes/wc-update-functions.php | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 4bc1198b36e..d6ac6bdb9ce 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -137,6 +137,7 @@ class WC_Install { ), '3.9.0' => array( 'wc_update_390_remove_maxmind_database', + 'wc_update_390_change_geolocation_database_update_cron', ), ); @@ -424,6 +425,10 @@ class WC_Install { 'interval' => 2635200, 'display' => __( 'Monthly', 'woocommerce' ), ); + $schedules['fifteendays'] = array( + 'interval' => 1296000, + 'display' => __( 'Every 15 Days', 'woocommerce' ), + ); return $schedules; } @@ -452,11 +457,8 @@ class WC_Install { wp_schedule_event( time(), 'daily', 'woocommerce_cleanup_personal_data' ); wp_schedule_event( time() + ( 3 * HOUR_IN_SECONDS ), 'daily', 'woocommerce_cleanup_logs' ); wp_schedule_event( time() + ( 6 * HOUR_IN_SECONDS ), 'twicedaily', 'woocommerce_cleanup_sessions' ); - wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' ); + wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', ' woocommerce_geoip_updater' ); wp_schedule_event( time() + 10, apply_filters( 'woocommerce_tracker_event_recurrence', 'daily' ), 'woocommerce_tracker_send_event' ); - - // Trigger GeoIP updater action after 1 minute. - wp_schedule_single_event( time() + ( MINUTE_IN_SECONDS * 1 ), 'woocommerce_geoip_updater' ); } /** diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index 400b297af1c..b7e27224c73 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -2055,3 +2055,11 @@ function wc_update_390_remove_maxmind_database() { // Make sure to remove the file using the path as it was previously defined in WC_Geolocation! @unlink( WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb' ); // 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() + MINUTE_IN_SECONDS, 'fifteendays', ' woocommerce_geoip_updater' ); +} From 0f18570827b1f54aa34513db173a17c439f228b6 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Mon, 13 Jan 2020 21:02:22 -0800 Subject: [PATCH 54/78] Added the database path to the integration page for documentation purposes --- ...ass-wc-integration-maxmind-geolocation.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index bdb16ce21eb..fc33f0ed222 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -75,6 +75,35 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { add_filter( 'woocommerce_geolocate_ip', array( $this, 'geolocate_ip' ), 10, 2 ); } + /** + * Override the normal options so we can print the database file path to the admin, + */ + public function admin_options() { + parent::admin_options(); + + $database_path = esc_attr( $this->database_service->get_database_path() ); + $label = esc_html__( 'Database File Path', 'woocommerce' ); + $description = esc_html__( 'The path to the MaxMind database file that was downloaded by the integration.', 'woocommerce' ); + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo << + + + + + +

+ {$label} + +

{$description}

+
+ + + +INPUT; + } + /** * Initializes the settings fields. */ From b3b4e92fe1728381e927674ff6c2f10a8c95a469 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 12:20:46 -0300 Subject: [PATCH 55/78] Moved HTML to a single file --- ...ass-wc-integration-maxmind-geolocation.php | 22 +--------------- .../views/html-admin-options.php | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 21 deletions(-) create mode 100644 includes/integrations/maxmind-geolocation/views/html-admin-options.php diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index fc33f0ed222..fb2181bc89a 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -81,27 +81,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { public function admin_options() { parent::admin_options(); - $database_path = esc_attr( $this->database_service->get_database_path() ); - $label = esc_html__( 'Database File Path', 'woocommerce' ); - $description = esc_html__( 'The path to the MaxMind database file that was downloaded by the integration.', 'woocommerce' ); - - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo << - - - - - -
- {$label} - -

{$description}

-
- - - -INPUT; + include dirname( __FILE__ ) . '/views/html-admin-options.php'; } /** diff --git a/includes/integrations/maxmind-geolocation/views/html-admin-options.php b/includes/integrations/maxmind-geolocation/views/html-admin-options.php new file mode 100644 index 00000000000..2ca14f399dd --- /dev/null +++ b/includes/integrations/maxmind-geolocation/views/html-admin-options.php @@ -0,0 +1,25 @@ + + + + + + + +
+ + +
+ + +

+
+
From 978c5b5fb9bf05ddc465261fe8b3651ac9c1a716 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 15:22:53 -0300 Subject: [PATCH 56/78] Apply woocommerce_maxmind_geolocation_display_notices filter in notices class --- includes/admin/class-wc-admin-notices.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index 6ebdbfebcbc..393af70804d 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -454,6 +454,11 @@ class WC_Admin_Notices { * @since 3.9.0 */ public static function maxmind_missing_license_key_notice() { + if ( ! apply_filters( 'woocommerce_maxmind_geolocation_display_notices', true ) ) { + self::remove_notice( 'maxmind_license_key' ); + return; + } + if ( get_user_meta( get_current_user_id(), 'dismissed_maxmind_license_key_notice', true ) ) { self::remove_notice( 'maxmind_license_key' ); return; From 46110fa39c993c60d2f10d2ca432a50476209553 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 15:54:24 -0300 Subject: [PATCH 57/78] Introduced woocommerce_get_geolocation filter --- includes/class-wc-geolocation.php | 45 ++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index b770c169f5f..31721207914 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -136,25 +136,50 @@ class WC_Geolocation { * @return array */ public static function geolocate_ip( $ip_address = '', $fallback = false, $api_fallback = true ) { + // Filter to allow custom geolocation of the IP address. + $country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback ); + + if ( false !== $country_code ) { + return array( + 'country' => $country_code, + 'state' => '', + 'city' => '', + 'postcode' => '', + ); + } + if ( empty( $ip_address ) ) { $ip_address = self::get_ip_address(); } $country_code = self::get_country_code_from_headers(); - if ( false === $country_code ) { - // Filter to allow custom geolocation of the IP address. - $country_code = apply_filters( 'woocommerce_geolocate_ip', $country_code, $ip_address, $fallback, $api_fallback ); - } + /** + * Get geolocation filter. + * + * @since 3.9.0 + * @param array $geolocation Geolocation data, including country, state, city, and postcode. + * @param string $ip_address IP Address. + */ + $geolocation = apply_filters( + 'woocommerce_get_geolocation', + array( + 'country' => $country_code, + 'state' => '', + 'city' => '', + 'postcode' => '', + ), + $ip_address + ); // If we still haven't found a country code, let's consider doing an API lookup. - if ( false === $country_code && $api_fallback ) { - $country_code = self::geolocate_via_api( $ip_address ); + if ( false === $geolocation['country'] && $api_fallback ) { + $geolocation['country'] = self::geolocate_via_api( $ip_address ); } // It's possible that we're in a local environment, in which case the geolocation needs to be done from the // external address. - if ( false === $country_code && $fallback ) { + if ( false === $geolocation['country'] && $fallback ) { $external_ip_address = self::get_external_ip_address(); // Only bother with this if the external IP differs. @@ -164,8 +189,10 @@ class WC_Geolocation { } return array( - 'country' => $country_code ? $country_code : '', - 'state' => '', + 'country' => $geolocation['country'], + 'state' => $geolocation['state'], + 'city' => $geolocation['city'], + 'postcode' => $geolocation['postcode'], ); } From 992e13fb089b836d0d163d34f5b9cc99c9b5136c Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 16:24:07 -0300 Subject: [PATCH 58/78] Updated implementation of geolite2 --- includes/class-wc-geolocation.php | 6 ++--- ...ass-wc-integration-maxmind-geolocation.php | 22 ++++++++++++------- .../class-wc-tests-maxmind-integration.php | 12 +++++----- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 31721207914..54405684fb5 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -164,7 +164,7 @@ class WC_Geolocation { $geolocation = apply_filters( 'woocommerce_get_geolocation', array( - 'country' => $country_code, + 'country' => $country_code ? $country_code : '', 'state' => '', 'city' => '', 'postcode' => '', @@ -225,10 +225,10 @@ class WC_Geolocation { * Fetches the country code from the request headers, if one is available. * * @since 3.9.0 - * @return string|false The country code pulled from the headers, or false if one was not found. + * @return string The country code pulled from the headers, or empty string if one was not found. */ private static function get_country_code_from_headers() { - $country_code = false; + $country_code = ''; $headers = array( 'MM_COUNTRY_CODE', diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index fb2181bc89a..dcf42826b1b 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -72,7 +72,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { } // Bind to the geolocation filter for MaxMind database lookups. - add_filter( 'woocommerce_geolocate_ip', array( $this, 'geolocate_ip' ), 10, 2 ); + add_filter( 'woocommerce_get_geolocation', array( $this, 'get_geolocation' ), 10, 2 ); } /** @@ -196,22 +196,28 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { /** * Performs a geolocation lookup against the MaxMind database for the given IP address. * - * @param string $country_code The country code for the IP address. + * @param array $data Geolocation data. * @param string $ip_address The IP address to geolocate. - * @return string The country code for the IP address. + * @return array Geolocation including country code, state, city and postcode based on an IP address. */ - public function geolocate_ip( $country_code, $ip_address ) { - if ( false !== $country_code ) { - return $country_code; + public function get_geolocation( $data, $ip_address ) { + // WooCommerce look for headers first, and at this moment could be just enough. + if ( ! empty( $data['country'] ) ) { + return $data; } if ( empty( $ip_address ) ) { - return $country_code; + return $data; } $country_code = $this->database_service->get_iso_country_code_for_ip( $ip_address ); - return $country_code ? $country_code : false; + return array( + 'country' => $country_code ? $country_code : '', + 'state' => '', + 'city' => '', + 'postcode' => '', + ); } /** 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 index 53c40bd523a..e7bbbd3e517 100644 --- 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 @@ -77,18 +77,18 @@ class WC_Tests_MaxMind_Integration extends WC_Unit_Test_Case { * Make sure that the geolocate_ip method does not squash existing country codes. */ public function test_geolocate_ip_returns_existing_country_code() { - $country_code = ( new WC_Integration_MaxMind_Geolocation() )->geolocate_ip( 'US', '192.168.1.1' ); + $data = ( new WC_Integration_MaxMind_Geolocation() )->get_geolocation( array( 'country' => 'US' ), '192.168.1.1' ); - $this->assertEquals( 'US', $country_code ); + $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() { - $country_code = ( new WC_Integration_MaxMind_Geolocation() )->geolocate_ip( false, '' ); + $data = ( new WC_Integration_MaxMind_Geolocation() )->get_geolocation( array(), '' ); - $this->assertFalse( $country_code ); + $this->assertEmpty( $data ); } /** @@ -100,9 +100,9 @@ class WC_Tests_MaxMind_Integration extends WC_Unit_Test_Case { ->with( '192.168.1.1' ) ->willReturn( 'US' ); - $country_code = ( new WC_Integration_MaxMind_Geolocation() )->geolocate_ip( false, '192.168.1.1' ); + $data = ( new WC_Integration_MaxMind_Geolocation() )->get_geolocation( array(), '192.168.1.1' ); - $this->assertEquals( 'US', $country_code ); + $this->assertEquals( 'US', $data['country'] ); } /** From 10cdbf88bec02441353cf8ca9c6047ef9325e038 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 16:29:48 -0300 Subject: [PATCH 59/78] Use shop base address as default customer location --- includes/admin/settings/class-wc-settings-general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/settings/class-wc-settings-general.php b/includes/admin/settings/class-wc-settings-general.php index d928034556f..6e0126b00da 100644 --- a/includes/admin/settings/class-wc-settings-general.php +++ b/includes/admin/settings/class-wc-settings-general.php @@ -171,7 +171,7 @@ 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' => array( From f9c31589c61899bbece1844c2b6bf1cba478daca Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 16:44:01 -0300 Subject: [PATCH 60/78] Fixed conditional code --- includes/class-wc-geolocation.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 54405684fb5..64cf628f956 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -164,7 +164,7 @@ class WC_Geolocation { $geolocation = apply_filters( 'woocommerce_get_geolocation', array( - 'country' => $country_code ? $country_code : '', + 'country' => $country_code, 'state' => '', 'city' => '', 'postcode' => '', @@ -173,13 +173,13 @@ class WC_Geolocation { ); // If we still haven't found a country code, let's consider doing an API lookup. - if ( false === $geolocation['country'] && $api_fallback ) { + if ( '' === $geolocation['country'] && $api_fallback ) { $geolocation['country'] = self::geolocate_via_api( $ip_address ); } // It's possible that we're in a local environment, in which case the geolocation needs to be done from the // external address. - if ( false === $geolocation['country'] && $fallback ) { + if ( '' === $geolocation['country'] && $fallback ) { $external_ip_address = self::get_external_ip_address(); // Only bother with this if the external IP differs. From 23e1abe1dcb18822e158fd85b8caaa0597ce2b78 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Tue, 14 Jan 2020 16:45:57 -0300 Subject: [PATCH 61/78] Fix typo in php docblock --- includes/admin/class-wc-admin-notices.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index 393af70804d..5e60a380d91 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -431,7 +431,7 @@ class WC_Admin_Notices { } /** - * Add MaxMind MIssing license key notice. + * Add MaxMind missing license key notice. * * @since 3.9.0 */ @@ -449,7 +449,7 @@ class WC_Admin_Notices { } /** - * Display MaxMind Missing license key notice. + * Display MaxMind missing license key notice. * * @since 3.9.0 */ From 92478b47396551191d5bf7dffe179dcc0f7e10fe Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 16:57:07 -0300 Subject: [PATCH 62/78] Introduced woocommerce_maxmind_geolocation_update_database_periodically filter --- .../class-wc-integration-maxmind-geolocation.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php index dcf42826b1b..51965fd64f2 100644 --- a/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php +++ b/includes/integrations/maxmind-geolocation/class-wc-integration-maxmind-geolocation.php @@ -62,10 +62,18 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration { 'woocommerce_geolocation_update_database_periodically', array( true ), '3.9.0', - false, - 'MaxMind\'s TOS requires that the databases be updated or removed periodically.' + 'woocommerce_maxmind_geolocation_update_database_periodically' ); + /** + * Allows for the automatic database update to be disabled. + * Note that MaxMind's TOS requires that the databases be updated or removed periodically. + * + * @since 3.9.0 + * @param bool $bind_updater Whether or not the database should be updated periodically. + */ + $bind_updater = apply_filters( 'woocommerce_maxmind_geolocation_update_database_periodically', $bind_updater ); + // Bind to the scheduled updater action. if ( $bind_updater ) { add_action( 'woocommerce_geoip_updater', array( $this, 'update_database' ) ); From 241c6cd590fd01f2afc7defadb4d21e0c45f80ff Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Tue, 14 Jan 2020 17:07:12 -0300 Subject: [PATCH 63/78] Make context for admin notice documentation more clear --- includes/admin/views/html-notice-maxmind-license-key.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/views/html-notice-maxmind-license-key.php b/includes/admin/views/html-notice-maxmind-license-key.php index de4d751a78d..f6a28757fc7 100644 --- a/includes/admin/views/html-notice-maxmind-license-key.php +++ b/includes/admin/views/html-notice-maxmind-license-key.php @@ -1,6 +1,6 @@ Date: Tue, 14 Jan 2020 13:20:20 -0800 Subject: [PATCH 64/78] Removed the erroneous space on the woocommerce_geoip_updater scheduled event --- includes/class-wc-install.php | 2 +- includes/wc-update-functions.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index d6ac6bdb9ce..4c6b3ae1fde 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -457,7 +457,7 @@ class WC_Install { wp_schedule_event( time(), 'daily', 'woocommerce_cleanup_personal_data' ); wp_schedule_event( time() + ( 3 * HOUR_IN_SECONDS ), 'daily', 'woocommerce_cleanup_logs' ); wp_schedule_event( time() + ( 6 * HOUR_IN_SECONDS ), 'twicedaily', 'woocommerce_cleanup_sessions' ); - wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', ' woocommerce_geoip_updater' ); + wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', 'woocommerce_geoip_updater' ); wp_schedule_event( time() + 10, apply_filters( 'woocommerce_tracker_event_recurrence', 'daily' ), 'woocommerce_tracker_send_event' ); } diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index b7e27224c73..1f38c8b1ad6 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -2061,5 +2061,5 @@ function wc_update_390_remove_maxmind_database() { */ function wc_update_390_change_geolocation_database_update_cron() { wp_clear_scheduled_hook( 'woocommerce_geoip_updater' ); - wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', ' woocommerce_geoip_updater' ); + wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', 'woocommerce_geoip_updater' ); } From 1ac8eebac387515d3eeeb1336cf3e418dc2acc67 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 14 Jan 2020 13:32:59 -0800 Subject: [PATCH 65/78] Added clarity to the file path in the integration settings --- .../maxmind-geolocation/views/html-admin-options.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/integrations/maxmind-geolocation/views/html-admin-options.php b/includes/integrations/maxmind-geolocation/views/html-admin-options.php index 2ca14f399dd..a027e0072a1 100644 --- a/includes/integrations/maxmind-geolocation/views/html-admin-options.php +++ b/includes/integrations/maxmind-geolocation/views/html-admin-options.php @@ -18,7 +18,7 @@ defined( 'ABSPATH' ) || exit;
-

+

From c34a5b6ffedf20be2a7023dcad7c1939a5296183 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 14 Jan 2020 13:39:47 -0800 Subject: [PATCH 66/78] Added an update task to increase the database version --- includes/class-wc-install.php | 1 + includes/wc-update-functions.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 4c6b3ae1fde..8ba7a34ca11 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -138,6 +138,7 @@ class WC_Install { '3.9.0' => array( 'wc_update_390_remove_maxmind_database', 'wc_update_390_change_geolocation_database_update_cron', + 'wc_update_390_db_version', ), ); diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index 1f38c8b1ad6..3d2cf99a51e 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -2063,3 +2063,10 @@ function wc_update_390_change_geolocation_database_update_cron() { wp_clear_scheduled_hook( 'woocommerce_geoip_updater' ); wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', 'woocommerce_geoip_updater' ); } + +/** + * Update DB version. + */ +function wc_update_390_db_version() { + WC_Install::update_db_version( '3.9.0' ); +} From 27bcba1ac74c36f994158268daff57c404acea85 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 14 Jan 2020 13:44:41 -0800 Subject: [PATCH 67/78] Added a deprecation to the old Geolite library wrapper class' public methods --- includes/class-wc-geolite-integration.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/class-wc-geolite-integration.php b/includes/class-wc-geolite-integration.php index 15b7f054b3a..c661aa08d0c 100644 --- a/includes/class-wc-geolite-integration.php +++ b/includes/class-wc-geolite-integration.php @@ -15,6 +15,8 @@ defined( 'ABSPATH' ) || exit; /** * Geolite integration class. + * + * @deprecated 3.9.0 */ class WC_Geolite_Integration { @@ -47,8 +49,11 @@ class WC_Geolite_Integration { * * @param string $ip_address User IP address. * @return string + * @deprecated 3.9.0 */ public function get_country_iso( $ip_address ) { + wc_deprecated_function( 'get_country_iso', '3.9.0' ); + $iso_code = ''; try { From 42269f965c94b1cf51f09500ff44ddbfc90cfd68 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 14 Jan 2020 14:09:51 -0800 Subject: [PATCH 68/78] Added clarification that the MaxMind license key is not strictly necessary --- includes/admin/views/html-notice-maxmind-license-key.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/includes/admin/views/html-notice-maxmind-license-key.php b/includes/admin/views/html-notice-maxmind-license-key.php index f6a28757fc7..1ae8c8132f1 100644 --- a/includes/admin/views/html-notice-maxmind-license-key.php +++ b/includes/admin/views/html-notice-maxmind-license-key.php @@ -20,9 +20,10 @@ defined( 'ABSPATH' ) || exit; MaxMind integration settings page in order to use the geolocation service.', 'woocommerce' ), - admin_url( 'admin.php?page=wc-settings&tab=integration§ion=maxmind_geolocation' ) + /* translators: %1%s: integration page %2$s: general settings page */ + __( 'You must enter a valid license key on the MaxMind integration settings page in order to use the geolocation service. If you do not need geolocation for shipping or taxes, you should change the default customer location on the general settings page.', 'woocommerce' ), + admin_url( 'admin.php?page=wc-settings&tab=integration§ion=maxmind_geolocation' ), + admin_url( 'admin.php?page=wc-settings&tab=general' ) ) ); ?> From 5bafac30123868b8868ff3eb0e89ea28b5327767 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 14 Jan 2020 23:32:55 -0300 Subject: [PATCH 69/78] Improved maxmind_missing_license_key_notice logic --- includes/admin/class-wc-admin-notices.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index 5e60a380d91..c9006fff78e 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -454,12 +454,10 @@ class WC_Admin_Notices { * @since 3.9.0 */ public static function maxmind_missing_license_key_notice() { - if ( ! apply_filters( 'woocommerce_maxmind_geolocation_display_notices', true ) ) { - self::remove_notice( 'maxmind_license_key' ); - return; - } + $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 ( get_user_meta( get_current_user_id(), 'dismissed_maxmind_license_key_notice', true ) ) { + if ( $user_dismissed_notice || $filter_dismissed_notice ) { self::remove_notice( 'maxmind_license_key' ); return; } From 793dba81f1daca2a631fa1565158ba95987a16ba Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Wed, 15 Jan 2020 11:17:49 -0300 Subject: [PATCH 70/78] Fix failing unit test This commit fixes the unit test WC_Tests_API_Functions::test_wc_rest_upload_image_from_url_should_return_error_when_invalid_image_is_passed() which was failing due to a change in a WordPress core message with the following error: ``` 2) WC_Tests_API_Functions::test_wc_rest_upload_image_from_url_should_return_error_when_invalid_image_is_passed Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'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.' +'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.' /home/travis/build/woocommerce/woocommerce/tests/unit-tests/util/api-functions.php:89 ``` (https://travis-ci.org/woocommerce/woocommerce/jobs/637353161#L402) This test only fails when using WordPress nightly build (the yet to be released WP 5.4). To fix this problem, this commit adds an if statement to check for different error messages depending on the WordPress version that is being used to run the tests. In the future, we might want to refactor this test to remove its dependency to a WordPress error message to make it more robust and stable. --- tests/unit-tests/util/api-functions.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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() ); From 875c7f341b18a6e12707f4050500f20e3a8eb3ea Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 15 Jan 2020 15:07:53 +0000 Subject: [PATCH 71/78] Update dependency husky to v4 --- package-lock.json | 116 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 77 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index 35cdfbd2219..6dafbc87cbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", @@ -8922,28 +8916,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 +8997,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 } } }, @@ -13994,12 +14030,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", @@ -16628,6 +16658,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..7f4b13a8fba 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "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", From d9c22d60bea09c38f6d7a3ad7d7a33b2997f8bf1 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 15 Jan 2020 13:24:40 -0300 Subject: [PATCH 72/78] Use wp_mail() default args in WC_Email --- includes/emails/class-wc-email.php | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/includes/emails/class-wc-email.php b/includes/emails/class-wc-email.php index bae6396f853..14201db7274 100644 --- a/includes/emails/class-wc-email.php +++ b/includes/emails/class-wc-email.php @@ -441,17 +441,23 @@ class WC_Email extends WC_Settings_API { /** * Get email content type. * + * @param string $default_content_type Default wp_mail() content type. * @return string */ - public function get_content_type() { + public function get_content_type( $default_content_type = '' ) { switch ( $this->get_email_type() ) { case 'html': - return 'text/html'; + $content_type = 'text/html'; + break; case 'multipart': - return 'multipart/alternative'; + $content_type = 'multipart/alternative'; + break; default: - return 'text/plain'; + $content_type = 'text/plain'; + break; } + + return apply_filters( 'woocommerce_email_content_type', $content_type, $this, $default_content_type ); } /** @@ -599,21 +605,23 @@ class WC_Email extends WC_Settings_API { /** * Get the from name for outgoing emails. * + * @param string $from_name Default wp_mail() name associated with the "from" email address. * @return string */ - public function get_from_name() { - $from_name = apply_filters( 'woocommerce_email_from_name', get_option( 'woocommerce_email_from_name' ), $this ); + public function get_from_name( $from_name = '' ) { + $from_name = apply_filters( 'woocommerce_email_from_name', get_option( 'woocommerce_email_from_name' ), $this, $from_name ); return wp_specialchars_decode( esc_html( $from_name ), ENT_QUOTES ); } /** * Get the from address for outgoing emails. * + * @param string $from_email Default wp_mail() email address to send from. * @return string */ - public function get_from_address() { - $from_address = apply_filters( 'woocommerce_email_from_address', get_option( 'woocommerce_email_from_address' ), $this ); - return sanitize_email( $from_address ); + public function get_from_address( $from_email = '' ) { + $from_email = apply_filters( 'woocommerce_email_from_address', get_option( 'woocommerce_email_from_address' ), $this, $from_email ); + return sanitize_email( $from_email ); } /** From 2b503e0409f9e3854f755bf94881a34ddcfc0a9d Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 15 Jan 2020 10:24:13 -0800 Subject: [PATCH 73/78] Changed the MaxMind database update process to move the existing archive instead of deleting it --- includes/class-wc-install.php | 2 +- includes/wc-update-functions.php | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 8ba7a34ca11..fba3c6263e4 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -136,7 +136,7 @@ class WC_Install { 'wc_update_370_db_version', ), '3.9.0' => array( - 'wc_update_390_remove_maxmind_database', + 'wc_update_390_move_maxmind_database', 'wc_update_390_change_geolocation_database_update_cron', 'wc_update_390_db_version', ), diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index 3d2cf99a51e..f50f9e80c01 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -2048,12 +2048,23 @@ function wc_update_370_db_version() { } /** - * The TOS for MaxMind's databases require that they be deleted. Since we're making significant changes to - * the location and function of the database downloads, let's remove the legacy database altogether. + * 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_remove_maxmind_database() { - // Make sure to remove the file using the path as it was previously defined in WC_Geolocation! - @unlink( WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb' ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged +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 } /** From e56e5dfc50753360d465842c82e62c7ecaf01bd4 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 15 Jan 2020 10:25:51 -0800 Subject: [PATCH 74/78] Pushed the first woocommerce_geoip_updater execution to fifteen days in the future This will prevent the routine from deleting the pre-update archive that we just moved in the previous update routine. --- includes/wc-update-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index f50f9e80c01..cbb9218017e 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -2072,7 +2072,7 @@ function wc_update_390_move_maxmind_database() { */ function wc_update_390_change_geolocation_database_update_cron() { wp_clear_scheduled_hook( 'woocommerce_geoip_updater' ); - wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', 'woocommerce_geoip_updater' ); + wp_schedule_event( time() + ( DAY_IN_SECONDS * 15 ), 'fifteendays', 'woocommerce_geoip_updater' ); } /** From eedf82da38d497fa758600bef5d232090a6b5086 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 15 Jan 2020 20:40:55 -0300 Subject: [PATCH 75/78] Fixed coding standards --- includes/admin/views/html-admin-page-status-report.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/admin/views/html-admin-page-status-report.php b/includes/admin/views/html-admin-page-status-report.php index bca9f12d587..729882eab2f 100644 --- a/includes/admin/views/html-admin-page-status-report.php +++ b/includes/admin/views/html-admin-page-status-report.php @@ -565,7 +565,7 @@ $untested_plugins = $plugin_updates->get_untested_plugins( WC()->version, 'min get_untested_plugins( WC()->version, 'min ' . $plugin_name . ''; From 28718614d748b4498ed56bea259ecc9825bc5013 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 15 Jan 2020 21:17:57 -0300 Subject: [PATCH 76/78] Version 3.9.0-rc.3 --- composer.json | 4 ++-- composer.lock | 53 +++++++++++++++++++++++++------------------------ readme.txt | 1 + woocommerce.php | 2 +- 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index 48a0490eea3..d5c5e4a044d 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,8 @@ "automattic/jetpack-autoloader": "^1.2.0", "composer/installers": "1.7.0", "maxmind-db/reader": "1.6.0", - "woocommerce/woocommerce-blocks": "2.5.7", - "woocommerce/woocommerce-rest-api": "1.0.5" + "woocommerce/woocommerce-blocks": "2.5.10", + "woocommerce/woocommerce-rest-api": "1.0.6" }, "require-dev": { "phpunit/phpunit": "7.5.18", diff --git a/composer.lock b/composer.lock index 58b730a3f76..16ee08e844d 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": "16f33bdc0f7129c5ec814efd76744356", + "content-hash": "e8edf85437f4ee3362f0447d20314506", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -226,16 +226,16 @@ }, { "name": "woocommerce/woocommerce-blocks", - "version": "v2.5.7", + "version": "v2.5.10", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "24b6552d38204fbbdd87ec5ba76f3ec391b042d0" + "reference": "4a6d993c1df7ccd8581873ee56269efa00d49ddc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/24b6552d38204fbbdd87ec5ba76f3ec391b042d0", - "reference": "24b6552d38204fbbdd87ec5ba76f3ec391b042d0", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/4a6d993c1df7ccd8581873ee56269efa00d49ddc", + "reference": "4a6d993c1df7ccd8581873ee56269efa00d49ddc", "shasum": "" }, "require": { @@ -269,20 +269,20 @@ "gutenberg", "woocommerce" ], - "time": "2019-12-20T17:36:46+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": { @@ -309,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": [ @@ -587,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": { @@ -641,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", @@ -799,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": { @@ -820,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", @@ -846,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", @@ -897,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": { @@ -956,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", 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/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 From f81afa07949d4c7b3c9dacbe0fd35e06a989c36b Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 16 Jan 2020 00:58:45 +0000 Subject: [PATCH 77/78] Update dependency phpunit/phpunit to v7.5.20 --- composer.json | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index d5c5e4a044d..83dce1fda06 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "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 16ee08e844d..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": "e8edf85437f4ee3362f0447d20314506", + "content-hash": "316f960abc40df62fbc75b77930323fc", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -1213,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": { @@ -1293,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", From 8a3887d70e22190acbcc76ea206e6f94ffe8358b Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 16 Jan 2020 17:52:11 +0000 Subject: [PATCH 78/78] Update dependency eslint-plugin-jest to v23.6.0 --- package-lock.json | 37 ++++++++++++++++++++++--------------- package.json | 2 +- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index d07fa5c0c8a..5c6abb8430e 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": { @@ -3660,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" }, @@ -3708,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", @@ -6510,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": { diff --git a/package.json b/package.json index da7ff5f1e2a..14dfc773877 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "chai": "4.2.0", "chai-as-promised": "7.1.1", "commander": "4.1.0", - "eslint-plugin-jest": "23.1.1", + "eslint-plugin-jest": "23.6.0", "config": "3.2.4", "cross-env": "6.0.3", "eslint": "6.8.0",