├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.xml ├── build └── phar │ └── autoload.php.in ├── composer.json ├── composer.lock ├── composer └── bin │ └── phpab ├── phive.xml ├── phpab.bat ├── phpab.php ├── phpcs.xml ├── phpunit.xml.dist ├── samples └── sample.php ├── src ├── Application.php ├── AutoloadRenderer.php ├── CLI.php ├── Cache.php ├── CacheEntry.php ├── CacheWarmingListRenderer.php ├── CachingParser.php ├── Collector.php ├── CollectorResult.php ├── ComposerIterator.php ├── Config.php ├── DependencySorter.php ├── Factory.php ├── Logger.php ├── ParseResult.php ├── Parser.php ├── ParserInterface.php ├── PathComparator.php ├── PharBuilder.php ├── SourceFile.php ├── StaticListRenderer.php ├── StaticRenderer.php ├── StaticRequireListRenderer.php ├── Version.php ├── autoload.php └── templates │ ├── ci │ ├── default.php.tpl │ ├── phar.php.tpl │ └── php52.php.tpl │ ├── cs │ ├── default.php.tpl │ ├── phar.php.tpl │ └── php52.php.tpl │ ├── static.php.tpl │ └── staticphar.php.tpl └── tests ├── AutoloadRendererTest.php ├── ComposerIteratorTest.php ├── DuplicateDetectionTest.php ├── FactoryTest.php ├── ParserTest.php ├── PathComparatorTest.php ├── _data ├── bug65 │ ├── class.php │ └── trait.php ├── composer-array-issue-98 │ └── composer.json ├── dependency │ ├── file1.php │ ├── file2.php │ ├── ns01.php │ ├── ns02.php │ ├── ns11.php │ └── ns12.php ├── duplicates │ ├── a.php │ ├── b.php │ └── c.php ├── parser │ ├── anonymousclass.php │ ├── anonymousclass2.php │ ├── backed-enum.php │ ├── basic-enum.php │ ├── brackettest1.php │ ├── brackettest2.php │ ├── class.php │ ├── classname.php │ ├── extends.php │ ├── groupuse.php │ ├── groupuse2.php │ ├── implements1.php │ ├── implements2.php │ ├── implements3.php │ ├── implementsextends.php │ ├── inline-class.php │ ├── inline-interface.php │ ├── inline-trait.php │ ├── interface.php │ ├── interfaceextends1.php │ ├── interfaceextends2.php │ ├── invalid1.php │ ├── invalid2.php │ ├── invalid3.php │ ├── multiclass.php │ ├── namespace1.php │ ├── namespace2.php │ ├── namespace3.php │ ├── namespace4.php │ ├── namespace5.php │ ├── namespace6.php │ ├── namespace7.php │ ├── namespace8.php │ ├── namespaceconstant.php │ ├── nested.php │ ├── noclass.php │ ├── parseerror1.php │ ├── parseerror2.php │ ├── parseerror3.php │ ├── parseerror4.php │ ├── parseerror5.php │ ├── redeclaration.php │ ├── relative.php │ ├── token-constant.php │ ├── trait0.php │ ├── trait1.php │ ├── trait2.php │ ├── trait3.php │ ├── trait4.php │ ├── use1.php │ ├── use10.php │ ├── use2.php │ ├── use3.php │ ├── use4.php │ ├── use5.php │ ├── use6.php │ ├── use7.php │ ├── use8.php │ └── use9.php ├── recursion │ ├── composer.json │ └── vendor │ │ ├── bar │ │ └── foo │ │ │ ├── composer.json │ │ │ └── src │ │ │ └── foo.php │ │ └── foo │ │ └── bar │ │ ├── composer.json │ │ └── src │ │ └── bar.php └── templates │ ├── default.php.tpl │ └── simple.php ├── bug65Test.php ├── classdependencysorterTest.php └── init.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [theseer] 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | # Run on all pushes and on all pull requests. 5 | push: 6 | pull_request: 7 | # Allow manually triggering the workflow. 8 | workflow_dispatch: 9 | 10 | jobs: 11 | test: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | # Keys: 16 | # - experimental: Whether the build is "allowed to fail". 17 | matrix: 18 | php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] 19 | experimental: [false] 20 | 21 | include: 22 | # Nightly. 23 | - php: '8.3' 24 | experimental: true 25 | 26 | name: "PHP: ${{ matrix.php }}" 27 | 28 | continue-on-error: ${{ matrix.experimental }} 29 | 30 | steps: 31 | - name: Checkout code 32 | uses: actions/checkout@v2 33 | 34 | - name: Install PHP 35 | uses: shivammathur/setup-php@v2 36 | with: 37 | php-version: ${{ matrix.php }} 38 | ini-values: error_reporting=-1, display_errors=On, log_errors_max_len=0 39 | coverage: none 40 | tools: phive 41 | 42 | - name: Install java 43 | uses: actions/setup-java@v2 44 | with: 45 | java-version: 11 46 | distribution: 'zulu' 47 | 48 | # Install dependencies and handle caching in one go. 49 | # @link https://github.com/marketplace/actions/install-composer-dependencies 50 | - name: Install Composer dependencies 51 | uses: "ramsey/composer-install@v2" 52 | 53 | - name: Lint the code 54 | run: ant lint 55 | 56 | - name: Install tools 57 | run: ant install-tools 58 | 59 | - name: Run unit tests 60 | run: ./tools/phpunit --configuration phpunit.xml.dist 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | phpunit.xml 3 | .project 4 | .buildpath 5 | .settings 6 | .gitignore 7 | .idea 8 | vendor 9 | composer 10 | /tools 11 | cache.properties 12 | .phpunit.result.cache 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | # Release 1.29.3 4 | * Update Zeta Components for PHP 8.4 compatibilty 5 | 6 | # Release 1.29.2 7 | * Fix Issue [#115](https://github.com/theseer/Autoload/pull/115): Parser does not handle (class) constants named NAMESPACE 8 | 9 | # Release 1.29.1 10 | * Fix crash on generating error message for invalid token 11 | 12 | ## Release 1.29.0 13 | * Merge PR [#105](https://github.com/theseer/Autoload/pull/105): Return exit code from CLI::run(), rather than exiting [martin-rueegg] 14 | 15 | ## Release 1.28.0 16 | * Add support for composer's `vendor-dir` setting when building autoloader based on composer.json and custom vendor directory location 17 | 18 | ## Release 1.27.2 19 | * Fix/Avoid deprecation notices in PHP 8.2 20 | 21 | ## Release 1.27.1 22 | * Fix/Avoid deprecation notices in PHP 8.1 23 | 24 | ## Release 1.27.0 25 | * Update ConsoleTools to 1.7.3. for better PHP 8.1 compatibilty 26 | * Add support for ENUM types (basic and backed) 27 | 28 | ## Release 1.26.3 29 | * Update DirectoryScanner to 1.3.3 for PHP 8.1 compatibilty 30 | 31 | ## Release 1.26.2 32 | * Fix Issue [#99](https://github.com/theseer/Autoload/pull/99): Fix PHP 8.0 deprecation warnings [jrfnl] 33 | 34 | ## Release 1.26.1 35 | * Fix Issue [#98](https://github.com/theseer/Autoload/issues/98): Array to string conversion on parsing composer.json 36 | 37 | ## Release 1.26.0 38 | * Fix Issue [#95](https://github.com/theseer/Autoload/pull/95): Update Parser to work with PHP 8.0's new tokens 39 | * Fix Issue [#90](https://github.com/theseer/Autoload/pull/90): Warnings and Notices in ComposerIterator 40 | * Merge PR [#97](https://github.com/theseer/Autoload/pull/97): Fix for xdebug v3 41 | * Raise build requirement to PHP 7.2+ and PHPUnit 8.5; No change for runtime Version, so 5.3 is _still_ supported 42 | 43 | 44 | ## Release 1.25.9 45 | * Merge PR [#89](https://github.com/theseer/Autoload/pull/89): Throw an exception if the template file cannot be read 46 | * Update ConsoleTools, Fixes [#91](https://github.com/theseer/Autoload/issues/91) - Zeta Components ConsoleTools uses PHP syntax deprecated in PHP 7.4 47 | 48 | ## Release 1.25.8 49 | * Fix Regression [#92](https://github.com/theseer/Autoload/issues/92): PHPAB 1.25.7 generates broken PHAR for PHPUnit 50 | 51 | ## Release 1.25.7 52 | * Fix: Static require or compile lists now properly process pathes relative to and above the base directory 53 | 54 | ## Release 1.25.6 55 | * Fix: Add `lib-` prefixed dependencies in composer.json to ignore list 56 | 57 | ## Release 1.25.5 58 | * Merge PR [#86](https://github.com/theseer/Autoload/pull/86): Restore PHP 5.3 compatibility [Remi] 59 | 60 | ## Release 1.25.4 61 | * Ensure include/exclude filter gets applied also in composer.json mode when files are explicitly set 62 | * Ensure files do not get processed multiple times in case composer.json has duplicate definitions in autoload section 63 | 64 | ## Release 1.25.3 65 | * Fix [#83](https://github.com/theseer/Autoload/issues/83): Error with recursive Composer dependencies 66 | 67 | ## Release 1.25.2 68 | * Fix Parser to ignore "inline" use of keywords `class`, `interface` and `trait` 69 | 70 | ## Release 1.25.1 71 | * Merge PR [#81](https://github.com/theseer/Autoload/pull/81): Fix PHP 7.3 warnings [Remi] 72 | 73 | ## Release 1.25.0 74 | * Add support for generating static files to use for opcache warming (-w, optionally with --reset) 75 | * Minor internal cleanup 76 | 77 | ## Release 1.24.1 78 | * Merge PR [#78](https://github.com/theseer/Autoload/pull/78): Restore PHP 5.3 compatibility [Remi] 79 | 80 | ## Release 1.24.0 81 | * [#77](https://github.com/theseer/Autoload/issues/77): Change duplicate detection to collect all rather than exit on first 82 | 83 | ## Release 1.23.0 84 | * Add support for parsing code containing anonymous classes (PHP 7) 85 | * Some internal code cleanup 86 | 87 | ## Release 1.22.0 88 | * Merge PR [#73](https://github.com/theseer/Autoload/pull/73): no cs/ci dir for static tpl [Remi] 89 | * Merge PR [#74](https://github.com/theseer/Autoload/pull/74): auto add suffix to (short) template name [Remi] 90 | 91 | ## Release 1.21.0 92 | * Added --hash option to explicitly choose hash algorithm for phar generation (defaults to best available) 93 | 94 | ## Release 1.20.3 95 | * Merge PR [#68](https://github.com/theseer/Autoload/pull/68): return parent dir when 2 dirs have a common prefix 96 | * Merge PR [#67](https://github.com/theseer/Autoload/pull/67): don't use 'vendor' in test suite 97 | * Some internal code cleanup 98 | 99 | ## Release 1.20.2 100 | * Merge PR [#66](https://github.com/theseer/Autoload/pull/66): fix PathComparator when 0 in path [Remi] 101 | 102 | ## Release 1.20.1 103 | * Fix issue #65: Trait sorted after using class when --static is used 104 | * Fix issue #63: Workdirectory included as subdirectory in phar archive (Regression as of 1.19.0) 105 | 106 | ## Release 1.20.0 107 | * PHP 7: Added parsing support for new (grouped use syntax)[https://wiki.php.net/rfc/group_use_declarations] 108 | 109 | ## Release 1.19.2 110 | * Remove debugging artefact 111 | 112 | ## Release 1.19.1 113 | * Fix regression since 1.15.0: paranoid and trusting mode handling was switched 114 | 115 | ## Release 1.19.0 116 | * Fix filenames via CLI to actually work [Remi] 117 | * Changed default basedir to be based on the output file rather than the directory to be scanned [Remi] 118 | 119 | ## Release 1.18.0 120 | * Allow filenames as source instead of only allowing directories (this also fixes composer classmap issues) 121 | 122 | ## Release 1.17.0 123 | * Added support for parameter 'prepend' of spl_autoload_register to allow for prepending without changing templates 124 | * Added support for parameter 'exception' of spl_autoload_register to optionally disable exceptions on errors 125 | 126 | ## Release 1.16.1 127 | * Fix minor issues with composer.json handling 128 | * define date.timezone to avoid warning (in buildystem) [Remi] 129 | * Pear installation now deploys as phar 130 | 131 | ## Release 1.16.0 132 | 133 | * Added whitelist/blacklist filter for classnames/namespaces 134 | * Ensure ext/fileinfo is loaded 135 | 136 | ## Release 1.15.1 137 | 138 | * Fix regression for sorted static require lists 139 | 140 | ## Release 1.15.0 141 | 142 | * Added support for composer.json parsing 143 | * Added (optional) caching 144 | * Added explicit wildcard support for directory name matching 145 | * Changed error messages on unit redeclarations 146 | * Some code cleanup and refactoring of internals 147 | 148 | ## Release 1.14.2 149 | 150 | * Fix Trait handling in PHP 5.3 151 | * Changed file type for phpunit.xml.dist in pear package 152 | 153 | ## Release 1.14.1 154 | 155 | * Providing --alias in phar mode now sets ___PHAR___ accordingly 156 | * Updated DirectoryScanner to 1.3.0 157 | 158 | ## Release 1.14.0 159 | 160 | * Added support for PHP 5.5's classname::class constant to parser 161 | 162 | ## Release 1.13.1 163 | 164 | * Fix Regression, make composer installs work again 165 | 166 | ## Release 1.13.0 167 | 168 | * Added alias support to phar mode building 169 | 170 | ## Release 1.12.0 171 | 172 | * Added composer support (Thanks to HCO) 173 | * Made parser code more robust to not crash on invalid names 174 | 175 | ## Release 1.11.0 176 | 177 | * Added support for symlinks (Thanks to Jan Peterson) 178 | 179 | ## Release 1.10.3 180 | 181 | * Support empty indent 182 | * Fixed Trait parsing 183 | 184 | ## Release 1.10.2 185 | 186 | * Fixed mode flag handling on phar mode 187 | 188 | ## Release 1.10.1 189 | 190 | * Various regression fixes after internal cleanup 191 | * Use git version info for development checkouts 192 | 193 | ## Release 1.10.0 194 | 195 | * Added multi directory support 196 | * Added compression support to phar mode 197 | * Added support for openssl key signing of phars 198 | 199 | ##### Older Releases 200 | 201 | Please refer to the git history log for details 202 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Autoload Builder 2 | 3 | Copyright (c) 2010-2016 Arne Blankerts 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 ORCONTRIBUTORS 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 | # PHP Autoload Builder 2 | 3 | The PHP AutoloadBuilder CLI tool **phpab** is a command line application to automate the process of generating 4 | an autoload require file with the option of creating static require lists as well as phar archives. 5 | 6 | ## Features 7 | 8 | * scan multiple directories recursively in one run, optionally follow symlinks, wildcards or based on composer.json 9 | * Cache scan results 10 | * Template based autoload code 11 | * Custom variables for templates 12 | * Compatibility mode for PHP 5.2 compliant autoloader 13 | * Case sensitive as well as case insensitive classname mapping 14 | * Phar generation, with or without compression and openssl key signing 15 | * Static require list generation 16 | * Opcache warming list generation 17 | * Linting of generated code 18 | 19 | ## Requirements 20 | 21 | * PHP 5.3+ (Runtime, for development / tests: 7.2+) 22 | * Fileinfo (ext/fileinfo) 23 | * Tokenizer (ext/tokenizer) 24 | * For PHAR generation support: 25 | + ext/phar (write enabled: phar.readonly = Off) 26 | + ext/gzip (optional) 27 | + ext/bzip2 (optional) 28 | + ext/openssl (optional, for phar signing only) 29 | 30 | ## Installation 31 | 32 | ### Executable PHAR 33 | 34 | The recommended way to install **phpab** is by using [phive](https://phar.io): 35 | 36 | ``` 37 | phive install phpab 38 | ``` 39 | 40 | #### Manual install 41 | 42 | If you do not have phive installed or want to install manually, you can download the PHAR archive 43 | from the [Releases](https://github.com/theseer/Autoload/releases) tab. 44 | 45 | _Please note:_ 46 | On Linux/Unix based system the phar needs to be marked executable for direct execution: 47 | ``` 48 | [theseer@rikka ~]$ chmod +x phpab*.phar 49 | ``` 50 | 51 | ## Other Downloads 52 | 53 | * [Latest development snapshot](https://github.com/theseer/Autoload/archive/master.zip) (ZIP Archive) 54 | * [Releases (Source)](https://github.com/theseer/Autoload/tags) 55 | 56 | ## Usage 57 | ``` 58 | Usage: phpab [switches] [...] 59 | 60 | -i, --include File pattern to include (default: *.php) 61 | -e, --exclude File pattern to exclude 62 | 63 | --blacklist Blacklist classname or namespace (wildcards supported) 64 | --whitelist Whitelist classname or namespace (wildcards supported) 65 | 66 | -b, --basedir Basedir for filepaths 67 | -t, --template Path to code template to use 68 | 69 | -o, --output Output file for generated code (default: STDOUT) 70 | 71 | -p, --phar Create a phar archive (requires -o ) 72 | --all Include all files in given directory when creating a phar 73 | --alias Specify explicit internal phar alias filename (default: output filename) 74 | --hash Force given hash algorithm (SHA-1, SHA-256 or SHA-512) (requires -p, conflicts with --key) 75 | --bzip2 Compress phar archive using bzip2 (requires -p) (bzip2 required) 76 | --gzip Compress phar archive using gzip (requires -p) (gzip required) 77 | --key OpenSSL key file to use for signing phar archive (requires -p) (openssl required) 78 | 79 | -c, --compat Generate PHP 5.2 compatible code 80 | -s, --static Generate a static require file 81 | 82 | -w, --warm Generate a static opcache warming file 83 | --reset Add opcache reset call when generating opcache warming file 84 | 85 | -1, --prepend Register as first autoloader (prepend to stack, default: append) 86 | -d, --no-exception Do not throw exception on registration problem (default: throw exception) 87 | 88 | -n, --nolower Do not lowercase classnames for case insensitivity 89 | 90 | -q, --quiet Quiet mode, do not output any processing errors or information 91 | 92 | --cache Enable caching and set filename to use for cache storage 93 | 94 | --follow Enables following symbolic links (not compatible with phar mode) 95 | --format Dateformat string for timestamp 96 | --linebreak Linebreak style (CR, CRLF or LF, default: LF) 97 | --indent String used for indenting or number of spaces (default: 16 (compat 12) spaces) 98 | 99 | --tolerant Ignore Class Redeclarations in the same file 100 | --once Use require_once instead of require when creating a static require file 101 | 102 | --trusting Do not check mimetype of files prior to parsing (default) 103 | --paranoid Do check mimetype of files prior to parsing 104 | 105 | --var name=foo Assign value 'foo' to variable 'name' to be used in (custom) templates 106 | 107 | --lint Run lint on generated code and exit 108 | --lint-php PHP binary to use for linting (default: /usr/bin/php or c:\php\php.exe) 109 | 110 | -h, --help Prints this usage information 111 | -v, --version Prints the version and exits 112 | ``` 113 | 114 | ### Usage Examples 115 | 116 | [theseer@rikka ~]$ phpab -o src/autoload.php -b src composer.json 117 | 118 | [theseer@rikka ~]$ phpab -o opcache_warming.php -w --reset src 119 | 120 | [theseer@rikka ~]$ phpab -o src/autoload.inc.php src 121 | 122 | [theseer@rikka ~]$ phpab -c -o src/autoload.inc.php src 123 | 124 | [theseer@rikka ~]$ phpab -o src/core/autoload.inc.php -b src src 125 | 126 | [theseer@rikka ~]$ phpab -p -o framework.phar -b src composer.json 127 | 128 | [theseer@rikka ~]$ phpab -p -o framework.phar framework/src 129 | 130 | [theseer@rikka ~]$ phpab -p -o framework.phar --bzip2 --key sign.key framework/src 131 | 132 | [theseer@rikka ~]$ phpab -b . --tolerant -o zf1_autoload.php -e '*/Test/*' Zend 133 | 134 | 135 | ### Automation 136 | 137 | When using *phpab* it is necessary to recreate the autoload file every time a new class is created. 138 | This usually also happens after pulling from a repo or when switchting branches. 139 | Using a git `post-checkout` hook placed in `.git/hooks/post-update` this can be automated for most cases. 140 | 141 | #### Basic Sample: 142 | 143 | ```bash 144 | #!/bin/bash 145 | phpab -c -o src/autoload.inc.php src 146 | ``` 147 | 148 | #### Sample using an `ant build.xml` file. 149 | 150 | ```bash 151 | #!/bin/bash 152 | if [ -f build.xml ]; then 153 | ant -p | grep phpab > /dev/null 154 | 155 | if [ $? -eq 0 ]; then 156 | ant phpab > /dev/null & 157 | fi 158 | fi 159 | ``` 160 | 161 | ## Template Variables 162 | 163 | The generated code is based uppon templates provided by default in the templates subfolder. The template engine 164 | allows for simply replacing of name based placeholders. For now, only a few default variables are defined 165 | but API hooks / CLI parameters exist to set custom variables. 166 | 167 | Known variables are: 168 | * ```___CREATED___``` Set to a timestamp of creation, format can be adjusted 169 | * ```___CLASSLIST___``` The found list classes in form of a generated map 170 | * ```___BASEDIR___``` If a Basedir is set, the value will get removed from the file path and get replaced by __DIR__ 171 | 172 | Used in PHAR Mode only: 173 | * ```___PHAR___``` The filename of the generated phar or it's alias when --alias is given (see src/templates/phar.php.tpl) 174 | 175 | Custom variables as defined by passing --var name=value via cli are accessed by pre- and appending ___ to it: 176 | * ```___name___``` Going to be replaced by the value provided via cli param 177 | 178 | ## Changelog 179 | 180 | The [changelog](https://github.com/theseer/Autoload/blob/master/CHANGELOG.md) moved to its own document 181 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /build/phar/autoload.php.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getCLI()->run($_SERVER); 26 | exit(0); 27 | 28 | __HALT_COMPILER(); 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theseer/autoload", 3 | "description": "A tool and library to generate autoload code.", 4 | "require": { 5 | "php": ">=5.3", 6 | "ext-openssl": "*", 7 | "theseer/directoryscanner": "^1.3.3", 8 | "zetacomponents/console-tools": "^1.7" 9 | }, 10 | "require-dev": { 11 | "php": ">=7.2" 12 | }, 13 | "autoload": { 14 | "classmap": [ 15 | "src/" 16 | ] 17 | }, 18 | "license": "BSD-3-Clause", 19 | "authors": [ 20 | { 21 | "name": "Arne Blankerts", 22 | "email": "arne@blankerts.de" 23 | } 24 | ], 25 | "bin": [ 26 | "composer/bin/phpab" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /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": "aa1466787353808e328b7be65f96f706", 8 | "packages": [ 9 | { 10 | "name": "theseer/directoryscanner", 11 | "version": "1.3.3", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/theseer/DirectoryScanner.git", 15 | "reference": "4cdce31c1b5120779a01225b5b0968f9321342d6" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/theseer/DirectoryScanner/zipball/4cdce31c1b5120779a01225b5b0968f9321342d6", 20 | "reference": "4cdce31c1b5120779a01225b5b0968f9321342d6", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.1" 25 | }, 26 | "type": "library", 27 | "extra": { 28 | "branch-alias": { 29 | "dev-master": "1.0.x-dev" 30 | } 31 | }, 32 | "autoload": { 33 | "classmap": [ 34 | "src/" 35 | ] 36 | }, 37 | "notification-url": "https://packagist.org/downloads/", 38 | "license": [ 39 | "BSD-2-Clause" 40 | ], 41 | "authors": [ 42 | { 43 | "name": "Arne Blankerts", 44 | "email": "arne@blankerts.de", 45 | "role": "Developer" 46 | } 47 | ], 48 | "description": "A recursive directory scanner and filter", 49 | "support": { 50 | "issues": "https://github.com/theseer/DirectoryScanner/issues", 51 | "source": "https://github.com/theseer/DirectoryScanner/tree/1.3.3" 52 | }, 53 | "time": "2021-07-24T18:41:34+00:00" 54 | }, 55 | { 56 | "name": "zetacomponents/base", 57 | "version": "1.9.4", 58 | "source": { 59 | "type": "git", 60 | "url": "https://github.com/zetacomponents/Base.git", 61 | "reference": "b6ae5f6177f6e51c5fc3514800e1c3fb076ec4be" 62 | }, 63 | "dist": { 64 | "type": "zip", 65 | "url": "https://api.github.com/repos/zetacomponents/Base/zipball/b6ae5f6177f6e51c5fc3514800e1c3fb076ec4be", 66 | "reference": "b6ae5f6177f6e51c5fc3514800e1c3fb076ec4be", 67 | "shasum": "" 68 | }, 69 | "require-dev": { 70 | "phpunit/php-invoker": "^2.0|^3.1", 71 | "phpunit/phpunit": "~9.0", 72 | "zetacomponents/coding-standard": "dev-main", 73 | "zetacomponents/unit-test": "~1.2.3" 74 | }, 75 | "type": "library", 76 | "autoload": { 77 | "classmap": [ 78 | "src" 79 | ] 80 | }, 81 | "notification-url": "https://packagist.org/downloads/", 82 | "license": [ 83 | "Apache-2.0" 84 | ], 85 | "authors": [ 86 | { 87 | "name": "Sergey Alexeev" 88 | }, 89 | { 90 | "name": "Sebastian Bergmann" 91 | }, 92 | { 93 | "name": "Jan Borsodi" 94 | }, 95 | { 96 | "name": "Raymond Bosman" 97 | }, 98 | { 99 | "name": "Frederik Holljen" 100 | }, 101 | { 102 | "name": "Kore Nordmann" 103 | }, 104 | { 105 | "name": "Derick Rethans" 106 | }, 107 | { 108 | "name": "Vadym Savchuk" 109 | }, 110 | { 111 | "name": "Tobias Schlitt" 112 | }, 113 | { 114 | "name": "Alexandru Stanoi" 115 | } 116 | ], 117 | "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.", 118 | "homepage": "https://github.com/zetacomponents", 119 | "support": { 120 | "issues": "https://github.com/zetacomponents/Base/issues", 121 | "source": "https://github.com/zetacomponents/Base/tree/1.9.4" 122 | }, 123 | "time": "2022-11-30T16:16:25+00:00" 124 | }, 125 | { 126 | "name": "zetacomponents/console-tools", 127 | "version": "1.7.5", 128 | "source": { 129 | "type": "git", 130 | "url": "https://github.com/zetacomponents/ConsoleTools.git", 131 | "reference": "de081f422b574d638e62e15661bf833d80fac61a" 132 | }, 133 | "dist": { 134 | "type": "zip", 135 | "url": "https://api.github.com/repos/zetacomponents/ConsoleTools/zipball/de081f422b574d638e62e15661bf833d80fac61a", 136 | "reference": "de081f422b574d638e62e15661bf833d80fac61a", 137 | "shasum": "" 138 | }, 139 | "require": { 140 | "zetacomponents/base": "~1.8" 141 | }, 142 | "require-dev": { 143 | "phpunit/phpunit": "~9.0", 144 | "zetacomponents/unit-test": "*" 145 | }, 146 | "type": "library", 147 | "autoload": { 148 | "classmap": [ 149 | "src" 150 | ] 151 | }, 152 | "notification-url": "https://packagist.org/downloads/", 153 | "license": [ 154 | "Apache-2.0" 155 | ], 156 | "authors": [ 157 | { 158 | "name": "Sergey Alexeev" 159 | }, 160 | { 161 | "name": "Sebastian Bergmann" 162 | }, 163 | { 164 | "name": "Jan Borsodi" 165 | }, 166 | { 167 | "name": "Raymond Bosman" 168 | }, 169 | { 170 | "name": "Frederik Holljen" 171 | }, 172 | { 173 | "name": "Kore Nordmann" 174 | }, 175 | { 176 | "name": "Derick Rethans" 177 | }, 178 | { 179 | "name": "Vadym Savchuk" 180 | }, 181 | { 182 | "name": "Tobias Schlitt" 183 | }, 184 | { 185 | "name": "Alexandru Stanoi" 186 | } 187 | ], 188 | "description": "A set of classes to do different actions with the console (also called shell). It can render a progress bar, tables and a status bar and contains a class for parsing command line options.", 189 | "homepage": "https://github.com/zetacomponents", 190 | "support": { 191 | "issues": "https://github.com/zetacomponents/ConsoleTools/issues", 192 | "source": "https://github.com/zetacomponents/ConsoleTools/tree/1.7.5" 193 | }, 194 | "time": "2024-10-04T15:51:48+00:00" 195 | } 196 | ], 197 | "packages-dev": [], 198 | "aliases": [], 199 | "minimum-stability": "stable", 200 | "stability-flags": [], 201 | "prefer-stable": false, 202 | "prefer-lowest": false, 203 | "platform": { 204 | "php": ">=5.3", 205 | "ext-openssl": "*" 206 | }, 207 | "platform-dev": { 208 | "php": ">=7.2" 209 | }, 210 | "plugin-api-version": "2.6.0" 211 | } 212 | -------------------------------------------------------------------------------- /composer/bin/phpab: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modification, 8 | * are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of Arne Blankerts nor the names of contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, 23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 26 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @package Autoload 34 | * @author Arne Blankerts 35 | * @copyright Arne Blankerts , All rights reserved. 36 | * @license BSD License 37 | * 38 | * Exit codes: 39 | * 0 - No error 40 | * 1 - Execution Error 41 | * 3 - Parameter Error 42 | * 4 - Lint Error 43 | */ 44 | 45 | define('PHPAB_VERSION', '%development%'); 46 | 47 | $files = array( 48 | __DIR__ . '/../../vendor/autoload.php', 49 | __DIR__ . '/../../../../autoload.php' 50 | ); 51 | 52 | foreach ($files as $file) { 53 | if (file_exists($file)) { 54 | require $file; 55 | break; 56 | } 57 | } 58 | 59 | require __DIR__ . '/../../src/autoload.php'; 60 | 61 | $factory = new \TheSeer\Autoload\Factory(); 62 | $rc = $factory->getCLI()->run($_SERVER); 63 | exit($rc); 64 | -------------------------------------------------------------------------------- /phive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /phpab.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM phpab 3 | REM 4 | REM Copyright (c) 2009-2023, Arne Blankerts and contributors 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modification, 8 | * are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of Arne Blankerts nor the names of contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, 23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 26 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @package Autoload 34 | * @author Arne Blankerts 35 | * @copyright Arne Blankerts , All rights reserved. 36 | * @license BSD License 37 | * 38 | * Exit codes: 39 | * 0 - No error 40 | * 1 - Execution Error 41 | * 3 - Parameter Error 42 | * 4 - Lint Error 43 | * 5 - Duplicates found Error 44 | */ 45 | 46 | define('PHPAB_VERSION', '%development%'); 47 | 48 | if (!ini_get('date.timezone')) { 49 | ini_set('date.timezone', 'UTC'); 50 | } 51 | require __DIR__ . '/src/autoload.php'; 52 | 53 | $factory = new \TheSeer\Autoload\Factory(); 54 | $rc = $factory->getCLI()->run($_SERVER); 55 | exit($rc); 56 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Arne Blankerts' coding standard 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 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | tests 8 | 9 | 10 | 11 | 12 | 13 | src 14 | 15 | src/templates 16 | src/cli.php 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/sample.php: -------------------------------------------------------------------------------- 1 | parse(new \TheSeer\Autoload\SourceFile(__DIR__ . '/../src/Parser.php')); 8 | var_dump($result->getUnits(), $result->getDependenciesForUnit(strtolower(\TheSeer\Autoload\ParserException::class))); 9 | -------------------------------------------------------------------------------- /src/Application.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | * 37 | */ 38 | namespace TheSeer\Autoload { 39 | 40 | class Application { 41 | 42 | private $logger; 43 | private $factory; 44 | private $config; 45 | 46 | public function __construct(Logger $logger, Config $config, Factory $factory) { 47 | $this->logger = $logger; 48 | $this->config = $config; 49 | $this->factory = $factory; 50 | } 51 | 52 | public function run() { 53 | $result = $this->runCollector(); 54 | if (!$result->hasUnits()) { 55 | throw new ApplicationException('No units were found - process aborted.', ApplicationException::NoUnitsFound); 56 | } 57 | if ($result->hasDuplicates()) { 58 | return $this->showDuplicatesError($result->getDuplicates()); 59 | } 60 | 61 | if ($this->config->isCacheEnabled()) { 62 | $this->factory->getCache()->persist($this->config->getCacheFile()); 63 | } 64 | 65 | $template = @file_get_contents($this->config->getTemplate()); 66 | if ($template === false) { 67 | throw new ApplicationException("Failed to read the template file."); 68 | } 69 | 70 | $builder = $this->factory->getRenderer($result); 71 | $code = $builder->render($template); 72 | if ($this->config->isLintMode()) { 73 | return $this->runLint($code); 74 | } 75 | return $this->runSaver($code); 76 | } 77 | 78 | /** 79 | * @return CollectorResult 80 | */ 81 | private function runCollector() { 82 | if ($this->config->isFollowSymlinks()) { 83 | $this->logger->log('Following symbolic links is enabled.' . "\n\n"); 84 | } 85 | $collector = $this->factory->getCollector(); 86 | foreach ($this->config->getDirectories() as $directory) { 87 | if (is_dir($directory)) { 88 | $this->logger->log('Scanning directory ' . $directory . "\n"); 89 | $scanner = $this->factory->getScanner()->getIterator($directory); 90 | $collector->processDirectory($scanner); 91 | // this unset is needed to "fix" a segfault on shutdown in some PHP Versions 92 | unset($scanner); 93 | } else { 94 | $file = new \SplFileInfo($directory); 95 | $filter = $this->factory->getFilter(new \ArrayIterator(array($file))); 96 | foreach($filter as $file) { 97 | $this->logger->log('Scanning file ' . $file . "\n"); 98 | $collector->processFile($file); 99 | } 100 | } 101 | } 102 | return $collector->getResult(); 103 | } 104 | 105 | private function runSaver($code) { 106 | $output = $this->config->getOutputFile(); 107 | if (!$this->config->isPharMode()) { 108 | if ($output === 'STDOUT') { 109 | $this->logger->log("\n"); 110 | echo $code; 111 | $this->logger->log("\n\n"); 112 | return CLI::RC_OK; 113 | } 114 | // @codingStandardsIgnoreStart 115 | $written = @file_put_contents($output, $code); 116 | // @codingStandardsIgnoreEnd 117 | if ($written != strlen($code)) { 118 | $this->logger->log("Writing to file '$output' failed.", STDERR); 119 | return CLI::RC_EXEC_ERROR; 120 | } 121 | $this->logger->log("\nAutoload file {$output} generated.\n\n"); 122 | return CLI::RC_OK; 123 | } 124 | if (strpos($code, '__HALT_COMPILER();') === FALSE) { 125 | $this->logger->log( 126 | "Warning: Template used in phar mode did not contain required __HALT_COMPILER() call\n" . 127 | "which has been added automatically. The used stub code may not work as intended.\n\n", STDERR); 128 | $code .= $this->config->getLinebreak() . '__HALT_COMPILER();'; 129 | } 130 | $pharBuilder = $this->factory->getPharBuilder(); 131 | if ($keyfile = $this->config->getPharKey()) { 132 | $pharBuilder->setSignatureKey($this->loadPharSignatureKey($keyfile)); 133 | } 134 | if ($aliasName = $this->config->getPharAliasName()) { 135 | $pharBuilder->setAliasName($aliasName); 136 | } 137 | if ($this->config->hasPharHashAlgorithm()) { 138 | $pharBuilder->setSignatureType($this->config->getPharHashAlgorithm()); 139 | } 140 | $pharBuilder->build($output, $code); 141 | $this->logger->log("\nphar archive '{$output}' generated.\n\n"); 142 | return CLI::RC_OK; 143 | } 144 | 145 | private function loadPharSignatureKey($keyfile) { 146 | if (!extension_loaded('openssl')) { 147 | throw new ApplicationException('Extension for OpenSSL not loaded - cannot sign phar archive - process aborted.', 148 | ApplicationException::OpenSSLError); 149 | } 150 | $keydata = file_get_contents($keyfile); 151 | if (strpos($keydata, 'ENCRYPTED') !== FALSE) { 152 | $this->logger->log("Passphrase for key '$keyfile': "); 153 | $g = shell_exec('stty -g'); 154 | shell_exec('stty -echo'); 155 | $passphrase = trim(fgets(STDIN)); 156 | $this->logger->log("\n"); 157 | shell_exec('stty ' . $g); 158 | $private = openssl_pkey_get_private($keydata, $passphrase); 159 | } else { 160 | $private = openssl_pkey_get_private($keydata); 161 | } 162 | if (!$private) { 163 | throw new ApplicationException("Opening private key '$keyfile' failed - process aborted.\n\n", ApplicationException::OpenSSLError); 164 | } 165 | return $private; 166 | } 167 | 168 | 169 | /** 170 | * Execute a lint check on generated code 171 | * 172 | * @param string $code Generated code to lint 173 | * 174 | * @return boolean 175 | */ 176 | protected function runLint($code) { 177 | $dsp = array( 178 | 0 => array('pipe', 'r'), 179 | 1 => array('pipe', 'w'), 180 | 2 => array('pipe', 'w') 181 | ); 182 | 183 | $binary = $this->config->getPhp(); 184 | 185 | $process = proc_open($binary . ' -l', $dsp, $pipes); 186 | 187 | if (!is_resource($process)) { 188 | $this->logger->log("Opening php binary for linting failed.\n", STDERR); 189 | return 1; 190 | } 191 | 192 | fwrite($pipes[0], $code); 193 | fclose($pipes[0]); 194 | fclose($pipes[1]); 195 | 196 | $stderr = stream_get_contents($pipes[2]); 197 | fclose($pipes[2]); 198 | 199 | $rc = proc_close($process); 200 | 201 | if ($rc == 255) { 202 | $this->logger->log("Syntax errors during lint:\n" . 203 | str_replace('in - on line', 'in generated code on line', $stderr) . 204 | "\n", STDERR); 205 | return CLI::RC_LINT_ERROR; 206 | } 207 | 208 | $this->logger->log("Lint check of geneated code okay\n\n"); 209 | return CLI::RC_OK; 210 | } 211 | 212 | /** 213 | * @param array $duplicates 214 | * 215 | * @return int 216 | */ 217 | private function showDuplicatesError(array $duplicates) { 218 | $this->logger->log( 219 | sprintf("\nMultiple declarations of trait(s), interface(s) or class(es). Could not generate autoload map.\n"), 220 | STDERR 221 | ); 222 | foreach($duplicates as $unit => $files) { 223 | $this->logger->log( 224 | sprintf("\nUnit '%s' defined in:\n", $unit), 225 | STDERR 226 | ); 227 | 228 | /** @var array $files */ 229 | foreach($files as $file) { 230 | $this->logger->log( 231 | sprintf(" - %s\n", $file), 232 | STDERR 233 | ); 234 | 235 | } 236 | } 237 | return CLI::RC_DUPLICATES_ERROR; 238 | } 239 | 240 | } 241 | 242 | class ApplicationException extends \Exception { 243 | const NoUnitsFound = 1; 244 | const OpenSSLError = 2; 245 | } 246 | 247 | } 248 | -------------------------------------------------------------------------------- /src/AutoloadRenderer.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload { 39 | 40 | /** 41 | * Builds spl based autoload code for inclusion into projects 42 | * 43 | * @author Arne Blankerts 44 | * @copyright Arne Blankerts , All rights reserved. 45 | */ 46 | class AutoloadRenderer { 47 | 48 | /** 49 | * Associative array of classes (key) and the files (value) they are in 50 | * 51 | * @var array 52 | */ 53 | protected $classes; 54 | 55 | /** 56 | * An optional base dir to strip for the realpath of the filename 57 | * 58 | * @var string 59 | */ 60 | protected $baseDir = ''; 61 | 62 | /** 63 | * Indenting char(s) 64 | * 65 | * @var string 66 | */ 67 | protected $indent = ' '; 68 | 69 | /** 70 | * Char(s) used as linebreak 71 | * 72 | * @var string 73 | */ 74 | protected $linebreak = "\n"; 75 | 76 | /** 77 | * Timestamp of production start 78 | * 79 | * @var integer 80 | */ 81 | protected $timestamp; 82 | 83 | /** 84 | * Format string supplied to date() for use with ___CREATED___ 85 | * 86 | * @var string 87 | */ 88 | protected $dateformat = 'r'; 89 | 90 | /** 91 | * Variables for templates 92 | * 93 | * @var array 94 | */ 95 | protected $variables = array(); 96 | 97 | /** 98 | * Flag to toggle PHP 5.2 compat mode 99 | * 100 | * @var boolean 101 | */ 102 | protected $compat = false; 103 | 104 | /** 105 | * Flag to pass on to spl_autoload_register to prepend 106 | * 107 | * @var bool 108 | */ 109 | private $usePrepend = false; 110 | 111 | /** 112 | * Flag to pass on to spl_autoload_register to optionally throw exceptions on registration error 113 | * 114 | * @var bool 115 | */ 116 | private $throwExceptions = false; 117 | 118 | /** 119 | * Constructor of AutoloadRenderer class 120 | * 121 | * @param array $classlist Array of classes 122 | * 123 | */ 124 | public function __construct(array $classlist) { 125 | $this->classes = $classlist; 126 | ksort($this->classes); 127 | } 128 | 129 | /** 130 | * Toggle PHP 5.2 compat mode 131 | * 132 | * @param boolean $mode Mode to set compat to 133 | */ 134 | public function setCompat($mode) { 135 | $this->compat = $mode; 136 | } 137 | 138 | public function enableExceptions() { 139 | $this->throwExceptions = true; 140 | } 141 | 142 | public function prependAutoloader() { 143 | $this->usePrepend = true; 144 | } 145 | 146 | /** 147 | * Setter for the Basedir 148 | * 149 | * @param string $dir Path to strip from beginning of filenames 150 | * 151 | * @return void 152 | */ 153 | public function setBaseDir($dir) { 154 | $this->baseDir = $dir; 155 | } 156 | 157 | /** 158 | * Overwrite default or previously set indenting option 159 | * 160 | * @param string $indent Char(s) to use for indenting 161 | * 162 | * @return void 163 | */ 164 | public function setIndent($indent) { 165 | $this->indent = $indent; 166 | } 167 | 168 | /** 169 | * Overwrite default or previously set linebreak chars 170 | * 171 | * @param string $lbs Code to set linebreak 172 | * 173 | * @return void 174 | */ 175 | public function setLineBreak($lbs) { 176 | $this->linebreak = $lbs; 177 | } 178 | 179 | /** 180 | * Accessor for current linebreak setting 181 | * 182 | * @return string 183 | */ 184 | public function getLineBreak() { 185 | return $this->linebreak; 186 | } 187 | 188 | /** 189 | * Setter to use allow usage of fixed date/time for ___CREATED___ 190 | * 191 | * @param integer $time unix timestamp 192 | * 193 | * @throws AutoloadBuilderException 194 | */ 195 | public function setTimestamp($time) { 196 | if (!is_int($time) && null !== $time) { 197 | throw new AutoloadBuilderException("'$time' is not a unix timestamp", AutoloadBuilderException::InvalidTimestamp); 198 | } 199 | $this->timestamp = $time; 200 | } 201 | 202 | /** 203 | * Setter to adjust the date/time format output of ___CREATED___ 204 | * 205 | * @param string $frmt Date/Time format string 206 | */ 207 | public function setDateTimeFormat($frmt) { 208 | $this->dateformat = $frmt; 209 | } 210 | 211 | /** 212 | * Set a variable for use with template code 213 | * 214 | * @param string $name Key name (use as ___key___ in template) 215 | * @param string $value Value to use 216 | */ 217 | public function setVariable($name, $value) { 218 | $this->variables['___'.$name.'___'] = $value; 219 | } 220 | 221 | 222 | /** 223 | * Resolve relative location of file path to basedir if one is set and fix potential 224 | * broken windows pathnames when run on windows. 225 | * 226 | * @param string $fname 227 | * 228 | * @return string 229 | */ 230 | protected function resolvePath($fname) { 231 | if (empty($this->baseDir)) { 232 | return str_replace('\\', '/', $fname); 233 | } 234 | $basedir = explode(DIRECTORY_SEPARATOR, $this->baseDir); 235 | $filedir = explode(DIRECTORY_SEPARATOR, dirname(realpath($fname))); 236 | $pos = 0; 237 | $max = count($basedir); 238 | while (isset($filedir[$pos]) && $filedir[$pos] == $basedir[$pos]) { 239 | $pos++; 240 | if ($pos == $max) { 241 | break; 242 | } 243 | } 244 | if ($pos == 0) { 245 | return str_replace('\\', '/', $fname); 246 | } 247 | $rel = join('/', array_slice($filedir, $pos)); 248 | if (!empty($rel)) { 249 | $rel .= '/'; 250 | } 251 | if ($posclasses as $class => $file) { 267 | $fname = $this->resolvePath($file); 268 | $entries[] = "'". addslashes($class). "' => '$fname'"; 269 | } 270 | 271 | $baseDir = ''; 272 | if ($this->baseDir) { 273 | $baseDir = $this->compat ? 'dirname(__FILE__) . ' : '__DIR__ . '; 274 | } 275 | 276 | $replace = array_merge($this->variables, array( 277 | '___CREATED___' => date( $this->dateformat, $this->timestamp ? $this->timestamp : time()), 278 | '___CLASSLIST___' => join( ',' . $this->linebreak . $this->indent, $entries), 279 | '___BASEDIR___' => $baseDir, 280 | '___AUTOLOAD___' => 'autoload' . md5(serialize($entries)), 281 | '___EXCEPTION___' => $this->throwExceptions ? 'true' : 'false', 282 | '___PREPEND___' => $this->usePrepend ? 'true' : 'false' 283 | )); 284 | return str_replace(array_keys($replace), array_values($replace), $template); 285 | } 286 | 287 | } 288 | 289 | 290 | class AutoloadBuilderException extends \Exception { 291 | 292 | const TemplateNotFound = 1; 293 | const InvalidTimestamp = 2; 294 | 295 | } 296 | 297 | } 298 | -------------------------------------------------------------------------------- /src/Cache.php: -------------------------------------------------------------------------------- 1 | loadedEntries = $initialEntries; 19 | } 20 | 21 | /** 22 | * @param SourceFile $file 23 | * 24 | * @return bool 25 | */ 26 | public function hasResult(SourceFile $file) { 27 | $pathname = $file->getPathname(); 28 | if (!isset($this->loadedEntries[$pathname])) { 29 | return false; 30 | } 31 | return $this->loadedEntries[$pathname]->getTimestamp() === $file->getMTime(); 32 | } 33 | 34 | public function getResult(SourceFile $file) { 35 | if (!$this->hasResult($file)) { 36 | throw new CacheException('Entry not found'); 37 | } 38 | $pathname = $file->getPathname(); 39 | $entry = $this->loadedEntries[$pathname]; 40 | $this->usedEntries[$pathname] = $entry; 41 | return $entry->getResult(); 42 | } 43 | 44 | public function addResult(SourceFile $file, ParseResult $result) { 45 | $this->usedEntries[$file->getPathname()] = new CacheEntry($file->getMTime(), $result); 46 | } 47 | 48 | public function persist($fname) { 49 | if (file_exists($fname)) { 50 | unlink($fname); 51 | } 52 | file_put_contents($fname, serialize($this->usedEntries)); 53 | } 54 | } 55 | 56 | 57 | class CacheException extends \Exception { 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/CacheEntry.php: -------------------------------------------------------------------------------- 1 | timestamp = $timestamp; 18 | $this->result = $result; 19 | } 20 | 21 | /** 22 | * @return ParseResult 23 | */ 24 | public function getResult() { 25 | return $this->result; 26 | } 27 | 28 | /** 29 | * @return int 30 | */ 31 | public function getTimestamp() { 32 | return $this->timestamp; 33 | } 34 | 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/CacheWarmingListRenderer.php: -------------------------------------------------------------------------------- 1 | addReset = $addReset; 24 | $this->indent = $indent; 25 | $this->linebreak = $linebreak; 26 | } 27 | 28 | /** 29 | * @return string 30 | */ 31 | public function render(array $list) { 32 | $line = $this->indent . 'opcache_compile_file(___BASEDIR___\''; 33 | $glue = '\');' . $this->linebreak . $line; 34 | 35 | $firstLine = $this->addReset ? $this->indent . 'opcache_reset();' . $this->linebreak : ''; 36 | return $firstLine . $line . implode($glue, $list) . '\');'; 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/CachingParser.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 18 | $this->parser = $parser; 19 | } 20 | 21 | /** 22 | * Parse a given file for defintions of classes, traits and interfaces 23 | * 24 | * @param SourceFile $source file to process 25 | * 26 | * @return ParseResult 27 | */ 28 | public function parse(SourceFile $source) { 29 | if ($this->cache->hasResult($source)) { 30 | return $this->cache->getResult($source); 31 | } 32 | $result = $this->parser->parse($source); 33 | $this->cache->addResult($source, $result); 34 | return $result; 35 | } 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/Collector.php: -------------------------------------------------------------------------------- 1 | parser = $parser; 39 | $this->tolerantMode = $tolerantMode; 40 | $this->trustingMode = $trustingMode; 41 | $this->collectorResult = new CollectorResult($whitelist, $blacklist); 42 | } 43 | 44 | public function getResult() { 45 | return $this->collectorResult; 46 | } 47 | 48 | public function processDirectory(\Iterator $sources) { 49 | $worker = $this->trustingMode ? $sources : new PHPFilterIterator($sources); 50 | foreach($worker as $file) { 51 | $this->processFile($file); 52 | } 53 | } 54 | 55 | public function processFile(\SplFileInfo $file) { 56 | if ($this->collectorResult->hasResultFor($file)) { 57 | return; 58 | } 59 | try { 60 | $parseResult = $this->parser->parse(new SourceFile($file->getRealPath())); 61 | if ($parseResult->hasRedeclarations() && !$this->tolerantMode) { 62 | throw new CollectorException( 63 | sprintf( 64 | "Duplicate (potentially conditional) definitions of the following unit(s) found:\n\n\tUnit(s): %s\n\tFile: %s", 65 | join(', ', $parseResult->getRedeclarations()), 66 | $file->getRealPath() 67 | ), 68 | CollectorException::InFileRedeclarationFound 69 | ); 70 | } 71 | $this->collectorResult->addParseResult($file, $parseResult); 72 | } catch(ParserException $e) { 73 | throw new CollectorException( 74 | sprintf( 75 | "Could not process file '%s' due to parse errors: %s", 76 | $file->getRealPath(), 77 | $e->getMessage() 78 | ), 79 | CollectorException::ParseErrror, 80 | $e 81 | ); 82 | } catch(CollectorResultException $e) { 83 | throw new CollectorException( 84 | $e->getMessage(), 85 | CollectorException::RedeclarationFound 86 | ); 87 | } 88 | } 89 | } 90 | 91 | class CollectorException extends \Exception { 92 | const ParseErrror = 1; 93 | const RedeclarationFound = 2; 94 | const InFileRedeclarationFound = 3; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/CollectorResult.php: -------------------------------------------------------------------------------- 1 | whitelist = $whitelist; 38 | $this->blacklist = $blacklist; 39 | } 40 | 41 | public function hasResultFor(\SplFileInfo $file) { 42 | return isset($this->seenFiles[$file->getRealPath()]); 43 | } 44 | 45 | public function addParseResult(\SplFileInfo $file, ParseResult $result) { 46 | if (!$result->hasUnits()) { 47 | return; 48 | } 49 | $filename = $file->getRealPath(); 50 | $this->seenFiles[$filename] = true; 51 | 52 | foreach($result->getUnits() as $unit) { 53 | if (!$this->accept($unit)) { 54 | continue; 55 | } 56 | if (isset($this->units[$unit])) { 57 | if (!isset($this->duplicates[$unit])) { 58 | $this->duplicates[$unit] = array( $this->units[$unit] ); 59 | } 60 | $this->duplicates[$unit][] = $filename; 61 | continue; 62 | } 63 | $this->units[$unit] = $filename; 64 | $this->dependencies[$unit] = $result->getDependenciesForUnit($unit); 65 | } 66 | } 67 | 68 | public function hasUnits() { 69 | return count($this->units) > 0; 70 | } 71 | 72 | public function hasDuplicates() { 73 | return count($this->duplicates) > 0; 74 | } 75 | /** 76 | * @return array 77 | */ 78 | public function getDependencies() { 79 | return $this->dependencies; 80 | } 81 | 82 | /** 83 | * @return array 84 | */ 85 | public function getUnits() { 86 | return $this->units; 87 | } 88 | 89 | /** 90 | * @param string $unit 91 | * 92 | * @return bool 93 | */ 94 | private function accept($unit) { 95 | foreach($this->blacklist as $entry) { 96 | if (fnmatch($entry, $unit)) { 97 | return false; 98 | } 99 | } 100 | foreach($this->whitelist as $entry) { 101 | if (fnmatch($entry, $unit)) { 102 | return true; 103 | } 104 | } 105 | return false; 106 | } 107 | 108 | public function getDuplicates() { 109 | return $this->duplicates; 110 | } 111 | 112 | } 113 | 114 | class CollectorResultException extends \Exception { 115 | const DuplicateUnitName = 1; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/ComposerIterator.php: -------------------------------------------------------------------------------- 1 | isFile() || !$composerFile->isReadable()) { 17 | throw new ComposerIteratorException( 18 | sprintf('Composer file "%s" not found or not readable', $composerFile->getPathname()), 19 | ComposerIteratorException::InvalidComposerJsonFile 20 | ); 21 | } 22 | $composerDir = dirname($composerFile->getRealPath()); 23 | $composerData = json_decode(file_get_contents($composerFile->getRealPath()), true); 24 | 25 | $vendorDir = $composerDir . '/vendor'; 26 | if (isset($composerData['config']['vendor-dir'])) { 27 | $vendorDir = preg_replace( 28 | '/($HOME|~)/', 29 | $homeDirectory, 30 | $composerData['config']['vendor-dir'] 31 | ); 32 | } 33 | 34 | if (isset($composerData['require'])) { 35 | foreach($composerData['require'] as $require => $version) { 36 | if ($require === 'php' || strpos($require, 'ext-') === 0) { 37 | continue; 38 | } 39 | $this->processRequire($vendorDir, $require); 40 | } 41 | } 42 | if (isset($composerData['autoload'])) { 43 | $this->processAutoload($composerDir, $composerData['autoload']); 44 | } 45 | } 46 | 47 | private function processAutoload($baseDir, array $map) { 48 | if (isset($map['classmap'])) { 49 | foreach($map['classmap'] as $dir) { 50 | $this->addDirectory($baseDir . '/' . $dir); 51 | } 52 | } 53 | foreach(array('psr-0', 'psr-4') as $psr) { 54 | if (isset($map[$psr])) { 55 | foreach ($map[$psr] as $node => $dir) { 56 | if ($dir === '') { 57 | $this->addDirectory($baseDir); 58 | continue; 59 | } 60 | if (is_array($dir)) { 61 | foreach($dir as $d) { 62 | $this->addDirectory($baseDir . '/' . $d); 63 | } 64 | 65 | continue; 66 | } 67 | $this->addDirectory($baseDir . '/' . $dir); 68 | } 69 | } 70 | } 71 | } 72 | 73 | private function processRequire($basedir, $require) { 74 | if (isset($this->seen[$require])) { 75 | return; 76 | } 77 | $this->seen[$require] = true; 78 | 79 | $requireDir = $basedir . '/' . $require; 80 | 81 | $jsonFile = $this->findComposerJson($requireDir); 82 | if ($jsonFile === null) { 83 | return; 84 | } 85 | $jsonData = json_decode(file_get_contents($jsonFile), true); 86 | 87 | if (isset($jsonData['require'])) { 88 | foreach($jsonData['require'] as $entry => $version) { 89 | if ($entry === 'php' || strpos($entry, 'ext-') === 0 || strpos($entry, 'lib-') === 0) { 90 | continue; 91 | } 92 | $this->processRequire($basedir, $entry); 93 | } 94 | } 95 | 96 | if (isset($jsonData['autoload'])) { 97 | $this->processAutoload($requireDir, $jsonData['autoload']); 98 | return; 99 | } 100 | $this->addDirectory($requireDir); 101 | } 102 | 103 | private function findComposerJson($dir) { 104 | if (file_exists($dir . '/composer.json')) { 105 | return $dir . '/composer.json'; 106 | } 107 | foreach(glob($dir . '/*', GLOB_ONLYDIR) as $subDir) { 108 | $result = $this->findComposerJson($subDir); 109 | if ($result !== NULL) { 110 | return $result; 111 | } 112 | } 113 | } 114 | 115 | private function addDirectory($dir) { 116 | $dir = rtrim($dir, '/'); 117 | if (!in_array($dir, $this->directories)) { 118 | $this->directories[] = $dir; 119 | } 120 | } 121 | 122 | /** 123 | * (PHP 5 >= 5.0.0)
124 | * Return the current element 125 | * 126 | * @link http://php.net/manual/en/iterator.current.php 127 | * @return mixed Can return any type. 128 | */ 129 | #[\ReturnTypeWillChange] 130 | public function current() { 131 | return $this->directories[$this->pos]; 132 | } 133 | 134 | /** 135 | * (PHP 5 >= 5.0.0)
136 | * Move forward to next element 137 | * 138 | * @link http://php.net/manual/en/iterator.next.php 139 | * @return void Any returned value is ignored. 140 | */ 141 | #[\ReturnTypeWillChange] 142 | public function next() { 143 | $this->pos++; 144 | } 145 | 146 | /** 147 | * (PHP 5 >= 5.0.0)
148 | * Return the key of the current element 149 | * 150 | * @link http://php.net/manual/en/iterator.key.php 151 | * @return mixed scalar on success, or null on failure. 152 | */ 153 | #[\ReturnTypeWillChange] 154 | public function key() { 155 | return $this->pos; 156 | } 157 | 158 | /** 159 | * (PHP 5 >= 5.0.0)
160 | * Checks if current position is valid 161 | * 162 | * @link http://php.net/manual/en/iterator.valid.php 163 | * @return boolean The return value will be casted to boolean and then evaluated. 164 | * Returns true on success or false on failure. 165 | */ 166 | #[\ReturnTypeWillChange] 167 | public function valid() { 168 | return $this->pos < count($this->directories); 169 | } 170 | 171 | /** 172 | * (PHP 5 >= 5.0.0)
173 | * Rewind the Iterator to the first element 174 | * 175 | * @link http://php.net/manual/en/iterator.rewind.php 176 | * @return void Any returned value is ignored. 177 | */ 178 | #[\ReturnTypeWillChange] 179 | public function rewind() { 180 | $this->pos = 0; 181 | } 182 | } 183 | 184 | class ComposerIteratorException extends \Exception { 185 | const InvalidComposerJsonFile = 1; 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /src/Config.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | * 37 | */ 38 | namespace TheSeer\Autoload { 39 | 40 | class Config { 41 | 42 | private $quietMode = FALSE; 43 | private $directories = array(); 44 | private $outputFile = 'STDOUT'; 45 | private $pharMode = FALSE; 46 | private $include = array('*.php'); 47 | private $exclude = array(); 48 | private $whitelist = array('*'); 49 | private $blacklist = array(); 50 | private $baseDirectory = NULL; 51 | private $template; 52 | private $linebreak = "\n"; 53 | private $indent; 54 | private $lint = FALSE; 55 | private $php; 56 | private $compatMode = FALSE; 57 | private $staticMode = FALSE; 58 | private $warmMode = FALSE; 59 | private $tolerant = FALSE; 60 | private $trusting = TRUE; 61 | private $once = FALSE; 62 | private $reset = FALSE; 63 | private $lowercase = TRUE; 64 | private $dateFormat; 65 | private $variable = array(); 66 | private $pharCompression = 'NONE'; 67 | private $pharKey; 68 | private $pharAll = false; 69 | private $pharAliasName = ''; 70 | private $pharHashAlgorithm; 71 | private $followSymlinks = false; 72 | private $cacheFilename; 73 | private $prepend = false; 74 | private $exceptions = true; 75 | 76 | private $homeDirectory = ''; 77 | 78 | public function __construct(Array $directories) { 79 | $this->directories = $directories; 80 | $this->php = (PHP_OS === 'WIN' ? 'C:\php\php.exe' : '/usr/bin/php'); 81 | } 82 | 83 | public function setBaseDirectory($baseDirectory) { 84 | $this->baseDirectory = $baseDirectory; 85 | } 86 | 87 | public function setHomeDirectory($homeDir) { 88 | $this->homeDirectory = $homeDir; 89 | } 90 | 91 | public function getHomeDirectory() { 92 | return $this->homeDirectory; 93 | } 94 | 95 | public function getBaseDirectory() { 96 | if ($this->baseDirectory !== NULL) { 97 | return realpath($this->baseDirectory); 98 | } 99 | if ($this->isPharMode()) { 100 | $comparator = new PathComparator($this->directories); 101 | return $comparator->getCommonBase(); 102 | } 103 | if ($this->outputFile != 'STDOUT') { 104 | return realpath(dirname($this->outputFile) ?: '.'); 105 | } 106 | $tmp = $this->getDirectories(); 107 | return realpath(is_dir($tmp[0]) ? $tmp[0] : (dirname($tmp[0]) ?: '.')); 108 | } 109 | 110 | public function setCompatMode($compatMode) { 111 | $this->compatMode = $compatMode; 112 | } 113 | 114 | public function isCompatMode() { 115 | return $this->compatMode === true; 116 | } 117 | 118 | public function setDateFormat($dateFormat) { 119 | $this->dateFormat = $dateFormat; 120 | } 121 | 122 | public function getDateFormat() { 123 | return $this->dateFormat; 124 | } 125 | 126 | public function setExclude(Array $exclude) { 127 | $this->exclude = $exclude; 128 | } 129 | 130 | public function getExclude() { 131 | return $this->exclude; 132 | } 133 | 134 | public function setInclude(Array $include) { 135 | $this->include = $include; 136 | } 137 | 138 | public function getInclude() { 139 | return $this->include; 140 | } 141 | 142 | /** 143 | * @return array 144 | */ 145 | public function getBlacklist() { 146 | return $this->blacklist; 147 | } 148 | 149 | /** 150 | * @param array $blacklist 151 | */ 152 | public function setBlacklist($blacklist) { 153 | $this->blacklist = $blacklist; 154 | } 155 | 156 | /** 157 | * @return array 158 | */ 159 | public function getWhitelist() { 160 | return $this->whitelist; 161 | } 162 | 163 | /** 164 | * @param array $whitelist 165 | */ 166 | public function setWhitelist($whitelist) { 167 | $this->whitelist = $whitelist; 168 | } 169 | 170 | public function setIndent($indent) { 171 | $this->indent = $indent; 172 | } 173 | 174 | public function getIndent() { 175 | if ($this->indent !== NULL) { 176 | if (is_numeric($this->indent) && (int)$this->indent == $this->indent) { 177 | return str_repeat(' ', (int)$this->indent); 178 | } 179 | return $this->indent; 180 | } 181 | if ($this->isStaticMode() || $this->isWarmMode()) { 182 | return ''; 183 | } 184 | return str_repeat(' ', $this->isCompatMode() ? 12 : 16); 185 | } 186 | 187 | public function setLinebreak($linebreak) { 188 | $lbr = array('LF' => "\n", 'CR' => "\r", 'CRLF' => "\r\n" ); 189 | if (isset($lbr[$linebreak])) { 190 | $this->linebreak = $lbr[$linebreak]; 191 | } else { 192 | $this->linebreak = $linebreak; 193 | } 194 | } 195 | 196 | public function getLinebreak() { 197 | return $this->linebreak; 198 | } 199 | 200 | public function setLintMode($lint) { 201 | $this->lint = (boolean)$lint; 202 | } 203 | 204 | public function isLintMode() { 205 | return $this->lint; 206 | } 207 | 208 | public function setLowercaseMode($lowercase) { 209 | $this->lowercase = (boolean)$lowercase; 210 | } 211 | 212 | public function isLowercaseMode() { 213 | return $this->lowercase; 214 | } 215 | 216 | public function setOnceMode($once) { 217 | $this->once = (boolean)$once; 218 | } 219 | 220 | public function isOnceMode() { 221 | return $this->once; 222 | } 223 | 224 | public function setOutputFile($outputFile) { 225 | $this->outputFile = $outputFile; 226 | } 227 | 228 | public function getOutputFile() { 229 | return $this->outputFile; 230 | } 231 | 232 | public function enablePharMode($compression = 'NONE', $all = true, $key = NULL, $alias = NULL) { 233 | $this->pharMode = true; 234 | $this->pharCompression = $compression; 235 | $this->pharAll = (boolean)$all; 236 | $this->pharKey = $key; 237 | $this->pharAliasName = $alias; 238 | } 239 | 240 | public function isPharMode() { 241 | return $this->pharMode; 242 | } 243 | 244 | public function isPharAllMode() { 245 | return $this->pharAll; 246 | } 247 | 248 | public function getPharCompression() { 249 | return $this->pharCompression; 250 | } 251 | 252 | public function getPharKey() { 253 | return $this->pharKey; 254 | } 255 | 256 | public function getPharAliasName() { 257 | return $this->pharAliasName; 258 | } 259 | 260 | public function hasPharHashAlgorithm() { 261 | return $this->pharHashAlgorithm !== null; 262 | } 263 | 264 | /** 265 | * @return string 266 | */ 267 | public function getPharHashAlgorithm() { 268 | return $this->pharHashAlgorithm; 269 | } 270 | 271 | /** 272 | * @param string $pharHashAlgorithm 273 | */ 274 | public function setPharHashAlgorithm($pharHashAlgorithm) { 275 | if (!in_array($pharHashAlgorithm, array('SHA-512','SHA-256','SHA-1'))) { 276 | throw new \InvalidArgumentException( 277 | sprintf('Algorithm %s not supported', $pharHashAlgorithm) 278 | ); 279 | } 280 | $this->pharHashAlgorithm = $pharHashAlgorithm; 281 | } 282 | 283 | public function setPhp($php) { 284 | $this->php = $php; 285 | } 286 | 287 | public function getPhp() { 288 | return $this->php; 289 | } 290 | 291 | public function setQuietMode($quietMode) { 292 | $this->quietMode = (boolean)$quietMode; 293 | } 294 | 295 | public function setStaticMode($staticMode) { 296 | $this->staticMode = (boolean)$staticMode; 297 | $this->warmMode = FALSE; 298 | } 299 | 300 | public function isStaticMode() { 301 | return $this->staticMode; 302 | } 303 | 304 | public function setWarmMode($warmMode) { 305 | $this->warmMode = (boolean)$warmMode; 306 | $this->staticMode = FALSE; 307 | } 308 | 309 | public function isWarmMode() { 310 | return $this->warmMode; 311 | } 312 | 313 | public function setResetMode($resetMode) { 314 | $this->reset = (boolean)$resetMode; 315 | } 316 | 317 | public function isResetMode() { 318 | return $this->reset; 319 | } 320 | 321 | public function setTemplate($template) { 322 | $this->template = $template; 323 | } 324 | 325 | public function getTemplate() { 326 | $tplType = $this->isLowercaseMode() ? 'ci' : 'cs'; 327 | $template = $this->template; 328 | if ($template !== NULL) { 329 | if (!file_exists($template)) { 330 | $alternative = __DIR__.'/templates/'. $tplType .'/'.$template; 331 | if (file_exists($alternative)) { 332 | $template = $alternative; 333 | } 334 | $alternative .= '.php.tpl'; 335 | if (file_exists($alternative)) { 336 | $template = $alternative; 337 | } 338 | } 339 | return $template; 340 | } 341 | 342 | // determine auto template to use 343 | $tplFile = 'default.php.tpl'; 344 | if ($this->isCompatMode()) { 345 | $tplFile = 'php52.php.tpl'; 346 | } 347 | 348 | if ($this->isPharMode()) { 349 | if ($this->isStaticMode()) { 350 | $tplFile = 'staticphar.php.tpl'; 351 | $tplType = '.'; 352 | } else { 353 | $tplFile = 'phar.php.tpl'; 354 | } 355 | } elseif ($this->isStaticMode() || $this->isWarmMode()) { 356 | $tplFile = 'static.php.tpl'; 357 | $tplType = '.'; 358 | } 359 | 360 | return __DIR__.'/templates/'.$tplType.'/'.$tplFile; 361 | 362 | } 363 | 364 | public function setTolerantMode($tolerant) { 365 | $this->tolerant = (boolean)$tolerant; 366 | } 367 | 368 | public function isTolerantMode() { 369 | return $this->tolerant; 370 | } 371 | 372 | public function setTrusting($trusting) { 373 | $this->trusting = (boolean)$trusting; 374 | } 375 | 376 | public function setFollowSymlinks($followSymlinks) { 377 | $this->followSymlinks = (boolean)$followSymlinks; 378 | } 379 | 380 | public function isFollowSymlinks() { 381 | return $this->followSymlinks; 382 | } 383 | 384 | public function isTrustingMode() { 385 | return $this->trusting; 386 | } 387 | 388 | public function setVariable($name, $value) { 389 | $this->variable[$name] = $value; 390 | } 391 | 392 | public function getVariables() { 393 | return $this->variable; 394 | } 395 | 396 | public function isQuietMode() { 397 | return $this->quietMode; 398 | } 399 | 400 | public function getDirectories() { 401 | $list = array(); 402 | foreach($this->directories as $dir) { 403 | if (is_file($dir) && basename($dir) == 'composer.json') { 404 | foreach(new ComposerIterator(new \SplFileInfo($dir), $this->getHomeDirectory()) as $d) { 405 | $list[] = $d; 406 | } 407 | } else { 408 | foreach(glob($dir) as $match) { 409 | $list[] = $match; 410 | } 411 | } 412 | } 413 | return $list; 414 | } 415 | 416 | public function setCacheFile($filename) { 417 | $this->cacheFilename = $filename; 418 | } 419 | 420 | public function isCacheEnabled() { 421 | return $this->cacheFilename !== NULL; 422 | } 423 | 424 | public function getCacheFile() { 425 | return $this->cacheFilename; 426 | } 427 | 428 | public function enablePrepend() { 429 | $this->prepend = true; 430 | } 431 | 432 | public function usePrepend() { 433 | return $this->prepend; 434 | } 435 | 436 | public function disableExceptions() { 437 | $this->exceptions = false; 438 | } 439 | 440 | public function useExceptions() { 441 | return $this->exceptions; 442 | } 443 | 444 | } 445 | } 446 | -------------------------------------------------------------------------------- /src/DependencySorter.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload { 39 | 40 | /** 41 | * Sorting classes by depdendency for static requires 42 | * 43 | * @author Arne Blankerts 44 | * @copyright Arne Blankerts , All rights reserved. 45 | */ 46 | class ClassDependencySorter { 47 | 48 | private $classList; 49 | private $dependencies; 50 | 51 | private $level; 52 | 53 | private $sorted = array(); 54 | 55 | public function __construct(Array $classes, Array $dependencies) { 56 | $this->classList = $classes; 57 | $this->dependencies = $dependencies; 58 | } 59 | 60 | public function process() { 61 | $this->level = 0; 62 | foreach($this->classList as $class => $file) { 63 | if (!in_array($class, $this->sorted)) { 64 | $this->resolve($class); 65 | } 66 | } 67 | 68 | $res = array(); 69 | foreach($this->sorted as $class) { 70 | if (!isset($this->classList[$class])) { 71 | continue; 72 | } 73 | $res[$class] = $this->classList[$class]; 74 | } 75 | return $res; 76 | } 77 | 78 | private function resolve($class) { 79 | $this->level++; 80 | if ($this->level == 50) { 81 | throw new ClassDependencySorterException("Can't resolve more than 50 levels of dependencies", ClassDependencySorterException::TooManyDependencyLevels); 82 | } 83 | if (isset($this->dependencies[$class])) { 84 | foreach($this->dependencies[$class] as $depclass) { 85 | if (!in_array($depclass, $this->sorted)) { 86 | $this->resolve($depclass); 87 | } 88 | } 89 | } 90 | $this->sorted[] = $class; 91 | $this->level--; 92 | } 93 | } 94 | 95 | class ClassDependencySorterException extends \Exception { 96 | 97 | const TooManyDependencyLevels = 1; 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Factory.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | * 37 | */ 38 | namespace TheSeer\Autoload { 39 | 40 | use TheSeer\DirectoryScanner\DirectoryScanner; 41 | use TheSeer\DirectoryScanner\IncludeExcludeFilterIterator; 42 | 43 | class Factory { 44 | 45 | /** 46 | * @var Config 47 | */ 48 | private $config; 49 | 50 | /** 51 | * @var Cache 52 | */ 53 | private $cache; 54 | 55 | /** 56 | * @param \TheSeer\Autoload\Config $config 57 | */ 58 | public function setConfig(Config $config) { 59 | $this->config = $config; 60 | } 61 | 62 | /** 63 | * @return CLI 64 | */ 65 | public function getCLI() { 66 | return new CLI($this); 67 | } 68 | 69 | /** 70 | * @return Application 71 | */ 72 | public function getApplication() { 73 | return new Application($this->getLogger(), $this->config, $this); 74 | } 75 | 76 | public function getLogger() { 77 | return new Logger($this->config->isQuietMode()); 78 | } 79 | 80 | /** 81 | * @return Parser 82 | */ 83 | public function getParser() { 84 | $parser = new Parser( 85 | $this->config->isLowercaseMode() 86 | ); 87 | if (!$this->config->isCacheEnabled()) { 88 | return $parser; 89 | } 90 | return new CachingParser( 91 | $this->getCache(), 92 | $parser 93 | ); 94 | } 95 | 96 | /** 97 | * @return Cache 98 | */ 99 | public function getCache() { 100 | if (!$this->cache instanceof Cache) { 101 | $fname = $this->config->getCacheFile(); 102 | if (file_exists($fname)) { 103 | $data = unserialize(file_get_contents($fname)); 104 | } else { 105 | $data = array(); 106 | } 107 | $this->cache = new Cache($data); 108 | } 109 | return $this->cache; 110 | } 111 | 112 | public function getCollector() { 113 | return new Collector( 114 | $this->getParser(), 115 | $this->config->isTolerantMode(), 116 | $this->config->isTrustingMode(), 117 | $this->config->getWhitelist(), 118 | $this->config->getBlacklist() 119 | ); 120 | } 121 | 122 | /** 123 | * Get instance of DirectoryScanner with filter options applied 124 | * 125 | * @param bool $filter 126 | * @return DirectoryScanner 127 | */ 128 | public function getScanner($filter = TRUE) { 129 | $scanner = new DirectoryScanner; 130 | if ($filter) { 131 | $scanner->setIncludes($this->config->getInclude()); 132 | $scanner->setExcludes($this->config->getExclude()); 133 | } 134 | if ($this->config->isFollowSymlinks()) { 135 | $scanner->setFlag(\FilesystemIterator::FOLLOW_SYMLINKS); 136 | } 137 | return $scanner; 138 | } 139 | 140 | public function getFilter(\Iterator $files) { 141 | $filter = new IncludeExcludeFilterIterator($files); 142 | $filter->setInclude($this->config->getInclude()); 143 | $filter->setExclude($this->config->getExclude()); 144 | return $filter; 145 | } 146 | 147 | 148 | public function getPharBuilder() { 149 | $builder = new PharBuilder( 150 | $this->getScanner(!$this->config->isPharAllMode()), 151 | $this->config->getBaseDirectory() 152 | ); 153 | $builder->setCompressionMode($this->config->getPharCompression()); 154 | foreach($this->config->getDirectories() as $directory) { 155 | $builder->addDirectory($directory); 156 | } 157 | 158 | return $builder; 159 | } 160 | 161 | /** 162 | * Helper to get instance of AutoloadRenderer with cli options applied 163 | * 164 | * @param CollectorResult $result 165 | * 166 | * @throws \RuntimeException 167 | * @return \TheSeer\Autoload\AutoloadRenderer|\TheSeer\Autoload\StaticRenderer 168 | */ 169 | public function getRenderer(CollectorResult $result) { 170 | $isStatic = $this->config->isStaticMode(); 171 | $isPhar = $this->config->isPharMode(); 172 | $isCompat = $this->config->isCompatMode(); 173 | $isOnce = $this->config->isOnceMode(); 174 | $isWarm = $this->config->isWarmMode(); 175 | $isReset = $this->config->isResetMode(); 176 | 177 | if ($isWarm === TRUE) { 178 | $renderer = new StaticRenderer( 179 | $result->getUnits(), 180 | $this->getCacheWarmingListRenderer($isReset) 181 | ); 182 | $renderer->setDependencies($result->getDependencies()); 183 | $renderer->setPharMode($isPhar); 184 | } else if ($isStatic === TRUE) { 185 | $renderer = new StaticRenderer( 186 | $result->getUnits(), 187 | $this->getStaticRequireListRenderer($isOnce) 188 | ); 189 | $renderer->setDependencies($result->getDependencies()); 190 | $renderer->setPharMode($isPhar); 191 | } else { 192 | $renderer = new AutoloadRenderer($result->getUnits()); 193 | if ($this->config->usePrepend()) { 194 | $renderer->prependAutoloader(); 195 | } 196 | if ($this->config->useExceptions()) { 197 | $renderer->enableExceptions(); 198 | } 199 | } 200 | 201 | $renderer->setCompat($isCompat); 202 | 203 | $basedir = $this->config->getBaseDirectory(); 204 | if (!$basedir || !is_dir($basedir)) { 205 | throw new \RuntimeException("Given basedir '{$basedir}' does not exist or is not a directory"); 206 | } 207 | $renderer->setBaseDir($basedir); 208 | 209 | $format = $this->config->getDateFormat(); 210 | if ($format) { 211 | $renderer->setDateTimeFormat($format); 212 | } 213 | 214 | $renderer->setIndent($this->config->getIndent()); 215 | $renderer->setLineBreak($this->config->getLinebreak()); 216 | 217 | foreach($this->config->getVariables() as $name => $value) { 218 | $renderer->setVariable($name, $value); 219 | } 220 | 221 | return $renderer; 222 | } 223 | 224 | private function getStaticRequireListRenderer($useOnce) { 225 | return new StaticRequireListRenderer( 226 | $useOnce, 227 | $this->config->getIndent(), 228 | $this->config->getLinebreak() 229 | ); 230 | } 231 | 232 | private function getCacheWarmingListRenderer($addReset) { 233 | return new CacheWarmingListRenderer( 234 | $addReset, 235 | $this->config->getIndent(), 236 | $this->config->getLinebreak() 237 | ); 238 | } 239 | 240 | } 241 | 242 | } 243 | -------------------------------------------------------------------------------- /src/Logger.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | * 37 | */ 38 | namespace TheSeer\Autoload { 39 | 40 | class Logger { 41 | 42 | private $quiet = FALSE; 43 | 44 | /** 45 | * @param bool $quietMode 46 | */ 47 | public function __construct($quietMode = FALSE) { 48 | $this->quiet = $quietMode; 49 | } 50 | 51 | public function log($message, $target = STDOUT) { 52 | if ($this->quiet) { 53 | return; 54 | } 55 | fwrite($target, $message); 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ParseResult.php: -------------------------------------------------------------------------------- 1 | units = $units; 23 | $this->dependencies = $dependencies; 24 | $this->redeclarations = $redeclarations; 25 | } 26 | 27 | public function hasUnits() { 28 | return count($this->units) > 0; 29 | } 30 | 31 | public function hasRedeclarations() { 32 | return count($this->redeclarations) > 0; 33 | } 34 | 35 | /** 36 | * 37 | * @param string $unit 38 | * 39 | * @return array 40 | */ 41 | public function getDependenciesForUnit($unit) { 42 | if (!isset($this->dependencies[$unit])) { 43 | return array(); 44 | } 45 | return $this->dependencies[$unit]; 46 | } 47 | 48 | /** 49 | * @return \string[] 50 | */ 51 | public function getRedeclarations() { 52 | return $this->redeclarations; 53 | } 54 | 55 | /** 56 | * @return \string[] 57 | */ 58 | public function getUnits() { 59 | return $this->units; 60 | } 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/ParserInterface.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright Arne Blankerts , All rights reserved. 9 | */ 10 | interface ParserInterface { 11 | 12 | /** 13 | * Parse a given file for defintions of classes, traits and interfaces 14 | * 15 | * @param SourceFile $source file to process 16 | * 17 | * @return ParseResult 18 | */ 19 | public function parse(SourceFile $source); 20 | } 21 | -------------------------------------------------------------------------------- /src/PathComparator.php: -------------------------------------------------------------------------------- 1 | directories[] = realpath($dir).'/'; 19 | } 20 | } 21 | 22 | public function getCommonBase() { 23 | if (count($this->directories) === 0) { 24 | return '/'; 25 | } 26 | $result = $this->directories[0]; 27 | foreach($this->directories as $dir) { 28 | $result = substr($dir, 0, $this->commonPrefix($result, $dir)).'/'; 29 | } 30 | return (rtrim($result, '/') ?: '/'); 31 | } 32 | 33 | 34 | private function commonPrefix( $s1, $s2 ) { 35 | $l1 = strlen($s1); 36 | $l2 = strlen($s2); 37 | $i=0; 38 | while($i < $l1 && $i < $l2 && $s1[$i] == $s2[$i]) { 39 | $i++; 40 | } 41 | return strrpos(substr($s1, 0, $i), '/'); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/PharBuilder.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | * 37 | */ 38 | namespace TheSeer\Autoload { 39 | 40 | use TheSeer\DirectoryScanner\DirectoryScanner; 41 | 42 | class PharBuilder { 43 | 44 | private $scanner; 45 | private $compression; 46 | private $key; 47 | private $basedir; 48 | private $aliasName; 49 | private $signatureType; 50 | 51 | private $directories = array(); 52 | 53 | private $supportedSignatureTypes = array( 54 | 'SHA-512' => \Phar::SHA512, 55 | 'SHA-256' => \Phar::SHA256, 56 | 'SHA-1' => \Phar::SHA1 57 | ); 58 | 59 | public function __construct(DirectoryScanner $scanner, $basedir) { 60 | $this->scanner = $scanner; 61 | $this->basedir = $basedir; 62 | } 63 | 64 | public function setCompressionMode($mode) { 65 | $this->compression = $mode; 66 | } 67 | 68 | public function setSignatureType($type) { 69 | if (!in_array($type, array_keys($this->supportedSignatureTypes))) { 70 | throw new \InvalidArgumentException( 71 | sprintf('Signature type "%s" not known or not supported by this PHP installation.', $type) 72 | ); 73 | } 74 | $this->signatureType = $type; 75 | } 76 | 77 | public function setSignatureKey($key) { 78 | $this->key = $key; 79 | } 80 | 81 | public function addDirectory($directory) { 82 | $this->directories[] = $directory; 83 | } 84 | 85 | public function setAliasName($name) { 86 | $this->aliasName = $name; 87 | } 88 | 89 | public function build($filename, $stub) { 90 | if (file_exists($filename)) { 91 | unlink($filename); 92 | } 93 | $phar = new \Phar($filename, 0, $this->aliasName != '' ? $this->aliasName : basename($filename)); 94 | $phar->startBuffering(); 95 | $phar->setStub($stub); 96 | if ($this->key !== NULL) { 97 | $privateKey = ''; 98 | openssl_pkey_export($this->key, $privateKey); 99 | $phar->setSignatureAlgorithm(\Phar::OPENSSL, $privateKey); 100 | $keyDetails = openssl_pkey_get_details($this->key); 101 | file_put_contents($filename . '.pubkey', $keyDetails['key']); 102 | } else { 103 | $phar->setSignatureAlgorithm($this->selectSignatureType()); 104 | } 105 | 106 | $basedir = $this->basedir ? $this->basedir : $this->directories[0]; 107 | foreach($this->directories as $directory) { 108 | $phar->buildFromIterator($this->scanner->__invoke($directory), $basedir); 109 | } 110 | 111 | if ($this->compression !== \Phar::NONE) { 112 | $phar->compressFiles($this->compression); 113 | } 114 | $phar->stopBuffering(); 115 | } 116 | 117 | private function selectSignatureType() { 118 | if ($this->signatureType !== NULL) { 119 | return $this->supportedSignatureTypes[$this->signatureType]; 120 | } 121 | $supported = \Phar::getSupportedSignatures(); 122 | foreach($this->supportedSignatureTypes as $candidate => $type) { 123 | if (in_array($candidate, $supported)) { 124 | return $type; 125 | } 126 | } 127 | 128 | // Is there any PHP Version out there that does not support at least SHA-1? 129 | // But hey, fallback to md5, better than nothing 130 | return \Phar::MD5; 131 | } 132 | 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/SourceFile.php: -------------------------------------------------------------------------------- 1 | getRealPath())); 8 | } 9 | 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/StaticListRenderer.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload { 39 | 40 | /** 41 | * Builds static require list for inclusion into projects 42 | * 43 | * @author Arne Blankerts 44 | * @copyright Arne Blankerts , All rights reserved. 45 | */ 46 | class StaticRenderer extends AutoloadRenderer { 47 | 48 | private $dependencies; 49 | private $phar; 50 | private $require = 'require'; 51 | 52 | /** 53 | * @var StaticListRenderer 54 | */ 55 | private $renderHelper; 56 | 57 | public function __construct(array $classlist, StaticListRenderer $renderHelper) { 58 | parent::__construct($classlist); 59 | $this->renderHelper = $renderHelper; 60 | } 61 | 62 | /** 63 | * Setter for Dependency Array 64 | * @param array $dep Dependency Array from classfinder 65 | */ 66 | public function setDependencies(Array $dep) { 67 | $this->dependencies = $dep; 68 | } 69 | 70 | /** 71 | * Toggle phar outut mode 72 | * 73 | * @param boolean $phar 74 | */ 75 | public function setPharMode($phar) { 76 | $this->phar = (boolean)$phar; 77 | } 78 | 79 | /** 80 | * Toggle wether or not to use require_once over require 81 | * 82 | * @param boolean $mode 83 | */ 84 | public function setRequireOnce($mode) { 85 | } 86 | 87 | 88 | /** 89 | * @param string $template 90 | * 91 | * @return string 92 | */ 93 | public function render($template) { 94 | $baseDir = ''; 95 | if ($this->phar) { 96 | $baseDir = "'phar://". $this->variables['___PHAR___']."' . "; 97 | } else if ($this->baseDir) { 98 | $baseDir = $this->compat ? 'dirname(__FILE__) . ' : '__DIR__ . '; 99 | } 100 | 101 | $entries = array(); 102 | foreach($this->sortByDependency() as $fname) { 103 | $entries[] = $this->resolvePath($fname); 104 | } 105 | 106 | $replace = array_merge( 107 | $this->variables, 108 | array( 109 | '___CREATED___' => date( $this->dateformat, $this->timestamp ? $this->timestamp : time()), 110 | '___FILELIST___' => $this->renderHelper->render($entries), 111 | '___BASEDIR___' => $baseDir, 112 | '___AUTOLOAD___' => uniqid('autoload', true) 113 | ) 114 | ); 115 | 116 | return str_replace(array_keys($replace), array_values($replace), $template); 117 | } 118 | 119 | /** 120 | * Helper to sort classes/interfaces and traits based on their depdendency info 121 | * 122 | * @return array 123 | */ 124 | protected function sortByDependency() { 125 | $sorter = new ClassDependencySorter($this->classes, $this->dependencies); 126 | $list = $sorter->process(); 127 | 128 | return array_unique($list); 129 | } 130 | 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/StaticRequireListRenderer.php: -------------------------------------------------------------------------------- 1 | useOnce = $useOnce; 20 | $this->indent = $indent; 21 | $this->linebreak = $linebreak; 22 | } 23 | 24 | /** 25 | * @return string 26 | */ 27 | public function render(array $list) { 28 | $require = (boolean)$this->useOnce ? 'require_once' : 'require'; 29 | $require .= ' ___BASEDIR___\''; 30 | $glue = '\';' . $this->linebreak . $this->indent . $require; 31 | 32 | return $this->indent . $require . implode($glue, $list) . '\';'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Version.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | * 37 | */ 38 | namespace TheSeer\Autoload { 39 | 40 | class Version { 41 | 42 | private static $version = NULL; 43 | 44 | public static function getVersion() { 45 | if (self::$version === NULL) { 46 | self::$version = PHPAB_VERSION; 47 | if (PHPAB_VERSION == '%development%') { 48 | $cwd = getcwd(); 49 | chdir(__DIR__); 50 | $git = exec('command -p git describe --always --dirty 2>/dev/null', $foo, $rc); 51 | chdir($cwd); 52 | if ($rc === 0) { 53 | self::$version = $git; 54 | } 55 | } 56 | } 57 | return self::$version; 58 | } 59 | 60 | public static function getInfoString() { 61 | return 'phpab ' . self::getVersion() . ' - Copyright (C) 2009 - ' . date('Y') . ' by Arne Blankerts and Contributors'; 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/autoload.php: -------------------------------------------------------------------------------- 1 | '/../vendor/zetacomponents/base/src/base.php', 11 | 'ezcbaseautoloadexception' => '/../vendor/zetacomponents/base/src/exceptions/autoload.php', 12 | 'ezcbaseautoloadoptions' => '/../vendor/zetacomponents/base/src/options/autoload.php', 13 | 'ezcbaseconfigurationinitializer' => '/../vendor/zetacomponents/base/src/interfaces/configuration_initializer.php', 14 | 'ezcbasedoubleclassrepositoryprefixexception' => '/../vendor/zetacomponents/base/src/exceptions/double_class_repository_prefix.php', 15 | 'ezcbaseexception' => '/../vendor/zetacomponents/base/src/exceptions/exception.php', 16 | 'ezcbaseexportable' => '/../vendor/zetacomponents/base/src/interfaces/exportable.php', 17 | 'ezcbaseextensionnotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/extension_not_found.php', 18 | 'ezcbasefeatures' => '/../vendor/zetacomponents/base/src/features.php', 19 | 'ezcbasefile' => '/../vendor/zetacomponents/base/src/file.php', 20 | 'ezcbasefileexception' => '/../vendor/zetacomponents/base/src/exceptions/file_exception.php', 21 | 'ezcbasefilefindcontext' => '/../vendor/zetacomponents/base/src/structs/file_find_context.php', 22 | 'ezcbasefileioexception' => '/../vendor/zetacomponents/base/src/exceptions/file_io.php', 23 | 'ezcbasefilenotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/file_not_found.php', 24 | 'ezcbasefilepermissionexception' => '/../vendor/zetacomponents/base/src/exceptions/file_permission.php', 25 | 'ezcbasefunctionalitynotsupportedexception' => '/../vendor/zetacomponents/base/src/exceptions/functionality_not_supported.php', 26 | 'ezcbaseinit' => '/../vendor/zetacomponents/base/src/init.php', 27 | 'ezcbaseinitcallbackconfiguredexception' => '/../vendor/zetacomponents/base/src/exceptions/init_callback_configured.php', 28 | 'ezcbaseinitinvalidcallbackclassexception' => '/../vendor/zetacomponents/base/src/exceptions/invalid_callback_class.php', 29 | 'ezcbaseinvalidparentclassexception' => '/../vendor/zetacomponents/base/src/exceptions/invalid_parent_class.php', 30 | 'ezcbasemetadata' => '/../vendor/zetacomponents/base/src/metadata.php', 31 | 'ezcbasemetadatapearreader' => '/../vendor/zetacomponents/base/src/metadata/pear.php', 32 | 'ezcbasemetadatatarballreader' => '/../vendor/zetacomponents/base/src/metadata/tarball.php', 33 | 'ezcbaseoptions' => '/../vendor/zetacomponents/base/src/options.php', 34 | 'ezcbasepersistable' => '/../vendor/zetacomponents/base/src/interfaces/persistable.php', 35 | 'ezcbasepropertynotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/property_not_found.php', 36 | 'ezcbasepropertypermissionexception' => '/../vendor/zetacomponents/base/src/exceptions/property_permission.php', 37 | 'ezcbaserepositorydirectory' => '/../vendor/zetacomponents/base/src/structs/repository_directory.php', 38 | 'ezcbasesettingnotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/setting_not_found.php', 39 | 'ezcbasesettingvalueexception' => '/../vendor/zetacomponents/base/src/exceptions/setting_value.php', 40 | 'ezcbasestruct' => '/../vendor/zetacomponents/base/src/struct.php', 41 | 'ezcbasevalueexception' => '/../vendor/zetacomponents/base/src/exceptions/value.php', 42 | 'ezcbasewhateverexception' => '/../vendor/zetacomponents/base/src/exceptions/whatever.php', 43 | 'ezcconsoleargument' => '/../vendor/zetacomponents/console-tools/src/input/argument.php', 44 | 'ezcconsoleargumentalreadyregisteredexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_already_registered.php', 45 | 'ezcconsoleargumentexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument.php', 46 | 'ezcconsoleargumentmandatoryviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_mandatory_violation.php', 47 | 'ezcconsolearguments' => '/../vendor/zetacomponents/console-tools/src/input/arguments.php', 48 | 'ezcconsoleargumenttypeviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_type_violation.php', 49 | 'ezcconsoledialog' => '/../vendor/zetacomponents/console-tools/src/interfaces/dialog.php', 50 | 'ezcconsoledialogabortexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/dialog_abort.php', 51 | 'ezcconsoledialogoptions' => '/../vendor/zetacomponents/console-tools/src/options/dialog.php', 52 | 'ezcconsoledialogvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/dialog_validator.php', 53 | 'ezcconsoledialogviewer' => '/../vendor/zetacomponents/console-tools/src/dialog_viewer.php', 54 | 'ezcconsoleexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/exception.php', 55 | 'ezcconsoleinput' => '/../vendor/zetacomponents/console-tools/src/input.php', 56 | 'ezcconsoleinputhelpgenerator' => '/../vendor/zetacomponents/console-tools/src/interfaces/input_help_generator.php', 57 | 'ezcconsoleinputstandardhelpgenerator' => '/../vendor/zetacomponents/console-tools/src/input/help_generators/standard.php', 58 | 'ezcconsoleinputvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/input_validator.php', 59 | 'ezcconsoleinvalidoptionnameexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/invalid_option_name.php', 60 | 'ezcconsoleinvalidoutputtargetexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/invalid_output_target.php', 61 | 'ezcconsolemenudialog' => '/../vendor/zetacomponents/console-tools/src/dialog/menu_dialog.php', 62 | 'ezcconsolemenudialogdefaultvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/menu_dialog_default.php', 63 | 'ezcconsolemenudialogoptions' => '/../vendor/zetacomponents/console-tools/src/options/menu_dialog.php', 64 | 'ezcconsolemenudialogvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/menu_dialog_validator.php', 65 | 'ezcconsolenopositionstoredexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/no_position_stored.php', 66 | 'ezcconsolenovaliddialogresultexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/no_valid_dialog_result.php', 67 | 'ezcconsoleoption' => '/../vendor/zetacomponents/console-tools/src/input/option.php', 68 | 'ezcconsoleoptionalreadyregisteredexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_already_registered.php', 69 | 'ezcconsoleoptionargumentsviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_arguments_violation.php', 70 | 'ezcconsoleoptiondependencyviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_dependency_violation.php', 71 | 'ezcconsoleoptionexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option.php', 72 | 'ezcconsoleoptionexclusionviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_exclusion_violation.php', 73 | 'ezcconsoleoptionmandatoryviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_mandatory_violation.php', 74 | 'ezcconsoleoptionmissingvalueexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_missing_value.php', 75 | 'ezcconsoleoptionnoaliasexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_no_alias.php', 76 | 'ezcconsoleoptionnotexistsexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_not_exists.php', 77 | 'ezcconsoleoptionrule' => '/../vendor/zetacomponents/console-tools/src/structs/option_rule.php', 78 | 'ezcconsoleoptionstringnotwellformedexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_string_not_wellformed.php', 79 | 'ezcconsoleoptiontoomanyvaluesexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_too_many_values.php', 80 | 'ezcconsoleoptiontypeviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_type_violation.php', 81 | 'ezcconsoleoutput' => '/../vendor/zetacomponents/console-tools/src/output.php', 82 | 'ezcconsoleoutputformat' => '/../vendor/zetacomponents/console-tools/src/structs/output_format.php', 83 | 'ezcconsoleoutputformats' => '/../vendor/zetacomponents/console-tools/src/structs/output_formats.php', 84 | 'ezcconsoleoutputoptions' => '/../vendor/zetacomponents/console-tools/src/options/output.php', 85 | 'ezcconsoleprogressbar' => '/../vendor/zetacomponents/console-tools/src/progressbar.php', 86 | 'ezcconsoleprogressbaroptions' => '/../vendor/zetacomponents/console-tools/src/options/progressbar.php', 87 | 'ezcconsoleprogressmonitor' => '/../vendor/zetacomponents/console-tools/src/progressmonitor.php', 88 | 'ezcconsoleprogressmonitoroptions' => '/../vendor/zetacomponents/console-tools/src/options/progressmonitor.php', 89 | 'ezcconsolequestiondialog' => '/../vendor/zetacomponents/console-tools/src/dialog/question_dialog.php', 90 | 'ezcconsolequestiondialogcollectionvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_collection.php', 91 | 'ezcconsolequestiondialogmappingvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_mapping.php', 92 | 'ezcconsolequestiondialogoptions' => '/../vendor/zetacomponents/console-tools/src/options/question_dialog.php', 93 | 'ezcconsolequestiondialogregexvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_regex.php', 94 | 'ezcconsolequestiondialogtypevalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_type.php', 95 | 'ezcconsolequestiondialogvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/question_dialog_validator.php', 96 | 'ezcconsolestandardinputvalidator' => '/../vendor/zetacomponents/console-tools/src/input/validators/standard.php', 97 | 'ezcconsolestatusbar' => '/../vendor/zetacomponents/console-tools/src/statusbar.php', 98 | 'ezcconsolestatusbaroptions' => '/../vendor/zetacomponents/console-tools/src/options/statusbar.php', 99 | 'ezcconsolestringtool' => '/../vendor/zetacomponents/console-tools/src/tools/string.php', 100 | 'ezcconsoletable' => '/../vendor/zetacomponents/console-tools/src/table.php', 101 | 'ezcconsoletablecell' => '/../vendor/zetacomponents/console-tools/src/table/cell.php', 102 | 'ezcconsoletableoptions' => '/../vendor/zetacomponents/console-tools/src/options/table.php', 103 | 'ezcconsoletablerow' => '/../vendor/zetacomponents/console-tools/src/table/row.php', 104 | 'ezcconsoletoomanyargumentsexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_too_many.php', 105 | 'theseer\\autoload\\application' => '/Application.php', 106 | 'theseer\\autoload\\applicationexception' => '/Application.php', 107 | 'theseer\\autoload\\autoloadbuilderexception' => '/AutoloadRenderer.php', 108 | 'theseer\\autoload\\autoloadrenderer' => '/AutoloadRenderer.php', 109 | 'theseer\\autoload\\cache' => '/Cache.php', 110 | 'theseer\\autoload\\cacheentry' => '/CacheEntry.php', 111 | 'theseer\\autoload\\cacheexception' => '/Cache.php', 112 | 'theseer\\autoload\\cachewarminglistrenderer' => '/CacheWarmingListRenderer.php', 113 | 'theseer\\autoload\\cachingparser' => '/CachingParser.php', 114 | 'theseer\\autoload\\classdependencysorter' => '/DependencySorter.php', 115 | 'theseer\\autoload\\classdependencysorterexception' => '/DependencySorter.php', 116 | 'theseer\\autoload\\cli' => '/CLI.php', 117 | 'theseer\\autoload\\clienvironmentexception' => '/CLI.php', 118 | 'theseer\\autoload\\collector' => '/Collector.php', 119 | 'theseer\\autoload\\collectorexception' => '/Collector.php', 120 | 'theseer\\autoload\\collectorresult' => '/CollectorResult.php', 121 | 'theseer\\autoload\\collectorresultexception' => '/CollectorResult.php', 122 | 'theseer\\autoload\\composeriterator' => '/ComposerIterator.php', 123 | 'theseer\\autoload\\composeriteratorexception' => '/ComposerIterator.php', 124 | 'theseer\\autoload\\config' => '/Config.php', 125 | 'theseer\\autoload\\factory' => '/Factory.php', 126 | 'theseer\\autoload\\logger' => '/Logger.php', 127 | 'theseer\\autoload\\parser' => '/Parser.php', 128 | 'theseer\\autoload\\parseresult' => '/ParseResult.php', 129 | 'theseer\\autoload\\parserexception' => '/Parser.php', 130 | 'theseer\\autoload\\parserinterface' => '/ParserInterface.php', 131 | 'theseer\\autoload\\pathcomparator' => '/PathComparator.php', 132 | 'theseer\\autoload\\pharbuilder' => '/PharBuilder.php', 133 | 'theseer\\autoload\\sourcefile' => '/SourceFile.php', 134 | 'theseer\\autoload\\staticlistrenderer' => '/StaticListRenderer.php', 135 | 'theseer\\autoload\\staticrenderer' => '/StaticRenderer.php', 136 | 'theseer\\autoload\\staticrequirelistrenderer' => '/StaticRequireListRenderer.php', 137 | 'theseer\\autoload\\version' => '/Version.php', 138 | 'theseer\\directoryscanner\\directoryscanner' => '/../vendor/theseer/directoryscanner/src/directoryscanner.php', 139 | 'theseer\\directoryscanner\\exception' => '/../vendor/theseer/directoryscanner/src/directoryscanner.php', 140 | 'theseer\\directoryscanner\\filesonlyfilteriterator' => '/../vendor/theseer/directoryscanner/src/filesonlyfilter.php', 141 | 'theseer\\directoryscanner\\includeexcludefilteriterator' => '/../vendor/theseer/directoryscanner/src/includeexcludefilter.php', 142 | 'theseer\\directoryscanner\\phpfilteriterator' => '/../vendor/theseer/directoryscanner/src/phpfilter.php' 143 | ); 144 | } 145 | $cn = strtolower($class); 146 | if (isset($classes[$cn])) { 147 | require __DIR__ . $classes[$cn]; 148 | } 149 | }, 150 | true, 151 | false 152 | ); 153 | // @codeCoverageIgnoreEnd 154 | -------------------------------------------------------------------------------- /src/templates/ci/default.php.tpl: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload\Tests { 39 | 40 | use TheSeer\Autoload\AutoloadBuilderException; 41 | use TheSeer\Autoload\AutoloadRenderer; 42 | 43 | /** 44 | * @author Arne Blankerts 45 | * @copyright Arne Blankerts , All rights reserved. 46 | */ 47 | class AutoloadRendererTest extends \PHPUnit\Framework\TestCase { 48 | 49 | private $classlist; 50 | private $template; 51 | 52 | public function setUp(): void { 53 | $this->classlist = array(); 54 | $this->classlist['demo1'] = realpath(__DIR__ . '/_data/parser/class.php'); 55 | $this->classlist['demo2'] = realpath(__DIR__ . '/_data/parser/class.php'); 56 | $this->template = file_get_contents(__DIR__ . '/_data/templates/default.php.tpl'); 57 | } 58 | 59 | /** 60 | * @covers \TheSeer\Autoload\AutoloadRenderer::__construct 61 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 62 | */ 63 | public function testDefaultRendering() { 64 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 65 | $expected = " \$classes = array(\n 'demo1' => '".__DIR__."/_data/parser/class.php',\n"; 66 | $expected = strtr($expected, '\\', '/'); 67 | $this->assertStringContainsString($expected, $ab->render($this->template)); 68 | $expected = "require \$classes[\$cn]"; 69 | $this->assertStringContainsString($expected, $ab->render($this->template)); 70 | } 71 | 72 | /** 73 | * 74 | * @covers \TheSeer\Autoload\AutoloadRenderer::setLinebreak 75 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 76 | */ 77 | public function testWindowsLFRendering() { 78 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 79 | $ab->setLineBreak("\r\n"); 80 | $expected = "_data/parser/class.php',\r\n"; 81 | $this->assertStringContainsString($expected, $ab->render($this->template)); 82 | } 83 | 84 | /** 85 | * 86 | * @covers \TheSeer\Autoload\AutoloadRenderer::setLinebreak 87 | * @covers \TheSeer\Autoload\AutoloadRenderer::getLinebreak 88 | */ 89 | public function testSettingAndGettingLinebreakWorks() { 90 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 91 | $ab->setLineBreak('foo'); 92 | $this->assertEquals('foo', $ab->getLineBreak()); 93 | } 94 | 95 | /** 96 | * 97 | * @covers \TheSeer\Autoload\AutoloadRenderer::setIndent 98 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 99 | */ 100 | public function testIndentWithTabsRendering() { 101 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 102 | $ab->setIndent("\t"); 103 | $expected = "\t'demo2'"; 104 | $this->assertStringContainsString($expected, $ab->render($this->template)); 105 | } 106 | 107 | 108 | /** 109 | * 110 | * @covers \TheSeer\Autoload\AutoloadRenderer::setBaseDir 111 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 112 | */ 113 | public function testSetBaseDirRendering() { 114 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 115 | $ab->setBaseDir(realpath(__DIR__ . '/..')); 116 | $result = $ab->render($this->template); 117 | 118 | $expected = "require __DIR__ . \$classes[\$cn];"; 119 | $expected = strtr($expected, '\\', '/'); 120 | $this->assertStringContainsString($expected, $result); 121 | 122 | $expected = " \$classes = array(\n 'demo1' => '/tests/_data/parser/class.php',\n"; 123 | $this->assertStringContainsString($expected, $result); 124 | } 125 | 126 | /** 127 | * 128 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 129 | */ 130 | public function testRenderingInCompatMode() { 131 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 132 | $ab->setCompat(true); 133 | $ab->setBaseDir(realpath(__DIR__)); 134 | $expected = "require dirname(__FILE__) . \$classes[\$cn];"; 135 | $this->assertStringContainsString($expected, $ab->render($this->template)); 136 | 137 | } 138 | 139 | /** 140 | * @covers \TheSeer\Autoload\AutoloadRenderer::resolvePath 141 | */ 142 | public function testRelativeSubBaseDirRendering() { 143 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 144 | $ab->setBaseDir(realpath(__DIR__.'/_data/dependency')); 145 | $expected = "'demo1' => '/../parser/class.php'"; 146 | $this->assertStringContainsString($expected, $ab->render($this->template)); 147 | } 148 | 149 | public function testSettingInvalidTimestamp() { 150 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 151 | $this->expectException(AutoloadBuilderException::class); 152 | $ab->setTimestamp('Bad'); 153 | } 154 | 155 | public function testSettingTimestamp() { 156 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 157 | $now = time(); 158 | $ab->setTimestamp($now); 159 | $this->assertEquals(date('r',$now), $ab->render('___CREATED___')); 160 | } 161 | 162 | /** 163 | * 164 | * @depends testSettingTimestamp 165 | */ 166 | public function testSettingDateTimeFormat() { 167 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 168 | $now = time(); 169 | $ab->setTimestamp($now); 170 | $ab->setDateTimeFormat('dmYHis'); 171 | $this->assertEquals(date('dmYHis',$now), $ab->render('___CREATED___')); 172 | } 173 | 174 | /** 175 | * 176 | * @covers \TheSeer\Autoload\AutoloadRenderer::setVariable 177 | */ 178 | public function testSetVariable() { 179 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 180 | $ab->setVariable('TEST','variableValue'); 181 | $this->assertEquals('variableValue', $ab->render('___TEST___')); 182 | } 183 | 184 | /** 185 | * 186 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 187 | */ 188 | public function testGetUniqueReproducibleValueForAutoloadName() { 189 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 190 | $first = $ab->render('___AUTOLOAD___'); 191 | $this->assertEquals($first, $ab->render('___AUTOLOAD___')); 192 | } 193 | 194 | /** 195 | * 196 | * @covers \TheSeer\Autoload\AutoloadRenderer::render 197 | */ 198 | public function testGetUniqueValueForAutoloadName() { 199 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 200 | $first = $ab->render('___AUTOLOAD___'); 201 | 202 | $aSecond = $this->classlist; 203 | array_pop($aSecond); 204 | $ab = new \TheSeer\Autoload\AutoloadRenderer($aSecond); 205 | $this->assertNotEquals($first, $ab->render('___AUTOLOAD___')); 206 | } 207 | 208 | /** 209 | * @covers \TheSeer\Autoload\AutoloadRenderer::setCompat 210 | */ 211 | public function testSetCompatMode() { 212 | $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); 213 | $ab->setCompat(true); 214 | $ab->setBaseDir('.'); 215 | $this->assertEquals('dirname(__FILE__) . ', $ab->render('___BASEDIR___')); 216 | } 217 | 218 | } 219 | 220 | } 221 | -------------------------------------------------------------------------------- /tests/ComposerIteratorTest.php: -------------------------------------------------------------------------------- 1 | $entry) { 15 | $this->assertEquals($expected[$pos], $entry); 16 | } 17 | } 18 | 19 | public function testPSR14ArrayIsSupported() { 20 | $iterator = new ComposerIterator(new \SplFileInfo(__DIR__ . '/_data/composer-array-issue-98/composer.json'), array()); 21 | $expected = array( 22 | __DIR__ . '/_data/composer-array-issue-98/../src', 23 | __DIR__ . '/_data/composer-array-issue-98/modules', 24 | __DIR__ . '/_data/composer-array-issue-98/src' 25 | ); 26 | foreach($iterator as $pos => $entry) { 27 | $this->assertEquals($expected[$pos], $entry); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /tests/DuplicateDetectionTest.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload\Tests { 39 | 40 | use TheSeer\Autoload\Config; 41 | use TheSeer\Autoload\Factory; 42 | 43 | class DuplicateDetectionTest extends \PHPUnit\Framework\TestCase { 44 | 45 | public function testBugIsFixed() { 46 | $config = new Config(array()); 47 | $config->setLowercaseMode(true); 48 | 49 | $factory = new Factory(); 50 | $factory->setConfig($config); 51 | 52 | $collector = $factory->getCollector(); 53 | 54 | $scanner = $factory->getScanner()->getIterator(__DIR__ . '/_data/duplicates'); 55 | $collector->processDirectory($scanner); 56 | 57 | $result = $collector->getResult(); 58 | 59 | $this->assertTrue($result->hasDuplicates()); 60 | 61 | $duplicates = $result->getDuplicates(); 62 | $this->assertCount(1, $duplicates); 63 | $this->assertArrayHasKey('a\\b\\c\\duplicate', $duplicates); 64 | $this->assertCount(3, $duplicates['a\\b\\c\\duplicate']); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/FactoryTest.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload\Tests { 39 | 40 | use TheSeer\Autoload\Application; 41 | use TheSeer\Autoload\Config; 42 | use TheSeer\Autoload\CLI; 43 | use TheSeer\Autoload\Factory; 44 | 45 | class FactoryTest extends \PHPUnit\Framework\TestCase { 46 | 47 | private $factory; 48 | private $config; 49 | 50 | public function setUp(): void { 51 | $this->factory = new Factory(); 52 | $this->config = new Config(array()); 53 | $this->factory->setConfig($this->config); 54 | } 55 | 56 | public function testApp() { 57 | $app = $this->factory->getApplication(); 58 | $this->assertTrue($app instanceof Application); 59 | } 60 | 61 | public function testCli() { 62 | $app = $this->factory->getCLI(); 63 | $this->assertTrue($app instanceof CLI); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/PathComparatorTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($common, $comparator->getCommonBase()); 15 | } 16 | 17 | public function directoriesProvider() { 18 | return array( 19 | 'empty' => array( 20 | array(), '/' 21 | ), 22 | 'single' => array( 23 | array(__DIR__), __DIR__ 24 | ), 25 | 'two' => array( 26 | array(__DIR__, dirname(__DIR__)), dirname(__DIR__) 27 | ), 28 | 'shortfirst' => array( 29 | array(dirname(__DIR__), __DIR__), dirname(__DIR__) 30 | ), 31 | 'parents' => array( 32 | array(__DIR__ . '/../src', __DIR__ . '/../tests/_data'), dirname(__DIR__) 33 | ), 34 | 'with0' => array( 35 | array($a=__DIR__.'/_data/parser/trait0.php'), $a 36 | ), 37 | 'dirwithprefix' => array( 38 | array(__DIR__.'/_data/parser/trait0.php', __DIR__.'/_data/parser/trait1.php'), __DIR__.'/_data/parser' 39 | ), 40 | 'dirwithoutprefix' => array( 41 | array(__DIR__, '/usr'), '/' 42 | ) 43 | ); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tests/_data/bug65/class.php: -------------------------------------------------------------------------------- 1 | = 5.5.9", 5 | "bar/foo": "0.0" 6 | }, 7 | "autoload": { 8 | "psr-4": { 9 | "": ["../src/", "modules/"], 10 | "MyApp\\": "src/" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/_data/dependency/file1.php: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /tests/_data/dependency/file2.php: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /tests/_data/dependency/ns01.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/classname.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/groupuse.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/implements2.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/inline-class.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/interfaceextends1.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/interfaceextends2.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace1.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace2.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace3.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace4.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace5.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace6.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace7.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/namespace8.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/nested.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/parseerror1.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/use10.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/use3.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/use4.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/use5.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/use6.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_data/parser/use7.php: -------------------------------------------------------------------------------- 1 | = 5.5.9", 5 | "bar/foo": "0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/_data/recursion/vendor/bar/foo/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "recursion", 3 | "require": { 4 | "php": ">= 5.5.9", 5 | "foo/bar": "0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/_data/recursion/vendor/bar/foo/src/foo.php: -------------------------------------------------------------------------------- 1 | = 5.5.9", 5 | "bar/foo": "0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/_data/recursion/vendor/foo/bar/src/bar.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/bug65Test.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload\Tests { 39 | 40 | use TheSeer\Autoload\ClassDependencySorter; 41 | use TheSeer\Autoload\Config; 42 | use TheSeer\Autoload\Factory; 43 | 44 | class Bug65Test extends \PHPUnit\Framework\TestCase { 45 | 46 | public function testBugIsFixed() { 47 | $config = new Config(array()); 48 | $config->setLowercaseMode(true); 49 | 50 | $factory = new Factory(); 51 | $factory->setConfig($config); 52 | 53 | $collector = $factory->getCollector(); 54 | 55 | $scanner = $factory->getScanner()->getIterator(__DIR__ . '/_data/bug65'); 56 | $collector->processDirectory($scanner); 57 | $result = $collector->getResult(); 58 | 59 | $sorter = new ClassDependencySorter($result->getUnits(), $result->getDependencies()); 60 | 61 | $expected = array( 62 | 'phpunit_extensions_database_testcase_trait' => __DIR__ . "/_data/bug65/trait.php", 63 | 'phpunit_extensions_database_testcase' => __DIR__ . "/_data/bug65/class.php" 64 | ); 65 | 66 | $this->assertEquals($expected, $sorter->process()); 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/classdependencysorterTest.php: -------------------------------------------------------------------------------- 1 | 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 ORCONTRIBUTORS 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 | * @package Autoload 33 | * @author Arne Blankerts 34 | * @copyright Arne Blankerts , All rights reserved. 35 | * @license BSD License 36 | */ 37 | 38 | namespace TheSeer\Autoload\Tests { 39 | 40 | use TheSeer\Autoload\ClassDependencySorterException; 41 | use TheSeer\Autoload\Parser; 42 | use TheSeer\Autoload\AutoloadRenderer; 43 | use TheSeer\Autoload\ClassDependencySorter; 44 | 45 | /** 46 | * Unit tests for ClassDependencySorter class 47 | * 48 | * @author Arne Blankerts 49 | * @copyright Arne Blankerts , All rights reserved. 50 | */ 51 | class ClassDependencySorterTest extends \PHPUnit\Framework\TestCase { 52 | 53 | 54 | public function testProcessingDependenciesInOneFile() { 55 | $classes = array( 56 | 'class1' => 'file1', 57 | 'class2' => 'file1' 58 | ); 59 | 60 | $dependency=array( 61 | 'class1' => array('class2') 62 | ); 63 | 64 | $x = new ClassDependencySorter($classes, $dependency); 65 | $r = $x->process(); 66 | 67 | $expectOrder=array('class2','class1'); 68 | $this->assertEquals(2, count($r)); 69 | $this->assertEquals($expectOrder, array_keys($r)); 70 | } 71 | 72 | public function testProcessingDependenciesOverFileBounderies() { 73 | 74 | $classes = array( 75 | 'class3' => 'file3', 76 | 'class1' => 'file1', 77 | 'class2' => 'file2' 78 | ); 79 | 80 | $dependency=array( 81 | 'class2' => array('class3'), 82 | 'class1' => array('class2') 83 | ); 84 | 85 | $x = new ClassDependencySorter($classes, $dependency); 86 | $r = $x->process(); 87 | 88 | $expectOrder=array( 89 | 'class3','class2','class1' 90 | ); 91 | 92 | $expectFilesOrder=array( 93 | 'file3','file2','file1' 94 | ); 95 | 96 | $this->assertEquals(3, count($r)); 97 | $this->assertEquals($expectOrder, array_keys($r)); 98 | $this->assertEquals($expectFilesOrder, array_unique(array_values($r))); 99 | } 100 | 101 | public function testRecusriveDependencyThrowsException() { 102 | $classes=array('test1' => 'file1'); 103 | $dependency=array('test1' => array('test1')); 104 | 105 | $x = new ClassDependencySorter($classes, $dependency); 106 | $this->expectException(ClassDependencySorterException::class); 107 | $r = $x->process(); 108 | 109 | } 110 | 111 | public function testUnkownDependencyGetsSkippedSilently() { 112 | $classes=array('test1' => 'file1'); 113 | $dependency=array('test1' => array('test2')); 114 | 115 | $x = new ClassDependencySorter($classes, $dependency); 116 | $r = $x->process(); 117 | $this->assertTrue(true); 118 | } 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /tests/init.php: -------------------------------------------------------------------------------- 1 |