├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── manifest.xsd ├── src ├── ManifestDocumentMapper.php ├── ManifestLoader.php ├── ManifestSerializer.php ├── exceptions │ ├── ElementCollectionException.php │ ├── Exception.php │ ├── InvalidApplicationNameException.php │ ├── InvalidEmailException.php │ ├── InvalidUrlException.php │ ├── ManifestDocumentException.php │ ├── ManifestDocumentLoadingException.php │ ├── ManifestDocumentMapperException.php │ ├── ManifestElementException.php │ ├── ManifestLoaderException.php │ └── NoEmailAddressException.php ├── values │ ├── Application.php │ ├── ApplicationName.php │ ├── Author.php │ ├── AuthorCollection.php │ ├── AuthorCollectionIterator.php │ ├── BundledComponent.php │ ├── BundledComponentCollection.php │ ├── BundledComponentCollectionIterator.php │ ├── CopyrightInformation.php │ ├── Email.php │ ├── Extension.php │ ├── Library.php │ ├── License.php │ ├── Manifest.php │ ├── PhpExtensionRequirement.php │ ├── PhpVersionRequirement.php │ ├── Requirement.php │ ├── RequirementCollection.php │ ├── RequirementCollectionIterator.php │ ├── Type.php │ └── Url.php └── xml │ ├── AuthorElement.php │ ├── AuthorElementCollection.php │ ├── BundlesElement.php │ ├── ComponentElement.php │ ├── ComponentElementCollection.php │ ├── ContainsElement.php │ ├── CopyrightElement.php │ ├── ElementCollection.php │ ├── ExtElement.php │ ├── ExtElementCollection.php │ ├── ExtensionElement.php │ ├── LicenseElement.php │ ├── ManifestDocument.php │ ├── ManifestElement.php │ ├── PhpElement.php │ └── RequiresElement.php └── tools └── php-cs-fixer.d ├── PhpdocSingleLineVarFixer.php └── header.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [theseer] 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "CI" 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | pull_request: null 8 | 9 | jobs: 10 | qa: 11 | name: "QA" 12 | 13 | runs-on: "ubuntu-latest" 14 | 15 | steps: 16 | - name: "Checkout" 17 | uses: "actions/checkout@v3.5.2" 18 | 19 | - name: "Set up PHP" 20 | uses: "shivammathur/setup-php@2.25.1" 21 | with: 22 | coverage: "none" 23 | php-version: "8.0" 24 | tools: "phive" 25 | 26 | - name: "Install dependencies with composer" 27 | run: "composer install --no-interaction --optimize-autoloader --prefer-dist" 28 | 29 | - name: "Install dependencies with phive" 30 | env: 31 | GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | run: "ant install-tools" 33 | 34 | - name: "Run php-cs-fixer" 35 | run: "ant php-cs-fixer" 36 | 37 | - name: "Run psalm" 38 | run: "ant psalm" 39 | 40 | tests: 41 | name: "Tests" 42 | 43 | runs-on: "ubuntu-latest" 44 | 45 | strategy: 46 | fail-fast: false 47 | 48 | matrix: 49 | php-versions: 50 | - "7.2" 51 | - "7.3" 52 | - "7.4" 53 | - "8.0" 54 | - "8.1" 55 | - "8.2" 56 | 57 | steps: 58 | - name: "Checkout" 59 | uses: "actions/checkout@v3.5.2" 60 | 61 | - name: "Set up PHP" 62 | uses: "shivammathur/setup-php@2.25.1" 63 | env: 64 | COMPOSER_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 65 | with: 66 | coverage: "pcov" 67 | extensions: "${{ env.extensions }}" 68 | ini-values: "display_errors=On, error_reporting=-1, memory_limit=2G" 69 | php-version: "${{ matrix.php-versions }}" 70 | tools: "phive" 71 | 72 | - name: "Install dependencies with composer" 73 | run: "composer install --no-interaction --optimize-autoloader --prefer-dist" 74 | 75 | - name: "Install dependencies with phive" 76 | env: 77 | GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 78 | run: "ant install-tools" 79 | 80 | - name: "Run PHPUnit" 81 | run: "tools/phpunit --coverage-clover build/logs/clover.xml" 82 | 83 | - name: "Send code coverage report to codecov.io" 84 | uses: "codecov/codecov-action@v3.1.4" 85 | with: 86 | files: "build/logs/clover.xml" 87 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | registerCustomFixers([ 9 | new \PharIo\CSFixer\PhpdocSingleLineVarFixer() 10 | ]) 11 | ->setRiskyAllowed(true) 12 | ->setRules( 13 | [ 14 | 'PharIo/phpdoc_single_line_var_fixer' => true, 15 | 16 | 'align_multiline_comment' => true, 17 | 'array_indentation' => true, 18 | 'array_syntax' => ['syntax' => 'short'], 19 | 'binary_operator_spaces' => [ 20 | 'operators' => [ 21 | '=' => 'align', 22 | '=>' => 'align', 23 | ], 24 | ], 25 | 'blank_line_after_namespace' => true, 26 | 'blank_line_after_opening_tag' => false, 27 | 'blank_line_before_statement' => [ 28 | 'statements' => [ 29 | 'break', 30 | 'continue', 31 | 'declare', 32 | 'do', 33 | 'for', 34 | 'foreach', 35 | 'if', 36 | 'include', 37 | 'include_once', 38 | 'require', 39 | 'require_once', 40 | 'return', 41 | 'switch', 42 | 'throw', 43 | 'try', 44 | 'while', 45 | 'yield', 46 | ], 47 | ], 48 | 'braces' => [ 49 | 'allow_single_line_closure' => false, 50 | 'position_after_anonymous_constructs' => 'same', 51 | 'position_after_control_structures' => 'same', 52 | 'position_after_functions_and_oop_constructs' => 'same' 53 | ], 54 | 'cast_spaces' => ['space' => 'none'], 55 | 56 | // This fixer removes the blank line at class start, no way to disable that, so we disable the fixer :( 57 | //'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], 58 | 59 | 'combine_consecutive_issets' => true, 60 | 'combine_consecutive_unsets' => true, 61 | 'compact_nullable_typehint' => true, 62 | 'concat_space' => ['spacing' => 'one'], 63 | 'date_time_immutable' => true, 64 | 'declare_equal_normalize' => ['space' => 'single'], 65 | 'declare_strict_types' => true, 66 | 'dir_constant' => true, 67 | 'elseif' => true, 68 | 'encoding' => true, 69 | 'full_opening_tag' => true, 70 | 'fully_qualified_strict_types' => true, 71 | 'function_declaration' => [ 72 | 'closure_function_spacing' => 'one' 73 | ], 74 | 'global_namespace_import' => [ 75 | 'import_classes' => true, 76 | 'import_constants' => true, 77 | 'import_functions' => true, 78 | ], 79 | 'header_comment' => ['header' => $header, 'separate' => 'none'], 80 | 'indentation_type' => true, 81 | 'is_null' => true, 82 | 'line_ending' => true, 83 | 'list_syntax' => ['syntax' => 'short'], 84 | 'logical_operators' => true, 85 | 'lowercase_cast' => true, 86 | 'constant_case' => ['case' => 'lower'], 87 | 'lowercase_keywords' => true, 88 | 'lowercase_static_reference' => true, 89 | 'magic_constant_casing' => true, 90 | 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'], 91 | 'modernize_types_casting' => true, 92 | 'multiline_comment_opening_closing' => true, 93 | 'multiline_whitespace_before_semicolons' => true, 94 | 'new_with_braces' => false, 95 | 'no_alias_functions' => true, 96 | 'no_alternative_syntax' => true, 97 | 'no_blank_lines_after_class_opening' => false, 98 | 'no_blank_lines_after_phpdoc' => true, 99 | 'no_blank_lines_before_namespace' => true, 100 | 'no_closing_tag' => true, 101 | 'no_empty_comment' => true, 102 | 'no_empty_phpdoc' => true, 103 | 'no_empty_statement' => true, 104 | 'no_extra_blank_lines' => true, 105 | 'no_homoglyph_names' => true, 106 | 'no_leading_import_slash' => true, 107 | 'no_leading_namespace_whitespace' => true, 108 | 'no_mixed_echo_print' => ['use' => 'print'], 109 | 'no_multiline_whitespace_around_double_arrow' => true, 110 | 'no_null_property_initialization' => true, 111 | 'no_php4_constructor' => true, 112 | 'no_short_bool_cast' => true, 113 | 'echo_tag_syntax' => ['format' => 'long'], 114 | 'no_singleline_whitespace_before_semicolons' => true, 115 | 'no_spaces_after_function_name' => true, 116 | 'no_spaces_inside_parenthesis' => true, 117 | 'no_superfluous_elseif' => true, 118 | 'no_superfluous_phpdoc_tags' => true, 119 | 'no_trailing_comma_in_list_call' => true, 120 | 'no_trailing_comma_in_singleline_array' => true, 121 | 'no_trailing_whitespace' => true, 122 | 'no_trailing_whitespace_in_comment' => true, 123 | 'no_unneeded_control_parentheses' => false, 124 | 'no_unneeded_curly_braces' => false, 125 | 'no_unneeded_final_method' => true, 126 | 'no_unreachable_default_argument_value' => true, 127 | 'no_unset_on_property' => true, 128 | 'no_unused_imports' => true, 129 | 'no_useless_else' => true, 130 | 'no_useless_return' => true, 131 | 'no_whitespace_before_comma_in_array' => true, 132 | 'no_whitespace_in_blank_line' => true, 133 | 'non_printable_character' => true, 134 | 'normalize_index_brace' => true, 135 | 'object_operator_without_whitespace' => true, 136 | 'ordered_class_elements' => [ 137 | 'order' => [ 138 | 'use_trait', 139 | 'constant_public', 140 | 'constant_protected', 141 | 'constant_private', 142 | 'property_public_static', 143 | 'property_protected_static', 144 | 'property_private_static', 145 | 'property_public', 146 | 'property_protected', 147 | 'property_private', 148 | 'method_public_static', 149 | 'construct', 150 | 'destruct', 151 | 'magic', 152 | 'phpunit', 153 | 'method_public', 154 | 'method_protected', 155 | 'method_private', 156 | 'method_protected_static', 157 | 'method_private_static', 158 | ], 159 | ], 160 | 'ordered_imports' => [ 161 | 'imports_order' => [ 162 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_CLASS, 163 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_CONST, 164 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_FUNCTION, 165 | ] 166 | ], 167 | 'phpdoc_add_missing_param_annotation' => true, 168 | 'phpdoc_align' => true, 169 | 'phpdoc_annotation_without_dot' => true, 170 | 'phpdoc_indent' => true, 171 | 'phpdoc_no_access' => true, 172 | 'phpdoc_no_empty_return' => true, 173 | 'phpdoc_no_package' => true, 174 | 'phpdoc_order' => true, 175 | 'phpdoc_return_self_reference' => true, 176 | 'phpdoc_scalar' => true, 177 | 'phpdoc_separation' => true, 178 | 'phpdoc_single_line_var_spacing' => true, 179 | 'phpdoc_to_comment' => true, 180 | 'phpdoc_trim' => true, 181 | 'phpdoc_trim_consecutive_blank_line_separation' => true, 182 | 'phpdoc_types' => ['groups' => ['simple', 'meta']], 183 | 'phpdoc_types_order' => true, 184 | 'phpdoc_to_return_type' => true, 185 | 'phpdoc_var_without_name' => true, 186 | 'pow_to_exponentiation' => true, 187 | 'protected_to_private' => true, 188 | 'return_assignment' => true, 189 | 'return_type_declaration' => ['space_before' => 'none'], 190 | 'self_accessor' => false, 191 | 'semicolon_after_instruction' => true, 192 | 'set_type_to_cast' => true, 193 | 'short_scalar_cast' => true, 194 | 'simplified_null_return' => true, 195 | 'single_blank_line_at_eof' => true, 196 | 'single_import_per_statement' => true, 197 | 'single_line_after_imports' => true, 198 | 'single_quote' => true, 199 | 'standardize_not_equals' => true, 200 | 'ternary_to_null_coalescing' => true, 201 | 'trailing_comma_in_multiline' => false, 202 | 'trim_array_spaces' => true, 203 | 'unary_operator_spaces' => true, 204 | 'visibility_required' => [ 205 | 'elements' => [ 206 | 'const', 207 | 'method', 208 | 'property', 209 | ], 210 | ], 211 | 'void_return' => true, 212 | 'whitespace_after_comma_in_array' => true, 213 | 'yoda_style' => false 214 | ] 215 | ) 216 | ->setFinder( 217 | PhpCsFixer\Finder::create() 218 | ->files() 219 | ->in(__DIR__ . '/build') 220 | ->in(__DIR__ . '/src') 221 | ->in(__DIR__ . '/tests') 222 | ->notName('autoload.php') 223 | ); 224 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to phar-io/manifest are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. 4 | 5 | ## [2.0.4] - 03-03-2024 6 | 7 | ### Changed 8 | 9 | - Make `EMail` an optional attribute for author 10 | - Stick with PHP 7.2 compatibilty 11 | - Do not use implict nullable type (thanks @sebastianbergmann), this should make things work on PHP 8.4 12 | 13 | ## [2.0.3] - 20.07.2021 14 | 15 | - Fixed PHP 7.2 / PHP 7.3 incompatibility introduced in previous release 16 | 17 | ## [2.0.2] - 20.07.2021 18 | 19 | - Fixed PHP 8.1 deprecation notice 20 | 21 | ## [2.0.1] - 27.06.2020 22 | 23 | This release now supports the use of PHP 7.2+ and ^8.0 24 | 25 | ## [2.0.0] - 10.05.2020 26 | 27 | This release now requires PHP 7.2+ 28 | 29 | ### Changed 30 | 31 | - Upgraded to phar-io/version 3.0 32 | - Version strings `v1.2.3` will now be converted to valid semantic version strings `1.2.3` 33 | - Abreviated strings like `1.0` will get expaneded to `1.0.0` 34 | 35 | ### Unreleased 36 | 37 | [Unreleased]: https://github.com/phar-io/manifest/compare/2.1.0...HEAD 38 | [2.1.0]: https://github.com/phar-io/manifest/compare/2.0.3...2.1.0 39 | [2.0.3]: https://github.com/phar-io/manifest/compare/2.0.2...2.0.3 40 | [2.0.2]: https://github.com/phar-io/manifest/compare/2.0.1...2.0.2 41 | [2.0.1]: https://github.com/phar-io/manifest/compare/2.0.0...2.0.1 42 | [2.0.0]: https://github.com/phar-io/manifest/compare/1.0.1...2.0.0 43 | [1.0.3]: https://github.com/phar-io/manifest/compare/1.0.2...1.0.3 44 | [1.0.2]: https://github.com/phar-io/manifest/compare/1.0.1...1.0.2 45 | [1.0.1]: https://github.com/phar-io/manifest/compare/1.0.0...1.0.1 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Phar.io - Manifest 2 | 3 | Copyright (c) 2016-2019 Arne Blankerts , Sebastian Heuer , Sebastian Bergmann , and contributors 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Arne Blankerts nor the names of contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, 22 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 24 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 25 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | POSSIBILITY OF SUCH DAMAGE. 31 | 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Manifest 2 | 3 | Component for reading [phar.io](https://phar.io/) manifest information from a [PHP Archive (PHAR)](http://php.net/phar). 4 | 5 | ## Installation 6 | 7 | You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): 8 | 9 | composer require phar-io/manifest 10 | 11 | If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: 12 | 13 | composer require --dev phar-io/manifest 14 | 15 | ## Usage Examples 16 | 17 | ### Read from `manifest.xml` 18 | ```php 19 | use PharIo\Manifest\ManifestLoader; 20 | use PharIo\Manifest\ManifestSerializer; 21 | 22 | $manifest = ManifestLoader::fromFile('manifest.xml'); 23 | 24 | var_dump($manifest); 25 | 26 | echo (new ManifestSerializer)->serializeToString($manifest); 27 | ``` 28 | 29 |
30 | Output 31 | 32 | ```shell 33 | object(PharIo\Manifest\Manifest)#14 (6) { 34 | ["name":"PharIo\Manifest\Manifest":private]=> 35 | object(PharIo\Manifest\ApplicationName)#10 (1) { 36 | ["name":"PharIo\Manifest\ApplicationName":private]=> 37 | string(12) "some/library" 38 | } 39 | ["version":"PharIo\Manifest\Manifest":private]=> 40 | object(PharIo\Version\Version)#12 (5) { 41 | ["originalVersionString":"PharIo\Version\Version":private]=> 42 | string(5) "1.0.0" 43 | ["major":"PharIo\Version\Version":private]=> 44 | object(PharIo\Version\VersionNumber)#13 (1) { 45 | ["value":"PharIo\Version\VersionNumber":private]=> 46 | int(1) 47 | } 48 | ["minor":"PharIo\Version\Version":private]=> 49 | object(PharIo\Version\VersionNumber)#23 (1) { 50 | ["value":"PharIo\Version\VersionNumber":private]=> 51 | int(0) 52 | } 53 | ["patch":"PharIo\Version\Version":private]=> 54 | object(PharIo\Version\VersionNumber)#22 (1) { 55 | ["value":"PharIo\Version\VersionNumber":private]=> 56 | int(0) 57 | } 58 | ["preReleaseSuffix":"PharIo\Version\Version":private]=> 59 | NULL 60 | } 61 | ["type":"PharIo\Manifest\Manifest":private]=> 62 | object(PharIo\Manifest\Library)#6 (0) { 63 | } 64 | ["copyrightInformation":"PharIo\Manifest\Manifest":private]=> 65 | object(PharIo\Manifest\CopyrightInformation)#19 (2) { 66 | ["authors":"PharIo\Manifest\CopyrightInformation":private]=> 67 | object(PharIo\Manifest\AuthorCollection)#9 (1) { 68 | ["authors":"PharIo\Manifest\AuthorCollection":private]=> 69 | array(1) { 70 | [0]=> 71 | object(PharIo\Manifest\Author)#15 (2) { 72 | ["name":"PharIo\Manifest\Author":private]=> 73 | string(13) "Reiner Zufall" 74 | ["email":"PharIo\Manifest\Author":private]=> 75 | object(PharIo\Manifest\Email)#16 (1) { 76 | ["email":"PharIo\Manifest\Email":private]=> 77 | string(16) "reiner@zufall.de" 78 | } 79 | } 80 | } 81 | } 82 | ["license":"PharIo\Manifest\CopyrightInformation":private]=> 83 | object(PharIo\Manifest\License)#11 (2) { 84 | ["name":"PharIo\Manifest\License":private]=> 85 | string(12) "BSD-3-Clause" 86 | ["url":"PharIo\Manifest\License":private]=> 87 | object(PharIo\Manifest\Url)#18 (1) { 88 | ["url":"PharIo\Manifest\Url":private]=> 89 | string(26) "https://domain.tld/LICENSE" 90 | } 91 | } 92 | } 93 | ["requirements":"PharIo\Manifest\Manifest":private]=> 94 | object(PharIo\Manifest\RequirementCollection)#17 (1) { 95 | ["requirements":"PharIo\Manifest\RequirementCollection":private]=> 96 | array(1) { 97 | [0]=> 98 | object(PharIo\Manifest\PhpVersionRequirement)#20 (1) { 99 | ["versionConstraint":"PharIo\Manifest\PhpVersionRequirement":private]=> 100 | object(PharIo\Version\SpecificMajorAndMinorVersionConstraint)#24 (3) { 101 | ["originalValue":"PharIo\Version\AbstractVersionConstraint":private]=> 102 | string(3) "7.0" 103 | ["major":"PharIo\Version\SpecificMajorAndMinorVersionConstraint":private]=> 104 | int(7) 105 | ["minor":"PharIo\Version\SpecificMajorAndMinorVersionConstraint":private]=> 106 | int(0) 107 | } 108 | } 109 | } 110 | } 111 | ["bundledComponents":"PharIo\Manifest\Manifest":private]=> 112 | object(PharIo\Manifest\BundledComponentCollection)#8 (1) { 113 | ["bundledComponents":"PharIo\Manifest\BundledComponentCollection":private]=> 114 | array(0) { 115 | } 116 | } 117 | } 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | ``` 130 |
131 | 132 | ### Create via API 133 | ```php 134 | $bundled = new \PharIo\Manifest\BundledComponentCollection(); 135 | $bundled->add( 136 | new \PharIo\Manifest\BundledComponent('vendor/packageA', new \PharIo\Version\Version('1.2.3-dev') 137 | ) 138 | ); 139 | 140 | $manifest = new PharIo\Manifest\Manifest( 141 | new \PharIo\Manifest\ApplicationName('vendor/package'), 142 | new \PharIo\Version\Version('1.0.0'), 143 | new \PharIo\Manifest\Library(), 144 | new \PharIo\Manifest\CopyrightInformation( 145 | new \PharIo\Manifest\AuthorCollection(), 146 | new \PharIo\Manifest\License( 147 | 'BSD-3-Clause', 148 | new \PharIo\Manifest\Url('https://spdx.org/licenses/BSD-3-Clause.html') 149 | ) 150 | ), 151 | new \PharIo\Manifest\RequirementCollection(), 152 | $bundled 153 | ); 154 | 155 | echo (new ManifestSerializer)->serializeToString($manifest); 156 | ``` 157 | 158 |
159 | Output 160 | 161 | ```xml 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | ``` 176 | 177 |
178 | 179 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phar-io/manifest", 3 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 4 | "license": "BSD-3-Clause", 5 | "authors": [ 6 | { 7 | "name": "Arne Blankerts", 8 | "email": "arne@blankerts.de", 9 | "role": "Developer" 10 | }, 11 | { 12 | "name": "Sebastian Heuer", 13 | "email": "sebastian@phpeople.de", 14 | "role": "Developer" 15 | }, 16 | { 17 | "name": "Sebastian Bergmann", 18 | "email": "sebastian@phpunit.de", 19 | "role": "Developer" 20 | } 21 | ], 22 | "support": { 23 | "issues": "https://github.com/phar-io/manifest/issues" 24 | }, 25 | "require": { 26 | "php": "^7.2 || ^8.0", 27 | "ext-dom": "*", 28 | "ext-phar": "*", 29 | "ext-libxml": "*", 30 | "ext-xmlwriter": "*", 31 | "phar-io/version": "^3.0.1" 32 | }, 33 | "autoload": { 34 | "classmap": [ 35 | "src/" 36 | ] 37 | }, 38 | "extra": { 39 | "branch-alias": { 40 | "dev-master": "2.0.x-dev" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "279b3c4fe44357abd924fdcc0cfa5664", 8 | "packages": [ 9 | { 10 | "name": "phar-io/version", 11 | "version": "3.2.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/phar-io/version.git", 15 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 20 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^7.2 || ^8.0" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "classmap": [ 29 | "src/" 30 | ] 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "BSD-3-Clause" 35 | ], 36 | "authors": [ 37 | { 38 | "name": "Arne Blankerts", 39 | "email": "arne@blankerts.de", 40 | "role": "Developer" 41 | }, 42 | { 43 | "name": "Sebastian Heuer", 44 | "email": "sebastian@phpeople.de", 45 | "role": "Developer" 46 | }, 47 | { 48 | "name": "Sebastian Bergmann", 49 | "email": "sebastian@phpunit.de", 50 | "role": "Developer" 51 | } 52 | ], 53 | "description": "Library for handling version information and constraints", 54 | "support": { 55 | "issues": "https://github.com/phar-io/version/issues", 56 | "source": "https://github.com/phar-io/version/tree/3.2.1" 57 | }, 58 | "time": "2022-02-21T01:04:05+00:00" 59 | } 60 | ], 61 | "packages-dev": [], 62 | "aliases": [], 63 | "minimum-stability": "stable", 64 | "stability-flags": [], 65 | "prefer-stable": false, 66 | "prefer-lowest": false, 67 | "platform": { 68 | "php": "^7.2 || ^8.0", 69 | "ext-dom": "*", 70 | "ext-phar": "*", 71 | "ext-libxml": "*", 72 | "ext-xmlwriter": "*" 73 | }, 74 | "platform-dev": [], 75 | "plugin-api-version": "2.3.0" 76 | } 77 | -------------------------------------------------------------------------------- /manifest.xsd: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /src/ManifestDocumentMapper.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\Exception as VersionException; 14 | use PharIo\Version\Version; 15 | use PharIo\Version\VersionConstraintParser; 16 | use Throwable; 17 | use function sprintf; 18 | 19 | class ManifestDocumentMapper { 20 | public function map(ManifestDocument $document): Manifest { 21 | try { 22 | $contains = $document->getContainsElement(); 23 | $type = $this->mapType($contains); 24 | $copyright = $this->mapCopyright($document->getCopyrightElement()); 25 | $requirements = $this->mapRequirements($document->getRequiresElement()); 26 | $bundledComponents = $this->mapBundledComponents($document); 27 | 28 | return new Manifest( 29 | new ApplicationName($contains->getName()), 30 | new Version($contains->getVersion()), 31 | $type, 32 | $copyright, 33 | $requirements, 34 | $bundledComponents 35 | ); 36 | } catch (Throwable $e) { 37 | throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); 38 | } 39 | } 40 | 41 | private function mapType(ContainsElement $contains): Type { 42 | switch ($contains->getType()) { 43 | case 'application': 44 | return Type::application(); 45 | case 'library': 46 | return Type::library(); 47 | case 'extension': 48 | return $this->mapExtension($contains->getExtensionElement()); 49 | } 50 | 51 | throw new ManifestDocumentMapperException( 52 | sprintf('Unsupported type %s', $contains->getType()) 53 | ); 54 | } 55 | 56 | private function mapCopyright(CopyrightElement $copyright): CopyrightInformation { 57 | $authors = new AuthorCollection(); 58 | 59 | foreach ($copyright->getAuthorElements() as $authorElement) { 60 | $authors->add( 61 | new Author( 62 | $authorElement->getName(), 63 | $authorElement->hasEMail() ? new Email($authorElement->getEmail()) : null 64 | ) 65 | ); 66 | } 67 | 68 | $licenseElement = $copyright->getLicenseElement(); 69 | $license = new License( 70 | $licenseElement->getType(), 71 | new Url($licenseElement->getUrl()) 72 | ); 73 | 74 | return new CopyrightInformation( 75 | $authors, 76 | $license 77 | ); 78 | } 79 | 80 | private function mapRequirements(RequiresElement $requires): RequirementCollection { 81 | $collection = new RequirementCollection(); 82 | $phpElement = $requires->getPHPElement(); 83 | $parser = new VersionConstraintParser; 84 | 85 | try { 86 | $versionConstraint = $parser->parse($phpElement->getVersion()); 87 | } catch (VersionException $e) { 88 | throw new ManifestDocumentMapperException( 89 | sprintf('Unsupported version constraint - %s', $e->getMessage()), 90 | (int)$e->getCode(), 91 | $e 92 | ); 93 | } 94 | 95 | $collection->add( 96 | new PhpVersionRequirement( 97 | $versionConstraint 98 | ) 99 | ); 100 | 101 | if (!$phpElement->hasExtElements()) { 102 | return $collection; 103 | } 104 | 105 | foreach ($phpElement->getExtElements() as $extElement) { 106 | $collection->add( 107 | new PhpExtensionRequirement($extElement->getName()) 108 | ); 109 | } 110 | 111 | return $collection; 112 | } 113 | 114 | private function mapBundledComponents(ManifestDocument $document): BundledComponentCollection { 115 | $collection = new BundledComponentCollection(); 116 | 117 | if (!$document->hasBundlesElement()) { 118 | return $collection; 119 | } 120 | 121 | foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) { 122 | $collection->add( 123 | new BundledComponent( 124 | $componentElement->getName(), 125 | new Version( 126 | $componentElement->getVersion() 127 | ) 128 | ) 129 | ); 130 | } 131 | 132 | return $collection; 133 | } 134 | 135 | private function mapExtension(ExtensionElement $extension): Extension { 136 | try { 137 | $versionConstraint = (new VersionConstraintParser)->parse($extension->getCompatible()); 138 | 139 | return Type::extension( 140 | new ApplicationName($extension->getFor()), 141 | $versionConstraint 142 | ); 143 | } catch (VersionException $e) { 144 | throw new ManifestDocumentMapperException( 145 | sprintf('Unsupported version constraint - %s', $e->getMessage()), 146 | (int)$e->getCode(), 147 | $e 148 | ); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/ManifestLoader.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use function sprintf; 14 | 15 | class ManifestLoader { 16 | public static function fromFile(string $filename): Manifest { 17 | try { 18 | return (new ManifestDocumentMapper())->map( 19 | ManifestDocument::fromFile($filename) 20 | ); 21 | } catch (Exception $e) { 22 | throw new ManifestLoaderException( 23 | sprintf('Loading %s failed.', $filename), 24 | (int)$e->getCode(), 25 | $e 26 | ); 27 | } 28 | } 29 | 30 | public static function fromPhar(string $filename): Manifest { 31 | return self::fromFile('phar://' . $filename . '/manifest.xml'); 32 | } 33 | 34 | public static function fromString(string $manifest): Manifest { 35 | try { 36 | return (new ManifestDocumentMapper())->map( 37 | ManifestDocument::fromString($manifest) 38 | ); 39 | } catch (Exception $e) { 40 | throw new ManifestLoaderException( 41 | 'Processing string failed', 42 | (int)$e->getCode(), 43 | $e 44 | ); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ManifestSerializer.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\AnyVersionConstraint; 14 | use PharIo\Version\Version; 15 | use PharIo\Version\VersionConstraint; 16 | use XMLWriter; 17 | use function count; 18 | use function file_put_contents; 19 | use function str_repeat; 20 | 21 | /** @psalm-suppress MissingConstructor */ 22 | class ManifestSerializer { 23 | /** @var XMLWriter */ 24 | private $xmlWriter; 25 | 26 | public function serializeToFile(Manifest $manifest, string $filename): void { 27 | file_put_contents( 28 | $filename, 29 | $this->serializeToString($manifest) 30 | ); 31 | } 32 | 33 | public function serializeToString(Manifest $manifest): string { 34 | $this->startDocument(); 35 | 36 | $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType()); 37 | $this->addCopyright($manifest->getCopyrightInformation()); 38 | $this->addRequirements($manifest->getRequirements()); 39 | $this->addBundles($manifest->getBundledComponents()); 40 | 41 | return $this->finishDocument(); 42 | } 43 | 44 | private function startDocument(): void { 45 | $xmlWriter = new XMLWriter(); 46 | $xmlWriter->openMemory(); 47 | $xmlWriter->setIndent(true); 48 | $xmlWriter->setIndentString(str_repeat(' ', 4)); 49 | $xmlWriter->startDocument('1.0', 'UTF-8'); 50 | $xmlWriter->startElement('phar'); 51 | $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0'); 52 | 53 | $this->xmlWriter = $xmlWriter; 54 | } 55 | 56 | private function finishDocument(): string { 57 | $this->xmlWriter->endElement(); 58 | $this->xmlWriter->endDocument(); 59 | 60 | return $this->xmlWriter->outputMemory(); 61 | } 62 | 63 | private function addContains(ApplicationName $name, Version $version, Type $type): void { 64 | $this->xmlWriter->startElement('contains'); 65 | $this->xmlWriter->writeAttribute('name', $name->asString()); 66 | $this->xmlWriter->writeAttribute('version', $version->getVersionString()); 67 | 68 | switch (true) { 69 | case $type->isApplication(): { 70 | $this->xmlWriter->writeAttribute('type', 'application'); 71 | 72 | break; 73 | } 74 | 75 | case $type->isLibrary(): { 76 | $this->xmlWriter->writeAttribute('type', 'library'); 77 | 78 | break; 79 | } 80 | 81 | case $type->isExtension(): { 82 | $this->xmlWriter->writeAttribute('type', 'extension'); 83 | /* @var $type Extension */ 84 | $this->addExtension( 85 | $type->getApplicationName(), 86 | $type->getVersionConstraint() 87 | ); 88 | 89 | break; 90 | } 91 | 92 | default: { 93 | $this->xmlWriter->writeAttribute('type', 'custom'); 94 | } 95 | } 96 | 97 | $this->xmlWriter->endElement(); 98 | } 99 | 100 | private function addCopyright(CopyrightInformation $copyrightInformation): void { 101 | $this->xmlWriter->startElement('copyright'); 102 | 103 | foreach ($copyrightInformation->getAuthors() as $author) { 104 | $this->xmlWriter->startElement('author'); 105 | $this->xmlWriter->writeAttribute('name', $author->getName()); 106 | $this->xmlWriter->writeAttribute('email', $author->getEmail()->asString()); 107 | $this->xmlWriter->endElement(); 108 | } 109 | 110 | $license = $copyrightInformation->getLicense(); 111 | 112 | $this->xmlWriter->startElement('license'); 113 | $this->xmlWriter->writeAttribute('type', $license->getName()); 114 | $this->xmlWriter->writeAttribute('url', $license->getUrl()->asString()); 115 | $this->xmlWriter->endElement(); 116 | 117 | $this->xmlWriter->endElement(); 118 | } 119 | 120 | private function addRequirements(RequirementCollection $requirementCollection): void { 121 | $phpRequirement = new AnyVersionConstraint(); 122 | $extensions = []; 123 | 124 | foreach ($requirementCollection as $requirement) { 125 | if ($requirement instanceof PhpVersionRequirement) { 126 | $phpRequirement = $requirement->getVersionConstraint(); 127 | 128 | continue; 129 | } 130 | 131 | if ($requirement instanceof PhpExtensionRequirement) { 132 | $extensions[] = $requirement->asString(); 133 | } 134 | } 135 | 136 | $this->xmlWriter->startElement('requires'); 137 | $this->xmlWriter->startElement('php'); 138 | $this->xmlWriter->writeAttribute('version', $phpRequirement->asString()); 139 | 140 | foreach ($extensions as $extension) { 141 | $this->xmlWriter->startElement('ext'); 142 | $this->xmlWriter->writeAttribute('name', $extension); 143 | $this->xmlWriter->endElement(); 144 | } 145 | 146 | $this->xmlWriter->endElement(); 147 | $this->xmlWriter->endElement(); 148 | } 149 | 150 | private function addBundles(BundledComponentCollection $bundledComponentCollection): void { 151 | if (count($bundledComponentCollection) === 0) { 152 | return; 153 | } 154 | $this->xmlWriter->startElement('bundles'); 155 | 156 | foreach ($bundledComponentCollection as $bundledComponent) { 157 | $this->xmlWriter->startElement('component'); 158 | $this->xmlWriter->writeAttribute('name', $bundledComponent->getName()); 159 | $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString()); 160 | $this->xmlWriter->endElement(); 161 | } 162 | 163 | $this->xmlWriter->endElement(); 164 | } 165 | 166 | private function addExtension(ApplicationName $applicationName, VersionConstraint $versionConstraint): void { 167 | $this->xmlWriter->startElement('extension'); 168 | $this->xmlWriter->writeAttribute('for', $applicationName->asString()); 169 | $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString()); 170 | $this->xmlWriter->endElement(); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/exceptions/ElementCollectionException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use InvalidArgumentException; 14 | 15 | class ElementCollectionException extends InvalidArgumentException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/Exception.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Throwable; 14 | 15 | interface Exception extends Throwable { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/InvalidApplicationNameException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use InvalidArgumentException; 14 | 15 | class InvalidApplicationNameException extends InvalidArgumentException implements Exception { 16 | public const InvalidFormat = 2; 17 | } 18 | -------------------------------------------------------------------------------- /src/exceptions/InvalidEmailException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use InvalidArgumentException; 14 | 15 | class InvalidEmailException extends InvalidArgumentException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/InvalidUrlException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use InvalidArgumentException; 14 | 15 | class InvalidUrlException extends InvalidArgumentException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/ManifestDocumentException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use RuntimeException; 14 | 15 | class ManifestDocumentException extends RuntimeException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/ManifestDocumentLoadingException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use LibXMLError; 14 | use function sprintf; 15 | 16 | class ManifestDocumentLoadingException extends \Exception implements Exception { 17 | /** @var LibXMLError[] */ 18 | private $libxmlErrors; 19 | 20 | /** 21 | * ManifestDocumentLoadingException constructor. 22 | * 23 | * @param LibXMLError[] $libxmlErrors 24 | */ 25 | public function __construct(array $libxmlErrors) { 26 | $this->libxmlErrors = $libxmlErrors; 27 | $first = $this->libxmlErrors[0]; 28 | 29 | parent::__construct( 30 | sprintf( 31 | '%s (Line: %d / Column: %d / File: %s)', 32 | $first->message, 33 | $first->line, 34 | $first->column, 35 | $first->file 36 | ), 37 | $first->code 38 | ); 39 | } 40 | 41 | /** 42 | * @return LibXMLError[] 43 | */ 44 | public function getLibxmlErrors(): array { 45 | return $this->libxmlErrors; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/exceptions/ManifestDocumentMapperException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use RuntimeException; 14 | 15 | class ManifestDocumentMapperException extends RuntimeException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/ManifestElementException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use RuntimeException; 14 | 15 | class ManifestElementException extends RuntimeException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/exceptions/ManifestLoaderException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ManifestLoaderException extends \Exception implements Exception { 14 | } 15 | -------------------------------------------------------------------------------- /src/exceptions/NoEmailAddressException.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use InvalidArgumentException; 14 | 15 | class NoEmailAddressException extends InvalidArgumentException implements Exception { 16 | } 17 | -------------------------------------------------------------------------------- /src/values/Application.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class Application extends Type { 14 | public function isApplication(): bool { 15 | return true; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/values/ApplicationName.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use function preg_match; 14 | use function sprintf; 15 | 16 | class ApplicationName { 17 | /** @var string */ 18 | private $name; 19 | 20 | public function __construct(string $name) { 21 | $this->ensureValidFormat($name); 22 | $this->name = $name; 23 | } 24 | 25 | public function asString(): string { 26 | return $this->name; 27 | } 28 | 29 | public function isEqual(ApplicationName $name): bool { 30 | return $this->name === $name->name; 31 | } 32 | 33 | private function ensureValidFormat(string $name): void { 34 | if (!preg_match('#\w/\w#', $name)) { 35 | throw new InvalidApplicationNameException( 36 | sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name), 37 | InvalidApplicationNameException::InvalidFormat 38 | ); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/values/Author.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use function sprintf; 14 | 15 | class Author { 16 | /** @var string */ 17 | private $name; 18 | 19 | /** @var null|Email */ 20 | private $email; 21 | 22 | public function __construct(string $name, ?Email $email = null) { 23 | $this->name = $name; 24 | $this->email = $email; 25 | } 26 | 27 | public function asString(): string { 28 | if (!$this->hasEmail()) { 29 | return $this->name; 30 | } 31 | 32 | return sprintf( 33 | '%s <%s>', 34 | $this->name, 35 | $this->email->asString() 36 | ); 37 | } 38 | 39 | public function getName(): string { 40 | return $this->name; 41 | } 42 | 43 | /** 44 | * @psalm-assert-if-true Email $this->email 45 | */ 46 | public function hasEmail(): bool { 47 | return $this->email !== null; 48 | } 49 | 50 | public function getEmail(): Email { 51 | if (!$this->hasEmail()) { 52 | throw new NoEmailAddressException(); 53 | } 54 | 55 | return $this->email; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/values/AuthorCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Countable; 14 | use IteratorAggregate; 15 | use function count; 16 | 17 | /** @template-implements IteratorAggregate */ 18 | class AuthorCollection implements Countable, IteratorAggregate { 19 | /** @var Author[] */ 20 | private $authors = []; 21 | 22 | public function add(Author $author): void { 23 | $this->authors[] = $author; 24 | } 25 | 26 | /** 27 | * @return Author[] 28 | */ 29 | public function getAuthors(): array { 30 | return $this->authors; 31 | } 32 | 33 | public function count(): int { 34 | return count($this->authors); 35 | } 36 | 37 | public function getIterator(): AuthorCollectionIterator { 38 | return new AuthorCollectionIterator($this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/values/AuthorCollectionIterator.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Iterator; 14 | use function count; 15 | 16 | /** @template-implements Iterator */ 17 | class AuthorCollectionIterator implements Iterator { 18 | /** @var Author[] */ 19 | private $authors; 20 | 21 | /** @var int */ 22 | private $position = 0; 23 | 24 | public function __construct(AuthorCollection $authors) { 25 | $this->authors = $authors->getAuthors(); 26 | } 27 | 28 | public function rewind(): void { 29 | $this->position = 0; 30 | } 31 | 32 | public function valid(): bool { 33 | return $this->position < count($this->authors); 34 | } 35 | 36 | public function key(): int { 37 | return $this->position; 38 | } 39 | 40 | public function current(): Author { 41 | return $this->authors[$this->position]; 42 | } 43 | 44 | public function next(): void { 45 | $this->position++; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/values/BundledComponent.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\Version; 14 | 15 | class BundledComponent { 16 | /** @var string */ 17 | private $name; 18 | 19 | /** @var Version */ 20 | private $version; 21 | 22 | public function __construct(string $name, Version $version) { 23 | $this->name = $name; 24 | $this->version = $version; 25 | } 26 | 27 | public function getName(): string { 28 | return $this->name; 29 | } 30 | 31 | public function getVersion(): Version { 32 | return $this->version; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/values/BundledComponentCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Countable; 14 | use IteratorAggregate; 15 | use function count; 16 | 17 | /** @template-implements IteratorAggregate */ 18 | class BundledComponentCollection implements Countable, IteratorAggregate { 19 | /** @var BundledComponent[] */ 20 | private $bundledComponents = []; 21 | 22 | public function add(BundledComponent $bundledComponent): void { 23 | $this->bundledComponents[] = $bundledComponent; 24 | } 25 | 26 | /** 27 | * @return BundledComponent[] 28 | */ 29 | public function getBundledComponents(): array { 30 | return $this->bundledComponents; 31 | } 32 | 33 | public function count(): int { 34 | return count($this->bundledComponents); 35 | } 36 | 37 | public function getIterator(): BundledComponentCollectionIterator { 38 | return new BundledComponentCollectionIterator($this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/values/BundledComponentCollectionIterator.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Iterator; 14 | use function count; 15 | 16 | /** @template-implements Iterator */ 17 | class BundledComponentCollectionIterator implements Iterator { 18 | /** @var BundledComponent[] */ 19 | private $bundledComponents; 20 | 21 | /** @var int */ 22 | private $position = 0; 23 | 24 | public function __construct(BundledComponentCollection $bundledComponents) { 25 | $this->bundledComponents = $bundledComponents->getBundledComponents(); 26 | } 27 | 28 | public function rewind(): void { 29 | $this->position = 0; 30 | } 31 | 32 | public function valid(): bool { 33 | return $this->position < count($this->bundledComponents); 34 | } 35 | 36 | public function key(): int { 37 | return $this->position; 38 | } 39 | 40 | public function current(): BundledComponent { 41 | return $this->bundledComponents[$this->position]; 42 | } 43 | 44 | public function next(): void { 45 | $this->position++; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/values/CopyrightInformation.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class CopyrightInformation { 14 | /** @var AuthorCollection */ 15 | private $authors; 16 | 17 | /** @var License */ 18 | private $license; 19 | 20 | public function __construct(AuthorCollection $authors, License $license) { 21 | $this->authors = $authors; 22 | $this->license = $license; 23 | } 24 | 25 | public function getAuthors(): AuthorCollection { 26 | return $this->authors; 27 | } 28 | 29 | public function getLicense(): License { 30 | return $this->license; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/values/Email.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use const FILTER_VALIDATE_EMAIL; 14 | use function filter_var; 15 | 16 | class Email { 17 | /** @var string */ 18 | private $email; 19 | 20 | public function __construct(string $email) { 21 | $this->ensureEmailIsValid($email); 22 | 23 | $this->email = $email; 24 | } 25 | 26 | public function asString(): string { 27 | return $this->email; 28 | } 29 | 30 | private function ensureEmailIsValid(string $url): void { 31 | if (filter_var($url, FILTER_VALIDATE_EMAIL) === false) { 32 | throw new InvalidEmailException; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/values/Extension.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\Version; 14 | use PharIo\Version\VersionConstraint; 15 | 16 | class Extension extends Type { 17 | /** @var ApplicationName */ 18 | private $application; 19 | 20 | /** @var VersionConstraint */ 21 | private $versionConstraint; 22 | 23 | public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) { 24 | $this->application = $application; 25 | $this->versionConstraint = $versionConstraint; 26 | } 27 | 28 | public function getApplicationName(): ApplicationName { 29 | return $this->application; 30 | } 31 | 32 | public function getVersionConstraint(): VersionConstraint { 33 | return $this->versionConstraint; 34 | } 35 | 36 | public function isExtension(): bool { 37 | return true; 38 | } 39 | 40 | public function isExtensionFor(ApplicationName $name): bool { 41 | return $this->application->isEqual($name); 42 | } 43 | 44 | public function isCompatibleWith(ApplicationName $name, Version $version): bool { 45 | return $this->isExtensionFor($name) && $this->versionConstraint->complies($version); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/values/Library.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class Library extends Type { 14 | public function isLibrary(): bool { 15 | return true; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/values/License.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class License { 14 | /** @var string */ 15 | private $name; 16 | 17 | /** @var Url */ 18 | private $url; 19 | 20 | public function __construct(string $name, Url $url) { 21 | $this->name = $name; 22 | $this->url = $url; 23 | } 24 | 25 | public function getName(): string { 26 | return $this->name; 27 | } 28 | 29 | public function getUrl(): Url { 30 | return $this->url; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/values/Manifest.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\Version; 14 | 15 | class Manifest { 16 | /** @var ApplicationName */ 17 | private $name; 18 | 19 | /** @var Version */ 20 | private $version; 21 | 22 | /** @var Type */ 23 | private $type; 24 | 25 | /** @var CopyrightInformation */ 26 | private $copyrightInformation; 27 | 28 | /** @var RequirementCollection */ 29 | private $requirements; 30 | 31 | /** @var BundledComponentCollection */ 32 | private $bundledComponents; 33 | 34 | public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) { 35 | $this->name = $name; 36 | $this->version = $version; 37 | $this->type = $type; 38 | $this->copyrightInformation = $copyrightInformation; 39 | $this->requirements = $requirements; 40 | $this->bundledComponents = $bundledComponents; 41 | } 42 | 43 | public function getName(): ApplicationName { 44 | return $this->name; 45 | } 46 | 47 | public function getVersion(): Version { 48 | return $this->version; 49 | } 50 | 51 | public function getType(): Type { 52 | return $this->type; 53 | } 54 | 55 | public function getCopyrightInformation(): CopyrightInformation { 56 | return $this->copyrightInformation; 57 | } 58 | 59 | public function getRequirements(): RequirementCollection { 60 | return $this->requirements; 61 | } 62 | 63 | public function getBundledComponents(): BundledComponentCollection { 64 | return $this->bundledComponents; 65 | } 66 | 67 | public function isApplication(): bool { 68 | return $this->type->isApplication(); 69 | } 70 | 71 | public function isLibrary(): bool { 72 | return $this->type->isLibrary(); 73 | } 74 | 75 | public function isExtension(): bool { 76 | return $this->type->isExtension(); 77 | } 78 | 79 | public function isExtensionFor(ApplicationName $application, ?Version $version = null): bool { 80 | if (!$this->isExtension()) { 81 | return false; 82 | } 83 | 84 | /** @var Extension $type */ 85 | $type = $this->type; 86 | 87 | if ($version !== null) { 88 | return $type->isCompatibleWith($application, $version); 89 | } 90 | 91 | return $type->isExtensionFor($application); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/values/PhpExtensionRequirement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class PhpExtensionRequirement implements Requirement { 14 | /** @var string */ 15 | private $extension; 16 | 17 | public function __construct(string $extension) { 18 | $this->extension = $extension; 19 | } 20 | 21 | public function asString(): string { 22 | return $this->extension; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/values/PhpVersionRequirement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\VersionConstraint; 14 | 15 | class PhpVersionRequirement implements Requirement { 16 | /** @var VersionConstraint */ 17 | private $versionConstraint; 18 | 19 | public function __construct(VersionConstraint $versionConstraint) { 20 | $this->versionConstraint = $versionConstraint; 21 | } 22 | 23 | public function getVersionConstraint(): VersionConstraint { 24 | return $this->versionConstraint; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/values/Requirement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | interface Requirement { 14 | } 15 | -------------------------------------------------------------------------------- /src/values/RequirementCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Countable; 14 | use IteratorAggregate; 15 | use function count; 16 | 17 | /** @template-implements IteratorAggregate */ 18 | class RequirementCollection implements Countable, IteratorAggregate { 19 | /** @var Requirement[] */ 20 | private $requirements = []; 21 | 22 | public function add(Requirement $requirement): void { 23 | $this->requirements[] = $requirement; 24 | } 25 | 26 | /** 27 | * @return Requirement[] 28 | */ 29 | public function getRequirements(): array { 30 | return $this->requirements; 31 | } 32 | 33 | public function count(): int { 34 | return count($this->requirements); 35 | } 36 | 37 | public function getIterator(): RequirementCollectionIterator { 38 | return new RequirementCollectionIterator($this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/values/RequirementCollectionIterator.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use Iterator; 14 | use function count; 15 | 16 | /** @template-implements Iterator */ 17 | class RequirementCollectionIterator implements Iterator { 18 | /** @var Requirement[] */ 19 | private $requirements; 20 | 21 | /** @var int */ 22 | private $position = 0; 23 | 24 | public function __construct(RequirementCollection $requirements) { 25 | $this->requirements = $requirements->getRequirements(); 26 | } 27 | 28 | public function rewind(): void { 29 | $this->position = 0; 30 | } 31 | 32 | public function valid(): bool { 33 | return $this->position < count($this->requirements); 34 | } 35 | 36 | public function key(): int { 37 | return $this->position; 38 | } 39 | 40 | public function current(): Requirement { 41 | return $this->requirements[$this->position]; 42 | } 43 | 44 | public function next(): void { 45 | $this->position++; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/values/Type.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use PharIo\Version\VersionConstraint; 14 | 15 | abstract class Type { 16 | public static function application(): Application { 17 | return new Application; 18 | } 19 | 20 | public static function library(): Library { 21 | return new Library; 22 | } 23 | 24 | public static function extension(ApplicationName $application, VersionConstraint $versionConstraint): Extension { 25 | return new Extension($application, $versionConstraint); 26 | } 27 | 28 | /** @psalm-assert-if-true Application $this */ 29 | public function isApplication(): bool { 30 | return false; 31 | } 32 | 33 | /** @psalm-assert-if-true Library $this */ 34 | public function isLibrary(): bool { 35 | return false; 36 | } 37 | 38 | /** @psalm-assert-if-true Extension $this */ 39 | public function isExtension(): bool { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/values/Url.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use const FILTER_VALIDATE_URL; 14 | use function filter_var; 15 | 16 | class Url { 17 | /** @var string */ 18 | private $url; 19 | 20 | public function __construct(string $url) { 21 | $this->ensureUrlIsValid($url); 22 | 23 | $this->url = $url; 24 | } 25 | 26 | public function asString(): string { 27 | return $this->url; 28 | } 29 | 30 | /** 31 | * @throws InvalidUrlException 32 | */ 33 | private function ensureUrlIsValid(string $url): void { 34 | if (filter_var($url, FILTER_VALIDATE_URL) === false) { 35 | throw new InvalidUrlException; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/xml/AuthorElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class AuthorElement extends ManifestElement { 14 | public function getName(): string { 15 | return $this->getAttributeValue('name'); 16 | } 17 | 18 | public function getEmail(): string { 19 | return $this->getAttributeValue('email'); 20 | } 21 | 22 | public function hasEMail(): bool { 23 | return $this->hasAttribute('email'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/xml/AuthorElementCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class AuthorElementCollection extends ElementCollection { 14 | public function current(): AuthorElement { 15 | return new AuthorElement( 16 | $this->getCurrentElement() 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/xml/BundlesElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class BundlesElement extends ManifestElement { 14 | public function getComponentElements(): ComponentElementCollection { 15 | return new ComponentElementCollection( 16 | $this->getChildrenByName('component') 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/xml/ComponentElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ComponentElement extends ManifestElement { 14 | public function getName(): string { 15 | return $this->getAttributeValue('name'); 16 | } 17 | 18 | public function getVersion(): string { 19 | return $this->getAttributeValue('version'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/xml/ComponentElementCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ComponentElementCollection extends ElementCollection { 14 | public function current(): ComponentElement { 15 | return new ComponentElement( 16 | $this->getCurrentElement() 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/xml/ContainsElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ContainsElement extends ManifestElement { 14 | public function getName(): string { 15 | return $this->getAttributeValue('name'); 16 | } 17 | 18 | public function getVersion(): string { 19 | return $this->getAttributeValue('version'); 20 | } 21 | 22 | public function getType(): string { 23 | return $this->getAttributeValue('type'); 24 | } 25 | 26 | public function getExtensionElement(): ExtensionElement { 27 | return new ExtensionElement( 28 | $this->getChildByName('extension') 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/xml/CopyrightElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class CopyrightElement extends ManifestElement { 14 | public function getAuthorElements(): AuthorElementCollection { 15 | return new AuthorElementCollection( 16 | $this->getChildrenByName('author') 17 | ); 18 | } 19 | 20 | public function getLicenseElement(): LicenseElement { 21 | return new LicenseElement( 22 | $this->getChildByName('license') 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/xml/ElementCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use DOMElement; 14 | use DOMNodeList; 15 | use Iterator; 16 | use ReturnTypeWillChange; 17 | use function count; 18 | use function get_class; 19 | use function sprintf; 20 | 21 | /** @template-implements Iterator */ 22 | abstract class ElementCollection implements Iterator { 23 | /** @var DOMElement[] */ 24 | private $nodes = []; 25 | 26 | /** @var int */ 27 | private $position; 28 | 29 | public function __construct(DOMNodeList $nodeList) { 30 | $this->position = 0; 31 | $this->importNodes($nodeList); 32 | } 33 | 34 | #[ReturnTypeWillChange] 35 | abstract public function current(); 36 | 37 | public function next(): void { 38 | $this->position++; 39 | } 40 | 41 | public function key(): int { 42 | return $this->position; 43 | } 44 | 45 | public function valid(): bool { 46 | return $this->position < count($this->nodes); 47 | } 48 | 49 | public function rewind(): void { 50 | $this->position = 0; 51 | } 52 | 53 | protected function getCurrentElement(): DOMElement { 54 | return $this->nodes[$this->position]; 55 | } 56 | 57 | private function importNodes(DOMNodeList $nodeList): void { 58 | foreach ($nodeList as $node) { 59 | if (!$node instanceof DOMElement) { 60 | throw new ElementCollectionException( 61 | sprintf('\DOMElement expected, got \%s', get_class($node)) 62 | ); 63 | } 64 | 65 | $this->nodes[] = $node; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/xml/ExtElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ExtElement extends ManifestElement { 14 | public function getName(): string { 15 | return $this->getAttributeValue('name'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/xml/ExtElementCollection.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ExtElementCollection extends ElementCollection { 14 | public function current(): ExtElement { 15 | return new ExtElement( 16 | $this->getCurrentElement() 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/xml/ExtensionElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class ExtensionElement extends ManifestElement { 14 | public function getFor(): string { 15 | return $this->getAttributeValue('for'); 16 | } 17 | 18 | public function getCompatible(): string { 19 | return $this->getAttributeValue('compatible'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/xml/LicenseElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class LicenseElement extends ManifestElement { 14 | public function getType(): string { 15 | return $this->getAttributeValue('type'); 16 | } 17 | 18 | public function getUrl(): string { 19 | return $this->getAttributeValue('url'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/xml/ManifestDocument.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use DOMDocument; 14 | use DOMElement; 15 | use Throwable; 16 | use function count; 17 | use function file_get_contents; 18 | use function is_file; 19 | use function libxml_clear_errors; 20 | use function libxml_get_errors; 21 | use function libxml_use_internal_errors; 22 | use function sprintf; 23 | 24 | class ManifestDocument { 25 | public const XMLNS = 'https://phar.io/xml/manifest/1.0'; 26 | 27 | /** @var DOMDocument */ 28 | private $dom; 29 | 30 | public static function fromFile(string $filename): ManifestDocument { 31 | if (!is_file($filename)) { 32 | throw new ManifestDocumentException( 33 | sprintf('File "%s" not found', $filename) 34 | ); 35 | } 36 | 37 | return self::fromString( 38 | file_get_contents($filename) 39 | ); 40 | } 41 | 42 | public static function fromString(string $xmlString): ManifestDocument { 43 | $prev = libxml_use_internal_errors(true); 44 | libxml_clear_errors(); 45 | 46 | try { 47 | $dom = new DOMDocument(); 48 | $dom->loadXML($xmlString); 49 | $errors = libxml_get_errors(); 50 | libxml_use_internal_errors($prev); 51 | } catch (Throwable $t) { 52 | throw new ManifestDocumentException($t->getMessage(), 0, $t); 53 | } 54 | 55 | if (count($errors) !== 0) { 56 | throw new ManifestDocumentLoadingException($errors); 57 | } 58 | 59 | return new self($dom); 60 | } 61 | 62 | private function __construct(DOMDocument $dom) { 63 | $this->ensureCorrectDocumentType($dom); 64 | 65 | $this->dom = $dom; 66 | } 67 | 68 | public function getContainsElement(): ContainsElement { 69 | return new ContainsElement( 70 | $this->fetchElementByName('contains') 71 | ); 72 | } 73 | 74 | public function getCopyrightElement(): CopyrightElement { 75 | return new CopyrightElement( 76 | $this->fetchElementByName('copyright') 77 | ); 78 | } 79 | 80 | public function getRequiresElement(): RequiresElement { 81 | return new RequiresElement( 82 | $this->fetchElementByName('requires') 83 | ); 84 | } 85 | 86 | public function hasBundlesElement(): bool { 87 | return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1; 88 | } 89 | 90 | public function getBundlesElement(): BundlesElement { 91 | return new BundlesElement( 92 | $this->fetchElementByName('bundles') 93 | ); 94 | } 95 | 96 | private function ensureCorrectDocumentType(DOMDocument $dom): void { 97 | $root = $dom->documentElement; 98 | 99 | if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) { 100 | throw new ManifestDocumentException('Not a phar.io manifest document'); 101 | } 102 | } 103 | 104 | private function fetchElementByName(string $elementName): DOMElement { 105 | $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); 106 | 107 | if (!$element instanceof DOMElement) { 108 | throw new ManifestDocumentException( 109 | sprintf('Element %s missing', $elementName) 110 | ); 111 | } 112 | 113 | return $element; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/xml/ManifestElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | use DOMElement; 14 | use DOMNodeList; 15 | use function sprintf; 16 | 17 | class ManifestElement { 18 | public const XMLNS = 'https://phar.io/xml/manifest/1.0'; 19 | 20 | /** @var DOMElement */ 21 | private $element; 22 | 23 | public function __construct(DOMElement $element) { 24 | $this->element = $element; 25 | } 26 | 27 | protected function getAttributeValue(string $name): string { 28 | if (!$this->element->hasAttribute($name)) { 29 | throw new ManifestElementException( 30 | sprintf( 31 | 'Attribute %s not set on element %s', 32 | $name, 33 | $this->element->localName 34 | ) 35 | ); 36 | } 37 | 38 | return $this->element->getAttribute($name); 39 | } 40 | 41 | protected function hasAttribute(string $name): bool { 42 | return $this->element->hasAttribute($name); 43 | } 44 | 45 | protected function getChildByName(string $elementName): DOMElement { 46 | $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); 47 | 48 | if (!$element instanceof DOMElement) { 49 | throw new ManifestElementException( 50 | sprintf('Element %s missing', $elementName) 51 | ); 52 | } 53 | 54 | return $element; 55 | } 56 | 57 | protected function getChildrenByName(string $elementName): DOMNodeList { 58 | $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName); 59 | 60 | if ($elementList->length === 0) { 61 | throw new ManifestElementException( 62 | sprintf('Element(s) %s missing', $elementName) 63 | ); 64 | } 65 | 66 | return $elementList; 67 | } 68 | 69 | protected function hasChild(string $elementName): bool { 70 | return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/xml/PhpElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class PhpElement extends ManifestElement { 14 | public function getVersion(): string { 15 | return $this->getAttributeValue('version'); 16 | } 17 | 18 | public function hasExtElements(): bool { 19 | return $this->hasChild('ext'); 20 | } 21 | 22 | public function getExtElements(): ExtElementCollection { 23 | return new ExtElementCollection( 24 | $this->getChildrenByName('ext') 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/xml/RequiresElement.php: -------------------------------------------------------------------------------- 1 | , Sebastian Heuer , Sebastian Bergmann and contributors 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | */ 11 | namespace PharIo\Manifest; 12 | 13 | class RequiresElement extends ManifestElement { 14 | public function getPHPElement(): PhpElement { 15 | return new PhpElement( 16 | $this->getChildByName('php') 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.php: -------------------------------------------------------------------------------- 1 | isTokenKindFound(T_DOC_COMMENT); 34 | } 35 | 36 | public function isRisky(): bool { 37 | return false; 38 | } 39 | 40 | public function fix(\SplFileInfo $file, Tokens $tokens): void { 41 | foreach($tokens as $index => $token) { 42 | if (!$token->isGivenKind(T_DOC_COMMENT)) { 43 | continue; 44 | } 45 | if (\stripos($token->getContent(), '@var') === false) { 46 | continue; 47 | } 48 | 49 | if (preg_match('#^/\*\*[\s\*]+(@var[^\r\n]+)[\s\*]*\*\/$#u', $token->getContent(), $matches) !== 1) { 50 | continue; 51 | } 52 | $newContent = '/** ' . \rtrim($matches[1]) . ' */'; 53 | if ($newContent === $token->getContent()) { 54 | continue; 55 | } 56 | $tokens[$index] = new Token([T_DOC_COMMENT, $newContent]); 57 | } 58 | } 59 | 60 | public function getPriority(): int { 61 | return 0; 62 | } 63 | 64 | public function getName(): string { 65 | return 'PharIo/phpdoc_single_line_var_fixer'; 66 | } 67 | 68 | public function supports(\SplFileInfo $file): bool { 69 | return true; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /tools/php-cs-fixer.d/header.txt: -------------------------------------------------------------------------------- 1 | This file is part of PharIo\Manifest. 2 | 3 | Copyright (c) Arne Blankerts , Sebastian Heuer , Sebastian Bergmann and contributors 4 | 5 | For the full copyright and license information, please view the LICENSE 6 | file that was distributed with this source code. 7 | --------------------------------------------------------------------------------