├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── development ├── Dockerfile ├── docker-compose.yaml └── src │ └── index.php ├── phpunit.xml ├── src └── Geocoder.php └── tests ├── GeocoderTest.php └── bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '5.6' 4 | - '7.0' 5 | install: composer install --dev 6 | notifications: 7 | slack: 8 | secure: GQXj8rWtu5rgdP/RQuzSf7gzFFtb3FLkKF9piPjNlzBffmSlA9TK9/t42LMNMVIOpkOA5XOlK06+9y6N25tzTL/z+CKlm9jDyfOwDjXds70RzTl4Y038sN7R3GPQWusFqstHMQVgXaLcjj9QZ45KIdbObqUkdRvcEAI8Fp45edJOnyTiNxaBC0G4af3QgWXOwuZQC5z553jDnMUs6cZ40YNT4fBpgCovJRL3iS1PcCqQhGllbzCtZYr4m4rNuSb0r321pj2RWS6V8yiWaaQ9l8PzjOolo11gT26Mjq41KMHa9t4LU/OfQoA8+Ln1fyq6Y8mcFgzvDrso0lwZ6GslM3DgAeZPZ2n6rQHp2w6o7NLZXBs2Omo9W15jj2NqAbtrvYQ3nDKDFFjXeUfhVvNSu4zs31RfqWQbfz0pt8fXNaIOKAIiGamk/s4BT473OkxxqxH+cGt9D27KtXEPO4Sfzb6m0Z5ZB+JG0W8LdxdfmpHJgNU+cxJwPxZxQsOojp9GLJUS7o3+PFocv2B53Iq4zy9IpX7Muku6FBchuVRZvYhOFaYksVXXsj+NSyIc1mYHqHfVLyvWW2Q7aQu/fCxntQTgD63WD94ig6rodqFEvCFjaWquQpafaLNddb/cuyst1Uz/25HlIVA3U3YU6Qy0OQhUYdaRw/FHrX30ypgY1ao= 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016, 2017 what3words Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # what3words w3w-php-wrapper 2 | 3 | A PHP library to use the [what3words REST API](https://docs.what3words.com/api/v3/). 4 | 5 | # Overview 6 | 7 | The what3words PHP wrapper gives you programmatic access to 8 | 9 | - convert a 3 word address to coordinates 10 | - convert coordinates to a 3 word address 11 | - autosuggest functionality which takes a slightly incorrect 3 word address, and suggests a list of valid 3 word addresses 12 | - obtain a section of the 3m x 3m what3words grid for a bounding box. 13 | - determine the currently support 3 word address languages. 14 | 15 | ## Authentication 16 | 17 | To use this library you’ll need to obtain an API key, please visit [https://what3words.com/select-plan](https://what3words.com/select-plan) and sign up for an account. 18 | 19 | # Installation 20 | 21 | #### Composer 22 | 23 | To use this library in your project, place the following line in your composer.json: 24 | 25 | ```php 26 | "what3words/w3w-php-wrapper": "3.*" 27 | ``` 28 | 29 | #### Manual 30 | 31 | To manually include this file, place [Geocoder.php](https://github.com/what3words/w3w-php-wrapper/blob/master/src/Geocoder.php) into your project, and require_once("Geocoder.php") 32 | 33 | ### Initialise 34 | 35 | ```php 36 | use What3words\Geocoder\Geocoder; 37 | use What3words\Geocoder\AutoSuggestOption; 38 | 39 | $api = new Geocoder(""); 40 | ``` 41 | 42 | #### Options 43 | 44 | You can also provide header values and referer (for restricted API keys). 45 | 46 | ```php 47 | use What3words\Geocoder\Geocoder; 48 | use What3words\Geocoder\GeocoderOptions; 49 | 50 | $options = GeocoderOptions::referer("https://my.site.com/*")->headers(["X-Custom-Header: my.site.com"]); 51 | 52 | $api = new Geocoder("", $options); 53 | 54 | ``` 55 | 56 | ## Convert To Coordinates 57 | 58 | Convert a 3 word address to a position, expressed as coordinates of latitude and longitude. 59 | 60 | This function takes the words parameter as a string of 3 words `'table.book.chair'` 61 | 62 | The returned payload from the `convertToCoordinates` method is described in the [what3words REST API documentation](https://docs.what3words.com/api/v3/#convert-to-coordinates). 63 | 64 | #### Code Example 65 | 66 | ```php 67 | $result = $api->convertToCoordinates("index.home.raft"); 68 | print_r($result); 69 | ``` 70 | 71 | ## Convert To 3 Word Address 72 | 73 | Convert coordinates, expressed as latitude and longitude to a 3 word address. 74 | 75 | The returned payload from the `convertTo3wa` method is described in the [what3words REST API documentation](https://docs.what3words.com/api/v3/#convert-to-3wa). 76 | 77 | #### Code Example 78 | 79 | ```php 80 | $result = $api->convertTo3wa(51.432393,-0.348023); 81 | print_r($result); 82 | ``` 83 | 84 | ## Available Languages 85 | 86 | This function returns the currently supported languages. It will return the two letter code ([ISO 639](https://en.wikipedia.org/wiki/ISO_639)), and the name of the language both in that language and in English. 87 | 88 | The returned payload from the `convertTo3wa` method is described in the [what3words REST API documentation](https://docs.what3words.com/api/v3/#available-languages) 89 | 90 | #### Code Example 91 | 92 | ```php 93 | $result = $api->availableLanguages(); 94 | print_r($result); 95 | ``` 96 | 97 | ## Grid Section 98 | 99 | Returns a section of the 3m x 3m what3words grid for a given area. The requested box must not exceed 4km from corner to corner, or a BadBoundingBoxTooBig error will be returned. Latitudes must be >= -90 and <= 90, but longitudes are allowed to wrap around 180. To specify a bounding-box that crosses the anti-meridian, use longitude greater than 180. Example value: 50.0, 179.995, 50.01, 180.0005. 100 | 101 | The returned payload from the `gridSection` function is described in the [what3words REST API documentation](https://docs.what3words.com/api/v3/#grid-section) 102 | 103 | #### Code Example 104 | 105 | ```php 106 | $result = $api->gridSection(39.903795, 116.384550, 39.902718, 116.383122); 107 | print_r($result); 108 | ``` 109 | 110 | ## AutoSuggest 111 | 112 | Returns a list of 3 word addresses based on user input and other parameters. 113 | 114 | This method provides corrections for the following types of input error: 115 | 116 | - typing errors 117 | - spelling errors 118 | - misremembered words (e.g. singular vs. plural) 119 | - words in the wrong order 120 | 121 | The `autoSuggest` method determines possible corrections to the supplied 3 word address string based on the probability of the input errors listed above and returns a ranked list of suggestions. This method can also take into consideration the geographic proximity of possible corrections to a given location to further improve the suggestions returned. 122 | 123 | ### Input 3 word address 124 | 125 | You will only receive results back if the partial 3 word address string you submit contains the first two words and at least the first character of the third word; otherwise an error message will be returned. 126 | 127 | ### Clipping and Focus 128 | 129 | We provide various `clip` policies to allow you to specify a geographic area that is used to exclude results that are not likely to be relevant to your users. We recommend that you use the clipping to give a more targeted, shorter set of results to your user. If you know your user’s current location, we also strongly recommend that you use the `focus` to return results which are likely to be more relevant. 130 | 131 | In summary, the clip policy is used to optionally restrict the list of candidate AutoSuggest results, after which, if focus has been supplied, this will be used to rank the results in order of relevancy to the focus. 132 | 133 | The returned payload from the `autosuggest` method is described in the [what3words REST API documentation](https://docs.what3words.com/api/v2/#autosuggest-result). 134 | 135 | ### Usage 136 | 137 | The first parameter is the partial three words, or voice data. It is followed by an array of AutoSuggestOption objects. The last parameter is the completion block. The AutoSuggestOption objects in the array are created using static convenience functions of the form: 138 | 139 | ```php 140 | AutoSuggestOption::fallbackLanguage("de"); 141 | AutoSuggestOption::focus($latitude, $longitude); 142 | ``` 143 | 144 | #### Code Example #1 145 | 146 | ```php 147 | $result = $api->autosuggest("fun.with.code"); 148 | print_r($result); 149 | ``` 150 | 151 | #### Code Example #2 152 | 153 | Focus on (51.4243877,-0.34745) and look for 6 results. 154 | 155 | ```php 156 | $result = $api->autosuggest("fun.with.code", [AutoSuggestOption::focus(51.4243877,-0.34745), AutoSuggestOption::numberResults(6)]); 157 | print_r($result); 158 | ``` 159 | 160 | #### Code Example #3 161 | 162 | Validate what3words 163 | 164 | ```php 165 | $result = $api->isPossible3wa("filled.count.soap"); 166 | print_r($result); // yields 1 167 | 168 | $result = $api->isPossible3wa("not a 3wa"); 169 | print_r($result); // yields 0 170 | 171 | $result = $api->findPossible3wa('from "index.home.raft" to " "filled.count.soap"'); 172 | print_r(implode(", ", $result)); // yields "index.home.raft, filled.count.soap" 173 | 174 | $result = $api->isValid3wa('filled.count.soapp'); 175 | print_r($result ? $result : 'invalid'); // yields 'invalid' 176 | 177 | ``` 178 | 179 | ## Handling Errors 180 | 181 | All the functions will return an stdClass Object containing the requested data, or on failure, they will return `false`. If `false` is returned, call `get_error()`, and it will return an associative array containing a `code` value and a `message` value. 182 | 183 | ```php 184 | print_r($api->getError()); 185 | ``` 186 | 187 | Error values are listed in the [what3words REST API documentation](https://docs.what3words.com/api/v3/#error-handling). 188 | 189 | ## Development (using Docker) 190 | 191 | You can see `w3w-php-wrapper` in action by running `docker compose watch` (make sure you're running this from the `development` directory) and open http://localhost:9000 on your browser. Any changes you make to the source code will be reloaded as you refresh your browser, just ensure you have loaded your environment variable named: `W3W_API_KEY` by running `export W3W_API_KEY=`. 192 | 193 | ```sh 194 | $ export W3W_API_KEY=KEYFROMW3W 195 | $ docker compose watch 196 | [+] Building 0.6s (18/18) FINISHED 197 | [+] Running 1/1 198 | ✔ Container php-server Started 0.0s 199 | Watch configuration for service "server": 200 | - Action sync for path "/w3w-php-wrapper/development/src" 201 | - Action sync for path "/w3w-php-wrapper/src" 202 | - Action sync for path "/w3w-php-wrapper/tests" 203 | ``` 204 | 205 | ### Running tests (using Docker) 206 | 207 | Once you've spin up the container, you can run `docker exec php-server /var/www/html/vendor/bin/phpunit` to execute the unit tests. 208 | 209 | ``` 210 | $ docker exec php-server /var/www/html/vendor/bin/phpunit 211 | PHPUnit 5.5.4 by Sebastian Bergmann and contributors. 212 | 213 | ...................... 22 / 22 (100%) 214 | 215 | Time: 1.57 seconds, Memory: 3.25MB 216 | 217 | OK (22 tests, 25 assertions) 218 | ``` 219 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "what3words/w3w-php-wrapper", 3 | "description": "A PHP library to use the what3words RESTful API", 4 | "type": "library", 5 | "keywords": ["what3words", "geocoding", "3 word address"], 6 | "homepage": "https://github.com/what3words/w3w-php-wrapper", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "what3words", 11 | "email": "support@what3words.com", 12 | "homepage": "http://developer.what3words.com" 13 | } 14 | ], 15 | "support": { 16 | "email": "support@what3words.com", 17 | "issues": "https://github.com/what3words/w3w-php-wrapper/issues", 18 | "source": "https://github.com/what3words/w3w-php-wrapper", 19 | "docs": "https://developer.what3words.com" 20 | }, 21 | "require": { 22 | "php": ">=5.6" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "^5.3" 26 | }, 27 | "archive": { 28 | "exclude": ["vendor", ".DS_Store"] 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "What3words\\Geocoder\\": "src" 33 | } 34 | }, 35 | "extra": { 36 | "thanks": "Thanks from all of us at index.home.raft for using what3words" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "3903d1f169b4f2d62aa93d1d20e10fd9", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "doctrine/instantiator", 12 | "version": "1.0.5", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/instantiator.git", 16 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 21 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": ">=5.3,<8.0-DEV" 26 | }, 27 | "require-dev": { 28 | "athletic/athletic": "~0.1.8", 29 | "ext-pdo": "*", 30 | "ext-phar": "*", 31 | "phpunit/phpunit": "~4.0", 32 | "squizlabs/php_codesniffer": "~2.0" 33 | }, 34 | "type": "library", 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "1.0.x-dev" 38 | } 39 | }, 40 | "autoload": { 41 | "psr-4": { 42 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 43 | } 44 | }, 45 | "notification-url": "https://packagist.org/downloads/", 46 | "license": [ 47 | "MIT" 48 | ], 49 | "authors": [ 50 | { 51 | "name": "Marco Pivetta", 52 | "email": "ocramius@gmail.com", 53 | "homepage": "http://ocramius.github.com/" 54 | } 55 | ], 56 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 57 | "homepage": "https://github.com/doctrine/instantiator", 58 | "keywords": [ 59 | "constructor", 60 | "instantiate" 61 | ], 62 | "support": { 63 | "issues": "https://github.com/doctrine/instantiator/issues", 64 | "source": "https://github.com/doctrine/instantiator/tree/1.0.5" 65 | }, 66 | "funding": [ 67 | { 68 | "url": "https://www.doctrine-project.org/sponsorship.html", 69 | "type": "custom" 70 | }, 71 | { 72 | "url": "https://www.patreon.com/phpdoctrine", 73 | "type": "patreon" 74 | }, 75 | { 76 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 77 | "type": "tidelift" 78 | } 79 | ], 80 | "time": "2015-06-14T21:17:01+00:00" 81 | }, 82 | { 83 | "name": "myclabs/deep-copy", 84 | "version": "1.7.0", 85 | "source": { 86 | "type": "git", 87 | "url": "https://github.com/myclabs/DeepCopy.git", 88 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" 89 | }, 90 | "dist": { 91 | "type": "zip", 92 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 93 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 94 | "shasum": "" 95 | }, 96 | "require": { 97 | "php": "^5.6 || ^7.0" 98 | }, 99 | "require-dev": { 100 | "doctrine/collections": "^1.0", 101 | "doctrine/common": "^2.6", 102 | "phpunit/phpunit": "^4.1" 103 | }, 104 | "type": "library", 105 | "autoload": { 106 | "files": [ 107 | "src/DeepCopy/deep_copy.php" 108 | ], 109 | "psr-4": { 110 | "DeepCopy\\": "src/DeepCopy/" 111 | } 112 | }, 113 | "notification-url": "https://packagist.org/downloads/", 114 | "license": [ 115 | "MIT" 116 | ], 117 | "description": "Create deep copies (clones) of your objects", 118 | "keywords": [ 119 | "clone", 120 | "copy", 121 | "duplicate", 122 | "object", 123 | "object graph" 124 | ], 125 | "support": { 126 | "issues": "https://github.com/myclabs/DeepCopy/issues", 127 | "source": "https://github.com/myclabs/DeepCopy/tree/1.x" 128 | }, 129 | "time": "2017-10-19T19:58:43+00:00" 130 | }, 131 | { 132 | "name": "phpdocumentor/reflection-common", 133 | "version": "1.0.1", 134 | "source": { 135 | "type": "git", 136 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 137 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 138 | }, 139 | "dist": { 140 | "type": "zip", 141 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 142 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 143 | "shasum": "" 144 | }, 145 | "require": { 146 | "php": ">=5.5" 147 | }, 148 | "require-dev": { 149 | "phpunit/phpunit": "^4.6" 150 | }, 151 | "type": "library", 152 | "extra": { 153 | "branch-alias": { 154 | "dev-master": "1.0.x-dev" 155 | } 156 | }, 157 | "autoload": { 158 | "psr-4": { 159 | "phpDocumentor\\Reflection\\": [ 160 | "src" 161 | ] 162 | } 163 | }, 164 | "notification-url": "https://packagist.org/downloads/", 165 | "license": [ 166 | "MIT" 167 | ], 168 | "authors": [ 169 | { 170 | "name": "Jaap van Otterdijk", 171 | "email": "opensource@ijaap.nl" 172 | } 173 | ], 174 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 175 | "homepage": "http://www.phpdoc.org", 176 | "keywords": [ 177 | "FQSEN", 178 | "phpDocumentor", 179 | "phpdoc", 180 | "reflection", 181 | "static analysis" 182 | ], 183 | "support": { 184 | "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", 185 | "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" 186 | }, 187 | "time": "2017-09-11T18:02:19+00:00" 188 | }, 189 | { 190 | "name": "phpdocumentor/reflection-docblock", 191 | "version": "3.3.2", 192 | "source": { 193 | "type": "git", 194 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 195 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" 196 | }, 197 | "dist": { 198 | "type": "zip", 199 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", 200 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", 201 | "shasum": "" 202 | }, 203 | "require": { 204 | "php": "^5.6 || ^7.0", 205 | "phpdocumentor/reflection-common": "^1.0.0", 206 | "phpdocumentor/type-resolver": "^0.4.0", 207 | "webmozart/assert": "^1.0" 208 | }, 209 | "require-dev": { 210 | "mockery/mockery": "^0.9.4", 211 | "phpunit/phpunit": "^4.4" 212 | }, 213 | "type": "library", 214 | "autoload": { 215 | "psr-4": { 216 | "phpDocumentor\\Reflection\\": [ 217 | "src/" 218 | ] 219 | } 220 | }, 221 | "notification-url": "https://packagist.org/downloads/", 222 | "license": [ 223 | "MIT" 224 | ], 225 | "authors": [ 226 | { 227 | "name": "Mike van Riel", 228 | "email": "me@mikevanriel.com" 229 | } 230 | ], 231 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 232 | "support": { 233 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", 234 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/3.x" 235 | }, 236 | "time": "2017-11-10T14:09:06+00:00" 237 | }, 238 | { 239 | "name": "phpdocumentor/type-resolver", 240 | "version": "0.4.0", 241 | "source": { 242 | "type": "git", 243 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 244 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 245 | }, 246 | "dist": { 247 | "type": "zip", 248 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 249 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 250 | "shasum": "" 251 | }, 252 | "require": { 253 | "php": "^5.5 || ^7.0", 254 | "phpdocumentor/reflection-common": "^1.0" 255 | }, 256 | "require-dev": { 257 | "mockery/mockery": "^0.9.4", 258 | "phpunit/phpunit": "^5.2||^4.8.24" 259 | }, 260 | "type": "library", 261 | "extra": { 262 | "branch-alias": { 263 | "dev-master": "1.0.x-dev" 264 | } 265 | }, 266 | "autoload": { 267 | "psr-4": { 268 | "phpDocumentor\\Reflection\\": [ 269 | "src/" 270 | ] 271 | } 272 | }, 273 | "notification-url": "https://packagist.org/downloads/", 274 | "license": [ 275 | "MIT" 276 | ], 277 | "authors": [ 278 | { 279 | "name": "Mike van Riel", 280 | "email": "me@mikevanriel.com" 281 | } 282 | ], 283 | "support": { 284 | "issues": "https://github.com/phpDocumentor/TypeResolver/issues", 285 | "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" 286 | }, 287 | "time": "2017-07-14T14:27:02+00:00" 288 | }, 289 | { 290 | "name": "phpspec/prophecy", 291 | "version": "v1.10.3", 292 | "source": { 293 | "type": "git", 294 | "url": "https://github.com/phpspec/prophecy.git", 295 | "reference": "451c3cd1418cf640de218914901e51b064abb093" 296 | }, 297 | "dist": { 298 | "type": "zip", 299 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", 300 | "reference": "451c3cd1418cf640de218914901e51b064abb093", 301 | "shasum": "" 302 | }, 303 | "require": { 304 | "doctrine/instantiator": "^1.0.2", 305 | "php": "^5.3|^7.0", 306 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", 307 | "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", 308 | "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" 309 | }, 310 | "require-dev": { 311 | "phpspec/phpspec": "^2.5 || ^3.2", 312 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 313 | }, 314 | "type": "library", 315 | "extra": { 316 | "branch-alias": { 317 | "dev-master": "1.10.x-dev" 318 | } 319 | }, 320 | "autoload": { 321 | "psr-4": { 322 | "Prophecy\\": "src/Prophecy" 323 | } 324 | }, 325 | "notification-url": "https://packagist.org/downloads/", 326 | "license": [ 327 | "MIT" 328 | ], 329 | "authors": [ 330 | { 331 | "name": "Konstantin Kudryashov", 332 | "email": "ever.zet@gmail.com", 333 | "homepage": "http://everzet.com" 334 | }, 335 | { 336 | "name": "Marcello Duarte", 337 | "email": "marcello.duarte@gmail.com" 338 | } 339 | ], 340 | "description": "Highly opinionated mocking framework for PHP 5.3+", 341 | "homepage": "https://github.com/phpspec/prophecy", 342 | "keywords": [ 343 | "Double", 344 | "Dummy", 345 | "fake", 346 | "mock", 347 | "spy", 348 | "stub" 349 | ], 350 | "support": { 351 | "issues": "https://github.com/phpspec/prophecy/issues", 352 | "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" 353 | }, 354 | "time": "2020-03-05T15:02:03+00:00" 355 | }, 356 | { 357 | "name": "phpunit/php-code-coverage", 358 | "version": "4.0.8", 359 | "source": { 360 | "type": "git", 361 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 362 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" 363 | }, 364 | "dist": { 365 | "type": "zip", 366 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 367 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 368 | "shasum": "" 369 | }, 370 | "require": { 371 | "ext-dom": "*", 372 | "ext-xmlwriter": "*", 373 | "php": "^5.6 || ^7.0", 374 | "phpunit/php-file-iterator": "^1.3", 375 | "phpunit/php-text-template": "^1.2", 376 | "phpunit/php-token-stream": "^1.4.2 || ^2.0", 377 | "sebastian/code-unit-reverse-lookup": "^1.0", 378 | "sebastian/environment": "^1.3.2 || ^2.0", 379 | "sebastian/version": "^1.0 || ^2.0" 380 | }, 381 | "require-dev": { 382 | "ext-xdebug": "^2.1.4", 383 | "phpunit/phpunit": "^5.7" 384 | }, 385 | "suggest": { 386 | "ext-xdebug": "^2.5.1" 387 | }, 388 | "type": "library", 389 | "extra": { 390 | "branch-alias": { 391 | "dev-master": "4.0.x-dev" 392 | } 393 | }, 394 | "autoload": { 395 | "classmap": [ 396 | "src/" 397 | ] 398 | }, 399 | "notification-url": "https://packagist.org/downloads/", 400 | "license": [ 401 | "BSD-3-Clause" 402 | ], 403 | "authors": [ 404 | { 405 | "name": "Sebastian Bergmann", 406 | "email": "sb@sebastian-bergmann.de", 407 | "role": "lead" 408 | } 409 | ], 410 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 411 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 412 | "keywords": [ 413 | "coverage", 414 | "testing", 415 | "xunit" 416 | ], 417 | "support": { 418 | "irc": "irc://irc.freenode.net/phpunit", 419 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 420 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/4.0" 421 | }, 422 | "time": "2017-04-02T07:44:40+00:00" 423 | }, 424 | { 425 | "name": "phpunit/php-file-iterator", 426 | "version": "1.4.5", 427 | "source": { 428 | "type": "git", 429 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 430 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 431 | }, 432 | "dist": { 433 | "type": "zip", 434 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 435 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 436 | "shasum": "" 437 | }, 438 | "require": { 439 | "php": ">=5.3.3" 440 | }, 441 | "type": "library", 442 | "extra": { 443 | "branch-alias": { 444 | "dev-master": "1.4.x-dev" 445 | } 446 | }, 447 | "autoload": { 448 | "classmap": [ 449 | "src/" 450 | ] 451 | }, 452 | "notification-url": "https://packagist.org/downloads/", 453 | "license": [ 454 | "BSD-3-Clause" 455 | ], 456 | "authors": [ 457 | { 458 | "name": "Sebastian Bergmann", 459 | "email": "sb@sebastian-bergmann.de", 460 | "role": "lead" 461 | } 462 | ], 463 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 464 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 465 | "keywords": [ 466 | "filesystem", 467 | "iterator" 468 | ], 469 | "support": { 470 | "irc": "irc://irc.freenode.net/phpunit", 471 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 472 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" 473 | }, 474 | "time": "2017-11-27T13:52:08+00:00" 475 | }, 476 | { 477 | "name": "phpunit/php-text-template", 478 | "version": "1.2.1", 479 | "source": { 480 | "type": "git", 481 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 482 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 483 | }, 484 | "dist": { 485 | "type": "zip", 486 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 487 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 488 | "shasum": "" 489 | }, 490 | "require": { 491 | "php": ">=5.3.3" 492 | }, 493 | "type": "library", 494 | "autoload": { 495 | "classmap": [ 496 | "src/" 497 | ] 498 | }, 499 | "notification-url": "https://packagist.org/downloads/", 500 | "license": [ 501 | "BSD-3-Clause" 502 | ], 503 | "authors": [ 504 | { 505 | "name": "Sebastian Bergmann", 506 | "email": "sebastian@phpunit.de", 507 | "role": "lead" 508 | } 509 | ], 510 | "description": "Simple template engine.", 511 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 512 | "keywords": [ 513 | "template" 514 | ], 515 | "support": { 516 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 517 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" 518 | }, 519 | "time": "2015-06-21T13:50:34+00:00" 520 | }, 521 | { 522 | "name": "phpunit/php-timer", 523 | "version": "1.0.9", 524 | "source": { 525 | "type": "git", 526 | "url": "https://github.com/sebastianbergmann/php-timer.git", 527 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 528 | }, 529 | "dist": { 530 | "type": "zip", 531 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 532 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 533 | "shasum": "" 534 | }, 535 | "require": { 536 | "php": "^5.3.3 || ^7.0" 537 | }, 538 | "require-dev": { 539 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 540 | }, 541 | "type": "library", 542 | "extra": { 543 | "branch-alias": { 544 | "dev-master": "1.0-dev" 545 | } 546 | }, 547 | "autoload": { 548 | "classmap": [ 549 | "src/" 550 | ] 551 | }, 552 | "notification-url": "https://packagist.org/downloads/", 553 | "license": [ 554 | "BSD-3-Clause" 555 | ], 556 | "authors": [ 557 | { 558 | "name": "Sebastian Bergmann", 559 | "email": "sb@sebastian-bergmann.de", 560 | "role": "lead" 561 | } 562 | ], 563 | "description": "Utility class for timing", 564 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 565 | "keywords": [ 566 | "timer" 567 | ], 568 | "support": { 569 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 570 | "source": "https://github.com/sebastianbergmann/php-timer/tree/master" 571 | }, 572 | "time": "2017-02-26T11:10:40+00:00" 573 | }, 574 | { 575 | "name": "phpunit/php-token-stream", 576 | "version": "1.4.12", 577 | "source": { 578 | "type": "git", 579 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 580 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 581 | }, 582 | "dist": { 583 | "type": "zip", 584 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", 585 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 586 | "shasum": "" 587 | }, 588 | "require": { 589 | "ext-tokenizer": "*", 590 | "php": ">=5.3.3" 591 | }, 592 | "require-dev": { 593 | "phpunit/phpunit": "~4.2" 594 | }, 595 | "type": "library", 596 | "extra": { 597 | "branch-alias": { 598 | "dev-master": "1.4-dev" 599 | } 600 | }, 601 | "autoload": { 602 | "classmap": [ 603 | "src/" 604 | ] 605 | }, 606 | "notification-url": "https://packagist.org/downloads/", 607 | "license": [ 608 | "BSD-3-Clause" 609 | ], 610 | "authors": [ 611 | { 612 | "name": "Sebastian Bergmann", 613 | "email": "sebastian@phpunit.de" 614 | } 615 | ], 616 | "description": "Wrapper around PHP's tokenizer extension.", 617 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 618 | "keywords": [ 619 | "tokenizer" 620 | ], 621 | "support": { 622 | "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", 623 | "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" 624 | }, 625 | "abandoned": true, 626 | "time": "2017-12-04T08:55:13+00:00" 627 | }, 628 | { 629 | "name": "phpunit/phpunit", 630 | "version": "5.6.3", 631 | "source": { 632 | "type": "git", 633 | "url": "https://github.com/sebastianbergmann/phpunit.git", 634 | "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c" 635 | }, 636 | "dist": { 637 | "type": "zip", 638 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c", 639 | "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c", 640 | "shasum": "" 641 | }, 642 | "require": { 643 | "ext-dom": "*", 644 | "ext-json": "*", 645 | "ext-libxml": "*", 646 | "ext-mbstring": "*", 647 | "ext-xml": "*", 648 | "myclabs/deep-copy": "~1.3", 649 | "php": "^5.6 || ^7.0", 650 | "phpspec/prophecy": "^1.3.1", 651 | "phpunit/php-code-coverage": "^4.0.1", 652 | "phpunit/php-file-iterator": "~1.4", 653 | "phpunit/php-text-template": "~1.2", 654 | "phpunit/php-timer": "^1.0.6", 655 | "phpunit/phpunit-mock-objects": "^3.2", 656 | "sebastian/comparator": "~1.1", 657 | "sebastian/diff": "~1.2", 658 | "sebastian/environment": "^1.3 || ^2.0", 659 | "sebastian/exporter": "~1.2", 660 | "sebastian/global-state": "~1.0", 661 | "sebastian/object-enumerator": "~1.0", 662 | "sebastian/resource-operations": "~1.0", 663 | "sebastian/version": "~1.0|~2.0", 664 | "symfony/yaml": "~2.1|~3.0" 665 | }, 666 | "conflict": { 667 | "phpdocumentor/reflection-docblock": "3.0.2" 668 | }, 669 | "require-dev": { 670 | "ext-pdo": "*" 671 | }, 672 | "suggest": { 673 | "ext-xdebug": "*", 674 | "phpunit/php-invoker": "~1.1" 675 | }, 676 | "bin": [ 677 | "phpunit" 678 | ], 679 | "type": "library", 680 | "extra": { 681 | "branch-alias": { 682 | "dev-master": "5.6.x-dev" 683 | } 684 | }, 685 | "autoload": { 686 | "classmap": [ 687 | "src/" 688 | ] 689 | }, 690 | "notification-url": "https://packagist.org/downloads/", 691 | "license": [ 692 | "BSD-3-Clause" 693 | ], 694 | "authors": [ 695 | { 696 | "name": "Sebastian Bergmann", 697 | "email": "sebastian@phpunit.de", 698 | "role": "lead" 699 | } 700 | ], 701 | "description": "The PHP Unit Testing framework.", 702 | "homepage": "https://phpunit.de/", 703 | "keywords": [ 704 | "phpunit", 705 | "testing", 706 | "xunit" 707 | ], 708 | "support": { 709 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 710 | "source": "https://github.com/sebastianbergmann/phpunit/tree/5.6.3" 711 | }, 712 | "time": "2016-11-14T06:39:40+00:00" 713 | }, 714 | { 715 | "name": "phpunit/phpunit-mock-objects", 716 | "version": "3.4.4", 717 | "source": { 718 | "type": "git", 719 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 720 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" 721 | }, 722 | "dist": { 723 | "type": "zip", 724 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", 725 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", 726 | "shasum": "" 727 | }, 728 | "require": { 729 | "doctrine/instantiator": "^1.0.2", 730 | "php": "^5.6 || ^7.0", 731 | "phpunit/php-text-template": "^1.2", 732 | "sebastian/exporter": "^1.2 || ^2.0" 733 | }, 734 | "conflict": { 735 | "phpunit/phpunit": "<5.4.0" 736 | }, 737 | "require-dev": { 738 | "phpunit/phpunit": "^5.4" 739 | }, 740 | "suggest": { 741 | "ext-soap": "*" 742 | }, 743 | "type": "library", 744 | "extra": { 745 | "branch-alias": { 746 | "dev-master": "3.2.x-dev" 747 | } 748 | }, 749 | "autoload": { 750 | "classmap": [ 751 | "src/" 752 | ] 753 | }, 754 | "notification-url": "https://packagist.org/downloads/", 755 | "license": [ 756 | "BSD-3-Clause" 757 | ], 758 | "authors": [ 759 | { 760 | "name": "Sebastian Bergmann", 761 | "email": "sb@sebastian-bergmann.de", 762 | "role": "lead" 763 | } 764 | ], 765 | "description": "Mock Object library for PHPUnit", 766 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 767 | "keywords": [ 768 | "mock", 769 | "xunit" 770 | ], 771 | "support": { 772 | "irc": "irc://irc.freenode.net/phpunit", 773 | "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", 774 | "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.4" 775 | }, 776 | "abandoned": true, 777 | "time": "2017-06-30T09:13:00+00:00" 778 | }, 779 | { 780 | "name": "sebastian/code-unit-reverse-lookup", 781 | "version": "1.0.3", 782 | "source": { 783 | "type": "git", 784 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 785 | "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54" 786 | }, 787 | "dist": { 788 | "type": "zip", 789 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", 790 | "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", 791 | "shasum": "" 792 | }, 793 | "require": { 794 | "php": ">=5.6" 795 | }, 796 | "require-dev": { 797 | "phpunit/phpunit": "^8.5" 798 | }, 799 | "type": "library", 800 | "extra": { 801 | "branch-alias": { 802 | "dev-master": "1.0.x-dev" 803 | } 804 | }, 805 | "autoload": { 806 | "classmap": [ 807 | "src/" 808 | ] 809 | }, 810 | "notification-url": "https://packagist.org/downloads/", 811 | "license": [ 812 | "BSD-3-Clause" 813 | ], 814 | "authors": [ 815 | { 816 | "name": "Sebastian Bergmann", 817 | "email": "sebastian@phpunit.de" 818 | } 819 | ], 820 | "description": "Looks up which function or method a line of code belongs to", 821 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 822 | "support": { 823 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 824 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.3" 825 | }, 826 | "funding": [ 827 | { 828 | "url": "https://github.com/sebastianbergmann", 829 | "type": "github" 830 | } 831 | ], 832 | "time": "2024-03-01T13:45:45+00:00" 833 | }, 834 | { 835 | "name": "sebastian/comparator", 836 | "version": "1.2.4", 837 | "source": { 838 | "type": "git", 839 | "url": "https://github.com/sebastianbergmann/comparator.git", 840 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 841 | }, 842 | "dist": { 843 | "type": "zip", 844 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 845 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 846 | "shasum": "" 847 | }, 848 | "require": { 849 | "php": ">=5.3.3", 850 | "sebastian/diff": "~1.2", 851 | "sebastian/exporter": "~1.2 || ~2.0" 852 | }, 853 | "require-dev": { 854 | "phpunit/phpunit": "~4.4" 855 | }, 856 | "type": "library", 857 | "extra": { 858 | "branch-alias": { 859 | "dev-master": "1.2.x-dev" 860 | } 861 | }, 862 | "autoload": { 863 | "classmap": [ 864 | "src/" 865 | ] 866 | }, 867 | "notification-url": "https://packagist.org/downloads/", 868 | "license": [ 869 | "BSD-3-Clause" 870 | ], 871 | "authors": [ 872 | { 873 | "name": "Jeff Welch", 874 | "email": "whatthejeff@gmail.com" 875 | }, 876 | { 877 | "name": "Volker Dusch", 878 | "email": "github@wallbash.com" 879 | }, 880 | { 881 | "name": "Bernhard Schussek", 882 | "email": "bschussek@2bepublished.at" 883 | }, 884 | { 885 | "name": "Sebastian Bergmann", 886 | "email": "sebastian@phpunit.de" 887 | } 888 | ], 889 | "description": "Provides the functionality to compare PHP values for equality", 890 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 891 | "keywords": [ 892 | "comparator", 893 | "compare", 894 | "equality" 895 | ], 896 | "support": { 897 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 898 | "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" 899 | }, 900 | "time": "2017-01-29T09:50:25+00:00" 901 | }, 902 | { 903 | "name": "sebastian/diff", 904 | "version": "1.4.3", 905 | "source": { 906 | "type": "git", 907 | "url": "https://github.com/sebastianbergmann/diff.git", 908 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 909 | }, 910 | "dist": { 911 | "type": "zip", 912 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 913 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 914 | "shasum": "" 915 | }, 916 | "require": { 917 | "php": "^5.3.3 || ^7.0" 918 | }, 919 | "require-dev": { 920 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 921 | }, 922 | "type": "library", 923 | "extra": { 924 | "branch-alias": { 925 | "dev-master": "1.4-dev" 926 | } 927 | }, 928 | "autoload": { 929 | "classmap": [ 930 | "src/" 931 | ] 932 | }, 933 | "notification-url": "https://packagist.org/downloads/", 934 | "license": [ 935 | "BSD-3-Clause" 936 | ], 937 | "authors": [ 938 | { 939 | "name": "Kore Nordmann", 940 | "email": "mail@kore-nordmann.de" 941 | }, 942 | { 943 | "name": "Sebastian Bergmann", 944 | "email": "sebastian@phpunit.de" 945 | } 946 | ], 947 | "description": "Diff implementation", 948 | "homepage": "https://github.com/sebastianbergmann/diff", 949 | "keywords": [ 950 | "diff" 951 | ], 952 | "support": { 953 | "issues": "https://github.com/sebastianbergmann/diff/issues", 954 | "source": "https://github.com/sebastianbergmann/diff/tree/1.4" 955 | }, 956 | "time": "2017-05-22T07:24:03+00:00" 957 | }, 958 | { 959 | "name": "sebastian/environment", 960 | "version": "2.0.0", 961 | "source": { 962 | "type": "git", 963 | "url": "https://github.com/sebastianbergmann/environment.git", 964 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" 965 | }, 966 | "dist": { 967 | "type": "zip", 968 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 969 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 970 | "shasum": "" 971 | }, 972 | "require": { 973 | "php": "^5.6 || ^7.0" 974 | }, 975 | "require-dev": { 976 | "phpunit/phpunit": "^5.0" 977 | }, 978 | "type": "library", 979 | "extra": { 980 | "branch-alias": { 981 | "dev-master": "2.0.x-dev" 982 | } 983 | }, 984 | "autoload": { 985 | "classmap": [ 986 | "src/" 987 | ] 988 | }, 989 | "notification-url": "https://packagist.org/downloads/", 990 | "license": [ 991 | "BSD-3-Clause" 992 | ], 993 | "authors": [ 994 | { 995 | "name": "Sebastian Bergmann", 996 | "email": "sebastian@phpunit.de" 997 | } 998 | ], 999 | "description": "Provides functionality to handle HHVM/PHP environments", 1000 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1001 | "keywords": [ 1002 | "Xdebug", 1003 | "environment", 1004 | "hhvm" 1005 | ], 1006 | "support": { 1007 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1008 | "source": "https://github.com/sebastianbergmann/environment/tree/master" 1009 | }, 1010 | "time": "2016-11-26T07:53:53+00:00" 1011 | }, 1012 | { 1013 | "name": "sebastian/exporter", 1014 | "version": "1.2.2", 1015 | "source": { 1016 | "type": "git", 1017 | "url": "https://github.com/sebastianbergmann/exporter.git", 1018 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 1019 | }, 1020 | "dist": { 1021 | "type": "zip", 1022 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 1023 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 1024 | "shasum": "" 1025 | }, 1026 | "require": { 1027 | "php": ">=5.3.3", 1028 | "sebastian/recursion-context": "~1.0" 1029 | }, 1030 | "require-dev": { 1031 | "ext-mbstring": "*", 1032 | "phpunit/phpunit": "~4.4" 1033 | }, 1034 | "type": "library", 1035 | "extra": { 1036 | "branch-alias": { 1037 | "dev-master": "1.3.x-dev" 1038 | } 1039 | }, 1040 | "autoload": { 1041 | "classmap": [ 1042 | "src/" 1043 | ] 1044 | }, 1045 | "notification-url": "https://packagist.org/downloads/", 1046 | "license": [ 1047 | "BSD-3-Clause" 1048 | ], 1049 | "authors": [ 1050 | { 1051 | "name": "Jeff Welch", 1052 | "email": "whatthejeff@gmail.com" 1053 | }, 1054 | { 1055 | "name": "Volker Dusch", 1056 | "email": "github@wallbash.com" 1057 | }, 1058 | { 1059 | "name": "Bernhard Schussek", 1060 | "email": "bschussek@2bepublished.at" 1061 | }, 1062 | { 1063 | "name": "Sebastian Bergmann", 1064 | "email": "sebastian@phpunit.de" 1065 | }, 1066 | { 1067 | "name": "Adam Harvey", 1068 | "email": "aharvey@php.net" 1069 | } 1070 | ], 1071 | "description": "Provides the functionality to export PHP variables for visualization", 1072 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1073 | "keywords": [ 1074 | "export", 1075 | "exporter" 1076 | ], 1077 | "support": { 1078 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1079 | "source": "https://github.com/sebastianbergmann/exporter/tree/master" 1080 | }, 1081 | "time": "2016-06-17T09:04:28+00:00" 1082 | }, 1083 | { 1084 | "name": "sebastian/global-state", 1085 | "version": "1.1.1", 1086 | "source": { 1087 | "type": "git", 1088 | "url": "https://github.com/sebastianbergmann/global-state.git", 1089 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1090 | }, 1091 | "dist": { 1092 | "type": "zip", 1093 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1094 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1095 | "shasum": "" 1096 | }, 1097 | "require": { 1098 | "php": ">=5.3.3" 1099 | }, 1100 | "require-dev": { 1101 | "phpunit/phpunit": "~4.2" 1102 | }, 1103 | "suggest": { 1104 | "ext-uopz": "*" 1105 | }, 1106 | "type": "library", 1107 | "extra": { 1108 | "branch-alias": { 1109 | "dev-master": "1.0-dev" 1110 | } 1111 | }, 1112 | "autoload": { 1113 | "classmap": [ 1114 | "src/" 1115 | ] 1116 | }, 1117 | "notification-url": "https://packagist.org/downloads/", 1118 | "license": [ 1119 | "BSD-3-Clause" 1120 | ], 1121 | "authors": [ 1122 | { 1123 | "name": "Sebastian Bergmann", 1124 | "email": "sebastian@phpunit.de" 1125 | } 1126 | ], 1127 | "description": "Snapshotting of global state", 1128 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1129 | "keywords": [ 1130 | "global state" 1131 | ], 1132 | "support": { 1133 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1134 | "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1" 1135 | }, 1136 | "time": "2015-10-12T03:26:01+00:00" 1137 | }, 1138 | { 1139 | "name": "sebastian/object-enumerator", 1140 | "version": "1.0.0", 1141 | "source": { 1142 | "type": "git", 1143 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1144 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" 1145 | }, 1146 | "dist": { 1147 | "type": "zip", 1148 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", 1149 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", 1150 | "shasum": "" 1151 | }, 1152 | "require": { 1153 | "php": ">=5.6", 1154 | "sebastian/recursion-context": "~1.0" 1155 | }, 1156 | "require-dev": { 1157 | "phpunit/phpunit": "~5" 1158 | }, 1159 | "type": "library", 1160 | "extra": { 1161 | "branch-alias": { 1162 | "dev-master": "1.0.x-dev" 1163 | } 1164 | }, 1165 | "autoload": { 1166 | "classmap": [ 1167 | "src/" 1168 | ] 1169 | }, 1170 | "notification-url": "https://packagist.org/downloads/", 1171 | "license": [ 1172 | "BSD-3-Clause" 1173 | ], 1174 | "authors": [ 1175 | { 1176 | "name": "Sebastian Bergmann", 1177 | "email": "sebastian@phpunit.de" 1178 | } 1179 | ], 1180 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1181 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1182 | "support": { 1183 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1184 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/master" 1185 | }, 1186 | "time": "2016-01-28T13:25:10+00:00" 1187 | }, 1188 | { 1189 | "name": "sebastian/recursion-context", 1190 | "version": "1.0.5", 1191 | "source": { 1192 | "type": "git", 1193 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1194 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" 1195 | }, 1196 | "dist": { 1197 | "type": "zip", 1198 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 1199 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 1200 | "shasum": "" 1201 | }, 1202 | "require": { 1203 | "php": ">=5.3.3" 1204 | }, 1205 | "require-dev": { 1206 | "phpunit/phpunit": "~4.4" 1207 | }, 1208 | "type": "library", 1209 | "extra": { 1210 | "branch-alias": { 1211 | "dev-master": "1.0.x-dev" 1212 | } 1213 | }, 1214 | "autoload": { 1215 | "classmap": [ 1216 | "src/" 1217 | ] 1218 | }, 1219 | "notification-url": "https://packagist.org/downloads/", 1220 | "license": [ 1221 | "BSD-3-Clause" 1222 | ], 1223 | "authors": [ 1224 | { 1225 | "name": "Jeff Welch", 1226 | "email": "whatthejeff@gmail.com" 1227 | }, 1228 | { 1229 | "name": "Sebastian Bergmann", 1230 | "email": "sebastian@phpunit.de" 1231 | }, 1232 | { 1233 | "name": "Adam Harvey", 1234 | "email": "aharvey@php.net" 1235 | } 1236 | ], 1237 | "description": "Provides functionality to recursively process PHP variables", 1238 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1239 | "support": { 1240 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1241 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/master" 1242 | }, 1243 | "time": "2016-10-03T07:41:43+00:00" 1244 | }, 1245 | { 1246 | "name": "sebastian/resource-operations", 1247 | "version": "1.0.0", 1248 | "source": { 1249 | "type": "git", 1250 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1251 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1252 | }, 1253 | "dist": { 1254 | "type": "zip", 1255 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1256 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1257 | "shasum": "" 1258 | }, 1259 | "require": { 1260 | "php": ">=5.6.0" 1261 | }, 1262 | "type": "library", 1263 | "extra": { 1264 | "branch-alias": { 1265 | "dev-master": "1.0.x-dev" 1266 | } 1267 | }, 1268 | "autoload": { 1269 | "classmap": [ 1270 | "src/" 1271 | ] 1272 | }, 1273 | "notification-url": "https://packagist.org/downloads/", 1274 | "license": [ 1275 | "BSD-3-Clause" 1276 | ], 1277 | "authors": [ 1278 | { 1279 | "name": "Sebastian Bergmann", 1280 | "email": "sebastian@phpunit.de" 1281 | } 1282 | ], 1283 | "description": "Provides a list of PHP built-in functions that operate on resources", 1284 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1285 | "support": { 1286 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 1287 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" 1288 | }, 1289 | "time": "2015-07-28T20:34:47+00:00" 1290 | }, 1291 | { 1292 | "name": "sebastian/version", 1293 | "version": "2.0.1", 1294 | "source": { 1295 | "type": "git", 1296 | "url": "https://github.com/sebastianbergmann/version.git", 1297 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1298 | }, 1299 | "dist": { 1300 | "type": "zip", 1301 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1302 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1303 | "shasum": "" 1304 | }, 1305 | "require": { 1306 | "php": ">=5.6" 1307 | }, 1308 | "type": "library", 1309 | "extra": { 1310 | "branch-alias": { 1311 | "dev-master": "2.0.x-dev" 1312 | } 1313 | }, 1314 | "autoload": { 1315 | "classmap": [ 1316 | "src/" 1317 | ] 1318 | }, 1319 | "notification-url": "https://packagist.org/downloads/", 1320 | "license": [ 1321 | "BSD-3-Clause" 1322 | ], 1323 | "authors": [ 1324 | { 1325 | "name": "Sebastian Bergmann", 1326 | "email": "sebastian@phpunit.de", 1327 | "role": "lead" 1328 | } 1329 | ], 1330 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1331 | "homepage": "https://github.com/sebastianbergmann/version", 1332 | "support": { 1333 | "issues": "https://github.com/sebastianbergmann/version/issues", 1334 | "source": "https://github.com/sebastianbergmann/version/tree/master" 1335 | }, 1336 | "time": "2016-10-03T07:35:21+00:00" 1337 | }, 1338 | { 1339 | "name": "symfony/polyfill-ctype", 1340 | "version": "v1.19.0", 1341 | "source": { 1342 | "type": "git", 1343 | "url": "https://github.com/symfony/polyfill-ctype.git", 1344 | "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" 1345 | }, 1346 | "dist": { 1347 | "type": "zip", 1348 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", 1349 | "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", 1350 | "shasum": "" 1351 | }, 1352 | "require": { 1353 | "php": ">=5.3.3" 1354 | }, 1355 | "suggest": { 1356 | "ext-ctype": "For best performance" 1357 | }, 1358 | "type": "library", 1359 | "extra": { 1360 | "thanks": { 1361 | "url": "https://github.com/symfony/polyfill", 1362 | "name": "symfony/polyfill" 1363 | }, 1364 | "branch-alias": { 1365 | "dev-main": "1.19-dev" 1366 | } 1367 | }, 1368 | "autoload": { 1369 | "files": [ 1370 | "bootstrap.php" 1371 | ], 1372 | "psr-4": { 1373 | "Symfony\\Polyfill\\Ctype\\": "" 1374 | } 1375 | }, 1376 | "notification-url": "https://packagist.org/downloads/", 1377 | "license": [ 1378 | "MIT" 1379 | ], 1380 | "authors": [ 1381 | { 1382 | "name": "Gert de Pagter", 1383 | "email": "BackEndTea@gmail.com" 1384 | }, 1385 | { 1386 | "name": "Symfony Community", 1387 | "homepage": "https://symfony.com/contributors" 1388 | } 1389 | ], 1390 | "description": "Symfony polyfill for ctype functions", 1391 | "homepage": "https://symfony.com", 1392 | "keywords": [ 1393 | "compatibility", 1394 | "ctype", 1395 | "polyfill", 1396 | "portable" 1397 | ], 1398 | "support": { 1399 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" 1400 | }, 1401 | "funding": [ 1402 | { 1403 | "url": "https://symfony.com/sponsor", 1404 | "type": "custom" 1405 | }, 1406 | { 1407 | "url": "https://github.com/fabpot", 1408 | "type": "github" 1409 | }, 1410 | { 1411 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1412 | "type": "tidelift" 1413 | } 1414 | ], 1415 | "time": "2020-10-23T09:01:57+00:00" 1416 | }, 1417 | { 1418 | "name": "symfony/yaml", 1419 | "version": "v3.4.47", 1420 | "source": { 1421 | "type": "git", 1422 | "url": "https://github.com/symfony/yaml.git", 1423 | "reference": "88289caa3c166321883f67fe5130188ebbb47094" 1424 | }, 1425 | "dist": { 1426 | "type": "zip", 1427 | "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", 1428 | "reference": "88289caa3c166321883f67fe5130188ebbb47094", 1429 | "shasum": "" 1430 | }, 1431 | "require": { 1432 | "php": "^5.5.9|>=7.0.8", 1433 | "symfony/polyfill-ctype": "~1.8" 1434 | }, 1435 | "conflict": { 1436 | "symfony/console": "<3.4" 1437 | }, 1438 | "require-dev": { 1439 | "symfony/console": "~3.4|~4.0" 1440 | }, 1441 | "suggest": { 1442 | "symfony/console": "For validating YAML files using the lint command" 1443 | }, 1444 | "type": "library", 1445 | "autoload": { 1446 | "psr-4": { 1447 | "Symfony\\Component\\Yaml\\": "" 1448 | }, 1449 | "exclude-from-classmap": [ 1450 | "/Tests/" 1451 | ] 1452 | }, 1453 | "notification-url": "https://packagist.org/downloads/", 1454 | "license": [ 1455 | "MIT" 1456 | ], 1457 | "authors": [ 1458 | { 1459 | "name": "Fabien Potencier", 1460 | "email": "fabien@symfony.com" 1461 | }, 1462 | { 1463 | "name": "Symfony Community", 1464 | "homepage": "https://symfony.com/contributors" 1465 | } 1466 | ], 1467 | "description": "Symfony Yaml Component", 1468 | "homepage": "https://symfony.com", 1469 | "support": { 1470 | "source": "https://github.com/symfony/yaml/tree/v3.4.47" 1471 | }, 1472 | "funding": [ 1473 | { 1474 | "url": "https://symfony.com/sponsor", 1475 | "type": "custom" 1476 | }, 1477 | { 1478 | "url": "https://github.com/fabpot", 1479 | "type": "github" 1480 | }, 1481 | { 1482 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1483 | "type": "tidelift" 1484 | } 1485 | ], 1486 | "time": "2020-10-24T10:57:07+00:00" 1487 | }, 1488 | { 1489 | "name": "webmozart/assert", 1490 | "version": "1.9.1", 1491 | "source": { 1492 | "type": "git", 1493 | "url": "https://github.com/webmozarts/assert.git", 1494 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" 1495 | }, 1496 | "dist": { 1497 | "type": "zip", 1498 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", 1499 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", 1500 | "shasum": "" 1501 | }, 1502 | "require": { 1503 | "php": "^5.3.3 || ^7.0 || ^8.0", 1504 | "symfony/polyfill-ctype": "^1.8" 1505 | }, 1506 | "conflict": { 1507 | "phpstan/phpstan": "<0.12.20", 1508 | "vimeo/psalm": "<3.9.1" 1509 | }, 1510 | "require-dev": { 1511 | "phpunit/phpunit": "^4.8.36 || ^7.5.13" 1512 | }, 1513 | "type": "library", 1514 | "autoload": { 1515 | "psr-4": { 1516 | "Webmozart\\Assert\\": "src/" 1517 | } 1518 | }, 1519 | "notification-url": "https://packagist.org/downloads/", 1520 | "license": [ 1521 | "MIT" 1522 | ], 1523 | "authors": [ 1524 | { 1525 | "name": "Bernhard Schussek", 1526 | "email": "bschussek@gmail.com" 1527 | } 1528 | ], 1529 | "description": "Assertions to validate method input/output with nice error messages.", 1530 | "keywords": [ 1531 | "assert", 1532 | "check", 1533 | "validate" 1534 | ], 1535 | "support": { 1536 | "issues": "https://github.com/webmozarts/assert/issues", 1537 | "source": "https://github.com/webmozarts/assert/tree/1.9.1" 1538 | }, 1539 | "time": "2020-07-08T17:02:28+00:00" 1540 | } 1541 | ], 1542 | "aliases": [], 1543 | "minimum-stability": "stable", 1544 | "stability-flags": [], 1545 | "prefer-stable": false, 1546 | "prefer-lowest": false, 1547 | "platform": { 1548 | "php": ">=5.6" 1549 | }, 1550 | "platform-dev": [], 1551 | "plugin-api-version": "2.6.0" 1552 | } 1553 | -------------------------------------------------------------------------------- /development/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=linux/amd64 composer:1.10.0 AS dev-deps 2 | WORKDIR /app 3 | RUN --mount=type=bind,source=./composer.json,target=composer.json \ 4 | --mount=type=bind,source=./composer.lock,target=composer.lock \ 5 | --mount=type=cache,target=/tmp/cache \ 6 | composer install --no-interaction 7 | 8 | FROM --platform=linux/amd64 php:5.6-apache AS base 9 | RUN docker-php-ext-install pdo pdo_mysql 10 | RUN echo 'alias phpunit="/var/www/html/vendor/bin/phpunit"' >> ~/.bashrc 11 | 12 | COPY ./src /var/www/html 13 | COPY ./development/src /var/www/html 14 | COPY ./phpunit.xml /var/www/html 15 | 16 | FROM base AS development 17 | COPY ./tests /var/www/html/tests 18 | RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" 19 | COPY --from=dev-deps app/vendor/ /var/www/html/vendor -------------------------------------------------------------------------------- /development/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | server: 3 | container_name: php-server 4 | build: 5 | context: .. 6 | dockerfile: ./development/Dockerfile 7 | target: development 8 | ports: 9 | - 9000:80 10 | environment: 11 | - W3W_API_KEY=${W3W_API_KEY} 12 | develop: 13 | watch: 14 | - action: sync 15 | path: ./src 16 | target: /var/www/html 17 | - action: sync 18 | path: ../src 19 | target: /var/www/html 20 | - action: sync 21 | path: ../tests 22 | target: /var/www/html/tests 23 | -------------------------------------------------------------------------------- /development/src/index.php: -------------------------------------------------------------------------------- 1 | convertToCoordinates($what3words); 10 | } 11 | 12 | ?> 13 | 14 | 15 | 16 | 17 | 18 | 19 | what3words 20 | 21 | 51 | 52 | 53 | 54 |
55 | what3words: 56 | 57 |
58 | Nearest Place: ' . $result['nearestPlace'] . ', ' . $result['country'] . ''; 61 | echo '
Coordinates: ' . $result['coordinates']['lat'] . ', ' . $result['coordinates']['lng'] . '
'; 62 | } 63 | if ($what3words && (!$result || !$result['coordinates'])) { 64 | echo '
Error: Invalid what3words
'; 65 | } 66 | ?> 67 | 68 | 69 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Geocoder.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Dave Duprey 8 | * @author Frederick lee 9 | * @copyright 2016, 2017, 2024 what3words Ltd 10 | * @link http://developer.what3words.com 11 | * @license MIT 12 | * @version 3.5.1 13 | * @package What3words\Geocoder 14 | */ 15 | 16 | namespace What3words\Geocoder; 17 | 18 | class Geocoder 19 | { 20 | private $version = "3.5.1"; // if changing this, remember to change the comment block at the top, and match everything with the git tag 21 | private $apiKey = ""; 22 | private $error = []; 23 | private $baseUrl = "https://api.what3words.com/v3/"; 24 | private $wrapper = "what3words-PHP/x.x.x (PHP x.x.x; OS x.x.x)"; 25 | private $referer = null; 26 | private $headers = []; 27 | 28 | // To construct this you need API key. You can get one here: https://accounts.what3words.com/en/register/ 29 | // - parameter apiKey: What3Words api key 30 | // - parameter options: Geocoder options 31 | public function __construct($apiKey, GeocoderOptions $options = null) 32 | { 33 | $this->apiKey = $apiKey; 34 | $this->wrapper = "what3words-PHP/" . $this->version . " (PHP " . phpversion() . "; " . php_uname("s") . " " . php_uname("r") . ")"; 35 | if ($options) { 36 | $this->headers = $options->getHeaders(); 37 | $this->referer = $options->getReferer() ?: $this->referer; 38 | $this->baseUrl = $options->getBaseUrl() ?: $this->baseUrl; 39 | } 40 | } 41 | 42 | 43 | // Call this to see the last error. Errors are indicated when any call return 'false' 44 | public function getError() 45 | { 46 | return $this->error; 47 | } 48 | 49 | // Returns a three word address from a latitude and longitude 50 | // - parameters latitude, longitude: coordinates of the place in question 51 | // - parameter language: A supported 3 word address language as an ISO 639-1 2 letter code. Defaults to en 52 | // - parameter format: Return data format type; can be one of json (the default) or geojson 53 | public function convertTo3wa($latitude, $longitude, $language = "en", $format = "json") 54 | { 55 | return $this->performRequest("convert-to-3wa", ["coordinates" => "$latitude,$longitude", "language" => $language, "format" => $format]); 56 | } 57 | 58 | // Convert a 3 word address to a latitude and longitude. 59 | // - parameter words: A 3 word address as a string 60 | // - parameter format: Return data format type; can be one of json (the default) or geojson 61 | public function convertToCoordinates($words, $format = "json") 62 | { 63 | return $this->performRequest("convert-to-coordinates", ["words" => $words, "format" => $format]); 64 | } 65 | 66 | // Returns a section of the 3m x 3m what3words grid for a given area. 67 | // - parameters south_lat, west_lng, north_lat, east_lng, for which the grid should be returned. The requested box must not exceed 4km from corner to corner, or a BadBoundingBoxTooBig error will be returned. Latitudes must be >= -90 and <= 90, but longitudes are allowed to wrap around 180. To specify a bounding-box that crosses the anti-meridian, use longitude greater than 180. Example value: "50.0,179.995,50.01,180.0005" . 68 | // - parameter format: Return data format type; can be one of json (the default) or geojson Example value:format=Format.json 69 | public function gridSection($south_lat, $west_lng, $north_lat, $east_lng, $format = "json") 70 | { 71 | return $this->performRequest("grid-section", ["bounding-box" => "$south_lat,$west_lng,$north_lat,$east_lng", "format" => $format]); 72 | } 73 | 74 | // Retrieves a list all available 3 word address languages, including the ISO 639-1 2 letter code, english name and native name. 75 | public function availableLanguages() 76 | { 77 | return $this->performRequest("available-languages", []); 78 | } 79 | 80 | // AutoSuggest can take a slightly incorrect 3 word address, and suggest a list of valid 3 word addresses. 81 | // - parameter input: The full or partial 3 word address to obtain suggestions for. At minimum this must be the first two complete words plus at least one character from the third word. 82 | // - options are taken as an array of arrays, each subarray made using the static helper functions in AutoSuggestOption. Eg: 83 | // - autosuggest(input: "filled.count.soap", options: [AutoSuggestOption::fallback_language("de"), AutoSuggestOption::clip_to_country("GB") ]); 84 | // 85 | // - option AutoSuggestOption::number_results(): The number of AutoSuggest results to return. A maximum of 100 results can be specified, if a number greater than this is requested, this will be truncated to the maximum. The default is 3 86 | // - option AutoSuggestOption::focus(): This is a location, specified as a latitude (often where the user making the query is). If specified, the results will be weighted to give preference to those near the focus. For convenience, longitude is allowed to wrap around the 180 line, so 361 is equivalent to 1. 87 | // - option AutoSuggestOption::number_focus_results(): Specifies the number of results (must be <= n-results) within the results set which will have a focus. Defaults to n-results. This allows you to run autosuggest with a mix of focussed and unfocussed results, to give you a "blend" of the two. This is exactly what the old V2 standarblend did, and standardblend behaviour can easily be replicated by passing n-focus-results=1, which will return just one focussed result and the rest unfocussed. 88 | // - option AutoSuggestOption::bounding_country(): Restricts autosuggest to only return results inside the countries specified by comma-separated list of uppercase ISO 3166-1 alpha-2 country codes (for example, to restrict to Belgium and the UK, use clip-to-country=GB,BE). Clip-to-country will also accept lowercase country codes. Entries must be two a-z letters. WARNING: If the two-letter code does not correspond to a country, there is no error: API simply returns no results. eg: "NZ,AU" 89 | // - option AutoSuggestOption::bounding_box(south_lat:Double, west_lng:Double, north_lat: Double, east_lng:Double): Restrict autosuggest results to a bounding box, specified by coordinates. Such as south_lat,west_lng,north_lat,east_lng, where: south_lat <= north_lat west_lng <= east_lng In other words, latitudes and longitudes should be specified order of increasing size. Lng is allowed to wrap, so that you can specify bounding boxes which cross the ante-meridian: -4,178.2,22,195.4 Example value: "51.521,-0.343,52.6,2.3324" 90 | // - option AutoSuggestOption::bounding_circle(lat:Double, lng:Double, kilometres:Double): Restrict autosuggest results to a circle, specified by lat,lng,kilometres. For convenience, longitude is allowed to wrap around 180 degrees. For example 181 is equivalent to -179. Example value: "51.521,-0.343,142" 91 | // - option AutoSuggestOption::bounding_polygon(array(lat,lng, lat,lng, ...)): Restrict autosuggest results to a polygon, specified by a comma-separated list of lat,lng pairs. The polygon should be closed, i.e. the first element should be repeated as the last element; also the list should contain at least 4 entries. The API is currently limited to accepting up to 25 pairs. Example value: "51.521,-0.343,52.6,2.3324,54.234,8.343,51.521,-0.343" 92 | // - option AutoSuggestOption::input_type(): For power users, used to specify voice input mode. Can be text (default), vocon-hybrid, nmdp-asr or generic-voice. See voice recognition section for more details. 93 | // - option AutoSuggestOption::fallback_language(): For normal text input, specifies a fallback language, which will help guide AutoSuggest if the input is particularly messy. If specified, this parameter must be a supported 3 word address language as an ISO 639-1 2 letter code. For voice input (see voice section), language must always be specified. 94 | public function autosuggest($input, $options = []) 95 | { 96 | $parameters = ["input" => $input]; 97 | 98 | foreach ($options as $option) { 99 | $parameters = array_merge($parameters, $option); 100 | } 101 | 102 | return $this->performRequest("autosuggest", $parameters); 103 | } 104 | 105 | // Determines if the string passed in is the form of a three word address. 106 | // This does not validate whether it is a real address as it returns 1 for x.x.x 107 | public function isPossible3wa($input) 108 | { 109 | $regex = "/^\/*(?:[^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+|'<,.>?\/\";:£§º©®\s]+[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+|[^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+([\x{0020}\x{00A0}][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+){1,3}[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+([\x{0020}\x{00A0}][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+){1,3}[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+([\x{0020}\x{00A0}][^0-9`~!@#$%^&*()+\-_=[{\]}\\|'<,.>?\/\";:£§º©®\s]+){1,3})$/"; 110 | return preg_match($regex, $input); 111 | } 112 | 113 | // Searches the string passed in for all substrings in the form of a three word address. 114 | // This does not validate whether it is a real address as it will return Array([0] => x.x.x) as a result 115 | public function findPossible3wa($input) 116 | { 117 | $regex = "/[^0-9`~!@#$%^&*()+\-_=[{\]}\|'<,.>?\/\";:£§º©®\s]+[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\|'<,.>?\/\";:£§º©®\s]+[.。。・・︒។։။۔።।][^0-9`~!@#$%^&*()+\-_=[{\]}\|'<,.>?\/\";:£§º©®\s]+/"; 118 | preg_match_all($regex, $input, $matches); 119 | if (count($matches) === 1) { 120 | return $matches[0]; 121 | } 122 | return []; 123 | } 124 | 125 | // Determines if the string passed in is a real three word address. 126 | // It calls the API to verify it refers to an actual place on earth. 127 | // Returns 1 if valid, 0 if not 128 | public function isValid3wa($input) 129 | { 130 | switch ($this->isPossible3wa($input)) { 131 | case 1: 132 | $result = $this->autosuggest($input, [AutoSuggestOption::numberResults(1)]); 133 | if (count($result["suggestions"]) == 1 && $result["suggestions"][0]["words"] == $input) { 134 | return 1; 135 | } 136 | break; 137 | default: 138 | return 0; 139 | } 140 | } 141 | 142 | //////////////////////////////////////////////////////////////// 143 | 144 | // Prepare the call to the API server 145 | private function performRequest($command, $parameters) 146 | { 147 | // make an array out of the dictionary so that each element is a key value pair glued together with an '=', and urlencode the parameters 148 | $param_array = []; 149 | foreach ($parameters as $key => $value) { 150 | $param_array[] = "$key=" . urlencode($value); 151 | } 152 | 153 | // glue the array together unto a string with elements connected with '&' 154 | $params = implode("&", $param_array); 155 | 156 | // put the whole URL together now 157 | $url = "{$this->baseUrl}{$command}?{$params}"; 158 | 159 | // call the server 160 | $data = $this->call($url); 161 | if (isset($data["error"])) { 162 | $this->error["code"] = $data["error"]["code"]; 163 | $this->error["message"] = $data["error"]["message"]; 164 | $data = false; 165 | } 166 | 167 | return $data; 168 | } 169 | 170 | 171 | // Make the call to the API server 172 | private function call($url) 173 | { 174 | $handle = curl_init(); 175 | 176 | $headers = array_merge(["X-W3W-Wrapper: {$this->wrapper}", "X-API-Key: {$this->apiKey}"], $this->headers); 177 | // set the options 178 | curl_setopt($handle, CURLOPT_URL, $url); 179 | curl_setopt($handle, CURLOPT_HTTPHEADER, $headers); 180 | curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); 181 | curl_setopt($handle, CURLOPT_ENCODING, ""); 182 | curl_setopt($handle, CURLOPT_MAXREDIRS, 10); 183 | curl_setopt($handle, CURLOPT_TIMEOUT, 30); 184 | if (defined('CURL_HTTP_VERSION_2_0')) { 185 | curl_setopt($handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); 186 | } else { 187 | curl_setopt($handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 188 | } 189 | curl_setopt($handle, CURLOPT_CUSTOMREQUEST, "GET"); 190 | if (!empty($this->referer)) { 191 | curl_setopt($handle, CURLOPT_REFERER, $this->referer); 192 | } 193 | // make the call 194 | $output = curl_exec($handle); 195 | if (!$output) { 196 | $this->error["code"] = "BadConnection"; 197 | $this->error["message"] = curl_error($handle); 198 | } 199 | curl_close($handle); 200 | $json = json_decode($output, true); 201 | return $json ?: false; 202 | } 203 | } 204 | 205 | class GeocoderOptions 206 | { 207 | private static $instance = null; 208 | private $baseUrl = null; 209 | private $referer = null; 210 | private $headers = []; 211 | 212 | private function __construct() 213 | { 214 | } 215 | private static function getInstance() 216 | { 217 | if (self::$instance === null) { 218 | self::$instance = new self(); 219 | } 220 | return self::$instance; 221 | } 222 | public static function host($host) 223 | { 224 | $instance = self::getInstance(); 225 | $instance->host = $host; 226 | return $instance; 227 | } 228 | public static function referer($referer) 229 | { 230 | $instance = self::getInstance(); 231 | $instance->referer = $referer; 232 | return $instance; 233 | } 234 | public static function headers(array $headers) 235 | { 236 | $instance = self::getInstance(); 237 | $instance->headers = $headers; 238 | return $instance; 239 | } 240 | public function getBaseUrl() 241 | { 242 | return $this->baseUrl; 243 | } 244 | public function getReferer() 245 | { 246 | return $this->referer; 247 | } 248 | public function getHeaders() 249 | { 250 | return $this->headers; 251 | } 252 | } 253 | 254 | // These are static helper functions that creates options (as array) to be passed into autosuggest 255 | class AutoSuggestOption 256 | { 257 | public static function fallbackLanguage($language) 258 | { 259 | return ["language" => $language]; 260 | } 261 | 262 | public static function numberResults($number_of_results) 263 | { 264 | return ["n-results" => $number_of_results]; 265 | } 266 | 267 | public static function focus($latitude, $longitude) 268 | { 269 | return ["focus" => "$latitude,$longitude"]; 270 | } 271 | 272 | public static function numberFocusResults($number_focus_results) 273 | { 274 | return ["n-focus-results" => $number_focus_results]; 275 | } 276 | 277 | public static function inputType($input_type) 278 | { 279 | return ["input-type" => $input_type]; 280 | } 281 | 282 | public static function preferLand($land) 283 | { 284 | if ($land) { 285 | return ["prefer-land" => "true"]; 286 | } else { 287 | return ["prefer-land" => "false"]; 288 | } 289 | } 290 | 291 | public static function clipToCountry($country) 292 | { 293 | return ["clip-to-country" => $country]; 294 | } 295 | 296 | public static function clipToCircle($latitude, $longitude, $radius) 297 | { 298 | return ["clip-to-circle" => "$latitude,$longitude,$radius"]; 299 | } 300 | 301 | public static function clipToBoundingBox($south_lat, $west_lng, $north_lat, $east_lng) 302 | { 303 | return ["clip-to-bounding-box" => "$south_lat,$west_lng,$north_lat,$east_lng"]; 304 | } 305 | 306 | public static function clipToPolygon($points = []) 307 | { 308 | return ["clip-to-polygon" => implode(",", $points)]; 309 | } 310 | 311 | } 312 | 313 | 314 | -------------------------------------------------------------------------------- /tests/GeocoderTest.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2016, 2017 what3words Ltd 8 | * @link http://developer.what3words.com 9 | * @license MIT 10 | * @version 3.5.1 11 | * @package What3words\Geocoder\Test 12 | */ 13 | 14 | namespace What3words\Geocoder\Test; 15 | 16 | require_once "./Geocoder.php"; 17 | 18 | use What3words\Geocoder\Geocoder; 19 | use What3words\Geocoder\AutoSuggestOption; 20 | use PHPUnit\Framework\TestCase; 21 | 22 | class GeocoderTest extends TestCase 23 | { 24 | protected $geocoder; 25 | 26 | protected function setUp() 27 | { 28 | $this->geocoder = new Geocoder(getenv('W3W_API_KEY')); 29 | } 30 | 31 | public function testBuildGeocoder() 32 | { 33 | $this->assertObjectHasAttribute('apiKey', $this->geocoder); 34 | } 35 | 36 | public function testInvalidKey() 37 | { 38 | $geocoder = new Geocoder("BADKEY"); 39 | 40 | $geocoder->convertToCoordinates("index.home.raft"); 41 | $error = $geocoder->getError(); 42 | 43 | $this->assertEquals("InvalidKey", $error["code"]); 44 | } 45 | 46 | public function testConvertToCoordinates() 47 | { 48 | $result = $this->geocoder->convertToCoordinates('index.home.raft'); 49 | $this->assertEquals(51.521251, $result["coordinates"]["lat"]); 50 | } 51 | 52 | 53 | public function testConvertTo3wa() 54 | { 55 | $result = $this->geocoder->convertTo3wa(51.521251, -0.203586); 56 | $this->assertEquals("index.home.raft", $result["words"]); 57 | } 58 | 59 | public function testGrid() 60 | { 61 | $result = $this->geocoder->gridSection(39.903795, 116.384550, 39.902718, 116.383122); 62 | $this->assertEquals(80, count($result["lines"])); 63 | } 64 | 65 | public function testLanguages() 66 | { 67 | $result = $this->geocoder->availableLanguages(); 68 | $this->assertTrue(count($result["languages"]) > 1); 69 | } 70 | 71 | 72 | public function testAutosuggest() 73 | { 74 | $result = $this->geocoder->autosuggest('index.home.raft'); 75 | $this->assertEquals("index.home.raft", $result["suggestions"][0]["words"]); 76 | } 77 | 78 | public function testAutosuggestNonEnglish() 79 | { 80 | $result = $this->geocoder->autosuggest("有些.明.火"); 81 | $this->assertEquals("有些.驰名.护耳", $result["suggestions"][0]["words"]); 82 | } 83 | 84 | public function testAutosuggestBoundingBox() 85 | { 86 | $result = $this->geocoder->autosuggest('geschaft.planter.carciofi', [AutoSuggestOption::clipToBoundingBox(51.521, -0.343, 52.6, 2.3324)]); 87 | $this->assertEquals("restate.piante.carciofo", $result["suggestions"][0]["words"]); 88 | } 89 | 90 | 91 | public function testAutosuggestFocus() 92 | { 93 | $result = $this->geocoder->autosuggest("geschaft.planter.carciofi", [AutoSuggestOption::focus(51.4243877, -0.34745)]); 94 | $this->assertEquals("restate.piante.carciofo", $result["suggestions"][0]["words"]); 95 | } 96 | 97 | 98 | public function testAutosuggestCountry() 99 | { 100 | $result = $this->geocoder->autosuggest("oui.oui.oui", [AutoSuggestOption::clipToCountry("fr")]); 101 | $this->assertEquals("oust.souk.souk", $result["suggestions"][0]["words"]); 102 | } 103 | 104 | 105 | public function testAutosuggestCircle() 106 | { 107 | $result = $this->geocoder->autosuggest("mitiger.tarir.prolong", [AutoSuggestOption::clipToCircle(51.521238, -0.203607, 1.0)]); 108 | $this->assertEquals("mitiger.tarir.prolonger", $result["suggestions"][0]["words"]); 109 | } 110 | 111 | public function testAutosuggestPolygon() 112 | { 113 | $result = $this->geocoder->autosuggest("scenes.irritated.sparkle", [AutoSuggestOption::clipToPolygon([51.0, 0.0, 51.0, 0.1, 51.1, 0.1, 51.1, 0.0, 51.0, 0.0])]); 114 | $this->assertEquals("scenes.irritated.sparkles", $result["suggestions"][0]["words"]); 115 | } 116 | 117 | public function testAutosuggestFallBackLanguage() 118 | { 119 | $result = $this->geocoder->autosuggest("aaa.aaa.aaa", [AutoSuggestOption::fallbackLanguage("de")]); 120 | $this->assertEquals("saal.saal.saal", $result["suggestions"][0]["words"]); 121 | } 122 | 123 | 124 | public function testAutosuggestNumberFocusResults() 125 | { 126 | $result = $this->geocoder->autosuggest("geschaft.planter.carciofi", [AutoSuggestOption::focus(51.4243877, -0.34745), AutoSuggestOption::numberFocusResults(2)]); 127 | $this->assertTrue($result["suggestions"][0]["distanceToFocusKm"] < 100); 128 | $this->assertTrue($result["suggestions"][2]["distanceToFocusKm"] > 100); 129 | } 130 | 131 | 132 | public function testAutosuggestNumberResults() 133 | { 134 | $result = $this->geocoder->autosuggest("fun.with.code", [AutoSuggestOption::numberResults(10)]); 135 | $this->assertEquals(10, count($result["suggestions"])); 136 | } 137 | 138 | public function testAutosuggestVoice() 139 | { 140 | $result = $this->geocoder->autosuggest('{"_isInGrammar":"yes","_isSpeech":"yes","_hypotheses":[{"_score":342516,"_startRule":"whatthreewordsgrammar#_main_","_conf":6546,"_endTimeMs":6360,"_beginTimeMs":1570,"_lmScore":300,"_items":[{"_type":"terminal","_score":34225,"_orthography":"tend","_conf":6964,"_endTimeMs":2250,"_beginTimeMs":1580},{"_type":"terminal","_score":47670,"_orthography":"artichokes","_conf":7176,"_endTimeMs":3180,"_beginTimeMs":2260},{"_type":"terminal","_score":43800,"_orthography":"poached","_conf":6181,"_endTimeMs":4060,"_beginTimeMs":3220}]},{"_score":342631,"_startRule":"whatthreewordsgrammar#_main_","_conf":6498,"_endTimeMs":6360,"_beginTimeMs":1570,"_lmScore":300,"_items":[{"_type":"terminal","_score":34340,"_orthography":"tent","_conf":6772,"_endTimeMs":2250,"_beginTimeMs":1580},{"_type":"terminal","_score":47670,"_orthography":"artichokes","_conf":7176,"_endTimeMs":3180,"_beginTimeMs":2260},{"_type":"terminal","_score":43800,"_orthography":"poached","_conf":6181,"_endTimeMs":4060,"_beginTimeMs":3220}]},{"_score":342668,"_startRule":"whatthreewordsgrammar#_main_","_conf":6474,"_endTimeMs":6360,"_beginTimeMs":1570,"_lmScore":300,"_items":[{"_type":"terminal","_score":34225,"_orthography":"tend","_conf":6964,"_endTimeMs":2250,"_beginTimeMs":1580},{"_type":"terminal","_score":47670,"_orthography":"artichokes","_conf":7176,"_endTimeMs":3180,"_beginTimeMs":2260},{"_type":"terminal","_score":41696,"_orthography":"perch","_conf":5950,"_endTimeMs":4020,"_beginTimeMs":3220}]},{"_score":342670,"_startRule":"whatthreewordsgrammar#_main_","_conf":6474,"_endTimeMs":6360,"_beginTimeMs":1570,"_lmScore":300,"_items":[{"_type":"terminal","_score":34379,"_orthography":"tinge","_conf":6705,"_endTimeMs":2250,"_beginTimeMs":1580},{"_type":"terminal","_score":47670,"_orthography":"artichokes","_conf":7176,"_endTimeMs":3180,"_beginTimeMs":2260},{"_type":"terminal","_score":43800,"_orthography":"poached","_conf":6181,"_endTimeMs":4060,"_beginTimeMs":3220}]},{"_score":342783,"_startRule":"whatthreewordsgrammar#_main_","_conf":6426,"_endTimeMs":6360,"_beginTimeMs":1570,"_lmScore":300,"_items":[{"_type":"terminal","_score":34340,"_orthography":"tent","_conf":6772,"_endTimeMs":2250,"_beginTimeMs":1580},{"_type":"terminal","_score":47670,"_orthography":"artichokes","_conf":7176,"_endTimeMs":3180,"_beginTimeMs":2260},{"_type":"terminal","_score":41696,"_orthography":"perch","_conf":5950,"_endTimeMs":4020,"_beginTimeMs":3220}]},{"_score":342822,"_startRule":"whatthreewordsgrammar#_main_","_conf":6402,"_endTimeMs":6360,"_beginTimeMs":1570,"_lmScore":300,"_items":[{"_type":"terminal","_score":34379,"_orthography":"tinge","_conf":6705,"_endTimeMs":2250,"_beginTimeMs":1580},{"_type":"terminal","_score":47670,"_orthography":"artichokes","_conf":7176,"_endTimeMs":3180,"_beginTimeMs":2260},{"_type":"terminal","_score":41696,"_orthography":"perch","_conf":5950,"_endTimeMs":4020,"_beginTimeMs":3220}]}],"_resultType":"NBest"}', [AutoSuggestOption::inputType("vocon-hybrid"), AutoSuggestOption::fallbackLanguage("en")]); 141 | $this->assertEquals("tend.artichokes.perch", $result["suggestions"][0]["words"]); 142 | } 143 | 144 | public function testAutosuggestGenericVoice() 145 | { 146 | $result = $this->geocoder->autosuggest("filled count soap", [AutoSuggestOption::inputType("generic-voice"), AutoSuggestOption::fallbackLanguage("en")]); 147 | $this->assertEquals("filled.count.soap", $result["suggestions"][0]["words"]); 148 | } 149 | 150 | 151 | public function testAutosuggestPreferLand() 152 | { 153 | $options = [AutoSuggestOption::inputType("generic-voice"), AutoSuggestOption::fallbackLanguage("en"), AutoSuggestOption::preferLand(false)]; 154 | $result = $this->geocoder->autosuggest("bisect.nourishment.genuineness", $options); 155 | $this->assertEquals('SD', $result["suggestions"][2]["country"]); 156 | } 157 | 158 | public function testAutosuggestIsPossible3wa() 159 | { 160 | $this->assertEquals(1, $this->geocoder->isPossible3wa("filled.count.soap")); 161 | $this->assertEquals(0, $this->geocoder->isPossible3wa("not a 3wa")); 162 | $this->assertEquals(0, $this->geocoder->isPossible3wa("not.3wa address")); 163 | } 164 | 165 | public function testAutosuggestFindPossible3wa() 166 | { 167 | $result = $this->geocoder->findPossible3wa('from "index.home.raft" to " "filled.count.soap"'); 168 | $this->assertEquals(2, count($result)); 169 | } 170 | 171 | public function testAutosuggestIsValid3wa() 172 | { 173 | $this->assertEquals(1, $this->geocoder->isValid3wa('filled.count.soap')); 174 | } 175 | 176 | 177 | 178 | 179 | } 180 | 181 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2016, 2017 what3words Ltd 8 | * @link http://developer.what3words.com 9 | * @license MIT 10 | * @version 2.2.0 11 | * @package What3words\Geocoder 12 | */ 13 | 14 | require __DIR__ . '/../vendor/autoload.php'; 15 | 16 | define('API_KEY', getenv('W3W_API_KEY')); 17 | 18 | ?> 19 | --------------------------------------------------------------------------------