├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .php_cs ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── composer.json ├── etc └── composer-schema.json ├── phpunit.xml └── src ├── ConfigurationReader.php ├── ConfigurationValidator.php ├── Element ├── AbstractRepository.php ├── ArchiveConfiguration.php ├── Author.php ├── Configuration.php ├── InstallationMethod.php ├── PackageRepository.php ├── PackagistRepository.php ├── ProjectConfiguration.php ├── Repository.php ├── RepositoryInterface.php ├── ScriptConfiguration.php ├── Stability.php ├── SupportInformation.php └── VcsChangePolicy.php ├── Exception ├── ConfigurationExceptionInterface.php ├── ConfigurationReadException.php ├── InvalidConfigurationException.php ├── InvalidJsonException.php └── UndefinedPropertyException.php └── ObjectAccess.php /.gitattributes: -------------------------------------------------------------------------------- 1 | /test/ export-ignore 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | pull_request: 5 | schedule: 6 | - cron: 0 14 * * 0 # Sunday 2PM UTC = Monday 12AM AEST 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | php: ['7.2', '7.3', '7.4'] 14 | name: PHP ${{ matrix.php }} 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v1 18 | - name: Set up PHP 19 | uses: shivammathur/setup-php@master 20 | with: 21 | php-version: ${{ matrix.php }} 22 | extensions: mbstring 23 | coverage: pcov 24 | - name: Check PHP version 25 | run: php -v 26 | - name: Install dependencies 27 | run: make vendor 28 | - name: Make 29 | run: make ci 30 | - name: Upload coverage reports 31 | if: success() 32 | run: | 33 | test ! -z "$TOKEN" 34 | bash <(curl -s https://codecov.io/bash) -t "$TOKEN" -B "${{ github.ref }}" 35 | env: 36 | TOKEN: "${{ secrets.CODECOV_TOKEN }}" 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.makefiles/ 2 | /artifacts/ 3 | /composer.lock 4 | /vendor/ 5 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | setCacheFile(__DIR__ . '/artifacts/lint/php-cs-fixer/cache'); 5 | 6 | return $config; 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Composer configuration reader changelog 2 | 3 | ## 3.0.0 (2020-11-16) 4 | 5 | - **[BC BREAK]** PHP <7.2 is no longer supported. 6 | 7 | ## 2.1.0 (2017-11-02) 8 | 9 | - **[IMPROVED]** Added support for maps in `config.preferred-install` ([#12]). 10 | 11 | [#12]: https://github.com/eloquent/composer-config-reader/issues/12 12 | 13 | ## 2.0.2 (2016-12-20) 14 | 15 | - **[IMPROVED]** Removed dependency on [Isolator]. 16 | - **[FIXED]** Configurations that use repository name can now be parsed 17 | ([#10], [#11] - thanks [@spipu]). 18 | 19 | [#10]: https://github.com/eloquent/composer-config-reader/issues/10 20 | [#11]: https://github.com/eloquent/composer-config-reader/pull/11 21 | [@spipu]: https://github.com/spipu 22 | [isolator]: https://github.com/IcecaveStudios/isolator 23 | 24 | ## 2.0.1 (2016-06-23) 25 | 26 | - **[FIXED]** Configurations that disable the Packagist repo can now be parsed 27 | ([#7]). 28 | 29 | [#7]: https://github.com/eloquent/composer-config-reader/issues/7 30 | 31 | ## 2.0.0 (2014-01-22) 32 | 33 | - **[BC BREAK]** Element class constructors expanded to accomodate new Composer 34 | configuration settings 35 | - **[BC BREAK]** `Domain` namespace renamed to `Element` 36 | - **[BC BREAK]** Interfaces renamed to match naming conventions 37 | - **[BC BREAK]** Method names containing acronyms are now CamelCased properly 38 | - **[BC BREAK]** All enumerations have updated APIs as per enumeration version 39 | upgrade 40 | - **[MAINTENANCE]** General repository maintenance 41 | 42 | ## 1.1.2 (2013-03-04) 43 | 44 | - **[NEW]** [Archer] integration 45 | - **[NEW]** Implemented changelog 46 | 47 | [archer]: https://github.com/IcecaveStudios/archer 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | As a guideline, please follow this process when contributing: 4 | 5 | 1. [Fork the repository] 6 | 2. [Create a branch] 7 | 3. Make your changes 8 | 4. Use `make precommit` to run tests and code style checks 9 | 5. [Squash commits] if necessary 10 | 6. [Create a pull request] 11 | 12 | [create a branch]: https://help.github.com/articles/about-branches 13 | [create a pull request]: https://help.github.com/articles/creating-a-pull-request 14 | [fork the repository]: https://help.github.com/articles/fork-a-repo 15 | [squash commits]: https://help.github.com/articles/about-git-rebase 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2020 Erin Millard 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Powered by https://makefiles.dev/ 2 | 3 | PHP_SOURCE_FILES += etc/composer-schema.json 4 | 5 | -include .makefiles/Makefile 6 | -include .makefiles/pkg/php/v1/Makefile 7 | 8 | .makefiles/%: 9 | @curl -sfL https://makefiles.dev/v1 | bash /dev/stdin "$@" 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > # No longer maintained 2 | > 3 | > This package is no longer maintained. See [this statement] for more info. 4 | > 5 | > [this statement]: https://gist.github.com/ezzatron/713a548735febe3d76f8ca831bc895c0# Phony for PHPUnit 6 | 7 | # Composer configuration reader 8 | 9 | *A light-weight component for reading Composer configuration files.* 10 | 11 | [![Current version image][version-image]][current version] 12 | [![Current build status image][build-image]][current build status] 13 | [![Current coverage status image][coverage-image]][current coverage status] 14 | 15 | [build-image]: http://img.shields.io/travis/eloquent/composer-config-reader/master.svg?style=flat-square "Current build status for the master branch" 16 | [coverage-image]: https://img.shields.io/codecov/c/github/eloquent/composer-config-reader/master.svg?style=flat-square "Current test coverage for the master branch" 17 | [current build status]: https://travis-ci.org/eloquent/composer-config-reader 18 | [current coverage status]: https://codecov.io/github/eloquent/composer-config-reader 19 | [current version]: https://packagist.org/packages/eloquent/composer-config-reader 20 | [version-image]: https://img.shields.io/packagist/v/eloquent/composer-config-reader.svg?style=flat-square "This project uses semantic versioning" 21 | 22 | ## Installation and documentation 23 | 24 | - Available as [Composer] package [eloquent/composer-config-reader]. 25 | 26 | [composer]: http://getcomposer.org/ 27 | [eloquent/composer-config-reader]: https://packagist.org/packages/eloquent/composer-config-reader 28 | 29 | ## Usage 30 | 31 | Composer configuration reader is very simple to use, and a quick example should 32 | be self-explanatory: 33 | 34 | ```php 35 | $reader = new Eloquent\Composer\Configuration\ConfigurationReader; 36 | $configuration = $reader->read('/path/to/composer.json'); 37 | 38 | echo $configuration->name(); // outputs the package name 39 | ``` 40 | 41 | ## Configuration objects 42 | 43 | The following are the objects used to represent the configuration information. 44 | For a more detailed overview of the data available, simply look through the 45 | class definition (these classes are very simple). 46 | 47 | The following classes all exist in the `Eloquent\Composer\Configuration\Element` 48 | namespace. 49 | 50 | ### [Configuration] 51 | 52 | This is the main configuration object and has methods to access all the 53 | information available in the [Composer schema]. 54 | 55 | [composer schema]: http://getcomposer.org/doc/04-schema.md 56 | [configuration]: src/Element/Configuration.php 57 | 58 | #### Example methods 59 | 60 | * `name()`: The package name. 61 | * `description()`: The package description. 62 | * `dependencies()`: Equivalent to Composer `require`. 63 | * `devDependencies()`: Equivalent to Composer `require-dev`. 64 | * `autoloadPSR0()`: The autoload information for PSR-0 namespaces/paths. 65 | * `autoloadClassmap()`: The autoload information for classmapped paths. 66 | 67 | #### Helper methods 68 | 69 | A number of helper methods exist on the main configuration object to simplify 70 | the process of extracting useful information: 71 | 72 | * `projectName()`: The project name without the vendor prefix. 73 | * `vendorName()`: The vendor name without the project suffix. 74 | * `allDependencies()`: Combines `require` and `require-dev` into a single array. 75 | * `allPSR0SourcePaths()`: A flat array of all PSR-0-compliant source paths. 76 | * `allSourcePaths()`: A flat array of all source paths. 77 | 78 | ### [Repository], [PackageRepository] 79 | 80 | These objects describe the package's defined repositories. 81 | 82 | All repositories are represented by the `Repository` class, except for 83 | package-type repositories which use the `PackageRepository` class. 84 | 85 | See [Repositories]. 86 | 87 | [packagerepository]: src/Element/PackageRepository.php 88 | [repositories]: http://getcomposer.org/doc/05-repositories.md 89 | [repository]: src/Element/Repository.php 90 | 91 | #### Example methods 92 | 93 | * `type()`: The repository type. 94 | * `url()`: The repository URL (not available for `PackageRepository`). 95 | 96 | ### [Stability] 97 | 98 | This object is an [enumeration] of package stabilities, with the following 99 | members: 100 | 101 | * DEV 102 | * ALPHA 103 | * BETA 104 | * RC 105 | * STABLE 106 | 107 | It is currently only used to represent the value of the [minimum-stability] 108 | option. 109 | 110 | [enumeration]: https://github.com/eloquent/enumeration 111 | [minimum-stability]: http://getcomposer.org/doc/04-schema.md#minimum-stability 112 | [stability]: src/Element/Stability.php 113 | 114 | ### [Author] 115 | 116 | This object contains all information provided for a specific author. 117 | 118 | See [authors]. 119 | 120 | [author]: src/Element/Author.php 121 | [authors]: http://getcomposer.org/doc/04-schema.md#authors 122 | 123 | #### Example methods 124 | 125 | * `name()`: The author's name. 126 | * `email()`: The author's email address. 127 | 128 | ### [SupportInformation] 129 | 130 | This object describes the package's support contact information. 131 | 132 | See [support]. 133 | 134 | [support]: http://getcomposer.org/doc/04-schema.md#support 135 | [supportinformation]: src/Element/SupportInformation.php 136 | 137 | #### Example methods 138 | 139 | * `email()`: The support email address. 140 | * `issues()`: The URL of the issue tracking system. 141 | * `wiki()`: The URL of the wiki system. 142 | 143 | ### [ProjectConfiguration] 144 | 145 | This object describes configuration options specific to end-projects, such as 146 | the target directories for various resources provided by Composer. 147 | 148 | See [config]. 149 | 150 | [config]: http://getcomposer.org/doc/04-schema.md#config 151 | [projectconfiguration]: src/Element/ProjectConfiguration.php 152 | 153 | #### Example methods 154 | 155 | * `vendorDir()`: The project's vendor directory path. 156 | * `binDir()`: The project's binary directory path. 157 | 158 | ### [ScriptConfiguration] 159 | 160 | This object describes the Composer scripts defined by the package. 161 | 162 | See [Scripts]. 163 | 164 | [scriptconfiguration]: src/Element/ScriptConfiguration.php 165 | [scripts]: http://getcomposer.org/doc/articles/scripts.md 166 | 167 | #### Example methods 168 | 169 | * `preInstallCmd()`: The pre-install scripts. 170 | * `postInstallCmd()`: The post-install scripts. 171 | 172 | ### [ArchiveConfiguration] 173 | 174 | This object describes the settings for creating package archives. 175 | 176 | See [archive]. 177 | 178 | [archive]: http://getcomposer.org/doc/04-schema.md#archive 179 | [archiveconfiguration]: src/Element/ArchiveConfiguration.php 180 | 181 | #### Example methods 182 | 183 | * `exclude()`: A list of file exclusion patterns. 184 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eloquent/composer-config-reader", 3 | "description": "A light-weight component for reading Composer configuration files.", 4 | "keywords": ["composer", "configuration", "reader", "parser"], 5 | "homepage": "https://github.com/eloquent/composer-config-reader", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Erin Millard", 10 | "email": "ezzatron@gmail.com", 11 | "homepage": "http://ezzatron.com/" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=7.2", 16 | "eloquent/enumeration": "^6", 17 | "justinrainbow/json-schema": "^5" 18 | }, 19 | "require-dev": { 20 | "eloquent/code-style": "^1", 21 | "eloquent/phony-phpunit": "^6", 22 | "friendsofphp/php-cs-fixer": "^2", 23 | "phpunit/phpunit": "^8" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Eloquent\\Composer\\Configuration\\": "src" 28 | } 29 | }, 30 | "extra": { 31 | "branch-alias": { 32 | "dev-master": "3.0.x-dev" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /etc/composer-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "name": "Package", 4 | "type": "object", 5 | "additionalProperties": true, 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "Package name, including 'vendor-name/' prefix." 10 | }, 11 | "type": { 12 | "description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.", 13 | "type": "string", 14 | "pattern": "^[a-z0-9-]+$" 15 | }, 16 | "target-dir": { 17 | "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.", 18 | "type": "string" 19 | }, 20 | "description": { 21 | "type": "string", 22 | "description": "Short package description." 23 | }, 24 | "keywords": { 25 | "type": "array", 26 | "items": { 27 | "type": "string", 28 | "description": "A tag/keyword that this package relates to." 29 | } 30 | }, 31 | "homepage": { 32 | "type": "string", 33 | "description": "Homepage URL for the project.", 34 | "format": "uri" 35 | }, 36 | "readme": { 37 | "type": "string", 38 | "description": "Relative path to the readme document." 39 | }, 40 | "version": { 41 | "type": "string", 42 | "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.", 43 | "pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?|^dev-" 44 | }, 45 | "time": { 46 | "type": "string", 47 | "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format." 48 | }, 49 | "license": { 50 | "type": ["string", "array"], 51 | "description": "License name. Or an array of license names." 52 | }, 53 | "authors": { 54 | "$ref": "#/definitions/authors" 55 | }, 56 | "require": { 57 | "type": "object", 58 | "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.", 59 | "additionalProperties": { 60 | "type": "string" 61 | } 62 | }, 63 | "replace": { 64 | "type": "object", 65 | "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.", 66 | "additionalProperties": { 67 | "type": "string" 68 | } 69 | }, 70 | "conflict": { 71 | "type": "object", 72 | "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.", 73 | "additionalProperties": { 74 | "type": "string" 75 | } 76 | }, 77 | "provide": { 78 | "type": "object", 79 | "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.", 80 | "additionalProperties": { 81 | "type": "string" 82 | } 83 | }, 84 | "require-dev": { 85 | "type": "object", 86 | "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).", 87 | "additionalProperties": { 88 | "type": "string" 89 | } 90 | }, 91 | "suggest": { 92 | "type": "object", 93 | "description": "This is a hash of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).", 94 | "additionalProperties": { 95 | "type": "string" 96 | } 97 | }, 98 | "config": { 99 | "type": "object", 100 | "description": "Composer options.", 101 | "properties": { 102 | "process-timeout": { 103 | "type": "integer", 104 | "description": "The timeout in seconds for process executions, defaults to 300 (5mins)." 105 | }, 106 | "use-include-path": { 107 | "type": "boolean", 108 | "description": "If true, the Composer autoloader will also look for classes in the PHP include path." 109 | }, 110 | "preferred-install": { 111 | "type": ["string", "object"], 112 | "description": "The install method Composer will prefer to use, defaults to auto and can be any of source, dist, auto, or a hash of {\"pattern\": \"preference\"}." 113 | }, 114 | "notify-on-install": { 115 | "type": "boolean", 116 | "description": "Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour, defaults to true." 117 | }, 118 | "github-protocols": { 119 | "type": "array", 120 | "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].", 121 | "items": { 122 | "type": "string" 123 | } 124 | }, 125 | "github-oauth": { 126 | "type": "object", 127 | "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"\"}.", 128 | "additionalProperties": { 129 | "type": "string" 130 | } 131 | }, 132 | "gitlab-oauth": { 133 | "type": "object", 134 | "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"\"}.", 135 | "additionalProperties": { 136 | "type": "string" 137 | } 138 | }, 139 | "gitlab-token": { 140 | "type": "object", 141 | "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"\"}.", 142 | "additionalProperties": { 143 | "type": "string" 144 | } 145 | }, 146 | "bearer": { 147 | "type": "object", 148 | "description": "A hash of domain name => bearer authentication token, for example {\"example.com\":\"\"}.", 149 | "additionalProperties": { 150 | "type": "string" 151 | } 152 | }, 153 | "disable-tls": { 154 | "type": "boolean", 155 | "description": "Defaults to `false`. If set to true all HTTPS URLs will be tried with HTTP instead and no network level encryption is performed. Enabling this is a security risk and is NOT recommended. The better way is to enable the php_openssl extension in php.ini." 156 | }, 157 | "secure-http": { 158 | "type": "boolean", 159 | "description": "Defaults to `true`. If set to true only HTTPS URLs are allowed to be downloaded via Composer. If you really absolutely need HTTP access to something then you can disable it, but using \"Let's Encrypt\" to get a free SSL certificate is generally a better alternative." 160 | }, 161 | "cafile": { 162 | "type": "string", 163 | "description": "A way to set the path to the openssl CA file. In PHP 5.6+ you should rather set this via openssl.cafile in php.ini, although PHP 5.6+ should be able to detect your system CA file automatically." 164 | }, 165 | "capath": { 166 | "type": "string", 167 | "description": "If cafile is not specified or if the certificate is not found there, the directory pointed to by capath is searched for a suitable certificate. capath must be a correctly hashed certificate directory." 168 | }, 169 | "http-basic": { 170 | "type": "object", 171 | "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.", 172 | "additionalProperties": { 173 | "type": "object", 174 | "required": ["username", "password"], 175 | "properties": { 176 | "username": { 177 | "type": "string", 178 | "description": "The username used for HTTP Basic authentication" 179 | }, 180 | "password": { 181 | "type": "string", 182 | "description": "The password used for HTTP Basic authentication" 183 | } 184 | } 185 | } 186 | }, 187 | "store-auths": { 188 | "type": ["string", "boolean"], 189 | "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt." 190 | }, 191 | "platform": { 192 | "type": "object", 193 | "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.", 194 | "additionalProperties": { 195 | "type": "string" 196 | } 197 | }, 198 | "vendor-dir": { 199 | "type": "string", 200 | "description": "The location where all packages are installed, defaults to \"vendor\"." 201 | }, 202 | "bin-dir": { 203 | "type": "string", 204 | "description": "The location where all binaries are linked, defaults to \"vendor/bin\"." 205 | }, 206 | "data-dir": { 207 | "type": "string", 208 | "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes." 209 | }, 210 | "cache-dir": { 211 | "type": "string", 212 | "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows." 213 | }, 214 | "cache-files-dir": { 215 | "type": "string", 216 | "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"." 217 | }, 218 | "cache-repo-dir": { 219 | "type": "string", 220 | "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"." 221 | }, 222 | "cache-vcs-dir": { 223 | "type": "string", 224 | "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"." 225 | }, 226 | "cache-ttl": { 227 | "type": "integer", 228 | "description": "The default cache time-to-live, defaults to 15552000 (6 months)." 229 | }, 230 | "cache-files-ttl": { 231 | "type": "integer", 232 | "description": "The cache time-to-live for files, defaults to the value of cache-ttl." 233 | }, 234 | "cache-files-maxsize": { 235 | "type": ["string", "integer"], 236 | "description": "The cache max size for the files cache, defaults to \"300MiB\"." 237 | }, 238 | "bin-compat": { 239 | "enum": ["auto", "full"], 240 | "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)." 241 | }, 242 | "discard-changes": { 243 | "type": ["string", "boolean"], 244 | "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"." 245 | }, 246 | "autoloader-suffix": { 247 | "type": "string", 248 | "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated." 249 | }, 250 | "optimize-autoloader": { 251 | "type": "boolean", 252 | "description": "Always optimize when dumping the autoloader." 253 | }, 254 | "prepend-autoloader": { 255 | "type": "boolean", 256 | "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true." 257 | }, 258 | "classmap-authoritative": { 259 | "type": "boolean", 260 | "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false." 261 | }, 262 | "apcu-autoloader": { 263 | "type": "boolean", 264 | "description": "If true, the Composer autoloader will check for APCu and use it to cache found/not-found classes when the extension is enabled, defaults to false." 265 | }, 266 | "github-domains": { 267 | "type": "array", 268 | "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].", 269 | "items": { 270 | "type": "string" 271 | } 272 | }, 273 | "github-expose-hostname": { 274 | "type": "boolean", 275 | "description": "Defaults to true. If set to false, the OAuth tokens created to access the github API will have a date instead of the machine hostname." 276 | }, 277 | "gitlab-domains": { 278 | "type": "array", 279 | "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].", 280 | "items": { 281 | "type": "string" 282 | } 283 | }, 284 | "use-github-api": { 285 | "type": "boolean", 286 | "description": "Defaults to true. If set to false, globally disables the use of the GitHub API for all GitHub repositories and clones the repository as it would for any other repository." 287 | }, 288 | "archive-format": { 289 | "type": "string", 290 | "description": "The default archiving format when not provided on cli, defaults to \"tar\"." 291 | }, 292 | "archive-dir": { 293 | "type": "string", 294 | "description": "The default archive path when not provided on cli, defaults to \".\"." 295 | }, 296 | "htaccess-protect": { 297 | "type": "boolean", 298 | "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories." 299 | }, 300 | "sort-packages": { 301 | "type": "boolean", 302 | "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency." 303 | }, 304 | "lock": { 305 | "type": "boolean", 306 | "description": "Defaults to true. If set to false, Composer will not create a composer.lock file." 307 | } 308 | } 309 | }, 310 | "extra": { 311 | "type": ["object", "array"], 312 | "description": "Arbitrary extra data that can be used by plugins, for example, package of type composer-plugin may have a 'class' key defining an installer class name.", 313 | "additionalProperties": true 314 | }, 315 | "autoload": { 316 | "$ref": "#/definitions/autoload" 317 | }, 318 | "autoload-dev": { 319 | "type": "object", 320 | "description": "Description of additional autoload rules for development purpose (eg. a test suite).", 321 | "properties": { 322 | "psr-0": { 323 | "type": "object", 324 | "description": "This is a hash of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.", 325 | "additionalProperties": { 326 | "type": ["string", "array"], 327 | "items": { 328 | "type": "string" 329 | } 330 | } 331 | }, 332 | "psr-4": { 333 | "type": "object", 334 | "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", 335 | "additionalProperties": { 336 | "type": ["string", "array"], 337 | "items": { 338 | "type": "string" 339 | } 340 | } 341 | }, 342 | "classmap": { 343 | "type": "array", 344 | "description": "This is an array of directories that contain classes to be included in the class-map generation process." 345 | }, 346 | "files": { 347 | "type": "array", 348 | "description": "This is an array of files that are always required on every request." 349 | } 350 | } 351 | }, 352 | "archive": { 353 | "type": ["object"], 354 | "description": "Options for creating package archives for distribution.", 355 | "properties": { 356 | "exclude": { 357 | "type": "array", 358 | "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark." 359 | } 360 | } 361 | }, 362 | "repositories": { 363 | "type": ["object", "array"], 364 | "description": "A set of additional repositories where packages can be found.", 365 | "additionalProperties": { 366 | "anyOf": [ 367 | { "$ref": "#/definitions/repository" }, 368 | { "type": "boolean", "enum": [false] } 369 | ] 370 | }, 371 | "items": { 372 | "anyOf": [ 373 | { "$ref": "#/definitions/repository" }, 374 | { 375 | "type": "object", 376 | "additionalProperties": { "type": "boolean", "enum": [false] }, 377 | "minProperties": 1, 378 | "maxProperties": 1 379 | } 380 | ] 381 | } 382 | }, 383 | "minimum-stability": { 384 | "type": ["string"], 385 | "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.", 386 | "pattern": "^dev|alpha|beta|rc|RC|stable$" 387 | }, 388 | "prefer-stable": { 389 | "type": ["boolean"], 390 | "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages." 391 | }, 392 | "bin": { 393 | "type": ["string", "array"], 394 | "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).", 395 | "items": { 396 | "type": "string" 397 | } 398 | }, 399 | "include-path": { 400 | "type": ["array"], 401 | "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.", 402 | "items": { 403 | "type": "string" 404 | } 405 | }, 406 | "scripts": { 407 | "type": ["object"], 408 | "description": "Script listeners that will be executed before/after some events.", 409 | "properties": { 410 | "pre-install-cmd": { 411 | "type": ["array", "string"], 412 | "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands." 413 | }, 414 | "post-install-cmd": { 415 | "type": ["array", "string"], 416 | "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands." 417 | }, 418 | "pre-update-cmd": { 419 | "type": ["array", "string"], 420 | "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands." 421 | }, 422 | "post-update-cmd": { 423 | "type": ["array", "string"], 424 | "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands." 425 | }, 426 | "pre-status-cmd": { 427 | "type": ["array", "string"], 428 | "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands." 429 | }, 430 | "post-status-cmd": { 431 | "type": ["array", "string"], 432 | "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands." 433 | }, 434 | "pre-package-install": { 435 | "type": ["array", "string"], 436 | "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands." 437 | }, 438 | "post-package-install": { 439 | "type": ["array", "string"], 440 | "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands." 441 | }, 442 | "pre-package-update": { 443 | "type": ["array", "string"], 444 | "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands." 445 | }, 446 | "post-package-update": { 447 | "type": ["array", "string"], 448 | "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands." 449 | }, 450 | "pre-package-uninstall": { 451 | "type": ["array", "string"], 452 | "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands." 453 | }, 454 | "post-package-uninstall": { 455 | "type": ["array", "string"], 456 | "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands." 457 | }, 458 | "pre-autoload-dump": { 459 | "type": ["array", "string"], 460 | "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands." 461 | }, 462 | "post-autoload-dump": { 463 | "type": ["array", "string"], 464 | "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands." 465 | }, 466 | "post-root-package-install": { 467 | "type": ["array", "string"], 468 | "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands." 469 | }, 470 | "post-create-project-cmd": { 471 | "type": ["array", "string"], 472 | "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands." 473 | } 474 | } 475 | }, 476 | "scripts-descriptions": { 477 | "type": ["object"], 478 | "description": "Descriptions for custom commands, shown in console help.", 479 | "additionalProperties": { 480 | "type": "string" 481 | } 482 | }, 483 | "support": { 484 | "type": "object", 485 | "properties": { 486 | "email": { 487 | "type": "string", 488 | "description": "Email address for support.", 489 | "format": "email" 490 | }, 491 | "issues": { 492 | "type": "string", 493 | "description": "URL to the issue tracker.", 494 | "format": "uri" 495 | }, 496 | "forum": { 497 | "type": "string", 498 | "description": "URL to the forum.", 499 | "format": "uri" 500 | }, 501 | "wiki": { 502 | "type": "string", 503 | "description": "URL to the wiki.", 504 | "format": "uri" 505 | }, 506 | "irc": { 507 | "type": "string", 508 | "description": "IRC channel for support, as irc://server/channel.", 509 | "format": "uri" 510 | }, 511 | "chat": { 512 | "type": "string", 513 | "description": "URL to the support chat.", 514 | "format": "uri" 515 | }, 516 | "source": { 517 | "type": "string", 518 | "description": "URL to browse or download the sources.", 519 | "format": "uri" 520 | }, 521 | "docs": { 522 | "type": "string", 523 | "description": "URL to the documentation.", 524 | "format": "uri" 525 | }, 526 | "rss": { 527 | "type": "string", 528 | "description": "URL to the RSS feed.", 529 | "format": "uri" 530 | } 531 | } 532 | }, 533 | "funding": { 534 | "type": "array", 535 | "description": "A list of options to fund the development and maintenance of the package.", 536 | "items": { 537 | "type": "object", 538 | "properties": { 539 | "type": { 540 | "type": "string", 541 | "description": "Type of funding or platform through which funding is possible." 542 | }, 543 | "url": { 544 | "type": "string", 545 | "description": "URL to a website with details on funding and a way to fund the package.", 546 | "format": "uri" 547 | } 548 | } 549 | } 550 | }, 551 | "non-feature-branches": { 552 | "type": ["array"], 553 | "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.", 554 | "items": { 555 | "type": "string" 556 | } 557 | }, 558 | "abandoned": { 559 | "type": ["boolean", "string"], 560 | "description": "Indicates whether this package has been abandoned, it can be boolean or a package name/URL pointing to a recommended alternative. Defaults to false." 561 | }, 562 | "_comment": { 563 | "type": ["array", "string"], 564 | "description": "A key to store comments in" 565 | } 566 | }, 567 | "definitions": { 568 | "authors": { 569 | "type": "array", 570 | "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.", 571 | "items": { 572 | "type": "object", 573 | "additionalProperties": false, 574 | "required": [ "name"], 575 | "properties": { 576 | "name": { 577 | "type": "string", 578 | "description": "Full name of the author." 579 | }, 580 | "email": { 581 | "type": "string", 582 | "description": "Email address of the author.", 583 | "format": "email" 584 | }, 585 | "homepage": { 586 | "type": "string", 587 | "description": "Homepage URL for the author.", 588 | "format": "uri" 589 | }, 590 | "role": { 591 | "type": "string", 592 | "description": "Author's role in the project." 593 | } 594 | } 595 | } 596 | }, 597 | "autoload": { 598 | "type": "object", 599 | "description": "Description of how the package can be autoloaded.", 600 | "properties": { 601 | "psr-0": { 602 | "type": "object", 603 | "description": "This is a hash of namespaces (keys) and the directories they can be found in (values, can be arrays of paths) by the autoloader.", 604 | "additionalProperties": { 605 | "type": ["string", "array"], 606 | "items": { 607 | "type": "string" 608 | } 609 | } 610 | }, 611 | "psr-4": { 612 | "type": "object", 613 | "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", 614 | "additionalProperties": { 615 | "type": ["string", "array"], 616 | "items": { 617 | "type": "string" 618 | } 619 | } 620 | }, 621 | "classmap": { 622 | "type": "array", 623 | "description": "This is an array of directories that contain classes to be included in the class-map generation process." 624 | }, 625 | "files": { 626 | "type": "array", 627 | "description": "This is an array of files that are always required on every request." 628 | }, 629 | "exclude-from-classmap": { 630 | "type": "array", 631 | "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]" 632 | } 633 | } 634 | }, 635 | "repository": { 636 | "type": "object", 637 | "anyOf": [ 638 | { "$ref": "#/definitions/composer-repository" }, 639 | { "$ref": "#/definitions/vcs-repository" }, 640 | { "$ref": "#/definitions/path-repository" }, 641 | { "$ref": "#/definitions/artifact-repository" }, 642 | { "$ref": "#/definitions/pear-repository" }, 643 | { "$ref": "#/definitions/package-repository" } 644 | ] 645 | }, 646 | "composer-repository": { 647 | "type": "object", 648 | "required": ["type", "url"], 649 | "properties": { 650 | "type": { "type": "string", "enum": ["composer"] }, 651 | "url": { "type": "string" }, 652 | "options": { 653 | "type": "object", 654 | "additionalProperties": true 655 | }, 656 | "allow_ssl_downgrade": { "type": "boolean" }, 657 | "force-lazy-providers": { "type": "boolean" } 658 | } 659 | }, 660 | "vcs-repository": { 661 | "type": "object", 662 | "required": ["type", "url"], 663 | "properties": { 664 | "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] }, 665 | "url": { "type": "string" }, 666 | "no-api": { "type": "boolean" }, 667 | "secure-http": { "type": "boolean" }, 668 | "svn-cache-credentials": { "type": "boolean" }, 669 | "trunk-path": { "type": ["string", "boolean"] }, 670 | "branches-path": { "type": ["string", "boolean"] }, 671 | "tags-path": { "type": ["string", "boolean"] }, 672 | "package-path": { "type": "string" }, 673 | "depot": { "type": "string" }, 674 | "branch": { "type": "string" }, 675 | "unique_perforce_client_name": { "type": "string" }, 676 | "p4user": { "type": "string" }, 677 | "p4password": { "type": "string" } 678 | } 679 | }, 680 | "path-repository": { 681 | "type": "object", 682 | "required": ["type", "url"], 683 | "properties": { 684 | "type": { "type": "string", "enum": ["path"] }, 685 | "url": { "type": "string" }, 686 | "options": { 687 | "type": "object", 688 | "properties": { 689 | "symlink": { "type": ["boolean", "null"] } 690 | }, 691 | "additionalProperties": true 692 | } 693 | } 694 | }, 695 | "artifact-repository": { 696 | "type": "object", 697 | "required": ["type", "url"], 698 | "properties": { 699 | "type": { "type": "string", "enum": ["artifact"] }, 700 | "url": { "type": "string" } 701 | } 702 | }, 703 | "pear-repository": { 704 | "type": "object", 705 | "required": ["type", "url"], 706 | "properties": { 707 | "type": { "type": "string", "enum": ["pear"] }, 708 | "url": { "type": "string" }, 709 | "vendor-alias": { "type": "string" } 710 | } 711 | }, 712 | "package-repository": { 713 | "type": "object", 714 | "required": ["type", "package"], 715 | "properties": { 716 | "type": { "type": "string", "enum": ["package"] }, 717 | "package": { 718 | "oneOf": [ 719 | { "$ref": "#/definitions/inline-package" }, 720 | { 721 | "type": "array", 722 | "items": { "$ref": "#/definitions/inline-package" } 723 | } 724 | ] 725 | } 726 | } 727 | }, 728 | "inline-package": { 729 | "type": "object", 730 | "required": ["name", "version"], 731 | "properties": { 732 | "name": { 733 | "type": "string", 734 | "description": "Package name, including 'vendor-name/' prefix." 735 | }, 736 | "type": { 737 | "type": "string" 738 | }, 739 | "target-dir": { 740 | "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.", 741 | "type": "string" 742 | }, 743 | "description": { 744 | "type": "string" 745 | }, 746 | "keywords": { 747 | "type": "array", 748 | "items": { 749 | "type": "string" 750 | } 751 | }, 752 | "homepage": { 753 | "type": "string", 754 | "format": "uri" 755 | }, 756 | "version": { 757 | "type": "string" 758 | }, 759 | "time": { 760 | "type": "string" 761 | }, 762 | "license": { 763 | "type": [ 764 | "string", 765 | "array" 766 | ] 767 | }, 768 | "authors": { 769 | "$ref": "#/definitions/authors" 770 | }, 771 | "require": { 772 | "type": "object", 773 | "additionalProperties": { 774 | "type": "string" 775 | } 776 | }, 777 | "replace": { 778 | "type": "object", 779 | "additionalProperties": { 780 | "type": "string" 781 | } 782 | }, 783 | "conflict": { 784 | "type": "object", 785 | "additionalProperties": { 786 | "type": "string" 787 | } 788 | }, 789 | "provide": { 790 | "type": "object", 791 | "additionalProperties": { 792 | "type": "string" 793 | } 794 | }, 795 | "require-dev": { 796 | "type": "object", 797 | "additionalProperties": { 798 | "type": "string" 799 | } 800 | }, 801 | "suggest": { 802 | "type": "object", 803 | "additionalProperties": { 804 | "type": "string" 805 | } 806 | }, 807 | "extra": { 808 | "type": ["object", "array"], 809 | "additionalProperties": true 810 | }, 811 | "autoload": { 812 | "$ref": "#/definitions/autoload" 813 | }, 814 | "archive": { 815 | "type": ["object"], 816 | "properties": { 817 | "exclude": { 818 | "type": "array" 819 | } 820 | } 821 | }, 822 | "bin": { 823 | "type": ["string", "array"], 824 | "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).", 825 | "items": { 826 | "type": "string" 827 | } 828 | }, 829 | "include-path": { 830 | "type": ["array"], 831 | "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.", 832 | "items": { 833 | "type": "string" 834 | } 835 | }, 836 | "source": { 837 | "type": "object", 838 | "required": ["type", "url", "reference"], 839 | "properties": { 840 | "type": { 841 | "type": "string" 842 | }, 843 | "url": { 844 | "type": "string" 845 | }, 846 | "reference": { 847 | "type": "string" 848 | }, 849 | "mirrors": { 850 | "type": "array" 851 | } 852 | } 853 | }, 854 | "dist": { 855 | "type": "object", 856 | "required": ["type", "url"], 857 | "properties": { 858 | "type": { 859 | "type": "string" 860 | }, 861 | "url": { 862 | "type": "string" 863 | }, 864 | "reference": { 865 | "type": "string" 866 | }, 867 | "shasum": { 868 | "type": "string" 869 | }, 870 | "mirrors": { 871 | "type": "array" 872 | } 873 | } 874 | } 875 | }, 876 | "additionalProperties": true 877 | } 878 | } 879 | } 880 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | test/suite 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | src 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/ConfigurationReader.php: -------------------------------------------------------------------------------- 1 | validator = $validator; 40 | } 41 | 42 | /** 43 | * Get the configuration validator. 44 | * 45 | * @return ConfigurationValidator The configuration validator. 46 | */ 47 | public function validator() 48 | { 49 | return $this->validator; 50 | } 51 | 52 | /** 53 | * Read a Composer configuration file. 54 | * 55 | * @param string $path The configuration file path. 56 | * 57 | * @return Configuration The parsed configuration. 58 | * @throws ConfigurationExceptionInterface If there is a problem reading the configuration. 59 | */ 60 | public function read($path) 61 | { 62 | $data = $this->readJson($path); 63 | $this->validator()->validate($data); 64 | 65 | return $this->createConfiguration($data); 66 | } 67 | 68 | /** 69 | * Read JSON data from the supplied path. 70 | * 71 | * @param string $path The path to read from. 72 | * 73 | * @return ObjectAccess The parsed data. 74 | * @throws ConfigurationExceptionInterface If there is a problem reading the data. 75 | */ 76 | protected function readJson($path) 77 | { 78 | $jsonData = @file_get_contents($path); 79 | 80 | if (false === $jsonData) { 81 | throw new ConfigurationReadException($path); 82 | } 83 | 84 | $data = json_decode($jsonData); 85 | $jsonError = json_last_error(); 86 | if (JSON_ERROR_NONE !== $jsonError) { 87 | throw new InvalidJsonException($path, $jsonError); 88 | } 89 | 90 | return new ObjectAccess($data); 91 | } 92 | 93 | /** 94 | * Create a configuration object from the supplied JSON data. 95 | * 96 | * @param ObjectAccess $data The parsed JSON data. 97 | * 98 | * @return Configuration The newly created configuration object. 99 | */ 100 | protected function createConfiguration(ObjectAccess $data) 101 | { 102 | $autoloadData = new ObjectAccess( 103 | $data->getDefault('autoload', (object) []) 104 | ); 105 | 106 | return new Configuration( 107 | $data->getDefault('name'), 108 | $data->getDefault('description'), 109 | $data->getDefault('version'), 110 | $data->getDefault('type'), 111 | $data->getDefault('keywords'), 112 | $data->getDefault('homepage'), 113 | $this->createTime($data->getDefault('time')), 114 | $this->arrayize($data->getDefault('license')), 115 | $this->createAuthors($data->getDefault('authors')), 116 | $this->createSupport($data->getDefault('support')), 117 | $this->objectToArray($data->getDefault('require')), 118 | $this->objectToArray($data->getDefault('require-dev')), 119 | $this->objectToArray($data->getDefault('conflict')), 120 | $this->objectToArray($data->getDefault('replace')), 121 | $this->objectToArray($data->getDefault('provide')), 122 | $this->objectToArray($data->getDefault('suggest')), 123 | $this->createAutoloadPsr($autoloadData->getDefault('psr-4')), 124 | $this->createAutoloadPsr($autoloadData->getDefault('psr-0')), 125 | $autoloadData->getDefault('classmap'), 126 | $autoloadData->getDefault('files'), 127 | $data->getDefault('include-path'), 128 | $data->getDefault('target-dir'), 129 | $this->createStability($data->getDefault('minimum-stability')), 130 | $data->getDefault('prefer-stable'), 131 | $this->createRepositories((array) $data->getDefault('repositories')), 132 | $this->createProjectConfiguration($data->getDefault('config')), 133 | $this->createScripts($data->getDefault('scripts')), 134 | $data->getDefault('extra'), 135 | $data->getDefault('bin'), 136 | $this->createArchiveConfiguration($data->getDefault('archive')), 137 | $data->data() 138 | ); 139 | } 140 | 141 | /** 142 | * Create a time from the suppled raw value. 143 | * 144 | * @param string|null $time The raw time data. 145 | * 146 | * @return DateTime|null The newly created time object. 147 | */ 148 | protected function createTime($time) 149 | { 150 | if (null !== $time) { 151 | $time = new DateTime($time); 152 | } 153 | 154 | return $time; 155 | } 156 | 157 | /** 158 | * Create an author list from the supplied raw value. 159 | * 160 | * @param array|null $authors The raw author list data. 161 | * 162 | * @return array|null The newly created author list. 163 | */ 164 | protected function createAuthors(array $authors = null) 165 | { 166 | if (null !== $authors) { 167 | foreach ($authors as $index => $author) { 168 | $authors[$index] = $this->createAuthor( 169 | new ObjectAccess($author) 170 | ); 171 | } 172 | } 173 | 174 | return $authors; 175 | } 176 | 177 | /** 178 | * Create an author from the supplied raw value. 179 | * 180 | * @param ObjectAccess $author The raw author data. 181 | * 182 | * @return Author The newly created author. 183 | */ 184 | protected function createAuthor(ObjectAccess $author) 185 | { 186 | return new Author( 187 | $author->get('name'), 188 | $author->getDefault('email'), 189 | $author->getDefault('homepage'), 190 | $author->getDefault('role'), 191 | $author->data() 192 | ); 193 | } 194 | 195 | /** 196 | * Create a support information object from the supplied raw value. 197 | * 198 | * @param stdClass|null $support The raw support information. 199 | * 200 | * @return SupportInformation|null The newly created support information object. 201 | */ 202 | protected function createSupport(stdClass $support = null) 203 | { 204 | if (null !== $support) { 205 | $supportData = new ObjectAccess($support); 206 | $support = new SupportInformation( 207 | $supportData->getDefault('email'), 208 | $supportData->getDefault('issues'), 209 | $supportData->getDefault('forum'), 210 | $supportData->getDefault('wiki'), 211 | $supportData->getDefault('irc'), 212 | $supportData->getDefault('source'), 213 | $supportData->data() 214 | ); 215 | } 216 | 217 | return $support; 218 | } 219 | 220 | /** 221 | * Create PSR-style autoload information from the supplied raw value. 222 | * 223 | * This method currently works for both PSR-0 and PSR-4 data. 224 | * 225 | * @param stdClass|null $autoloadPsr The raw PSR autoload data. 226 | * 227 | * @return array>|null The newly created PSR autoload information. 228 | */ 229 | protected function createAutoloadPsr(stdClass $autoloadPsr = null) 230 | { 231 | if (null !== $autoloadPsr) { 232 | $autoloadPsr = $this->objectToArray($autoloadPsr); 233 | foreach ($autoloadPsr as $namespace => $paths) { 234 | $autoloadPsr[$namespace] = $this->arrayize($paths); 235 | } 236 | } 237 | 238 | return $autoloadPsr; 239 | } 240 | 241 | /** 242 | * Create a stability enumeration from the supplied raw data. 243 | * 244 | * @param string|null $stability The raw stability data. 245 | * 246 | * @return Stability|null The newly created stability enumeration. 247 | */ 248 | protected function createStability($stability) 249 | { 250 | if (null !== $stability) { 251 | $stability = Stability::memberByValue($stability, false); 252 | } 253 | 254 | return $stability; 255 | } 256 | 257 | /** 258 | * Create a repository list from the supplied raw value. 259 | * 260 | * @param array|null $repositories The raw repository list data. 261 | * 262 | * @return array|null The newly created repository list. 263 | */ 264 | protected function createRepositories(array $repositories = null) 265 | { 266 | if (null !== $repositories) { 267 | foreach ($repositories as $index => $repository) { 268 | $repositories[$index] = $this->createRepository( 269 | new ObjectAccess($repository) 270 | ); 271 | } 272 | } 273 | 274 | return $repositories; 275 | } 276 | 277 | /** 278 | * Create a repository from the supplied raw value. 279 | * 280 | * @param ObjectAccess $repository The raw repository data. 281 | * 282 | * @return RepositoryInterface The newly created repository. 283 | */ 284 | protected function createRepository(ObjectAccess $repository) 285 | { 286 | if ($repository->exists('packagist')) { 287 | return new PackagistRepository( 288 | $repository->get('packagist'), 289 | $repository->data() 290 | ); 291 | } 292 | 293 | $type = $repository->get('type'); 294 | 295 | if ('package' === $type) { 296 | $repository = new PackageRepository( 297 | $this->objectToArray($repository->get('package')), 298 | $this->objectToArray($repository->getDefault('options')), 299 | $repository->data() 300 | ); 301 | } else { 302 | $repository = new Repository( 303 | $type, 304 | $repository->getDefault('url'), 305 | $this->objectToArray($repository->getDefault('options')), 306 | $repository->data() 307 | ); 308 | } 309 | 310 | return $repository; 311 | } 312 | 313 | /** 314 | * Create a project configuration object from the supplied raw value. 315 | * 316 | * @param stdClass|null $config The raw project configuration data. 317 | * 318 | * @return ProjectConfiguration The newly created project configuration object. 319 | */ 320 | protected function createProjectConfiguration(stdClass $config = null) 321 | { 322 | if (null === $config) { 323 | return new ProjectConfiguration( 324 | null, 325 | null, 326 | null, 327 | null, 328 | null, 329 | null, 330 | null, 331 | $this->defaultCacheDir() 332 | ); 333 | } 334 | 335 | $configData = new ObjectAccess($config); 336 | 337 | $cacheDir = $configData->getDefault('cache-dir'); 338 | if (null === $cacheDir) { 339 | $cacheDir = $this->defaultCacheDir(); 340 | } 341 | 342 | return new ProjectConfiguration( 343 | $configData->getDefault('process-timeout'), 344 | $configData->getDefault('use-include-path'), 345 | $this->createInstallationMethod( 346 | $configData->getDefault('preferred-install') 347 | ), 348 | $configData->getDefault('github-protocols'), 349 | $this->objectToArray($configData->getDefault('github-oauth')), 350 | $configData->getDefault('vendor-dir'), 351 | $configData->getDefault('bin-dir'), 352 | $cacheDir, 353 | $configData->getDefault('cache-files-dir'), 354 | $configData->getDefault('cache-repo-dir'), 355 | $configData->getDefault('cache-vcs-dir'), 356 | $configData->getDefault('cache-files-ttl'), 357 | $configData->getDefault('cache-files-maxsize'), 358 | $configData->getDefault('prepend-autoloader'), 359 | $configData->getDefault('autoloader-suffix'), 360 | $configData->getDefault('optimize-autoloader'), 361 | $configData->getDefault('github-domains'), 362 | $configData->getDefault('notify-on-install'), 363 | $this->createVcsChangePolicy( 364 | $configData->getDefault('discard-changes') 365 | ), 366 | $configData->data() 367 | ); 368 | } 369 | 370 | /** 371 | * Get the default cache directory for the current environment. 372 | * 373 | * @return string|null The default cache directory, or null if the cache directory could not be determined. 374 | */ 375 | protected function defaultCacheDir() 376 | { 377 | $cacheDir = getenv('COMPOSER_CACHE_DIR'); 378 | if ($cacheDir) { 379 | return $cacheDir; 380 | } 381 | 382 | $home = getenv('COMPOSER_HOME'); 383 | $isWindows = defined('PHP_WINDOWS_VERSION_MAJOR'); 384 | 385 | if (!$home) { 386 | if ($isWindows) { 387 | if ($envAppData = getenv('APPDATA')) { 388 | $home = strtr($envAppData, '\\', '/') . '/Composer'; 389 | } 390 | } elseif ($envHome = getenv('HOME')) { 391 | $home = rtrim($envHome, '/') . '/.composer'; 392 | } 393 | } 394 | 395 | if ($home && !$cacheDir) { 396 | if ($isWindows) { 397 | if ($cacheDir = getenv('LOCALAPPDATA')) { 398 | $cacheDir .= '/Composer'; 399 | } else { 400 | $cacheDir = $home . '/cache'; 401 | } 402 | 403 | $cacheDir = strtr($cacheDir, '\\', '/'); 404 | } else { 405 | $cacheDir = $home . '/cache'; 406 | } 407 | } 408 | 409 | if (!$cacheDir) { 410 | return null; 411 | } 412 | 413 | return $cacheDir; 414 | } 415 | 416 | /** 417 | * Create a installation method enumeration from the supplied raw data. 418 | * 419 | * @param string|stdClass|null $method The raw installation method data. 420 | * 421 | * @return InstallationMethod|array|null The processed installation method. 422 | */ 423 | protected function createInstallationMethod($method) 424 | { 425 | if (is_string($method)) { 426 | return InstallationMethod::memberByValue($method, false); 427 | } 428 | 429 | if (is_object($method)) { 430 | $methods = []; 431 | 432 | foreach ($method as $project => $projectMethod) { 433 | $methods[$project] = 434 | InstallationMethod::memberByValue($projectMethod, false); 435 | } 436 | 437 | return $methods; 438 | } 439 | 440 | return null; 441 | } 442 | 443 | /** 444 | * Create a VCS change policy enumeration from the supplied raw data. 445 | * 446 | * @param string|null $policy The raw VCS change policy data. 447 | * 448 | * @return VcsChangePolicy|null The newly created VCS change policy enumeration. 449 | */ 450 | protected function createVcsChangePolicy($policy) 451 | { 452 | if (null !== $policy) { 453 | $policy = VcsChangePolicy::memberByValue($policy, false); 454 | } 455 | 456 | return $policy; 457 | } 458 | 459 | /** 460 | * Create a script configuration object from the supplied raw value. 461 | * 462 | * @param stdClass|null $scripts The raw script configuration data. 463 | * 464 | * @return ScriptConfiguration|null The newly created script configuration object. 465 | */ 466 | protected function createScripts(stdClass $scripts = null) 467 | { 468 | if (null !== $scripts) { 469 | $scriptsData = new ObjectAccess($scripts); 470 | $scripts = new ScriptConfiguration( 471 | $this->arrayize($scriptsData->getDefault('pre-install-cmd')), 472 | $this->arrayize($scriptsData->getDefault('post-install-cmd')), 473 | $this->arrayize($scriptsData->getDefault('pre-update-cmd')), 474 | $this->arrayize($scriptsData->getDefault('post-update-cmd')), 475 | $this->arrayize($scriptsData->getDefault('pre-status-cmd')), 476 | $this->arrayize($scriptsData->getDefault('post-status-cmd')), 477 | $this->arrayize($scriptsData->getDefault('pre-package-install')), 478 | $this->arrayize($scriptsData->getDefault('post-package-install')), 479 | $this->arrayize($scriptsData->getDefault('pre-package-update')), 480 | $this->arrayize($scriptsData->getDefault('post-package-update')), 481 | $this->arrayize($scriptsData->getDefault('pre-package-uninstall')), 482 | $this->arrayize($scriptsData->getDefault('post-package-uninstall')), 483 | $this->arrayize($scriptsData->getDefault('pre-autoload-dump')), 484 | $this->arrayize($scriptsData->getDefault('post-autoload-dump')), 485 | $this->arrayize($scriptsData->getDefault('post-root-package-install')), 486 | $this->arrayize($scriptsData->getDefault('post-create-project-cmd')), 487 | $scriptsData->data() 488 | ); 489 | } 490 | 491 | return $scripts; 492 | } 493 | 494 | /** 495 | * Create an archive configuration object from the supplied raw value. 496 | * 497 | * @param stdClass|null $archive The raw archive configuration data. 498 | * 499 | * @return ArchiveConfiguration|null The newly created archive configuration object. 500 | */ 501 | protected function createArchiveConfiguration(stdClass $archive = null) 502 | { 503 | if (null !== $archive) { 504 | $archiveData = new ObjectAccess($archive); 505 | $archive = new ArchiveConfiguration( 506 | $archiveData->getDefault('exclude'), 507 | $archiveData->data() 508 | ); 509 | } 510 | 511 | return $archive; 512 | } 513 | 514 | /** 515 | * Recursively convert the supplied object to an associative array. 516 | * 517 | * @param stdClass|null $data The object to convert. 518 | * 519 | * @return array The converted associative array. 520 | */ 521 | protected function objectToArray(stdClass $data = null) 522 | { 523 | if (null !== $data) { 524 | $data = (array) $data; 525 | foreach ($data as $key => $value) { 526 | if ($value instanceof stdClass) { 527 | $data[$key] = $this->objectToArray($value); 528 | } 529 | } 530 | } 531 | 532 | return $data; 533 | } 534 | 535 | /** 536 | * Normalize singular values into an array containing the initial value as 537 | * a single element. 538 | * 539 | * @param mixed $data The data to normalize. 540 | * 541 | * @return array The normalized value. 542 | */ 543 | protected function arrayize($data) 544 | { 545 | if (null !== $data && !is_array($data)) { 546 | $data = [$data]; 547 | } 548 | 549 | return $data; 550 | } 551 | 552 | private $validator; 553 | } 554 | -------------------------------------------------------------------------------- /src/ConfigurationValidator.php: -------------------------------------------------------------------------------- 1 | loadDefaultSchema(); 27 | } 28 | if (null === $validator) { 29 | $validator = new Validator(); 30 | } 31 | 32 | $this->schema = $schema; 33 | $this->validator = $validator; 34 | } 35 | 36 | /** 37 | * Get the schema. 38 | * 39 | * @return stdClass The schema. 40 | */ 41 | public function schema() 42 | { 43 | return $this->schema; 44 | } 45 | 46 | /** 47 | * Validate Composer configuration data. 48 | * 49 | * @param mixed $data The configuration data. 50 | * 51 | * @throws ConfigurationExceptionInterface If the data is invalid. 52 | */ 53 | public function validate($data) 54 | { 55 | $this->validator->reset(); 56 | $this->validator->check($data, $this->schema()); 57 | 58 | if (!$this->validator->isValid()) { 59 | throw new InvalidConfigurationException( 60 | $this->validator->getErrors() 61 | ); 62 | } 63 | } 64 | 65 | /** 66 | * Load the default Composer configuration schema. 67 | * 68 | * @return stdClass The parsed schema. 69 | */ 70 | protected function loadDefaultSchema() 71 | { 72 | return json_decode(file_get_contents($this->defaultSchemaPath())); 73 | } 74 | 75 | /** 76 | * Get the default Composer configuration schema path. 77 | * 78 | * @return string The schema path. 79 | */ 80 | protected function defaultSchemaPath() 81 | { 82 | return implode( 83 | DIRECTORY_SEPARATOR, 84 | [dirname(__DIR__), 'etc', 'composer-schema.json'] 85 | ); 86 | } 87 | 88 | private $schema; 89 | private $validator; 90 | } 91 | -------------------------------------------------------------------------------- /src/Element/AbstractRepository.php: -------------------------------------------------------------------------------- 1 | |null $options The repository options. 15 | * @param mixed $rawData The raw data describing the repository. 16 | */ 17 | public function __construct( 18 | $type, 19 | array $options = null, 20 | $rawData = null 21 | ) { 22 | if (null === $options) { 23 | $options = []; 24 | } 25 | 26 | $this->type = $type; 27 | $this->options = $options; 28 | $this->rawData = $rawData; 29 | } 30 | 31 | /** 32 | * Get the repository type. 33 | * 34 | * @return string The repository type. 35 | */ 36 | public function type() 37 | { 38 | return $this->type; 39 | } 40 | 41 | /** 42 | * Get the repository options. 43 | * 44 | * @return array The repository options. 45 | */ 46 | public function options() 47 | { 48 | return $this->options; 49 | } 50 | 51 | /** 52 | * Get the raw repository data. 53 | * 54 | * @return mixed The raw repository data. 55 | */ 56 | public function rawData() 57 | { 58 | return $this->rawData; 59 | } 60 | 61 | private $type; 62 | private $options; 63 | private $rawData; 64 | } 65 | -------------------------------------------------------------------------------- /src/Element/ArchiveConfiguration.php: -------------------------------------------------------------------------------- 1 | |null $exclude A list of patterns to exclude from the archive. 14 | */ 15 | public function __construct(array $exclude = null, $rawData = null) 16 | { 17 | if (null === $exclude) { 18 | $exclude = []; 19 | } 20 | 21 | $this->exclude = $exclude; 22 | $this->rawData = $rawData; 23 | } 24 | 25 | /** 26 | * Get the patterns of excluded files. 27 | * 28 | * @return array The exclude patterns. 29 | */ 30 | public function exclude() 31 | { 32 | return $this->exclude; 33 | } 34 | 35 | /** 36 | * Get the raw configuration data. 37 | * 38 | * @return mixed The raw configuration data. 39 | */ 40 | public function rawData() 41 | { 42 | return $this->rawData; 43 | } 44 | 45 | private $exclude; 46 | private $rawData; 47 | } 48 | -------------------------------------------------------------------------------- /src/Element/Author.php: -------------------------------------------------------------------------------- 1 | name = $name; 27 | $this->email = $email; 28 | $this->homepage = $homepage; 29 | $this->role = $role; 30 | $this->rawData = $rawData; 31 | } 32 | 33 | /** 34 | * Get the author's name. 35 | * 36 | * @return string The author's name. 37 | */ 38 | public function name() 39 | { 40 | return $this->name; 41 | } 42 | 43 | /** 44 | * Get the author's email address. 45 | * 46 | * @return string|null The author's email address. 47 | */ 48 | public function email() 49 | { 50 | return $this->email; 51 | } 52 | 53 | /** 54 | * Get the URI of the author's home page. 55 | * 56 | * @return string|null The URI of the author's home page. 57 | */ 58 | public function homepage() 59 | { 60 | return $this->homepage; 61 | } 62 | 63 | /** 64 | * Get the author's role. 65 | * 66 | * @return string|null The author's role. 67 | */ 68 | public function role() 69 | { 70 | return $this->role; 71 | } 72 | 73 | /** 74 | * Get the raw author data. 75 | * 76 | * @return mixed The raw author data. 77 | */ 78 | public function rawData() 79 | { 80 | return $this->rawData; 81 | } 82 | 83 | private $name; 84 | private $email; 85 | private $homepage; 86 | private $role; 87 | private $rawData; 88 | } 89 | -------------------------------------------------------------------------------- /src/Element/Configuration.php: -------------------------------------------------------------------------------- 1 | |null $keywords The keywords the package is related to. 26 | * @param string|null $homepage The URI of the package's home page. 27 | * @param DateTime|null $time The release date of this version. 28 | * @param array|null $license The licences the package is released under. 29 | * @param array|null $authors The authors of the package. 30 | * @param SupportInformation|null $support Support information for the package. 31 | * @param array|null $dependencies The package's dependencies. 32 | * @param array|null $devDependencies The package's development dependencies. 33 | * @param array|null $conflict Packages that conflict with this version of the package. 34 | * @param array|null $replace Packages that are replaced by this package. 35 | * @param array|null $provide Packages that are provided by this package. 36 | * @param array|null $suggest Suggested packages for use with this package. 37 | * @param array>|null $autoloadPsr4 PSR-4 autoloading configuration for the package. 38 | * @param array>|null $autoloadPsr0 PSR-0 autoloading configuration for the package. 39 | * @param array|null $autoloadClassmap Class map autoloading configuration for the package. 40 | * @param array|null $autoloadFiles File autoloading configuration for the package. 41 | * @param array|null $includePath Include path autoloading configuration for the package. 42 | * @param string|null $targetDir The target directory for installation. 43 | * @param Stability|null $minimumStability The minimum stability for packages. 44 | * @param bool|null $preferStable True if stable packages should take precedence. 45 | * @param array $repositories The custom repositories used by this package. 46 | * @param ProjectConfiguration|null $config The configuration options for the package that are specific to project-type repositories. 47 | * @param ScriptConfiguration|null $scripts The hook scripts for the package. 48 | * @param mixed $extra Arbitrary extra data contained in the project's configuration. 49 | * @param array|null $bin Binary executable files provided by the package. 50 | * @param ArchiveConfiguration|null $archive The archive configuration for the package. 51 | * @param mixed $rawData The raw data describing the configuration. 52 | */ 53 | public function __construct( 54 | $name = null, 55 | $description = null, 56 | $version = null, 57 | $type = null, 58 | array $keywords = null, 59 | $homepage = null, 60 | DateTime $time = null, 61 | array $license = null, 62 | array $authors = null, 63 | SupportInformation $support = null, 64 | array $dependencies = null, 65 | array $devDependencies = null, 66 | array $conflict = null, 67 | array $replace = null, 68 | array $provide = null, 69 | array $suggest = null, 70 | array $autoloadPsr4 = null, 71 | array $autoloadPsr0 = null, 72 | array $autoloadClassmap = null, 73 | array $autoloadFiles = null, 74 | array $includePath = null, 75 | $targetDir = null, 76 | Stability $minimumStability = null, 77 | $preferStable = null, 78 | array $repositories = null, 79 | ProjectConfiguration $config = null, 80 | ScriptConfiguration $scripts = null, 81 | $extra = null, 82 | array $bin = null, 83 | ArchiveConfiguration $archive = null, 84 | $rawData = null 85 | ) { 86 | if (null === $type) { 87 | $type = 'library'; 88 | } 89 | if (null === $keywords) { 90 | $keywords = []; 91 | } 92 | if (null === $license) { 93 | $license = []; 94 | } 95 | if (null === $authors) { 96 | $authors = []; 97 | } 98 | if (null === $support) { 99 | $support = new SupportInformation(); 100 | } 101 | if (null === $dependencies) { 102 | $dependencies = []; 103 | } 104 | if (null === $devDependencies) { 105 | $devDependencies = []; 106 | } 107 | if (null === $conflict) { 108 | $conflict = []; 109 | } 110 | if (null === $replace) { 111 | $replace = []; 112 | } 113 | if (null === $provide) { 114 | $provide = []; 115 | } 116 | if (null === $suggest) { 117 | $suggest = []; 118 | } 119 | if (null === $autoloadPsr4) { 120 | $autoloadPsr4 = []; 121 | } 122 | if (null === $autoloadPsr0) { 123 | $autoloadPsr0 = []; 124 | } 125 | if (null === $autoloadClassmap) { 126 | $autoloadClassmap = []; 127 | } 128 | if (null === $autoloadFiles) { 129 | $autoloadFiles = []; 130 | } 131 | if (null === $includePath) { 132 | $includePath = []; 133 | } 134 | if (null === $minimumStability) { 135 | $minimumStability = Stability::STABLE(); 136 | } 137 | if (null === $preferStable) { 138 | $preferStable = false; 139 | } 140 | if (null === $repositories) { 141 | $repositories = []; 142 | } 143 | if (null === $config) { 144 | $config = new ProjectConfiguration(); 145 | } 146 | if (null === $scripts) { 147 | $scripts = new ScriptConfiguration(); 148 | } 149 | if (null === $archive) { 150 | $archive = new ArchiveConfiguration(); 151 | } 152 | if (null === $bin) { 153 | $bin = []; 154 | } 155 | 156 | $this->name = $name; 157 | $this->description = $description; 158 | $this->version = $version; 159 | $this->type = $type; 160 | $this->keywords = $keywords; 161 | $this->homepage = $homepage; 162 | $this->time = $time; 163 | $this->license = $license; 164 | $this->authors = $authors; 165 | $this->support = $support; 166 | $this->dependencies = $dependencies; 167 | $this->devDependencies = $devDependencies; 168 | $this->conflict = $conflict; 169 | $this->replace = $replace; 170 | $this->provide = $provide; 171 | $this->suggest = $suggest; 172 | $this->autoloadPsr4 = $autoloadPsr4; 173 | $this->autoloadPsr0 = $autoloadPsr0; 174 | $this->autoloadClassmap = $autoloadClassmap; 175 | $this->autoloadFiles = $autoloadFiles; 176 | $this->includePath = $includePath; 177 | $this->targetDir = $targetDir; 178 | $this->minimumStability = $minimumStability; 179 | $this->preferStable = $preferStable; 180 | $this->repositories = $repositories; 181 | $this->config = $config; 182 | $this->scripts = $scripts; 183 | $this->extra = $extra; 184 | $this->bin = $bin; 185 | $this->archive = $archive; 186 | $this->rawData = $rawData; 187 | } 188 | 189 | /** 190 | * Get the package name, including vendor and project names. 191 | * 192 | * @return string|null The name. 193 | */ 194 | public function name() 195 | { 196 | return $this->name; 197 | } 198 | 199 | /** 200 | * Get the project name, without the vendor prefix. 201 | * 202 | * @return string|null The project name. 203 | */ 204 | public function projectName() 205 | { 206 | $name = $this->name(); 207 | if (null === $name) { 208 | return null; 209 | } 210 | 211 | $atoms = explode(static::NAME_SEPARATOR, $name); 212 | 213 | return array_pop($atoms); 214 | } 215 | 216 | /** 217 | * Get the vendor name, without the project suffix. 218 | * 219 | * @return string|null The vendor name. 220 | */ 221 | public function vendorName() 222 | { 223 | $name = $this->name(); 224 | if (null === $name) { 225 | return null; 226 | } 227 | 228 | $atoms = explode(static::NAME_SEPARATOR, $name); 229 | array_pop($atoms); 230 | if (count($atoms) < 1) { 231 | return null; 232 | } 233 | 234 | return implode(static::NAME_SEPARATOR, $atoms); 235 | } 236 | 237 | /** 238 | * Get the package description. 239 | * 240 | * @return string|null The description. 241 | */ 242 | public function description() 243 | { 244 | return $this->description; 245 | } 246 | 247 | /** 248 | * Get the package version. 249 | * 250 | * @return string|null The version. 251 | */ 252 | public function version() 253 | { 254 | return $this->version; 255 | } 256 | 257 | /** 258 | * Get the package type. 259 | * 260 | * @return string The type. 261 | */ 262 | public function type() 263 | { 264 | return $this->type; 265 | } 266 | 267 | /** 268 | * Get the package keywords. 269 | * 270 | * @return array The keywords. 271 | */ 272 | public function keywords() 273 | { 274 | return $this->keywords; 275 | } 276 | 277 | /** 278 | * Get the URI of the package's home page. 279 | * 280 | * @return string|null The home page. 281 | */ 282 | public function homepage() 283 | { 284 | return $this->homepage; 285 | } 286 | 287 | /** 288 | * Get the release date of this version. 289 | * 290 | * @return DateTime|null The release date. 291 | */ 292 | public function time() 293 | { 294 | return $this->time; 295 | } 296 | 297 | /** 298 | * Get the licences the package is released under. 299 | * 300 | * @return array|null The licences. 301 | */ 302 | public function license() 303 | { 304 | return $this->license; 305 | } 306 | 307 | /** 308 | * Get the authors of the package. 309 | * 310 | * @return array The authors. 311 | */ 312 | public function authors() 313 | { 314 | return $this->authors; 315 | } 316 | 317 | /** 318 | * Get support information for the package. 319 | * 320 | * @return SupportInformation The support information. 321 | */ 322 | public function support() 323 | { 324 | return $this->support; 325 | } 326 | 327 | /** 328 | * Get the package's dependencies, excluding development dependencies. 329 | * 330 | * @return array The dependencies. 331 | */ 332 | public function dependencies() 333 | { 334 | return $this->dependencies; 335 | } 336 | 337 | /** 338 | * Get the package's development dependencies. 339 | * 340 | * @return array The development dependencies. 341 | */ 342 | public function devDependencies() 343 | { 344 | return $this->devDependencies; 345 | } 346 | 347 | /** 348 | * Get all of the package's dependencies, including development, and 349 | * non-development dependencies. 350 | * 351 | * @return array All dependencies. 352 | */ 353 | public function allDependencies() 354 | { 355 | return array_merge( 356 | $this->dependencies(), 357 | $this->devDependencies() 358 | ); 359 | } 360 | 361 | /** 362 | * Get the packages that conflict with this version of the package. 363 | * 364 | * @return array The conflicting packages. 365 | */ 366 | public function conflict() 367 | { 368 | return $this->conflict; 369 | } 370 | 371 | /** 372 | * Get the packages that are replaced by this package. 373 | * 374 | * @return array The replaced packages. 375 | */ 376 | public function replace() 377 | { 378 | return $this->replace; 379 | } 380 | 381 | /** 382 | * Get the packages that are provided by this package. 383 | * 384 | * @return array The provided packages. 385 | */ 386 | public function provide() 387 | { 388 | return $this->provide; 389 | } 390 | 391 | /** 392 | * Get suggested packages for use with this package. 393 | * 394 | * @return array The suggested packages. 395 | */ 396 | public function suggest() 397 | { 398 | return $this->suggest; 399 | } 400 | 401 | /** 402 | * Get the PSR-4 autoloading configuration for the package. 403 | * 404 | * @return array> The PSR-4 autoloading configuration. 405 | */ 406 | public function autoloadPsr4() 407 | { 408 | return $this->autoloadPsr4; 409 | } 410 | 411 | /** 412 | * Get the PSR-0 autoloading configuration for the package. 413 | * 414 | * @return array> The PSR-0 autoloading configuration. 415 | */ 416 | public function autoloadPsr0() 417 | { 418 | return $this->autoloadPsr0; 419 | } 420 | 421 | /** 422 | * Get the class map autoloading configuration for the package. 423 | * 424 | * @return array The class map autoloading configuration. 425 | */ 426 | public function autoloadClassmap() 427 | { 428 | return $this->autoloadClassmap; 429 | } 430 | 431 | /** 432 | * Get the file autoloading configuration for the package. 433 | * 434 | * @return array The file autoloading configuration for the package. 435 | */ 436 | public function autoloadFiles() 437 | { 438 | return $this->autoloadFiles; 439 | } 440 | 441 | /** 442 | * Get the include path autoloading configuration for the package. 443 | * 444 | * @return array The include path autoloading configuration for the package. 445 | */ 446 | public function includePath() 447 | { 448 | return $this->includePath; 449 | } 450 | 451 | /** 452 | * Get an array of all source paths containing PSR-4 conformant code. 453 | * 454 | * @return array The PSR-4 source paths. 455 | */ 456 | public function allPsr4SourcePaths() 457 | { 458 | $autoloadPsr4Paths = []; 459 | foreach ($this->autoloadPsr4() as $namespace => $paths) { 460 | $autoloadPsr4Paths = array_merge($autoloadPsr4Paths, $paths); 461 | } 462 | 463 | return $autoloadPsr4Paths; 464 | } 465 | 466 | /** 467 | * Get an array of all source paths containing PSR-0 conformant code. 468 | * 469 | * @return array The PSR-0 source paths. 470 | */ 471 | public function allPsr0SourcePaths() 472 | { 473 | $autoloadPsr0Paths = []; 474 | foreach ($this->autoloadPsr0() as $namespace => $paths) { 475 | $autoloadPsr0Paths = array_merge($autoloadPsr0Paths, $paths); 476 | } 477 | 478 | return $autoloadPsr0Paths; 479 | } 480 | 481 | /** 482 | * Get an array of all source paths for this package. 483 | * 484 | * @return array All source paths. 485 | */ 486 | public function allSourcePaths() 487 | { 488 | return array_merge( 489 | $this->allPsr4SourcePaths(), 490 | $this->allPsr0SourcePaths(), 491 | $this->autoloadClassmap(), 492 | $this->autoloadFiles(), 493 | $this->includePath() 494 | ); 495 | } 496 | 497 | /** 498 | * Get the target directory for installation. 499 | * 500 | * @return string|null The target directory. 501 | */ 502 | public function targetDir() 503 | { 504 | return $this->targetDir; 505 | } 506 | 507 | /** 508 | * Get the minimum stability for packages. 509 | * 510 | * @return Stability The minimum stability. 511 | */ 512 | public function minimumStability() 513 | { 514 | return $this->minimumStability; 515 | } 516 | 517 | /** 518 | * Returns true if stable packages should take precedence. 519 | * 520 | * @return bool True if stable packages should take precedence. 521 | */ 522 | public function preferStable() 523 | { 524 | return $this->preferStable; 525 | } 526 | 527 | /** 528 | * Get the custom repositories used by this package. 529 | * 530 | * @return array The custom repositories. 531 | */ 532 | public function repositories() 533 | { 534 | return $this->repositories; 535 | } 536 | 537 | /** 538 | * Get the configuration options for the package that are specific to 539 | * project-type repositories. 540 | * 541 | * @return ProjectConfiguration The project configuration. 542 | */ 543 | public function config() 544 | { 545 | return $this->config; 546 | } 547 | 548 | /** 549 | * Get the hook scripts for the package. 550 | * 551 | * @return ScriptConfiguration The hook scripts. 552 | */ 553 | public function scripts() 554 | { 555 | return $this->scripts; 556 | } 557 | 558 | /** 559 | * Get the arbitrary extra data contained in the project's configuration. 560 | * 561 | * @return mixed The extra data. 562 | */ 563 | public function extra() 564 | { 565 | return $this->extra; 566 | } 567 | 568 | /** 569 | * Get the binary executable files provided by the package. 570 | * 571 | * @return array The executable files. 572 | */ 573 | public function bin() 574 | { 575 | return $this->bin; 576 | } 577 | 578 | /** 579 | * Get the archive configuration for the package. 580 | * 581 | * @return ArchiveConfiguration The archive configuration. 582 | */ 583 | public function archive() 584 | { 585 | return $this->archive; 586 | } 587 | 588 | /** 589 | * Get the raw configuration data. 590 | * 591 | * @return mixed The raw configuration data. 592 | */ 593 | public function rawData() 594 | { 595 | return $this->rawData; 596 | } 597 | 598 | private $name; 599 | private $description; 600 | private $version; 601 | private $type; 602 | private $keywords; 603 | private $homepage; 604 | private $time; 605 | private $license; 606 | private $authors; 607 | private $support; 608 | private $dependencies; 609 | private $devDependencies; 610 | private $conflict; 611 | private $replace; 612 | private $provide; 613 | private $suggest; 614 | private $autoloadPsr4; 615 | private $autoloadPsr0; 616 | private $autoloadClassmap; 617 | private $autoloadFiles; 618 | private $includePath; 619 | private $targetDir; 620 | private $minimumStability; 621 | private $preferStable; 622 | private $repositories; 623 | private $config; 624 | private $scripts; 625 | private $extra; 626 | private $bin; 627 | private $archive; 628 | private $rawData; 629 | } 630 | -------------------------------------------------------------------------------- /src/Element/InstallationMethod.php: -------------------------------------------------------------------------------- 1 | |null $options The repository options. 15 | * @param mixed $rawData The raw data describing the repository. 16 | */ 17 | public function __construct( 18 | array $packageData, 19 | array $options = null, 20 | $rawData = null 21 | ) { 22 | parent::__construct( 23 | 'package', 24 | $options, 25 | $rawData 26 | ); 27 | 28 | $this->packageData = $packageData; 29 | } 30 | 31 | /** 32 | * Get the raw package data. 33 | * 34 | * @return array The raw package data. 35 | */ 36 | public function packageData() 37 | { 38 | return $this->packageData; 39 | } 40 | 41 | private $packageData; 42 | } 43 | -------------------------------------------------------------------------------- /src/Element/PackagistRepository.php: -------------------------------------------------------------------------------- 1 | isEnabled = $isEnabled; 20 | $this->rawData = $rawData; 21 | } 22 | 23 | /** 24 | * Returns true if the Packagist repository is enabled. 25 | * 26 | * @return bool True if enabled. 27 | */ 28 | public function isEnabled() 29 | { 30 | return $this->isEnabled; 31 | } 32 | 33 | /** 34 | * Get the repository type. 35 | * 36 | * @return string The repository type. 37 | */ 38 | public function type() 39 | { 40 | return ''; 41 | } 42 | 43 | /** 44 | * Get the raw repository data. 45 | * 46 | * @return mixed The raw repository data. 47 | */ 48 | public function rawData() 49 | { 50 | return $this->rawData; 51 | } 52 | 53 | private $isEnabled; 54 | private $rawData; 55 | } 56 | -------------------------------------------------------------------------------- /src/Element/ProjectConfiguration.php: -------------------------------------------------------------------------------- 1 | |null $preferredInstall The preffered installation method. 16 | * @param array|null $githubProtocols The protocols to use when cloning from GitHub. 17 | * @param array|null $githubOauth An associative array of domain name to GitHub OAuth token. 18 | * @param string|null $vendorDir The vendor directory. 19 | * @param string|null $binDir The binary executable directory. 20 | * @param string|null $cacheDir The cache directory, or null if unknown. 21 | * @param string|null $cacheFilesDir The cache directory for package archives, or null if unknown. 22 | * @param string|null $cacheRepoDir The cache directory for package repositories, or null if unknown. 23 | * @param string|null $cacheVcsDir The cache directory for version control repositories, or null if unknown. 24 | * @param int|null $cacheFilesTtl The cache time-to-live for package archives in seconds. 25 | * @param int|null $cacheFilesMaxsize The maximum size of the package archive cache in bytes. 26 | * @param bool|null $prependAutoloader True if the autoloader should be prepended to existing autoloaders. 27 | * @param string|null $autoloaderSuffix The suffix used for the generated autoloader class name. 28 | * @param bool|null $optimizeAutoloader True if the autoloader should always be optimized. 29 | * @param array|null $githubDomains The list of domains to use in GitHub mode. 30 | * @param bool|null $notifyOnInstall True if the repository should be notified on installation. 31 | * @param VcsChangePolicy|null $discardChanges The policy for how to treat version control changes when installing or updating. 32 | * @param mixed $rawData The raw data describing the project configuration. 33 | */ 34 | public function __construct( 35 | $processTimeout = null, 36 | $useIncludePath = null, 37 | $preferredInstall = null, 38 | array $githubProtocols = null, 39 | array $githubOauth = null, 40 | $vendorDir = null, 41 | $binDir = null, 42 | $cacheDir = null, 43 | $cacheFilesDir = null, 44 | $cacheRepoDir = null, 45 | $cacheVcsDir = null, 46 | $cacheFilesTtl = null, 47 | $cacheFilesMaxsize = null, 48 | $prependAutoloader = null, 49 | $autoloaderSuffix = null, 50 | $optimizeAutoloader = null, 51 | array $githubDomains = null, 52 | $notifyOnInstall = null, 53 | VcsChangePolicy $discardChanges = null, 54 | $rawData = null 55 | ) { 56 | if (null === $processTimeout) { 57 | $processTimeout = 300; 58 | } 59 | if (null === $useIncludePath) { 60 | $useIncludePath = false; 61 | } 62 | if (null === $preferredInstall) { 63 | $preferredInstall = InstallationMethod::AUTO(); 64 | } 65 | if (null === $githubProtocols) { 66 | $githubProtocols = ['git', 'https']; 67 | } 68 | if (null === $githubOauth) { 69 | $githubOauth = []; 70 | } 71 | if (null === $vendorDir) { 72 | $vendorDir = 'vendor'; 73 | } 74 | if (null === $binDir) { 75 | $binDir = 'vendor/bin'; 76 | } 77 | if (null === $cacheFilesDir && null !== $cacheDir) { 78 | $cacheFilesDir = $cacheDir . '/files'; 79 | } 80 | if (null === $cacheRepoDir && null !== $cacheDir) { 81 | $cacheRepoDir = $cacheDir . '/repo'; 82 | } 83 | if (null === $cacheVcsDir && null !== $cacheDir) { 84 | $cacheVcsDir = $cacheDir . '/vcs'; 85 | } 86 | if (null === $cacheFilesTtl) { 87 | $cacheFilesTtl = 15552000; 88 | } 89 | if (null === $cacheFilesMaxsize) { 90 | $cacheFilesMaxsize = 314572800; 91 | } 92 | if (null === $prependAutoloader) { 93 | $prependAutoloader = true; 94 | } 95 | if (null === $optimizeAutoloader) { 96 | $optimizeAutoloader = false; 97 | } 98 | if (null === $githubDomains) { 99 | $githubDomains = ['github.com']; 100 | } 101 | if (null === $notifyOnInstall) { 102 | $notifyOnInstall = true; 103 | } 104 | if (null === $discardChanges) { 105 | $discardChanges = VcsChangePolicy::IGNORE(); 106 | } 107 | 108 | $this->processTimeout = $processTimeout; 109 | $this->useIncludePath = $useIncludePath; 110 | $this->preferredInstall = $preferredInstall; 111 | $this->githubProtocols = $githubProtocols; 112 | $this->githubOauth = $githubOauth; 113 | $this->vendorDir = $vendorDir; 114 | $this->binDir = $binDir; 115 | $this->cacheDir = $cacheDir; 116 | $this->cacheFilesDir = $cacheFilesDir; 117 | $this->cacheRepoDir = $cacheRepoDir; 118 | $this->cacheVcsDir = $cacheVcsDir; 119 | $this->cacheFilesTtl = $cacheFilesTtl; 120 | $this->cacheFilesMaxsize = $cacheFilesMaxsize; 121 | $this->prependAutoloader = $prependAutoloader; 122 | $this->autoloaderSuffix = $autoloaderSuffix; 123 | $this->optimizeAutoloader = $optimizeAutoloader; 124 | $this->githubDomains = $githubDomains; 125 | $this->notifyOnInstall = $notifyOnInstall; 126 | $this->discardChanges = $discardChanges; 127 | $this->rawData = $rawData; 128 | } 129 | 130 | /** 131 | * Get the process timeout. 132 | * 133 | * @return int The process timeout. 134 | */ 135 | public function processTimeout() 136 | { 137 | return $this->processTimeout; 138 | } 139 | 140 | /** 141 | * Returns true if the autoloader should look for classes in the PHP include 142 | * path. 143 | * 144 | * @return bool True if the autoloader should look for classes in the PHP include path. 145 | */ 146 | public function useIncludePath() 147 | { 148 | return $this->useIncludePath; 149 | } 150 | 151 | /** 152 | * Get the preferred installation method. 153 | * 154 | * @return InstallationMethod|array The preferred installation method. 155 | */ 156 | public function preferredInstall() 157 | { 158 | return $this->preferredInstall; 159 | } 160 | 161 | /** 162 | * Get the protocols to use when cloning from GitHub. 163 | * 164 | * @return array The protocols to use when cloning from GitHub. 165 | */ 166 | public function githubProtocols() 167 | { 168 | return $this->githubProtocols; 169 | } 170 | 171 | /** 172 | * Get the GitHub OAuth tokens. 173 | * 174 | * @return array The GitHub OAuth tokens. 175 | */ 176 | public function githubOauth() 177 | { 178 | return $this->githubOauth; 179 | } 180 | 181 | /** 182 | * Get the vendor directory. 183 | * 184 | * @return string The vendor directory. 185 | */ 186 | public function vendorDir() 187 | { 188 | return $this->vendorDir; 189 | } 190 | 191 | /** 192 | * Get the binary executable directory. 193 | * 194 | * @return string The binary executable directory. 195 | */ 196 | public function binDir() 197 | { 198 | return $this->binDir; 199 | } 200 | 201 | /** 202 | * Get the cache directory. 203 | * 204 | * @return string|null The cache directory, or null if the directory is unknown. 205 | */ 206 | public function cacheDir() 207 | { 208 | return $this->cacheDir; 209 | } 210 | 211 | /** 212 | * Get the cache directory for package archives. 213 | * 214 | * @return string|null The cache directory for package archives, or null if the directory is unknown. 215 | */ 216 | public function cacheFilesDir() 217 | { 218 | return $this->cacheFilesDir; 219 | } 220 | 221 | /** 222 | * Get the cache directory for package repositories. 223 | * 224 | * @return string|null The cache directory for package repositories, or null if the directory is unknown. 225 | */ 226 | public function cacheRepoDir() 227 | { 228 | return $this->cacheRepoDir; 229 | } 230 | 231 | /** 232 | * Get the cache directory for version control repositories. 233 | * 234 | * @return string|null The cache directory for version control repositories, or null if the directory is unknown. 235 | */ 236 | public function cacheVcsDir() 237 | { 238 | return $this->cacheVcsDir; 239 | } 240 | 241 | /** 242 | * Get the cache time-to-live for package archives in seconds. 243 | * 244 | * @return int The cache time-to-live for package archives in seconds. 245 | */ 246 | public function cacheFilesTtl() 247 | { 248 | return $this->cacheFilesTtl; 249 | } 250 | 251 | /** 252 | * Get the maximum size of the package archive cache in bytes. 253 | * 254 | * @return int The maximum size of the package archive cache in bytes. 255 | */ 256 | public function cacheFilesMaxsize() 257 | { 258 | return $this->cacheFilesMaxsize; 259 | } 260 | 261 | /** 262 | * Returns true if the autoloader should be prepended to existing 263 | * autoloaders. 264 | * 265 | * @return bool True if the autoloader should be prepended to existing autoloaders. 266 | */ 267 | public function prependAutoloader() 268 | { 269 | return $this->prependAutoloader; 270 | } 271 | 272 | /** 273 | * Get the suffix used for the generated autoloader class name. 274 | * 275 | * @return string|null The suffix used for the generated autoloader class name, or null if the suffix is random. 276 | */ 277 | public function autoloaderSuffix() 278 | { 279 | return $this->autoloaderSuffix; 280 | } 281 | 282 | /** 283 | * Returns true if the autoloader should always be optimized. 284 | * 285 | * @return bool True if the autoloader should always be optimized. 286 | */ 287 | public function optimizeAutoloader() 288 | { 289 | return $this->optimizeAutoloader; 290 | } 291 | 292 | /** 293 | * Get the list of domains to use in GitHub mode. 294 | * 295 | * @return array The list of domains to use in GitHub mode. 296 | */ 297 | public function githubDomains() 298 | { 299 | return $this->githubDomains; 300 | } 301 | 302 | /** 303 | * Returns true if notify-on-install is enabled. 304 | * 305 | * @return bool True if notify-on-install is enabled. 306 | */ 307 | public function notifyOnInstall() 308 | { 309 | return $this->notifyOnInstall; 310 | } 311 | 312 | /** 313 | * Get the policy for how to treat version control changes when installing 314 | * or updating. 315 | * 316 | * @return VcsChangePolicy The policy for how to treat version control changes when installing or updating. 317 | */ 318 | public function discardChanges() 319 | { 320 | return $this->discardChanges; 321 | } 322 | 323 | /** 324 | * Get the raw configuration data. 325 | * 326 | * @return mixed The raw configuration data. 327 | */ 328 | public function rawData() 329 | { 330 | return $this->rawData; 331 | } 332 | 333 | private $processTimeout; 334 | private $useIncludePath; 335 | private $preferredInstall; 336 | private $githubProtocols; 337 | private $githubOauth; 338 | private $vendorDir; 339 | private $binDir; 340 | private $cacheDir; 341 | private $cacheFilesDir; 342 | private $cacheRepoDir; 343 | private $cacheVcsDir; 344 | private $cacheFilesTtl; 345 | private $cacheFilesMaxsize; 346 | private $prependAutoloader; 347 | private $autoloaderSuffix; 348 | private $optimizeAutoloader; 349 | private $githubDomains; 350 | private $notifyOnInstall; 351 | private $discardChanges; 352 | private $rawData; 353 | } 354 | -------------------------------------------------------------------------------- /src/Element/Repository.php: -------------------------------------------------------------------------------- 1 | |null $options The repository options. 16 | * @param mixed $rawData The raw data describing the repository. 17 | */ 18 | public function __construct( 19 | $type, 20 | $uri = null, 21 | array $options = null, 22 | $rawData = null 23 | ) { 24 | parent::__construct( 25 | $type, 26 | $options, 27 | $rawData 28 | ); 29 | 30 | $this->uri = $uri; 31 | } 32 | 33 | /** 34 | * Get the repository URI. 35 | * 36 | * @return string|null The repository URI. 37 | */ 38 | public function uri() 39 | { 40 | return $this->uri; 41 | } 42 | 43 | private $uri; 44 | } 45 | -------------------------------------------------------------------------------- /src/Element/RepositoryInterface.php: -------------------------------------------------------------------------------- 1 | |null $preInstallCmd The pre-install commands. 14 | * @param array|null $postInstallCmd The post-install commands. 15 | * @param array|null $preUpdateCmd The pre-update commands. 16 | * @param array|null $postUpdateCmd The post-update commands. 17 | * @param array|null $preStatusCmd The pre-status commands. 18 | * @param array|null $postStatusCmd The post-status commands. 19 | * @param array|null $prePackageInstall The pre-package-install commands. 20 | * @param array|null $postPackageInstall The post-package-install commands. 21 | * @param array|null $prePackageUpdate The pre-package-update commands. 22 | * @param array|null $postPackageUpdate The post-package-update commands. 23 | * @param array|null $prePackageUninstall The pre-package-uninstall commands. 24 | * @param array|null $postPackageUninstall The post-package-uninstall commands. 25 | * @param array|null $preAutoloadDump The pre-autoload-dump commands. 26 | * @param array|null $postAutoloadDump The post-autoload-dump commands. 27 | * @param array|null $postRootPackageInstall The post-root-package-install commands. 28 | * @param array|null $postCreateProjectCmd The post-create-project commands. 29 | * @param mixed $rawData The raw data describing the script configuration. 30 | */ 31 | public function __construct( 32 | array $preInstallCmd = null, 33 | array $postInstallCmd = null, 34 | array $preUpdateCmd = null, 35 | array $postUpdateCmd = null, 36 | array $preStatusCmd = null, 37 | array $postStatusCmd = null, 38 | array $prePackageInstall = null, 39 | array $postPackageInstall = null, 40 | array $prePackageUpdate = null, 41 | array $postPackageUpdate = null, 42 | array $prePackageUninstall = null, 43 | array $postPackageUninstall = null, 44 | array $preAutoloadDump = null, 45 | array $postAutoloadDump = null, 46 | array $postRootPackageInstall = null, 47 | array $postCreateProjectCmd = null, 48 | $rawData = null 49 | ) { 50 | if (null === $preInstallCmd) { 51 | $preInstallCmd = []; 52 | } 53 | if (null === $postInstallCmd) { 54 | $postInstallCmd = []; 55 | } 56 | if (null === $preUpdateCmd) { 57 | $preUpdateCmd = []; 58 | } 59 | if (null === $postUpdateCmd) { 60 | $postUpdateCmd = []; 61 | } 62 | if (null === $preStatusCmd) { 63 | $preStatusCmd = []; 64 | } 65 | if (null === $postStatusCmd) { 66 | $postStatusCmd = []; 67 | } 68 | if (null === $prePackageInstall) { 69 | $prePackageInstall = []; 70 | } 71 | if (null === $postPackageInstall) { 72 | $postPackageInstall = []; 73 | } 74 | if (null === $prePackageUpdate) { 75 | $prePackageUpdate = []; 76 | } 77 | if (null === $postPackageUpdate) { 78 | $postPackageUpdate = []; 79 | } 80 | if (null === $prePackageUninstall) { 81 | $prePackageUninstall = []; 82 | } 83 | if (null === $postPackageUninstall) { 84 | $postPackageUninstall = []; 85 | } 86 | if (null === $preAutoloadDump) { 87 | $preAutoloadDump = []; 88 | } 89 | if (null === $postAutoloadDump) { 90 | $postAutoloadDump = []; 91 | } 92 | if (null === $postRootPackageInstall) { 93 | $postRootPackageInstall = []; 94 | } 95 | if (null === $postCreateProjectCmd) { 96 | $postCreateProjectCmd = []; 97 | } 98 | 99 | $this->preInstallCmd = $preInstallCmd; 100 | $this->postInstallCmd = $postInstallCmd; 101 | $this->preUpdateCmd = $preUpdateCmd; 102 | $this->postUpdateCmd = $postUpdateCmd; 103 | $this->preStatusCmd = $preStatusCmd; 104 | $this->postStatusCmd = $postStatusCmd; 105 | $this->prePackageInstall = $prePackageInstall; 106 | $this->postPackageInstall = $postPackageInstall; 107 | $this->prePackageUpdate = $prePackageUpdate; 108 | $this->postPackageUpdate = $postPackageUpdate; 109 | $this->prePackageUninstall = $prePackageUninstall; 110 | $this->postPackageUninstall = $postPackageUninstall; 111 | $this->preAutoloadDump = $preAutoloadDump; 112 | $this->postAutoloadDump = $postAutoloadDump; 113 | $this->postRootPackageInstall = $postRootPackageInstall; 114 | $this->postCreateProjectCmd = $postCreateProjectCmd; 115 | $this->rawData = $rawData; 116 | } 117 | 118 | /** 119 | * Get the pre-install commands. 120 | * 121 | * @return array The pre-install commands. 122 | */ 123 | public function preInstallCmd() 124 | { 125 | return $this->preInstallCmd; 126 | } 127 | 128 | /** 129 | * Get the post-install commands. 130 | * 131 | * @return array The post-install commands. 132 | */ 133 | public function postInstallCmd() 134 | { 135 | return $this->postInstallCmd; 136 | } 137 | 138 | /** 139 | * Get the pre-update commands. 140 | * 141 | * @return array The pre-update commands. 142 | */ 143 | public function preUpdateCmd() 144 | { 145 | return $this->preUpdateCmd; 146 | } 147 | 148 | /** 149 | * Get the post-update commands. 150 | * 151 | * @return array The post-update commands. 152 | */ 153 | public function postUpdateCmd() 154 | { 155 | return $this->postUpdateCmd; 156 | } 157 | 158 | /** 159 | * Get the pre-status commands. 160 | * 161 | * @return array The pre-status commands. 162 | */ 163 | public function preStatusCmd() 164 | { 165 | return $this->preStatusCmd; 166 | } 167 | 168 | /** 169 | * Get the post-status commands. 170 | * 171 | * @return array The post-status commands. 172 | */ 173 | public function postStatusCmd() 174 | { 175 | return $this->postStatusCmd; 176 | } 177 | 178 | /** 179 | * Get the pre-package-install commands. 180 | * 181 | * @return array The pre-package-install commands. 182 | */ 183 | public function prePackageInstall() 184 | { 185 | return $this->prePackageInstall; 186 | } 187 | 188 | /** 189 | * Get the post-package-install commands. 190 | * 191 | * @return array The post-package-install commands. 192 | */ 193 | public function postPackageInstall() 194 | { 195 | return $this->postPackageInstall; 196 | } 197 | 198 | /** 199 | * Get the pre-package-update commands. 200 | * 201 | * @return array The pre-package-update commands. 202 | */ 203 | public function prePackageUpdate() 204 | { 205 | return $this->prePackageUpdate; 206 | } 207 | 208 | /** 209 | * Get the post-package-update commands. 210 | * 211 | * @return array The post-package-update commands. 212 | */ 213 | public function postPackageUpdate() 214 | { 215 | return $this->postPackageUpdate; 216 | } 217 | 218 | /** 219 | * Get the pre-package-uninstall commands. 220 | * 221 | * @return array The pre-package-uninstall commands. 222 | */ 223 | public function prePackageUninstall() 224 | { 225 | return $this->prePackageUninstall; 226 | } 227 | 228 | /** 229 | * Get the post-package-uninstall commands. 230 | * 231 | * @return array The post-package-uninstall commands. 232 | */ 233 | public function postPackageUninstall() 234 | { 235 | return $this->postPackageUninstall; 236 | } 237 | 238 | /** 239 | * Get the pre-autoload-dump commands. 240 | * 241 | * @return array The pre-autoload-dump commands. 242 | */ 243 | public function preAutoloadDump() 244 | { 245 | return $this->preAutoloadDump; 246 | } 247 | 248 | /** 249 | * Get the post-autoload-dump commands. 250 | * 251 | * @return array The post-autoload-dump commands. 252 | */ 253 | public function postAutoloadDump() 254 | { 255 | return $this->postAutoloadDump; 256 | } 257 | 258 | /** 259 | * Get the post-root-package-install commands. 260 | * 261 | * @return array The post-root-package-install commands. 262 | */ 263 | public function postRootPackageInstall() 264 | { 265 | return $this->postRootPackageInstall; 266 | } 267 | 268 | /** 269 | * Get the post-create-project commands. 270 | * 271 | * @return array The post-create-project commands. 272 | */ 273 | public function postCreateProjectCmd() 274 | { 275 | return $this->postCreateProjectCmd; 276 | } 277 | 278 | /** 279 | * Get the raw configuration data. 280 | * 281 | * @return mixed The raw configuration data. 282 | */ 283 | public function rawData() 284 | { 285 | return $this->rawData; 286 | } 287 | 288 | private $preInstallCmd; 289 | private $postInstallCmd; 290 | private $preUpdateCmd; 291 | private $postUpdateCmd; 292 | private $preStatusCmd; 293 | private $postStatusCmd; 294 | private $prePackageInstall; 295 | private $postPackageInstall; 296 | private $prePackageUpdate; 297 | private $postPackageUpdate; 298 | private $prePackageUninstall; 299 | private $postPackageUninstall; 300 | private $preAutoloadDump; 301 | private $postAutoloadDump; 302 | private $postRootPackageInstall; 303 | private $postCreateProjectCmd; 304 | private $rawData; 305 | } 306 | -------------------------------------------------------------------------------- /src/Element/Stability.php: -------------------------------------------------------------------------------- 1 | email = $email; 31 | $this->issues = $issues; 32 | $this->forum = $forum; 33 | $this->wiki = $wiki; 34 | $this->irc = $irc; 35 | $this->source = $source; 36 | $this->rawData = $rawData; 37 | } 38 | 39 | /** 40 | * Get the support email address. 41 | * 42 | * @return string|null The support email address. 43 | */ 44 | public function email() 45 | { 46 | return $this->email; 47 | } 48 | 49 | /** 50 | * Get the URI of the issue tracker. 51 | * 52 | * @return string|null The URI of the issue tracker. 53 | */ 54 | public function issues() 55 | { 56 | return $this->issues; 57 | } 58 | 59 | /** 60 | * Get the URI of the forum. 61 | * 62 | * @return string|null The URI of the forum. 63 | */ 64 | public function forum() 65 | { 66 | return $this->forum; 67 | } 68 | 69 | /** 70 | * Get the URI of the wiki. 71 | * 72 | * @return string|null The URI of the wiki. 73 | */ 74 | public function wiki() 75 | { 76 | return $this->wiki; 77 | } 78 | 79 | /** 80 | * Get the URI of the IRC channel. 81 | * 82 | * @return string|null The URI of the IRC channel. 83 | */ 84 | public function irc() 85 | { 86 | return $this->irc; 87 | } 88 | 89 | /** 90 | * Get the URI to the source code. 91 | * 92 | * @return string|null The URI to the source code. 93 | */ 94 | public function source() 95 | { 96 | return $this->source; 97 | } 98 | 99 | /** 100 | * Get the raw configuration data. 101 | * 102 | * @return mixed The raw configuration data. 103 | */ 104 | public function rawData() 105 | { 106 | return $this->rawData; 107 | } 108 | 109 | private $email; 110 | private $issues; 111 | private $forum; 112 | private $wiki; 113 | private $irc; 114 | private $source; 115 | private $rawData; 116 | } 117 | -------------------------------------------------------------------------------- /src/Element/VcsChangePolicy.php: -------------------------------------------------------------------------------- 1 | path = $path; 22 | 23 | parent::__construct( 24 | sprintf("Unable to read Composer configuration from '%s'.", $path), 25 | 0, 26 | $previous 27 | ); 28 | } 29 | 30 | /** 31 | * Get the path to the configuration. 32 | * 33 | * @return string The configuration path. 34 | */ 35 | public function path() 36 | { 37 | return $this->path; 38 | } 39 | 40 | private $path; 41 | } 42 | -------------------------------------------------------------------------------- /src/Exception/InvalidConfigurationException.php: -------------------------------------------------------------------------------- 1 | > $errors The errors in the configuration. 17 | * @param Exception|null $previous The cause, if available. 18 | */ 19 | public function __construct(array $errors, Exception $previous = null) 20 | { 21 | $this->errors = $errors; 22 | 23 | parent::__construct($this->buildMessage($errors), 0, $previous); 24 | } 25 | 26 | /** 27 | * Get the errors in the configuration. 28 | * 29 | * @return array> The configuration errors. 30 | */ 31 | public function errors() 32 | { 33 | return $this->errors; 34 | } 35 | 36 | /** 37 | * Build the exception message. 38 | * 39 | * @param array> $errors The errors in the configuration. 40 | * 41 | * @return string The exception message. 42 | */ 43 | protected function buildMessage(array $errors) 44 | { 45 | $errorList = []; 46 | foreach ($errors as $error) { 47 | $errorList[] = sprintf( 48 | ' - [%s] %s', 49 | $error['property'], 50 | $error['message'] 51 | ); 52 | } 53 | 54 | return sprintf( 55 | "The supplied Composer configuration is invalid:\n%s", 56 | implode("\n", $errorList) 57 | ); 58 | } 59 | 60 | private $errors; 61 | } 62 | -------------------------------------------------------------------------------- /src/Exception/InvalidJsonException.php: -------------------------------------------------------------------------------- 1 | path = $path; 26 | $this->jsonErrorCode = $jsonErrorCode; 27 | switch ($jsonErrorCode) { 28 | case JSON_ERROR_DEPTH: 29 | $this->jsonErrorMessage = 30 | 'The maximum stack depth has been exceeded.'; 31 | break; 32 | case JSON_ERROR_STATE_MISMATCH: 33 | $this->jsonErrorMessage = 'Invalid or malformed JSON.'; 34 | break; 35 | case JSON_ERROR_CTRL_CHAR: 36 | $this->jsonErrorMessage = 37 | 'Control character error, possibly incorrectly encoded.'; 38 | break; 39 | case JSON_ERROR_SYNTAX: 40 | $this->jsonErrorMessage = 'Syntax error.'; 41 | break; 42 | case JSON_ERROR_UTF8: 43 | $this->jsonErrorMessage = 44 | 'Malformed UTF-8 characters, possibly incorrectly encoded.'; 45 | break; 46 | default: 47 | $this->jsonErrorMessage = 'Unknown error.'; 48 | } 49 | 50 | parent::__construct( 51 | sprintf( 52 | "Invalid JSON in Composer configuration at '%s': %s", 53 | $this->path(), 54 | $this->jsonErrorMessage() 55 | ), 56 | 0, 57 | $previous 58 | ); 59 | } 60 | 61 | /** 62 | * Get the path to the configuration. 63 | * 64 | * @return string The configuration path. 65 | */ 66 | public function path() 67 | { 68 | return $this->path; 69 | } 70 | 71 | /** 72 | * Get the error code supplied by PHP. 73 | * 74 | * @return int The error code. 75 | */ 76 | public function jsonErrorCode() 77 | { 78 | return $this->jsonErrorCode; 79 | } 80 | 81 | /** 82 | * Get the internal error message. 83 | * 84 | * @return string The internal error message. 85 | */ 86 | public function jsonErrorMessage() 87 | { 88 | return $this->jsonErrorMessage; 89 | } 90 | 91 | private $path; 92 | private $jsonErrorCode; 93 | private $jsonErrorMessage; 94 | } 95 | -------------------------------------------------------------------------------- /src/Exception/UndefinedPropertyException.php: -------------------------------------------------------------------------------- 1 | property = $property; 22 | 23 | parent::__construct( 24 | sprintf( 25 | "Undefined property '%s' in Composer configuration.", 26 | $this->property() 27 | ), 28 | 0, 29 | $previous 30 | ); 31 | } 32 | 33 | /** 34 | * Get the requested property name. 35 | * 36 | * @return string The property name. 37 | */ 38 | public function property() 39 | { 40 | return $this->property; 41 | } 42 | 43 | private $property; 44 | } 45 | -------------------------------------------------------------------------------- /src/ObjectAccess.php: -------------------------------------------------------------------------------- 1 | data = $data; 21 | } 22 | 23 | /** 24 | * Get the internal object. 25 | * 26 | * @return stdClass The internal object. 27 | */ 28 | public function data() 29 | { 30 | return $this->data; 31 | } 32 | 33 | /** 34 | * Returns true if the specified property exists. 35 | * 36 | * @param string $property The property name. 37 | * 38 | * @return bool True if the property exists. 39 | */ 40 | public function exists($property) 41 | { 42 | return property_exists($this->data(), $property); 43 | } 44 | 45 | /** 46 | * Get the value of the specified property. 47 | * 48 | * @param string $property The property name. 49 | * 50 | * @return mixed The value of the property. 51 | * @throws UndefinedPropertyException If the property does not exist. 52 | */ 53 | public function get($property) 54 | { 55 | if (!$this->exists($property)) { 56 | throw new UndefinedPropertyException($property); 57 | } 58 | 59 | return $this->data()->$property; 60 | } 61 | 62 | /** 63 | * Get the value of the specified property, and fall back to a default if 64 | * the property does not exist. 65 | * 66 | * @param string $property The property name. 67 | * @param mixed $default The default value to fall back to. 68 | * 69 | * @return mixed The value of the property, or the supplied default. 70 | */ 71 | public function getDefault($property, $default = null) 72 | { 73 | if (!$this->exists($property)) { 74 | return $default; 75 | } 76 | 77 | return $this->data()->$property; 78 | } 79 | 80 | private $data; 81 | } 82 | --------------------------------------------------------------------------------