├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGES.txt ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── Vagrantfile ├── composer.json ├── composer.lock ├── demo └── geocode.php ├── opencage_logo_300_150.png ├── phpcs.xml ├── phpunit.xml ├── src ├── AbstractGeocoder.php └── Geocoder.php └── tests ├── GeocoderTest.php └── bootstrap.php /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '15 22 2 * *' 8 | 9 | env: 10 | OPENCAGE_API_KEY: ${{ secrets.GEO_CODER_OPENCAGE_API_KEY }} 11 | 12 | jobs: 13 | test: 14 | strategy: 15 | matrix: 16 | # https://www.php.net/supported-versions.php 17 | php-version: ['8.2', '8.3', '8.4'] 18 | 19 | name: PHP OpenCage Geocode 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - name: Checkout repository 25 | uses: actions/checkout@v4 26 | 27 | - name: Set up PHP ${{ matrix.php-version }} 28 | uses: shivammathur/setup-php@v2 29 | with: 30 | php-version: ${{ matrix.php-version }} 31 | coverage: none 32 | 33 | - name: Install dependencies 34 | run: composer install --no-progress --no-suggest --no-interaction 35 | 36 | - name: Run tests 37 | run: | 38 | composer validate 39 | ./vendor/bin/phpunit 40 | SKIP_CURL=1 ./vendor/bin/phpunit 41 | 42 | - name: Run proxy tests 43 | run: | 44 | docker run -d --name=tinyproxy -p 8888:8888 monokal/tinyproxy:latest ANY 45 | PROXY=http://0.0.0.0:8888 ./vendor/bin/phpunit 46 | docker rm -f tinyproxy 47 | 48 | - name: Run Linter 49 | run: ./vendor/bin/phpcs . 50 | 51 | - name: Run PHPStan 52 | run: ./vendor/bin/phpstan analyse --level 5 src tests demo 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | vendor 3 | .phpunit.* -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | 3.3.1 -- Thu Nov 21 2024 2 | ===================================================== 3 | - add testing against PHP 8.4 4 | 5 | 3.3.0 -- Mon Mar 11 2024 6 | ===================================================== 7 | - add an HTTP header: User-Agent 8 | 9 | 3.2.2 -- Mon Feb 26 2024 10 | ===================================================== 11 | - add setProxy method 12 | 13 | 3.2.1 -- Fri Jan 26 2024 14 | ===================================================== 15 | - add testing against PHP 8.3 16 | - add PHPStan linting 17 | 18 | 3.2.0 -- Wed Jul 26 2023 19 | ===================================================== 20 | - requires PHP >= 8.0, PHP 7.4 no longer supported 21 | - add testing against PHP 8.2 22 | 23 | 3.1.1 -- Wed Dec 22 2021 24 | ===================================================== 25 | - add testing against PHP 8.1 26 | 27 | 3.1.0 -- Wed Sep 15 2021 28 | ===================================================== 29 | - Error response when curl encounters a network issue (e.g. DNS, old TLS cipher). Before it 30 | would silently fail. 31 | - Use test API keys in test suite for HTTP 200 and 402 responses 32 | 33 | 3.0.0 -- Thu Jan 28 2021 34 | ===================================================== 35 | - deprecate PHP 5.6, added PHP 8 36 | 37 | 2.1.0 -- Thu May 9 2019 38 | ===================================================== 39 | - file_get_contents printed errors and returned false. Instead those are 40 | caughed now and an empty valid JSON document with the error code is 41 | returned. file_get_contents is only used when the curl fetching doesn't 42 | work (rare) 43 | 44 | 2.0.3 -- Sat Apr 27 2019 45 | ===================================================== 46 | - API returns HTTP 401 for invalid key 47 | - add Vagrant setup for testing 48 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Using docker 2 | # 3 | # ```bash 4 | # docker build -t local/opencage-php . 5 | # 6 | # docker run -ti -v `pwd`:/usr/src/myapp local/opencage-php 7 | # 8 | # app@ee88ad785ca2:/usr/src/myapp$ composer install 9 | # app@ee88ad785ca2:/usr/src/myapp$ ./vendor/bin/phpunit 10 | # app@ee88ad785ca2:/usr/src/myapp$ SKIP_CURL=1 ./vendor/bin/phpunit 11 | # app@ee88ad785ca2:/usr/src/myapp$ ./vendor/bin/phpcs . 12 | # app@ee88ad785ca2:/usr/src/myapp$ ./vendor/bin/phpstan analyse --level 5 src tests demo 13 | # ``` 14 | 15 | FROM ubuntu:22.04 16 | 17 | ENV TZ=Europe/London 18 | 19 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 20 | 21 | RUN apt-get update -qq && \ 22 | apt-get install -y -qq curl vim php-cli php-curl php-xml php-mbstring unzip 23 | 24 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 25 | 26 | RUN useradd --user-group --system --create-home --no-log-init app 27 | 28 | COPY . /usr/src/myapp 29 | WORKDIR /usr/src/myapp 30 | 31 | RUN chown -R app:app /usr/src/myapp 32 | 33 | USER app 34 | 35 | VOLUME [ "/usr/src/myapp" ] 36 | 37 | CMD ["/bin/bash"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 OpenCage GmbH (https://opencagedata.com) 2 | Copyright (c) 2015 OpenCageData (https://opencagedata.com) 3 | Copyright (c) 2014 Lokku Limited (http://lokku.com/) 4 | Copyright (c) 2014 Gary Gale (http://www/garygale.com/) 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | 2. Redistributions in binary form must reproduce the above copyright notice, this 15 | list of conditions and the following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 27 | OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCage Geocoding API Library for PHP 2 | 3 | A [PHP](http://php.net/) library to use the [OpenCage geocoding API](https://opencagedata.com/api). 4 | 5 | ## Build Status / Code Quality 6 | 7 | [![Build Status](https://github.com/OpenCageData/php-opencage-geocode/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenCageData/php-opencage-geocode/actions/workflows/ci.yml) 8 | [![PHP version](https://badge.fury.io/ph/opencage%2Fgeocode.svg)](https://badge.fury.io/ph/opencage%2Fgeocode) 9 | ![Mastodon Follow](https://img.shields.io/mastodon/follow/109287663468501769?domain=https%3A%2F%2Fen.osm.town%2F&style=social) 10 | 11 | ## Overview 12 | This library attempts to use the [CURL](http://www.php.net/manual/en/book.curl.php) 13 | extension to access the OpenCage Geocoding API. If CURL support is not available, the 14 | library falls back to using [fopen wrappers](http://uk3.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen). 15 | 16 | To use the library you must either have the CURL extension compiled into your version 17 | of PHP. Alternatively configure the use of fopen wrappers via the `allow_url_fopen` 18 | directive in your `php.ini`. 19 | 20 | ### Authentication 21 | 22 | You need an API key, which you can sign up for [here](https://opencagedata.com). 23 | 24 | ### Tutorial 25 | 26 | You can find [a comprehensive tutorial for using this module on the OpenCage site](https://opencagedata.com/tutorials/geocode-in-php). 27 | 28 | ## Installation 29 | 30 | ### With Composer 31 | 32 | The recommended - and easiest way - to install is via [Composer](https://getcomposer.org/). 33 | Require the library in your project's `composer.json` file. 34 | 35 | ```php 36 | $ composer require opencage/geocode 37 | ``` 38 | 39 | Import the Geocoder class. 40 | 41 | ```php 42 | require "vendor/autoload.php"; 43 | ``` 44 | 45 | ### The old fashioned way 46 | 47 | See the file `demo/geocode.php` 48 | 49 | 50 | ## Geocoding 51 | 52 | ```php 53 | $geocoder = new \OpenCage\Geocoder\Geocoder('YOUR-API-KEY'); 54 | $result = $geocoder->geocode('82 Clerkenwell Road, London'); 55 | print_r($result); 56 | ``` 57 | 58 | ### Reverse geocoding 59 | 60 | ```php 61 | $geocoder = new \OpenCage\Geocoder\Geocoder('YOUR-API-KEY'); 62 | $result = $geocoder->geocode('43.831,4.360'); # latitude,longitude (y,x) 63 | print $result['results'][0]['formatted']; 64 | // 3 Rue de Rivarol, 30020 Nîmes, France 65 | ``` 66 | 67 | ### Set optional parameters 68 | 69 | See the full list at: 70 | [https://opencagedata.com/api#optional-params](https://opencagedata.com/api#optional-params) 71 | 72 | ```php 73 | $result = $geocoder->geocode('6 Rue Massillon, 30020 Nîmes, France', [ 74 | 'language' => 'fr', 75 | 'countrycode' => 'fr' 76 | ]); 77 | if ($result && $result['total_results'] > 0) { 78 | $first = $result['results'][0]; 79 | print $first['geometry']['lng'] . ';' . $first['geometry']['lat'] . ';' . $first['formatted'] . "\n"; 80 | // 4.360081;43.8316276;6 Rue Massillon, 30020 Nîmes, Frankreich 81 | } 82 | ``` 83 | 84 | ### Set a proxy URL 85 | 86 | ```php 87 | $geocoder->setProxy('http://proxy.example.com:1234'); 88 | $result = $geocoder->geocode("Brandenburger Tor, Berlin"); 89 | print_r($result['results'][0]['formatted']); 90 | // Brandenburger Tor, Unter den Linden, 10117 Berlin, Germany 91 | print_r($result['results'][0]['geometry']); 92 | // Array 93 | // ( 94 | // [lat] => 52.5166047 95 | // [lng] => 13.3809897 96 | // ) 97 | ``` 98 | 99 | ## Example results 100 | 101 | 102 | ```php 103 | Array 104 | ( 105 | [total_results] => 2 106 | [status] => Array 107 | ( 108 | [message] => OK 109 | [code] => 200 110 | ) 111 | [results] => Array 112 | ( 113 | [0] => Array 114 | ( 115 | [annotations] => Array 116 | ( 117 | [DMS] => Array 118 | ( 119 | [lat] => 51° 31' 21.60894'' N 120 | [lng] => 0° 6' 8.95198'' E 121 | ) 122 | 123 | [MGRS] => 30UYC0100511930 124 | [Maidenhead] => IO91wm75qk 125 | [Mercator] => Array 126 | ( 127 | [x] => -11408.763 128 | [y] => 6680801.955 129 | ) 130 | 131 | [OSGB] => Array 132 | ( 133 | [easting] => 531628.199 134 | [gridref] => TQ 316 821 135 | [northing] => 182177.015 136 | ) 137 | 138 | [OSM] => Array 139 | ( 140 | [url] => http://www.openstreetmap.org/?mlat=51.52267&mlon=-0.10249#map=17/51.52267/-0.10249 141 | ) 142 | 143 | [callingcode] => 44 144 | [geohash] => gcpvjemm7csmhczg9cvt 145 | [sun] => Array 146 | ( 147 | [rise] => Array 148 | ( 149 | [apparent] => 1452931140 150 | [astronomical] => 1452923940 151 | [civil] => 1452928800 152 | [nautical] => 1452926280 153 | ) 154 | 155 | [set] => Array 156 | ( 157 | [apparent] => 1452961320 158 | [astronomical] => 1452968520 159 | [civil] => 1452963660 160 | [nautical] => 1452966120 161 | ) 162 | 163 | ) 164 | 165 | [timezone] => Array 166 | ( 167 | [name] => Europe/London 168 | [now_in_dst] => 0 169 | [offset_sec] => 0 170 | [offset_string] => 0 171 | [short_name] => GMT 172 | ) 173 | 174 | [what3words] => Array 175 | ( 176 | [words] => gallons.trim.tips 177 | ) 178 | 179 | ) 180 | 181 | [bounds] => Array 182 | ( 183 | [northeast] => Array 184 | ( 185 | [lat] => 51.5227563 186 | [lng] => -0.1023801 187 | ) 188 | 189 | [southwest] => Array 190 | ( 191 | [lat] => 51.5226042 192 | [lng] => -0.1025907 193 | ) 194 | 195 | ) 196 | 197 | [components] => Array 198 | ( 199 | [city] => London 200 | [country] => United Kingdom 201 | [country_code] => gb 202 | [house_number] => 82 203 | [postcode] => EC1M 5RF 204 | [road] => Clerkenwell Road 205 | [state] => England 206 | [state_district] => Greater London 207 | [suburb] => Clerkenwell 208 | ) 209 | 210 | [confidence] => 10 211 | [formatted] => 82 Clerkenwell Road, London EC1M 5RF, United Kingdom 212 | [geometry] => Array 213 | ( 214 | [lat] => 51.52266915 215 | [lng] => -0.10248666188363 216 | ) 217 | 218 | ) 219 | 220 | [1] => Array 221 | ( 222 | [annotations] => Array 223 | ( 224 | [DMS] => Array 225 | ( 226 | [lat] => 51° 30' 30.70800'' N 227 | [lng] => 0° 7' 32.66400'' E 228 | ) 229 | 230 | [MGRS] => 30UXC9945410295 231 | [Maidenhead] => IO91wm42vb 232 | [Mercator] => Array 233 | ( 234 | [x] => -13997.313 235 | [y] => 6678279.278 236 | ) 237 | 238 | [OSGB] => Array 239 | ( 240 | [easting] => 530055.544 241 | [gridref] => TQ 300 805 242 | [northing] => 180563.298 243 | ) 244 | 245 | [OSM] => Array 246 | ( 247 | [url] => http://www.openstreetmap.org/?mlat=51.50853&mlon=-0.12574#map=17/51.50853/-0.12574 248 | ) 249 | 250 | [geohash] => gcpvj0u6yjcmwxz8bn43 251 | [sun] => Array 252 | ( 253 | [rise] => Array 254 | ( 255 | [apparent] => 1452931140 256 | [astronomical] => 1452923940 257 | [civil] => 1452928800 258 | [nautical] => 1452926340 259 | ) 260 | 261 | [set] => Array 262 | ( 263 | [apparent] => 1452961320 264 | [astronomical] => 1452968520 265 | [civil] => 1452963660 266 | [nautical] => 1452966120 267 | ) 268 | 269 | ) 270 | 271 | [timezone] => Array 272 | ( 273 | [name] => Europe/London 274 | [now_in_dst] => 0 275 | [offset_sec] => 0 276 | [offset_string] => 0 277 | [short_name] => GMT 278 | ) 279 | 280 | [what3words] => Array 281 | ( 282 | [words] => thing.then.link 283 | ) 284 | 285 | ) 286 | 287 | [bounds] => Array 288 | ( 289 | [northeast] => Array 290 | ( 291 | [lat] => 51.7202301025 292 | [lng] => 0.336111992598 293 | ) 294 | 295 | [southwest] => Array 296 | ( 297 | [lat] => 51.2786598206 298 | [lng] => -0.523222982883 299 | ) 300 | 301 | ) 302 | 303 | [components] => Array 304 | ( 305 | [country] => United Kingdom 306 | [county] => Greater London 307 | [state] => England 308 | [town] => London 309 | ) 310 | 311 | [confidence] => 1 312 | [formatted] => London, Greater London, United Kingdom 313 | [geometry] => Array 314 | ( 315 | [lat] => 51.50853 316 | [lng] => -0.12574 317 | ) 318 | 319 | ) 320 | 321 | ) 322 | ) 323 | ``` 324 | 325 | ## Copyright 326 | 327 | Copyright (c) OpenCage GmbH. See LICENSE for details. 328 | 329 | ## Who is OpenCage GmbH? 330 | 331 | 332 | 333 | We run a worldwide [geocoding API](https://opencagedata.com/api) and [geosearch](https://opencagedata.com/geosearch) service based on open data. 334 | Learn more [about us](https://opencagedata.com/about). 335 | 336 | We also run [Geomob](https://thegeomob.com), a series of regular meetups for location based service creators, where we do our best to highlight geoinnovation. If you like geo stuff, you will probably enjoy [the Geomob podcast](https://thegeomob.com/podcast/). 337 | 338 | -- end -- 339 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please see the [OpenCage security bounty page](https://opencagedata.com/security-bounty) 6 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | # The most common configuration options are documented and commented below. 6 | # For a complete reference, please see the online documentation at 7 | # https://docs.vagrantup.com. 8 | 9 | # Every Vagrant development environment requires a box. You can search for 10 | # boxes at https://vagrantcloud.com/search. 11 | config.vm.box = "bento/ubuntu-24.04" 12 | if RUBY_PLATFORM.include?('darwin') && RUBY_PLATFORM.include?('arm64') 13 | # Apple Silicon/M processor 14 | config.vm.box = 'gutehall/ubuntu24-04' 15 | end 16 | 17 | config.vm.synced_folder ".", "/home/vagrant/php-opencage-geocode" 18 | 19 | # Enable provisioning with a shell script. Additional provisioners such as 20 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 21 | # documentation for more information about their specific syntax and use. 22 | config.vm.provision "shell", inline: <<-SHELL 23 | apt-get update -qq 24 | apt-get install -y -qq php-cli php-curl php-xml php-mbstring unzip 25 | curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer 26 | cd /home/vagrant/php-opencage-geocode 27 | composer install 28 | # run tests: 29 | ./vendor/bin/phpunit 30 | ./vendor/bin/phpcs . 31 | SHELL 32 | end 33 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opencage/geocode", 3 | "description": "A PHP library for geocoding via the OpenCage Geocoder API", 4 | "license": "BSD-2-Clause", 5 | "authors": [ 6 | { 7 | "name": "OpenCage GmbH", 8 | "email": "support@opencagedata.com", 9 | "homepage": "https://opencagedata.com" 10 | } 11 | ], 12 | "autoload": { 13 | "psr-4": { 14 | "OpenCage\\Geocoder\\": "src" 15 | } 16 | }, 17 | "require": { 18 | "php": ">=8.0" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "~11.0", 22 | "squizlabs/php_codesniffer": "^3.7", 23 | "phpstan/phpstan": "^2.0.0" 24 | }, 25 | "archive": { 26 | "exclude": ["vendor", ".DS_Store"] 27 | }, 28 | "keywords": [ 29 | "geocode", 30 | "addresses", 31 | "geocoding", 32 | "opencagedata" 33 | ], 34 | "support": { 35 | "issues": "https://github.com/OpenCageData/php-opencage-geocode/issues", 36 | "source": "https://github.com/OpenCageData/php-opencage-geocode", 37 | "docs": "https://opencagedata.com/api" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /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": "a01464c881c41a49ed2eca71ef038ad4", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "myclabs/deep-copy", 12 | "version": "1.12.1", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/myclabs/DeepCopy.git", 16 | "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", 21 | "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^7.1 || ^8.0" 26 | }, 27 | "conflict": { 28 | "doctrine/collections": "<1.6.8", 29 | "doctrine/common": "<2.13.3 || >=3 <3.2.2" 30 | }, 31 | "require-dev": { 32 | "doctrine/collections": "^1.6.8", 33 | "doctrine/common": "^2.13.3 || ^3.2.2", 34 | "phpspec/prophecy": "^1.10", 35 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 36 | }, 37 | "type": "library", 38 | "autoload": { 39 | "files": [ 40 | "src/DeepCopy/deep_copy.php" 41 | ], 42 | "psr-4": { 43 | "DeepCopy\\": "src/DeepCopy/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "description": "Create deep copies (clones) of your objects", 51 | "keywords": [ 52 | "clone", 53 | "copy", 54 | "duplicate", 55 | "object", 56 | "object graph" 57 | ], 58 | "support": { 59 | "issues": "https://github.com/myclabs/DeepCopy/issues", 60 | "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" 61 | }, 62 | "funding": [ 63 | { 64 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 65 | "type": "tidelift" 66 | } 67 | ], 68 | "time": "2024-11-08T17:47:46+00:00" 69 | }, 70 | { 71 | "name": "nikic/php-parser", 72 | "version": "v5.3.1", 73 | "source": { 74 | "type": "git", 75 | "url": "https://github.com/nikic/PHP-Parser.git", 76 | "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" 77 | }, 78 | "dist": { 79 | "type": "zip", 80 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", 81 | "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", 82 | "shasum": "" 83 | }, 84 | "require": { 85 | "ext-ctype": "*", 86 | "ext-json": "*", 87 | "ext-tokenizer": "*", 88 | "php": ">=7.4" 89 | }, 90 | "require-dev": { 91 | "ircmaxell/php-yacc": "^0.0.7", 92 | "phpunit/phpunit": "^9.0" 93 | }, 94 | "bin": [ 95 | "bin/php-parse" 96 | ], 97 | "type": "library", 98 | "extra": { 99 | "branch-alias": { 100 | "dev-master": "5.0-dev" 101 | } 102 | }, 103 | "autoload": { 104 | "psr-4": { 105 | "PhpParser\\": "lib/PhpParser" 106 | } 107 | }, 108 | "notification-url": "https://packagist.org/downloads/", 109 | "license": [ 110 | "BSD-3-Clause" 111 | ], 112 | "authors": [ 113 | { 114 | "name": "Nikita Popov" 115 | } 116 | ], 117 | "description": "A PHP parser written in PHP", 118 | "keywords": [ 119 | "parser", 120 | "php" 121 | ], 122 | "support": { 123 | "issues": "https://github.com/nikic/PHP-Parser/issues", 124 | "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" 125 | }, 126 | "time": "2024-10-08T18:51:32+00:00" 127 | }, 128 | { 129 | "name": "phar-io/manifest", 130 | "version": "2.0.4", 131 | "source": { 132 | "type": "git", 133 | "url": "https://github.com/phar-io/manifest.git", 134 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 135 | }, 136 | "dist": { 137 | "type": "zip", 138 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 139 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 140 | "shasum": "" 141 | }, 142 | "require": { 143 | "ext-dom": "*", 144 | "ext-libxml": "*", 145 | "ext-phar": "*", 146 | "ext-xmlwriter": "*", 147 | "phar-io/version": "^3.0.1", 148 | "php": "^7.2 || ^8.0" 149 | }, 150 | "type": "library", 151 | "extra": { 152 | "branch-alias": { 153 | "dev-master": "2.0.x-dev" 154 | } 155 | }, 156 | "autoload": { 157 | "classmap": [ 158 | "src/" 159 | ] 160 | }, 161 | "notification-url": "https://packagist.org/downloads/", 162 | "license": [ 163 | "BSD-3-Clause" 164 | ], 165 | "authors": [ 166 | { 167 | "name": "Arne Blankerts", 168 | "email": "arne@blankerts.de", 169 | "role": "Developer" 170 | }, 171 | { 172 | "name": "Sebastian Heuer", 173 | "email": "sebastian@phpeople.de", 174 | "role": "Developer" 175 | }, 176 | { 177 | "name": "Sebastian Bergmann", 178 | "email": "sebastian@phpunit.de", 179 | "role": "Developer" 180 | } 181 | ], 182 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 183 | "support": { 184 | "issues": "https://github.com/phar-io/manifest/issues", 185 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 186 | }, 187 | "funding": [ 188 | { 189 | "url": "https://github.com/theseer", 190 | "type": "github" 191 | } 192 | ], 193 | "time": "2024-03-03T12:33:53+00:00" 194 | }, 195 | { 196 | "name": "phar-io/version", 197 | "version": "3.2.1", 198 | "source": { 199 | "type": "git", 200 | "url": "https://github.com/phar-io/version.git", 201 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 202 | }, 203 | "dist": { 204 | "type": "zip", 205 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 206 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 207 | "shasum": "" 208 | }, 209 | "require": { 210 | "php": "^7.2 || ^8.0" 211 | }, 212 | "type": "library", 213 | "autoload": { 214 | "classmap": [ 215 | "src/" 216 | ] 217 | }, 218 | "notification-url": "https://packagist.org/downloads/", 219 | "license": [ 220 | "BSD-3-Clause" 221 | ], 222 | "authors": [ 223 | { 224 | "name": "Arne Blankerts", 225 | "email": "arne@blankerts.de", 226 | "role": "Developer" 227 | }, 228 | { 229 | "name": "Sebastian Heuer", 230 | "email": "sebastian@phpeople.de", 231 | "role": "Developer" 232 | }, 233 | { 234 | "name": "Sebastian Bergmann", 235 | "email": "sebastian@phpunit.de", 236 | "role": "Developer" 237 | } 238 | ], 239 | "description": "Library for handling version information and constraints", 240 | "support": { 241 | "issues": "https://github.com/phar-io/version/issues", 242 | "source": "https://github.com/phar-io/version/tree/3.2.1" 243 | }, 244 | "time": "2022-02-21T01:04:05+00:00" 245 | }, 246 | { 247 | "name": "phpstan/phpstan", 248 | "version": "2.0.2", 249 | "source": { 250 | "type": "git", 251 | "url": "https://github.com/phpstan/phpstan.git", 252 | "reference": "6c98c7600fc717b2c78c11ef60040d5b1e359c82" 253 | }, 254 | "dist": { 255 | "type": "zip", 256 | "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6c98c7600fc717b2c78c11ef60040d5b1e359c82", 257 | "reference": "6c98c7600fc717b2c78c11ef60040d5b1e359c82", 258 | "shasum": "" 259 | }, 260 | "require": { 261 | "php": "^7.4|^8.0" 262 | }, 263 | "conflict": { 264 | "phpstan/phpstan-shim": "*" 265 | }, 266 | "bin": [ 267 | "phpstan", 268 | "phpstan.phar" 269 | ], 270 | "type": "library", 271 | "autoload": { 272 | "files": [ 273 | "bootstrap.php" 274 | ] 275 | }, 276 | "notification-url": "https://packagist.org/downloads/", 277 | "license": [ 278 | "MIT" 279 | ], 280 | "description": "PHPStan - PHP Static Analysis Tool", 281 | "keywords": [ 282 | "dev", 283 | "static analysis" 284 | ], 285 | "support": { 286 | "docs": "https://phpstan.org/user-guide/getting-started", 287 | "forum": "https://github.com/phpstan/phpstan/discussions", 288 | "issues": "https://github.com/phpstan/phpstan/issues", 289 | "security": "https://github.com/phpstan/phpstan/security/policy", 290 | "source": "https://github.com/phpstan/phpstan-src" 291 | }, 292 | "funding": [ 293 | { 294 | "url": "https://github.com/ondrejmirtes", 295 | "type": "github" 296 | }, 297 | { 298 | "url": "https://github.com/phpstan", 299 | "type": "github" 300 | } 301 | ], 302 | "time": "2024-11-17T14:17:00+00:00" 303 | }, 304 | { 305 | "name": "phpunit/php-code-coverage", 306 | "version": "11.0.7", 307 | "source": { 308 | "type": "git", 309 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 310 | "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" 311 | }, 312 | "dist": { 313 | "type": "zip", 314 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", 315 | "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", 316 | "shasum": "" 317 | }, 318 | "require": { 319 | "ext-dom": "*", 320 | "ext-libxml": "*", 321 | "ext-xmlwriter": "*", 322 | "nikic/php-parser": "^5.3.1", 323 | "php": ">=8.2", 324 | "phpunit/php-file-iterator": "^5.1.0", 325 | "phpunit/php-text-template": "^4.0.1", 326 | "sebastian/code-unit-reverse-lookup": "^4.0.1", 327 | "sebastian/complexity": "^4.0.1", 328 | "sebastian/environment": "^7.2.0", 329 | "sebastian/lines-of-code": "^3.0.1", 330 | "sebastian/version": "^5.0.2", 331 | "theseer/tokenizer": "^1.2.3" 332 | }, 333 | "require-dev": { 334 | "phpunit/phpunit": "^11.4.1" 335 | }, 336 | "suggest": { 337 | "ext-pcov": "PHP extension that provides line coverage", 338 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 339 | }, 340 | "type": "library", 341 | "extra": { 342 | "branch-alias": { 343 | "dev-main": "11.0.x-dev" 344 | } 345 | }, 346 | "autoload": { 347 | "classmap": [ 348 | "src/" 349 | ] 350 | }, 351 | "notification-url": "https://packagist.org/downloads/", 352 | "license": [ 353 | "BSD-3-Clause" 354 | ], 355 | "authors": [ 356 | { 357 | "name": "Sebastian Bergmann", 358 | "email": "sebastian@phpunit.de", 359 | "role": "lead" 360 | } 361 | ], 362 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 363 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 364 | "keywords": [ 365 | "coverage", 366 | "testing", 367 | "xunit" 368 | ], 369 | "support": { 370 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 371 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 372 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" 373 | }, 374 | "funding": [ 375 | { 376 | "url": "https://github.com/sebastianbergmann", 377 | "type": "github" 378 | } 379 | ], 380 | "time": "2024-10-09T06:21:38+00:00" 381 | }, 382 | { 383 | "name": "phpunit/php-file-iterator", 384 | "version": "5.1.0", 385 | "source": { 386 | "type": "git", 387 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 388 | "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" 389 | }, 390 | "dist": { 391 | "type": "zip", 392 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", 393 | "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", 394 | "shasum": "" 395 | }, 396 | "require": { 397 | "php": ">=8.2" 398 | }, 399 | "require-dev": { 400 | "phpunit/phpunit": "^11.0" 401 | }, 402 | "type": "library", 403 | "extra": { 404 | "branch-alias": { 405 | "dev-main": "5.0-dev" 406 | } 407 | }, 408 | "autoload": { 409 | "classmap": [ 410 | "src/" 411 | ] 412 | }, 413 | "notification-url": "https://packagist.org/downloads/", 414 | "license": [ 415 | "BSD-3-Clause" 416 | ], 417 | "authors": [ 418 | { 419 | "name": "Sebastian Bergmann", 420 | "email": "sebastian@phpunit.de", 421 | "role": "lead" 422 | } 423 | ], 424 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 425 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 426 | "keywords": [ 427 | "filesystem", 428 | "iterator" 429 | ], 430 | "support": { 431 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 432 | "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", 433 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" 434 | }, 435 | "funding": [ 436 | { 437 | "url": "https://github.com/sebastianbergmann", 438 | "type": "github" 439 | } 440 | ], 441 | "time": "2024-08-27T05:02:59+00:00" 442 | }, 443 | { 444 | "name": "phpunit/php-invoker", 445 | "version": "5.0.1", 446 | "source": { 447 | "type": "git", 448 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 449 | "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" 450 | }, 451 | "dist": { 452 | "type": "zip", 453 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", 454 | "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", 455 | "shasum": "" 456 | }, 457 | "require": { 458 | "php": ">=8.2" 459 | }, 460 | "require-dev": { 461 | "ext-pcntl": "*", 462 | "phpunit/phpunit": "^11.0" 463 | }, 464 | "suggest": { 465 | "ext-pcntl": "*" 466 | }, 467 | "type": "library", 468 | "extra": { 469 | "branch-alias": { 470 | "dev-main": "5.0-dev" 471 | } 472 | }, 473 | "autoload": { 474 | "classmap": [ 475 | "src/" 476 | ] 477 | }, 478 | "notification-url": "https://packagist.org/downloads/", 479 | "license": [ 480 | "BSD-3-Clause" 481 | ], 482 | "authors": [ 483 | { 484 | "name": "Sebastian Bergmann", 485 | "email": "sebastian@phpunit.de", 486 | "role": "lead" 487 | } 488 | ], 489 | "description": "Invoke callables with a timeout", 490 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 491 | "keywords": [ 492 | "process" 493 | ], 494 | "support": { 495 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 496 | "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", 497 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" 498 | }, 499 | "funding": [ 500 | { 501 | "url": "https://github.com/sebastianbergmann", 502 | "type": "github" 503 | } 504 | ], 505 | "time": "2024-07-03T05:07:44+00:00" 506 | }, 507 | { 508 | "name": "phpunit/php-text-template", 509 | "version": "4.0.1", 510 | "source": { 511 | "type": "git", 512 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 513 | "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" 514 | }, 515 | "dist": { 516 | "type": "zip", 517 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", 518 | "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", 519 | "shasum": "" 520 | }, 521 | "require": { 522 | "php": ">=8.2" 523 | }, 524 | "require-dev": { 525 | "phpunit/phpunit": "^11.0" 526 | }, 527 | "type": "library", 528 | "extra": { 529 | "branch-alias": { 530 | "dev-main": "4.0-dev" 531 | } 532 | }, 533 | "autoload": { 534 | "classmap": [ 535 | "src/" 536 | ] 537 | }, 538 | "notification-url": "https://packagist.org/downloads/", 539 | "license": [ 540 | "BSD-3-Clause" 541 | ], 542 | "authors": [ 543 | { 544 | "name": "Sebastian Bergmann", 545 | "email": "sebastian@phpunit.de", 546 | "role": "lead" 547 | } 548 | ], 549 | "description": "Simple template engine.", 550 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 551 | "keywords": [ 552 | "template" 553 | ], 554 | "support": { 555 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 556 | "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", 557 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" 558 | }, 559 | "funding": [ 560 | { 561 | "url": "https://github.com/sebastianbergmann", 562 | "type": "github" 563 | } 564 | ], 565 | "time": "2024-07-03T05:08:43+00:00" 566 | }, 567 | { 568 | "name": "phpunit/php-timer", 569 | "version": "7.0.1", 570 | "source": { 571 | "type": "git", 572 | "url": "https://github.com/sebastianbergmann/php-timer.git", 573 | "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" 574 | }, 575 | "dist": { 576 | "type": "zip", 577 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", 578 | "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", 579 | "shasum": "" 580 | }, 581 | "require": { 582 | "php": ">=8.2" 583 | }, 584 | "require-dev": { 585 | "phpunit/phpunit": "^11.0" 586 | }, 587 | "type": "library", 588 | "extra": { 589 | "branch-alias": { 590 | "dev-main": "7.0-dev" 591 | } 592 | }, 593 | "autoload": { 594 | "classmap": [ 595 | "src/" 596 | ] 597 | }, 598 | "notification-url": "https://packagist.org/downloads/", 599 | "license": [ 600 | "BSD-3-Clause" 601 | ], 602 | "authors": [ 603 | { 604 | "name": "Sebastian Bergmann", 605 | "email": "sebastian@phpunit.de", 606 | "role": "lead" 607 | } 608 | ], 609 | "description": "Utility class for timing", 610 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 611 | "keywords": [ 612 | "timer" 613 | ], 614 | "support": { 615 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 616 | "security": "https://github.com/sebastianbergmann/php-timer/security/policy", 617 | "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" 618 | }, 619 | "funding": [ 620 | { 621 | "url": "https://github.com/sebastianbergmann", 622 | "type": "github" 623 | } 624 | ], 625 | "time": "2024-07-03T05:09:35+00:00" 626 | }, 627 | { 628 | "name": "phpunit/phpunit", 629 | "version": "11.4.3", 630 | "source": { 631 | "type": "git", 632 | "url": "https://github.com/sebastianbergmann/phpunit.git", 633 | "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" 634 | }, 635 | "dist": { 636 | "type": "zip", 637 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", 638 | "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", 639 | "shasum": "" 640 | }, 641 | "require": { 642 | "ext-dom": "*", 643 | "ext-json": "*", 644 | "ext-libxml": "*", 645 | "ext-mbstring": "*", 646 | "ext-xml": "*", 647 | "ext-xmlwriter": "*", 648 | "myclabs/deep-copy": "^1.12.0", 649 | "phar-io/manifest": "^2.0.4", 650 | "phar-io/version": "^3.2.1", 651 | "php": ">=8.2", 652 | "phpunit/php-code-coverage": "^11.0.7", 653 | "phpunit/php-file-iterator": "^5.1.0", 654 | "phpunit/php-invoker": "^5.0.1", 655 | "phpunit/php-text-template": "^4.0.1", 656 | "phpunit/php-timer": "^7.0.1", 657 | "sebastian/cli-parser": "^3.0.2", 658 | "sebastian/code-unit": "^3.0.1", 659 | "sebastian/comparator": "^6.1.1", 660 | "sebastian/diff": "^6.0.2", 661 | "sebastian/environment": "^7.2.0", 662 | "sebastian/exporter": "^6.1.3", 663 | "sebastian/global-state": "^7.0.2", 664 | "sebastian/object-enumerator": "^6.0.1", 665 | "sebastian/type": "^5.1.0", 666 | "sebastian/version": "^5.0.2" 667 | }, 668 | "suggest": { 669 | "ext-soap": "To be able to generate mocks based on WSDL files" 670 | }, 671 | "bin": [ 672 | "phpunit" 673 | ], 674 | "type": "library", 675 | "extra": { 676 | "branch-alias": { 677 | "dev-main": "11.4-dev" 678 | } 679 | }, 680 | "autoload": { 681 | "files": [ 682 | "src/Framework/Assert/Functions.php" 683 | ], 684 | "classmap": [ 685 | "src/" 686 | ] 687 | }, 688 | "notification-url": "https://packagist.org/downloads/", 689 | "license": [ 690 | "BSD-3-Clause" 691 | ], 692 | "authors": [ 693 | { 694 | "name": "Sebastian Bergmann", 695 | "email": "sebastian@phpunit.de", 696 | "role": "lead" 697 | } 698 | ], 699 | "description": "The PHP Unit Testing framework.", 700 | "homepage": "https://phpunit.de/", 701 | "keywords": [ 702 | "phpunit", 703 | "testing", 704 | "xunit" 705 | ], 706 | "support": { 707 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 708 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 709 | "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" 710 | }, 711 | "funding": [ 712 | { 713 | "url": "https://phpunit.de/sponsors.html", 714 | "type": "custom" 715 | }, 716 | { 717 | "url": "https://github.com/sebastianbergmann", 718 | "type": "github" 719 | }, 720 | { 721 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 722 | "type": "tidelift" 723 | } 724 | ], 725 | "time": "2024-10-28T13:07:50+00:00" 726 | }, 727 | { 728 | "name": "sebastian/cli-parser", 729 | "version": "3.0.2", 730 | "source": { 731 | "type": "git", 732 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 733 | "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" 734 | }, 735 | "dist": { 736 | "type": "zip", 737 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", 738 | "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", 739 | "shasum": "" 740 | }, 741 | "require": { 742 | "php": ">=8.2" 743 | }, 744 | "require-dev": { 745 | "phpunit/phpunit": "^11.0" 746 | }, 747 | "type": "library", 748 | "extra": { 749 | "branch-alias": { 750 | "dev-main": "3.0-dev" 751 | } 752 | }, 753 | "autoload": { 754 | "classmap": [ 755 | "src/" 756 | ] 757 | }, 758 | "notification-url": "https://packagist.org/downloads/", 759 | "license": [ 760 | "BSD-3-Clause" 761 | ], 762 | "authors": [ 763 | { 764 | "name": "Sebastian Bergmann", 765 | "email": "sebastian@phpunit.de", 766 | "role": "lead" 767 | } 768 | ], 769 | "description": "Library for parsing CLI options", 770 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 771 | "support": { 772 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 773 | "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", 774 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" 775 | }, 776 | "funding": [ 777 | { 778 | "url": "https://github.com/sebastianbergmann", 779 | "type": "github" 780 | } 781 | ], 782 | "time": "2024-07-03T04:41:36+00:00" 783 | }, 784 | { 785 | "name": "sebastian/code-unit", 786 | "version": "3.0.1", 787 | "source": { 788 | "type": "git", 789 | "url": "https://github.com/sebastianbergmann/code-unit.git", 790 | "reference": "6bb7d09d6623567178cf54126afa9c2310114268" 791 | }, 792 | "dist": { 793 | "type": "zip", 794 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", 795 | "reference": "6bb7d09d6623567178cf54126afa9c2310114268", 796 | "shasum": "" 797 | }, 798 | "require": { 799 | "php": ">=8.2" 800 | }, 801 | "require-dev": { 802 | "phpunit/phpunit": "^11.0" 803 | }, 804 | "type": "library", 805 | "extra": { 806 | "branch-alias": { 807 | "dev-main": "3.0-dev" 808 | } 809 | }, 810 | "autoload": { 811 | "classmap": [ 812 | "src/" 813 | ] 814 | }, 815 | "notification-url": "https://packagist.org/downloads/", 816 | "license": [ 817 | "BSD-3-Clause" 818 | ], 819 | "authors": [ 820 | { 821 | "name": "Sebastian Bergmann", 822 | "email": "sebastian@phpunit.de", 823 | "role": "lead" 824 | } 825 | ], 826 | "description": "Collection of value objects that represent the PHP code units", 827 | "homepage": "https://github.com/sebastianbergmann/code-unit", 828 | "support": { 829 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 830 | "security": "https://github.com/sebastianbergmann/code-unit/security/policy", 831 | "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" 832 | }, 833 | "funding": [ 834 | { 835 | "url": "https://github.com/sebastianbergmann", 836 | "type": "github" 837 | } 838 | ], 839 | "time": "2024-07-03T04:44:28+00:00" 840 | }, 841 | { 842 | "name": "sebastian/code-unit-reverse-lookup", 843 | "version": "4.0.1", 844 | "source": { 845 | "type": "git", 846 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 847 | "reference": "183a9b2632194febd219bb9246eee421dad8d45e" 848 | }, 849 | "dist": { 850 | "type": "zip", 851 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", 852 | "reference": "183a9b2632194febd219bb9246eee421dad8d45e", 853 | "shasum": "" 854 | }, 855 | "require": { 856 | "php": ">=8.2" 857 | }, 858 | "require-dev": { 859 | "phpunit/phpunit": "^11.0" 860 | }, 861 | "type": "library", 862 | "extra": { 863 | "branch-alias": { 864 | "dev-main": "4.0-dev" 865 | } 866 | }, 867 | "autoload": { 868 | "classmap": [ 869 | "src/" 870 | ] 871 | }, 872 | "notification-url": "https://packagist.org/downloads/", 873 | "license": [ 874 | "BSD-3-Clause" 875 | ], 876 | "authors": [ 877 | { 878 | "name": "Sebastian Bergmann", 879 | "email": "sebastian@phpunit.de" 880 | } 881 | ], 882 | "description": "Looks up which function or method a line of code belongs to", 883 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 884 | "support": { 885 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 886 | "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", 887 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" 888 | }, 889 | "funding": [ 890 | { 891 | "url": "https://github.com/sebastianbergmann", 892 | "type": "github" 893 | } 894 | ], 895 | "time": "2024-07-03T04:45:54+00:00" 896 | }, 897 | { 898 | "name": "sebastian/comparator", 899 | "version": "6.2.1", 900 | "source": { 901 | "type": "git", 902 | "url": "https://github.com/sebastianbergmann/comparator.git", 903 | "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" 904 | }, 905 | "dist": { 906 | "type": "zip", 907 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", 908 | "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", 909 | "shasum": "" 910 | }, 911 | "require": { 912 | "ext-dom": "*", 913 | "ext-mbstring": "*", 914 | "php": ">=8.2", 915 | "sebastian/diff": "^6.0", 916 | "sebastian/exporter": "^6.0" 917 | }, 918 | "require-dev": { 919 | "phpunit/phpunit": "^11.4" 920 | }, 921 | "type": "library", 922 | "extra": { 923 | "branch-alias": { 924 | "dev-main": "6.2-dev" 925 | } 926 | }, 927 | "autoload": { 928 | "classmap": [ 929 | "src/" 930 | ] 931 | }, 932 | "notification-url": "https://packagist.org/downloads/", 933 | "license": [ 934 | "BSD-3-Clause" 935 | ], 936 | "authors": [ 937 | { 938 | "name": "Sebastian Bergmann", 939 | "email": "sebastian@phpunit.de" 940 | }, 941 | { 942 | "name": "Jeff Welch", 943 | "email": "whatthejeff@gmail.com" 944 | }, 945 | { 946 | "name": "Volker Dusch", 947 | "email": "github@wallbash.com" 948 | }, 949 | { 950 | "name": "Bernhard Schussek", 951 | "email": "bschussek@2bepublished.at" 952 | } 953 | ], 954 | "description": "Provides the functionality to compare PHP values for equality", 955 | "homepage": "https://github.com/sebastianbergmann/comparator", 956 | "keywords": [ 957 | "comparator", 958 | "compare", 959 | "equality" 960 | ], 961 | "support": { 962 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 963 | "security": "https://github.com/sebastianbergmann/comparator/security/policy", 964 | "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" 965 | }, 966 | "funding": [ 967 | { 968 | "url": "https://github.com/sebastianbergmann", 969 | "type": "github" 970 | } 971 | ], 972 | "time": "2024-10-31T05:30:08+00:00" 973 | }, 974 | { 975 | "name": "sebastian/complexity", 976 | "version": "4.0.1", 977 | "source": { 978 | "type": "git", 979 | "url": "https://github.com/sebastianbergmann/complexity.git", 980 | "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" 981 | }, 982 | "dist": { 983 | "type": "zip", 984 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", 985 | "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", 986 | "shasum": "" 987 | }, 988 | "require": { 989 | "nikic/php-parser": "^5.0", 990 | "php": ">=8.2" 991 | }, 992 | "require-dev": { 993 | "phpunit/phpunit": "^11.0" 994 | }, 995 | "type": "library", 996 | "extra": { 997 | "branch-alias": { 998 | "dev-main": "4.0-dev" 999 | } 1000 | }, 1001 | "autoload": { 1002 | "classmap": [ 1003 | "src/" 1004 | ] 1005 | }, 1006 | "notification-url": "https://packagist.org/downloads/", 1007 | "license": [ 1008 | "BSD-3-Clause" 1009 | ], 1010 | "authors": [ 1011 | { 1012 | "name": "Sebastian Bergmann", 1013 | "email": "sebastian@phpunit.de", 1014 | "role": "lead" 1015 | } 1016 | ], 1017 | "description": "Library for calculating the complexity of PHP code units", 1018 | "homepage": "https://github.com/sebastianbergmann/complexity", 1019 | "support": { 1020 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1021 | "security": "https://github.com/sebastianbergmann/complexity/security/policy", 1022 | "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" 1023 | }, 1024 | "funding": [ 1025 | { 1026 | "url": "https://github.com/sebastianbergmann", 1027 | "type": "github" 1028 | } 1029 | ], 1030 | "time": "2024-07-03T04:49:50+00:00" 1031 | }, 1032 | { 1033 | "name": "sebastian/diff", 1034 | "version": "6.0.2", 1035 | "source": { 1036 | "type": "git", 1037 | "url": "https://github.com/sebastianbergmann/diff.git", 1038 | "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" 1039 | }, 1040 | "dist": { 1041 | "type": "zip", 1042 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", 1043 | "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", 1044 | "shasum": "" 1045 | }, 1046 | "require": { 1047 | "php": ">=8.2" 1048 | }, 1049 | "require-dev": { 1050 | "phpunit/phpunit": "^11.0", 1051 | "symfony/process": "^4.2 || ^5" 1052 | }, 1053 | "type": "library", 1054 | "extra": { 1055 | "branch-alias": { 1056 | "dev-main": "6.0-dev" 1057 | } 1058 | }, 1059 | "autoload": { 1060 | "classmap": [ 1061 | "src/" 1062 | ] 1063 | }, 1064 | "notification-url": "https://packagist.org/downloads/", 1065 | "license": [ 1066 | "BSD-3-Clause" 1067 | ], 1068 | "authors": [ 1069 | { 1070 | "name": "Sebastian Bergmann", 1071 | "email": "sebastian@phpunit.de" 1072 | }, 1073 | { 1074 | "name": "Kore Nordmann", 1075 | "email": "mail@kore-nordmann.de" 1076 | } 1077 | ], 1078 | "description": "Diff implementation", 1079 | "homepage": "https://github.com/sebastianbergmann/diff", 1080 | "keywords": [ 1081 | "diff", 1082 | "udiff", 1083 | "unidiff", 1084 | "unified diff" 1085 | ], 1086 | "support": { 1087 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1088 | "security": "https://github.com/sebastianbergmann/diff/security/policy", 1089 | "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" 1090 | }, 1091 | "funding": [ 1092 | { 1093 | "url": "https://github.com/sebastianbergmann", 1094 | "type": "github" 1095 | } 1096 | ], 1097 | "time": "2024-07-03T04:53:05+00:00" 1098 | }, 1099 | { 1100 | "name": "sebastian/environment", 1101 | "version": "7.2.0", 1102 | "source": { 1103 | "type": "git", 1104 | "url": "https://github.com/sebastianbergmann/environment.git", 1105 | "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" 1106 | }, 1107 | "dist": { 1108 | "type": "zip", 1109 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", 1110 | "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", 1111 | "shasum": "" 1112 | }, 1113 | "require": { 1114 | "php": ">=8.2" 1115 | }, 1116 | "require-dev": { 1117 | "phpunit/phpunit": "^11.0" 1118 | }, 1119 | "suggest": { 1120 | "ext-posix": "*" 1121 | }, 1122 | "type": "library", 1123 | "extra": { 1124 | "branch-alias": { 1125 | "dev-main": "7.2-dev" 1126 | } 1127 | }, 1128 | "autoload": { 1129 | "classmap": [ 1130 | "src/" 1131 | ] 1132 | }, 1133 | "notification-url": "https://packagist.org/downloads/", 1134 | "license": [ 1135 | "BSD-3-Clause" 1136 | ], 1137 | "authors": [ 1138 | { 1139 | "name": "Sebastian Bergmann", 1140 | "email": "sebastian@phpunit.de" 1141 | } 1142 | ], 1143 | "description": "Provides functionality to handle HHVM/PHP environments", 1144 | "homepage": "https://github.com/sebastianbergmann/environment", 1145 | "keywords": [ 1146 | "Xdebug", 1147 | "environment", 1148 | "hhvm" 1149 | ], 1150 | "support": { 1151 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1152 | "security": "https://github.com/sebastianbergmann/environment/security/policy", 1153 | "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" 1154 | }, 1155 | "funding": [ 1156 | { 1157 | "url": "https://github.com/sebastianbergmann", 1158 | "type": "github" 1159 | } 1160 | ], 1161 | "time": "2024-07-03T04:54:44+00:00" 1162 | }, 1163 | { 1164 | "name": "sebastian/exporter", 1165 | "version": "6.1.3", 1166 | "source": { 1167 | "type": "git", 1168 | "url": "https://github.com/sebastianbergmann/exporter.git", 1169 | "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" 1170 | }, 1171 | "dist": { 1172 | "type": "zip", 1173 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", 1174 | "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", 1175 | "shasum": "" 1176 | }, 1177 | "require": { 1178 | "ext-mbstring": "*", 1179 | "php": ">=8.2", 1180 | "sebastian/recursion-context": "^6.0" 1181 | }, 1182 | "require-dev": { 1183 | "phpunit/phpunit": "^11.2" 1184 | }, 1185 | "type": "library", 1186 | "extra": { 1187 | "branch-alias": { 1188 | "dev-main": "6.1-dev" 1189 | } 1190 | }, 1191 | "autoload": { 1192 | "classmap": [ 1193 | "src/" 1194 | ] 1195 | }, 1196 | "notification-url": "https://packagist.org/downloads/", 1197 | "license": [ 1198 | "BSD-3-Clause" 1199 | ], 1200 | "authors": [ 1201 | { 1202 | "name": "Sebastian Bergmann", 1203 | "email": "sebastian@phpunit.de" 1204 | }, 1205 | { 1206 | "name": "Jeff Welch", 1207 | "email": "whatthejeff@gmail.com" 1208 | }, 1209 | { 1210 | "name": "Volker Dusch", 1211 | "email": "github@wallbash.com" 1212 | }, 1213 | { 1214 | "name": "Adam Harvey", 1215 | "email": "aharvey@php.net" 1216 | }, 1217 | { 1218 | "name": "Bernhard Schussek", 1219 | "email": "bschussek@gmail.com" 1220 | } 1221 | ], 1222 | "description": "Provides the functionality to export PHP variables for visualization", 1223 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1224 | "keywords": [ 1225 | "export", 1226 | "exporter" 1227 | ], 1228 | "support": { 1229 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1230 | "security": "https://github.com/sebastianbergmann/exporter/security/policy", 1231 | "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" 1232 | }, 1233 | "funding": [ 1234 | { 1235 | "url": "https://github.com/sebastianbergmann", 1236 | "type": "github" 1237 | } 1238 | ], 1239 | "time": "2024-07-03T04:56:19+00:00" 1240 | }, 1241 | { 1242 | "name": "sebastian/global-state", 1243 | "version": "7.0.2", 1244 | "source": { 1245 | "type": "git", 1246 | "url": "https://github.com/sebastianbergmann/global-state.git", 1247 | "reference": "3be331570a721f9a4b5917f4209773de17f747d7" 1248 | }, 1249 | "dist": { 1250 | "type": "zip", 1251 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", 1252 | "reference": "3be331570a721f9a4b5917f4209773de17f747d7", 1253 | "shasum": "" 1254 | }, 1255 | "require": { 1256 | "php": ">=8.2", 1257 | "sebastian/object-reflector": "^4.0", 1258 | "sebastian/recursion-context": "^6.0" 1259 | }, 1260 | "require-dev": { 1261 | "ext-dom": "*", 1262 | "phpunit/phpunit": "^11.0" 1263 | }, 1264 | "type": "library", 1265 | "extra": { 1266 | "branch-alias": { 1267 | "dev-main": "7.0-dev" 1268 | } 1269 | }, 1270 | "autoload": { 1271 | "classmap": [ 1272 | "src/" 1273 | ] 1274 | }, 1275 | "notification-url": "https://packagist.org/downloads/", 1276 | "license": [ 1277 | "BSD-3-Clause" 1278 | ], 1279 | "authors": [ 1280 | { 1281 | "name": "Sebastian Bergmann", 1282 | "email": "sebastian@phpunit.de" 1283 | } 1284 | ], 1285 | "description": "Snapshotting of global state", 1286 | "homepage": "https://www.github.com/sebastianbergmann/global-state", 1287 | "keywords": [ 1288 | "global state" 1289 | ], 1290 | "support": { 1291 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1292 | "security": "https://github.com/sebastianbergmann/global-state/security/policy", 1293 | "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" 1294 | }, 1295 | "funding": [ 1296 | { 1297 | "url": "https://github.com/sebastianbergmann", 1298 | "type": "github" 1299 | } 1300 | ], 1301 | "time": "2024-07-03T04:57:36+00:00" 1302 | }, 1303 | { 1304 | "name": "sebastian/lines-of-code", 1305 | "version": "3.0.1", 1306 | "source": { 1307 | "type": "git", 1308 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1309 | "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" 1310 | }, 1311 | "dist": { 1312 | "type": "zip", 1313 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", 1314 | "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", 1315 | "shasum": "" 1316 | }, 1317 | "require": { 1318 | "nikic/php-parser": "^5.0", 1319 | "php": ">=8.2" 1320 | }, 1321 | "require-dev": { 1322 | "phpunit/phpunit": "^11.0" 1323 | }, 1324 | "type": "library", 1325 | "extra": { 1326 | "branch-alias": { 1327 | "dev-main": "3.0-dev" 1328 | } 1329 | }, 1330 | "autoload": { 1331 | "classmap": [ 1332 | "src/" 1333 | ] 1334 | }, 1335 | "notification-url": "https://packagist.org/downloads/", 1336 | "license": [ 1337 | "BSD-3-Clause" 1338 | ], 1339 | "authors": [ 1340 | { 1341 | "name": "Sebastian Bergmann", 1342 | "email": "sebastian@phpunit.de", 1343 | "role": "lead" 1344 | } 1345 | ], 1346 | "description": "Library for counting the lines of code in PHP source code", 1347 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1348 | "support": { 1349 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1350 | "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", 1351 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" 1352 | }, 1353 | "funding": [ 1354 | { 1355 | "url": "https://github.com/sebastianbergmann", 1356 | "type": "github" 1357 | } 1358 | ], 1359 | "time": "2024-07-03T04:58:38+00:00" 1360 | }, 1361 | { 1362 | "name": "sebastian/object-enumerator", 1363 | "version": "6.0.1", 1364 | "source": { 1365 | "type": "git", 1366 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1367 | "reference": "f5b498e631a74204185071eb41f33f38d64608aa" 1368 | }, 1369 | "dist": { 1370 | "type": "zip", 1371 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", 1372 | "reference": "f5b498e631a74204185071eb41f33f38d64608aa", 1373 | "shasum": "" 1374 | }, 1375 | "require": { 1376 | "php": ">=8.2", 1377 | "sebastian/object-reflector": "^4.0", 1378 | "sebastian/recursion-context": "^6.0" 1379 | }, 1380 | "require-dev": { 1381 | "phpunit/phpunit": "^11.0" 1382 | }, 1383 | "type": "library", 1384 | "extra": { 1385 | "branch-alias": { 1386 | "dev-main": "6.0-dev" 1387 | } 1388 | }, 1389 | "autoload": { 1390 | "classmap": [ 1391 | "src/" 1392 | ] 1393 | }, 1394 | "notification-url": "https://packagist.org/downloads/", 1395 | "license": [ 1396 | "BSD-3-Clause" 1397 | ], 1398 | "authors": [ 1399 | { 1400 | "name": "Sebastian Bergmann", 1401 | "email": "sebastian@phpunit.de" 1402 | } 1403 | ], 1404 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1405 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1406 | "support": { 1407 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1408 | "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", 1409 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" 1410 | }, 1411 | "funding": [ 1412 | { 1413 | "url": "https://github.com/sebastianbergmann", 1414 | "type": "github" 1415 | } 1416 | ], 1417 | "time": "2024-07-03T05:00:13+00:00" 1418 | }, 1419 | { 1420 | "name": "sebastian/object-reflector", 1421 | "version": "4.0.1", 1422 | "source": { 1423 | "type": "git", 1424 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1425 | "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" 1426 | }, 1427 | "dist": { 1428 | "type": "zip", 1429 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", 1430 | "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", 1431 | "shasum": "" 1432 | }, 1433 | "require": { 1434 | "php": ">=8.2" 1435 | }, 1436 | "require-dev": { 1437 | "phpunit/phpunit": "^11.0" 1438 | }, 1439 | "type": "library", 1440 | "extra": { 1441 | "branch-alias": { 1442 | "dev-main": "4.0-dev" 1443 | } 1444 | }, 1445 | "autoload": { 1446 | "classmap": [ 1447 | "src/" 1448 | ] 1449 | }, 1450 | "notification-url": "https://packagist.org/downloads/", 1451 | "license": [ 1452 | "BSD-3-Clause" 1453 | ], 1454 | "authors": [ 1455 | { 1456 | "name": "Sebastian Bergmann", 1457 | "email": "sebastian@phpunit.de" 1458 | } 1459 | ], 1460 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1461 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1462 | "support": { 1463 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1464 | "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", 1465 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" 1466 | }, 1467 | "funding": [ 1468 | { 1469 | "url": "https://github.com/sebastianbergmann", 1470 | "type": "github" 1471 | } 1472 | ], 1473 | "time": "2024-07-03T05:01:32+00:00" 1474 | }, 1475 | { 1476 | "name": "sebastian/recursion-context", 1477 | "version": "6.0.2", 1478 | "source": { 1479 | "type": "git", 1480 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1481 | "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" 1482 | }, 1483 | "dist": { 1484 | "type": "zip", 1485 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", 1486 | "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", 1487 | "shasum": "" 1488 | }, 1489 | "require": { 1490 | "php": ">=8.2" 1491 | }, 1492 | "require-dev": { 1493 | "phpunit/phpunit": "^11.0" 1494 | }, 1495 | "type": "library", 1496 | "extra": { 1497 | "branch-alias": { 1498 | "dev-main": "6.0-dev" 1499 | } 1500 | }, 1501 | "autoload": { 1502 | "classmap": [ 1503 | "src/" 1504 | ] 1505 | }, 1506 | "notification-url": "https://packagist.org/downloads/", 1507 | "license": [ 1508 | "BSD-3-Clause" 1509 | ], 1510 | "authors": [ 1511 | { 1512 | "name": "Sebastian Bergmann", 1513 | "email": "sebastian@phpunit.de" 1514 | }, 1515 | { 1516 | "name": "Jeff Welch", 1517 | "email": "whatthejeff@gmail.com" 1518 | }, 1519 | { 1520 | "name": "Adam Harvey", 1521 | "email": "aharvey@php.net" 1522 | } 1523 | ], 1524 | "description": "Provides functionality to recursively process PHP variables", 1525 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 1526 | "support": { 1527 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1528 | "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", 1529 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" 1530 | }, 1531 | "funding": [ 1532 | { 1533 | "url": "https://github.com/sebastianbergmann", 1534 | "type": "github" 1535 | } 1536 | ], 1537 | "time": "2024-07-03T05:10:34+00:00" 1538 | }, 1539 | { 1540 | "name": "sebastian/type", 1541 | "version": "5.1.0", 1542 | "source": { 1543 | "type": "git", 1544 | "url": "https://github.com/sebastianbergmann/type.git", 1545 | "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" 1546 | }, 1547 | "dist": { 1548 | "type": "zip", 1549 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", 1550 | "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", 1551 | "shasum": "" 1552 | }, 1553 | "require": { 1554 | "php": ">=8.2" 1555 | }, 1556 | "require-dev": { 1557 | "phpunit/phpunit": "^11.3" 1558 | }, 1559 | "type": "library", 1560 | "extra": { 1561 | "branch-alias": { 1562 | "dev-main": "5.1-dev" 1563 | } 1564 | }, 1565 | "autoload": { 1566 | "classmap": [ 1567 | "src/" 1568 | ] 1569 | }, 1570 | "notification-url": "https://packagist.org/downloads/", 1571 | "license": [ 1572 | "BSD-3-Clause" 1573 | ], 1574 | "authors": [ 1575 | { 1576 | "name": "Sebastian Bergmann", 1577 | "email": "sebastian@phpunit.de", 1578 | "role": "lead" 1579 | } 1580 | ], 1581 | "description": "Collection of value objects that represent the types of the PHP type system", 1582 | "homepage": "https://github.com/sebastianbergmann/type", 1583 | "support": { 1584 | "issues": "https://github.com/sebastianbergmann/type/issues", 1585 | "security": "https://github.com/sebastianbergmann/type/security/policy", 1586 | "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" 1587 | }, 1588 | "funding": [ 1589 | { 1590 | "url": "https://github.com/sebastianbergmann", 1591 | "type": "github" 1592 | } 1593 | ], 1594 | "time": "2024-09-17T13:12:04+00:00" 1595 | }, 1596 | { 1597 | "name": "sebastian/version", 1598 | "version": "5.0.2", 1599 | "source": { 1600 | "type": "git", 1601 | "url": "https://github.com/sebastianbergmann/version.git", 1602 | "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" 1603 | }, 1604 | "dist": { 1605 | "type": "zip", 1606 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", 1607 | "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", 1608 | "shasum": "" 1609 | }, 1610 | "require": { 1611 | "php": ">=8.2" 1612 | }, 1613 | "type": "library", 1614 | "extra": { 1615 | "branch-alias": { 1616 | "dev-main": "5.0-dev" 1617 | } 1618 | }, 1619 | "autoload": { 1620 | "classmap": [ 1621 | "src/" 1622 | ] 1623 | }, 1624 | "notification-url": "https://packagist.org/downloads/", 1625 | "license": [ 1626 | "BSD-3-Clause" 1627 | ], 1628 | "authors": [ 1629 | { 1630 | "name": "Sebastian Bergmann", 1631 | "email": "sebastian@phpunit.de", 1632 | "role": "lead" 1633 | } 1634 | ], 1635 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1636 | "homepage": "https://github.com/sebastianbergmann/version", 1637 | "support": { 1638 | "issues": "https://github.com/sebastianbergmann/version/issues", 1639 | "security": "https://github.com/sebastianbergmann/version/security/policy", 1640 | "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" 1641 | }, 1642 | "funding": [ 1643 | { 1644 | "url": "https://github.com/sebastianbergmann", 1645 | "type": "github" 1646 | } 1647 | ], 1648 | "time": "2024-10-09T05:16:32+00:00" 1649 | }, 1650 | { 1651 | "name": "squizlabs/php_codesniffer", 1652 | "version": "3.11.1", 1653 | "source": { 1654 | "type": "git", 1655 | "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", 1656 | "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87" 1657 | }, 1658 | "dist": { 1659 | "type": "zip", 1660 | "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", 1661 | "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", 1662 | "shasum": "" 1663 | }, 1664 | "require": { 1665 | "ext-simplexml": "*", 1666 | "ext-tokenizer": "*", 1667 | "ext-xmlwriter": "*", 1668 | "php": ">=5.4.0" 1669 | }, 1670 | "require-dev": { 1671 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" 1672 | }, 1673 | "bin": [ 1674 | "bin/phpcbf", 1675 | "bin/phpcs" 1676 | ], 1677 | "type": "library", 1678 | "extra": { 1679 | "branch-alias": { 1680 | "dev-master": "3.x-dev" 1681 | } 1682 | }, 1683 | "notification-url": "https://packagist.org/downloads/", 1684 | "license": [ 1685 | "BSD-3-Clause" 1686 | ], 1687 | "authors": [ 1688 | { 1689 | "name": "Greg Sherwood", 1690 | "role": "Former lead" 1691 | }, 1692 | { 1693 | "name": "Juliette Reinders Folmer", 1694 | "role": "Current lead" 1695 | }, 1696 | { 1697 | "name": "Contributors", 1698 | "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" 1699 | } 1700 | ], 1701 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 1702 | "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", 1703 | "keywords": [ 1704 | "phpcs", 1705 | "standards", 1706 | "static analysis" 1707 | ], 1708 | "support": { 1709 | "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", 1710 | "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", 1711 | "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", 1712 | "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" 1713 | }, 1714 | "funding": [ 1715 | { 1716 | "url": "https://github.com/PHPCSStandards", 1717 | "type": "github" 1718 | }, 1719 | { 1720 | "url": "https://github.com/jrfnl", 1721 | "type": "github" 1722 | }, 1723 | { 1724 | "url": "https://opencollective.com/php_codesniffer", 1725 | "type": "open_collective" 1726 | } 1727 | ], 1728 | "time": "2024-11-16T12:02:36+00:00" 1729 | }, 1730 | { 1731 | "name": "theseer/tokenizer", 1732 | "version": "1.2.3", 1733 | "source": { 1734 | "type": "git", 1735 | "url": "https://github.com/theseer/tokenizer.git", 1736 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 1737 | }, 1738 | "dist": { 1739 | "type": "zip", 1740 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 1741 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 1742 | "shasum": "" 1743 | }, 1744 | "require": { 1745 | "ext-dom": "*", 1746 | "ext-tokenizer": "*", 1747 | "ext-xmlwriter": "*", 1748 | "php": "^7.2 || ^8.0" 1749 | }, 1750 | "type": "library", 1751 | "autoload": { 1752 | "classmap": [ 1753 | "src/" 1754 | ] 1755 | }, 1756 | "notification-url": "https://packagist.org/downloads/", 1757 | "license": [ 1758 | "BSD-3-Clause" 1759 | ], 1760 | "authors": [ 1761 | { 1762 | "name": "Arne Blankerts", 1763 | "email": "arne@blankerts.de", 1764 | "role": "Developer" 1765 | } 1766 | ], 1767 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1768 | "support": { 1769 | "issues": "https://github.com/theseer/tokenizer/issues", 1770 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 1771 | }, 1772 | "funding": [ 1773 | { 1774 | "url": "https://github.com/theseer", 1775 | "type": "github" 1776 | } 1777 | ], 1778 | "time": "2024-03-03T12:36:25+00:00" 1779 | } 1780 | ], 1781 | "aliases": [], 1782 | "minimum-stability": "stable", 1783 | "stability-flags": {}, 1784 | "prefer-stable": false, 1785 | "prefer-lowest": false, 1786 | "platform": { 1787 | "php": ">=8.0" 1788 | }, 1789 | "platform-dev": {}, 1790 | "plugin-api-version": "2.6.0" 1791 | } 1792 | -------------------------------------------------------------------------------- /demo/geocode.php: -------------------------------------------------------------------------------- 1 | geocode($query); 12 | print_r($result); 13 | -------------------------------------------------------------------------------- /opencage_logo_300_150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenCageData/php-opencage-geocode/3e6f38a08d3f42476667689267fe7b1fceedb1dd/opencage_logo_300_150.png -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | opencage geocode standard 5 | 6 | 7 | 8 | 9 | 10 | 11 | ./vendor/ 12 | ./tests/bootstrap.php 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | ./tests/ 18 | tests/bootstrap.php 19 | 20 | 21 | 22 | 23 | ./src/ 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/AbstractGeocoder.php: -------------------------------------------------------------------------------- 1 | remember to match everything with the git tag 8 | 9 | const TIMEOUT = 10; 10 | const URL = 'https://api.opencagedata.com/geocode/v1/json/?'; 11 | const PROXY = null; 12 | 13 | protected $key; 14 | protected $timeout; 15 | protected $url; 16 | protected $proxy; 17 | protected $user_agent; 18 | 19 | public function __construct($key = null) 20 | { 21 | if (isset($key) && !empty($key)) { 22 | $this->setKey($key); 23 | } 24 | $this->setTimeout(self::TIMEOUT); 25 | $this->user_agent = 'opencage-php/' . self::VERSION . ' (PHP ' . phpversion() . '; ' . php_uname('s') . ' ' . php_uname('r') . ')'; 26 | } 27 | 28 | public function setKey($key) 29 | { 30 | $this->key = $key; 31 | } 32 | 33 | public function setTimeout($timeout) 34 | { 35 | $this->timeout = $timeout; 36 | } 37 | 38 | public function setProxy($proxy) 39 | { 40 | $this->proxy = $proxy; 41 | } 42 | 43 | protected function getJSON($query) 44 | { 45 | if (function_exists('curl_version') && !getenv('SKIP_CURL')) { 46 | $ret = $this->getJSONByCurl($query); 47 | return $ret; 48 | } elseif (ini_get('allow_url_fopen')) { 49 | $ret = $this->getJSONByFopen($query); 50 | return $ret; 51 | } else { 52 | throw new \Exception('PHP is not compiled with CURL support and allow_url_fopen is disabled; giving up'); 53 | } 54 | } 55 | 56 | protected function getJSONByFopen($query) 57 | { 58 | $context = stream_context_create( 59 | [ 60 | 'http' => [ 61 | 'user_agent' => $this->user_agent, 62 | 'timeout' => $this->timeout 63 | ] 64 | ] 65 | ); 66 | 67 | error_clear_last(); 68 | 69 | $ret = @file_get_contents($query); 70 | 71 | if ($ret === false) { 72 | /** NOTE: https://github.com/phpstan/phpstan/issues/3213 */ 73 | /** @phpstan-ignore-next-line */ 74 | if (isset($http_response_header) && is_array($http_response_header)) { 75 | $error_message = $http_response_header[0]; 76 | if ($error = error_get_last()) { 77 | $error_message = $error['message']; 78 | } 79 | 80 | // print "got an eror: $error\n"; 81 | if (preg_match('/ 401 /', $error_message)) { 82 | // failed to open stream: HTTP request failed! HTTP/1.1 401 Unauthorized 83 | return $this->generateErrorJSON(401, 'invalid API key'); 84 | } elseif (preg_match('/ 402 /', $error_message)) { 85 | // failed to open stream: HTTP request failed! HTTP/1.1 402 Payment Required 86 | return $this->generateErrorJSON(402, 'quota exceeded'); 87 | } 88 | } else { 89 | // failed to open stream: php_network_getaddresses: getaddrinfo failed: No address associated with hostname 90 | return $this->generateErrorJSON(498, "network issue accessing $query"); 91 | } 92 | } 93 | 94 | return $ret; 95 | } 96 | 97 | protected function generateErrorJSON($code, $message) 98 | { 99 | $response = [ 100 | 'results' => [], 101 | 'total_results' => 0, 102 | 'status' => [ 103 | 'code' => $code, 104 | 'message' => $message 105 | ] 106 | ]; 107 | return json_encode($response); 108 | } 109 | 110 | protected function getJSONByCurl($query) 111 | { 112 | $ch = curl_init(); 113 | $options = [ 114 | CURLOPT_TIMEOUT => $this->timeout, 115 | CURLOPT_URL => $query, 116 | CURLOPT_RETURNTRANSFER => 1 117 | ]; 118 | if ($this->proxy) { 119 | $options[CURLOPT_PROXY] = $this->proxy; 120 | } 121 | curl_setopt_array($ch, $options); 122 | 123 | $headers = [ 124 | 'User-Agent: ' . $this->user_agent 125 | ]; 126 | 127 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 128 | 129 | $ret = curl_exec($ch); 130 | if ($ret === false) { 131 | return $this->generateErrorJSON(498, 'network issue '.curl_error($ch)); 132 | } 133 | return $ret; 134 | } 135 | 136 | abstract public function geocode($query); 137 | } 138 | -------------------------------------------------------------------------------- /src/Geocoder.php: -------------------------------------------------------------------------------- 1 | $paramValue) { 27 | $url .= '&'.$param.'=' . urlencode($paramValue); 28 | } 29 | } 30 | 31 | if (empty($this->key)) { 32 | throw new \Exception('Missing API key'); 33 | } 34 | $url .= '&key=' . $this->key; 35 | 36 | $ret = json_decode($this->getJSON($url), true); 37 | return $ret; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/GeocoderTest.php: -------------------------------------------------------------------------------- 1 | geocode('Johannesburg'); 15 | } catch (\Exception $e) { 16 | $this->assertEquals('Missing API key', $e->getMessage()); 17 | return; 18 | } 19 | $this->fail(); 20 | } 21 | 22 | public function testInvalidKey() 23 | { 24 | $geocoder = new Geocoder('invalid-APIKEY'); 25 | $result = $geocoder->geocode('Johannesburg'); 26 | // print_r($result); 27 | $this->assertEquals(401, $result['status']['code']); 28 | $this->assertEquals('invalid API key', $result['status']['message']); 29 | } 30 | 31 | public function testNetworkRequestError() 32 | { 33 | // https://opencagedata.com/api#testingkeys 34 | $geocoder = new Geocoder('6d0e711d72d74daeb2b0bfd2a5cdfdba'); 35 | $result = $geocoder->geocode('London', ['host' => 'doesnotexist.opencagedata.com']); 36 | // print_r($result); 37 | 38 | $this->assertEquals(498, $result['status']['code']); 39 | $this->assertStringContainsString('network issue', $result['status']['message']); 40 | $this->assertStringContainsString('doesnotexist.opencagedata.com', $result['status']['message']); 41 | } 42 | 43 | public function testOverQuota() 44 | { 45 | // https://opencagedata.com/api#testingkeys 46 | $geocoder = new Geocoder('4372eff77b8343cebfc843eb4da4ddc4'); 47 | $result = $geocoder->geocode('Johannesburg'); 48 | $this->assertEquals(402, $result['status']['code']); 49 | $this->assertEquals('quota exceeded', $result['status']['message']); 50 | } 51 | 52 | public function testLondon() 53 | { 54 | // https://opencagedata.com/api#testingkeys 55 | $geocoder = new Geocoder('6d0e711d72d74daeb2b0bfd2a5cdfdba'); 56 | $query = "82 Clerkenwell Road, London"; 57 | $result = $geocoder->geocode($query); 58 | 59 | // print_r($result); 60 | 61 | $this->assertEquals(200, $result['status']['code']); 62 | $this->assertEquals('OK', $result['status']['message']); 63 | } 64 | 65 | public function testProxy() 66 | { 67 | $proxy = getenv('PROXY'); 68 | if (!$proxy) { 69 | $this->markTestSkipped('PROXY environment variable not set'); 70 | } 71 | // https://opencagedata.com/api#testingkeys 72 | $geocoder = new Geocoder('6d0e711d72d74daeb2b0bfd2a5cdfdba'); 73 | $geocoder->setProxy($proxy); 74 | $query = "82 Clerkenwell Road, London"; 75 | $result = $geocoder->geocode($query); 76 | 77 | // print_r($result); 78 | 79 | $this->assertEquals(200, $result['status']['code']); 80 | $this->assertEquals('OK', $result['status']['message']); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 |