Added third-party dependency theseer\Autoload

This commit is contained in:
Netkas 2022-09-22 16:47:23 -04:00
parent a1ce77a455
commit 82527dd4c2
37 changed files with 3956 additions and 0 deletions

1
.gitignore vendored
View file

@ -12,5 +12,6 @@ src/ncc/ThirdParty/Symfony/Process/autoload_spl.php
src/ncc/ThirdParty/Symfony/Uid/autoload_spl.php
src/ncc/ThirdParty/Symfony/Filesystem/autoload_spl.php
src/ncc/ThirdParty/Symfony/Yaml/autoload_spl.php
src/ncc/ThirdParty/theseer/Autoload/autoload_spl.php
src/ncc/autoload_spl.php
src/ncc/autoload.php

View file

@ -10,6 +10,7 @@ autoload:
make src/ncc/ThirdParty/Symfony/Uid/autoload_spl.php
make src/ncc/ThirdParty/Symfony/Filesystem/autoload_spl.php
make src/ncc/ThirdParty/Symfony/Yaml/autoload_spl.php
make src/ncc/ThirdParty/theseer/Autoload/autoload_spl.php
make src/ncc/autoload_spl.php
cp src/autoload/autoload.php src/ncc/autoload.php
@ -41,6 +42,10 @@ src/ncc/ThirdParty/Symfony/Yaml/autoload_spl.php:
$(PHPCC) $(PHPAB) --output src/ncc/ThirdParty/Symfony/Yaml/autoload_spl.php \
src/ncc/ThirdParty/Symfony/Yaml
src/ncc/ThirdParty/theseer/Autoload/autoload_spl.php:
$(PHPCC) $(PHPAB) --output src/ncc/ThirdParty/theseer/Autoload/autoload_spl.php \
src/ncc/ThirdParty/theseer/Autoload
src/ncc/autoload_spl.php:
$(PHPCC) $(PHPAB) --output src/ncc/autoload_spl.php \
src/ncc/Abstracts \

View file

@ -22,6 +22,7 @@
$third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Uid' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Filesystem' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Yaml' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'theseer' . DIRECTORY_SEPARATOR . 'Autoload' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
];
foreach($target_files as $file)

View file

@ -0,0 +1,247 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*
*/
namespace TheSeer\Autoload {
class Application {
private $logger;
private $factory;
private $config;
public function __construct(Logger $logger, Config $config, Factory $factory) {
$this->logger = $logger;
$this->config = $config;
$this->factory = $factory;
}
public function run() {
$result = $this->runCollector();
if (!$result->hasUnits()) {
throw new ApplicationException('No units were found - process aborted.', ApplicationException::NoUnitsFound);
}
if ($result->hasDuplicates()) {
return $this->showDuplicatesError($result->getDuplicates());
}
if ($this->config->isCacheEnabled()) {
$this->factory->getCache()->persist($this->config->getCacheFile());
}
$template = @file_get_contents($this->config->getTemplate());
if ($template === false) {
throw new ApplicationException("Failed to read the template file.");
}
$builder = $this->factory->getRenderer($result);
$code = $builder->render($template);
if ($this->config->isLintMode()) {
return $this->runLint($code);
}
return $this->runSaver($code);
}
/**
* @return CollectorResult
*/
private function runCollector() {
if ($this->config->isFollowSymlinks()) {
$this->logger->log('Following symbolic links is enabled.' . "\n\n");
}
$collector = $this->factory->getCollector();
foreach ($this->config->getDirectories() as $directory) {
if (is_dir($directory)) {
$this->logger->log('Scanning directory ' . $directory . "\n");
$scanner = $this->factory->getScanner()->getIterator($directory);
$collector->processDirectory($scanner);
// this unset is needed to "fix" a segfault on shutdown in some PHP Versions
unset($scanner);
} else {
$file = new \SplFileInfo($directory);
$filter = $this->factory->getFilter(new \ArrayIterator(array($file)));
foreach($filter as $file) {
$this->logger->log('Scanning file ' . $file . "\n");
$collector->processFile($file);
}
}
}
return $collector->getResult();
}
private function runSaver($code) {
$output = $this->config->getOutputFile();
if (!$this->config->isPharMode()) {
if ($output === 'STDOUT') {
$this->logger->log("\n");
echo $code;
$this->logger->log("\n\n");
return CLI::RC_OK;
}
// @codingStandardsIgnoreStart
$written = @file_put_contents($output, $code);
// @codingStandardsIgnoreEnd
if ($written != strlen($code)) {
$this->logger->log("Writing to file '$output' failed.", STDERR);
return CLI::RC_EXEC_ERROR;
}
$this->logger->log("\nAutoload file {$output} generated.\n\n");
return CLI::RC_OK;
}
if (strpos($code, '__HALT_COMPILER();') === FALSE) {
$this->logger->log(
"Warning: Template used in phar mode did not contain required __HALT_COMPILER() call\n" .
"which has been added automatically. The used stub code may not work as intended.\n\n", STDERR);
$code .= $this->config->getLinebreak() . '__HALT_COMPILER();';
}
$pharBuilder = $this->factory->getPharBuilder();
if ($keyfile = $this->config->getPharKey()) {
$pharBuilder->setSignatureKey($this->loadPharSignatureKey($keyfile));
}
if ($aliasName = $this->config->getPharAliasName()) {
$pharBuilder->setAliasName($aliasName);
}
if ($this->config->hasPharHashAlgorithm()) {
$pharBuilder->setSignatureType($this->config->getPharHashAlgorithm());
}
$pharBuilder->build($output, $code);
$this->logger->log("\nphar archive '{$output}' generated.\n\n");
return CLI::RC_OK;
}
private function loadPharSignatureKey($keyfile) {
if (!extension_loaded('openssl')) {
throw new ApplicationException('Extension for OpenSSL not loaded - cannot sign phar archive - process aborted.',
ApplicationException::OpenSSLError);
}
$keydata = file_get_contents($keyfile);
if (strpos($keydata, 'ENCRYPTED') !== FALSE) {
$this->logger->log("Passphrase for key '$keyfile': ");
$g = shell_exec('stty -g');
shell_exec('stty -echo');
$passphrase = trim(fgets(STDIN));
$this->logger->log("\n");
shell_exec('stty ' . $g);
$private = openssl_pkey_get_private($keydata, $passphrase);
} else {
$private = openssl_pkey_get_private($keydata);
}
if (!$private) {
throw new ApplicationException("Opening private key '$keyfile' failed - process aborted.\n\n", ApplicationException::OpenSSLError);
}
return $private;
}
/**
* Execute a lint check on generated code
*
* @param string $code Generated code to lint
*
* @return boolean
*/
protected function runLint($code) {
$dsp = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w')
);
$binary = $this->config->getPhp();
$process = proc_open($binary . ' -l', $dsp, $pipes);
if (!is_resource($process)) {
$this->logger->log("Opening php binary for linting failed.\n", STDERR);
return 1;
}
fwrite($pipes[0], $code);
fclose($pipes[0]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$rc = proc_close($process);
if ($rc == 255) {
$this->logger->log("Syntax errors during lint:\n" .
str_replace('in - on line', 'in generated code on line', $stderr) .
"\n", STDERR);
return CLI::RC_LINT_ERROR;
}
$this->logger->log("Lint check of geneated code okay\n\n");
return CLI::RC_OK;
}
/**
* @param array $duplicates
*
* @return int
*/
private function showDuplicatesError(array $duplicates) {
$this->logger->log(
sprintf("\nMultiple declarations of trait(s), interface(s) or class(es). Could not generate autoload map.\n"),
STDERR
);
foreach($duplicates as $unit => $files) {
$this->logger->log(
sprintf("\nUnit '%s' defined in:\n", $unit),
STDERR
);
/** @var array $files */
foreach($files as $file) {
$this->logger->log(
sprintf(" - %s\n", $file),
STDERR
);
}
}
return CLI::RC_DUPLICATES_ERROR;
}
}
class ApplicationException extends \Exception {
const NoUnitsFound = 1;
const OpenSSLError = 2;
}
}

View file

@ -0,0 +1,297 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*/
namespace TheSeer\Autoload {
/**
* Builds spl based autoload code for inclusion into projects
*
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
*/
class AutoloadRenderer {
/**
* Associative array of classes (key) and the files (value) they are in
*
* @var array
*/
protected $classes;
/**
* An optional base dir to strip for the realpath of the filename
*
* @var string
*/
protected $baseDir = '';
/**
* Indenting char(s)
*
* @var string
*/
protected $indent = ' ';
/**
* Char(s) used as linebreak
*
* @var string
*/
protected $linebreak = "\n";
/**
* Timestamp of production start
*
* @var integer
*/
protected $timestamp;
/**
* Format string supplied to date() for use with ___CREATED___
*
* @var string
*/
protected $dateformat = 'r';
/**
* Variables for templates
*
* @var array
*/
protected $variables = array();
/**
* Flag to toggle PHP 5.2 compat mode
*
* @var boolean
*/
protected $compat = false;
/**
* Flag to pass on to spl_autoload_register to prepend
*
* @var bool
*/
private $usePrepend = false;
/**
* Flag to pass on to spl_autoload_register to optionally throw exceptions on registration error
*
* @var bool
*/
private $throwExceptions = false;
/**
* Constructor of AutoloadRenderer class
*
* @param array $classlist Array of classes
*
*/
public function __construct(array $classlist) {
$this->classes = $classlist;
ksort($this->classes);
}
/**
* Toggle PHP 5.2 compat mode
*
* @param boolean $mode Mode to set compat to
*/
public function setCompat($mode) {
$this->compat = $mode;
}
public function enableExceptions() {
$this->throwExceptions = true;
}
public function prependAutoloader() {
$this->usePrepend = true;
}
/**
* Setter for the Basedir
*
* @param string $dir Path to strip from beginning of filenames
*
* @return void
*/
public function setBaseDir($dir) {
$this->baseDir = $dir;
}
/**
* Overwrite default or previously set indenting option
*
* @param string $indent Char(s) to use for indenting
*
* @return void
*/
public function setIndent($indent) {
$this->indent = $indent;
}
/**
* Overwrite default or previously set linebreak chars
*
* @param string $lbs Code to set linebreak
*
* @return void
*/
public function setLineBreak($lbs) {
$this->linebreak = $lbs;
}
/**
* Accessor for current linebreak setting
*
* @return string
*/
public function getLineBreak() {
return $this->linebreak;
}
/**
* Setter to use allow usage of fixed date/time for ___CREATED___
*
* @param integer $time unix timestamp
*
* @throws AutoloadBuilderException
*/
public function setTimestamp($time) {
if (!is_int($time) && null !== $time) {
throw new AutoloadBuilderException("'$time' is not a unix timestamp", AutoloadBuilderException::InvalidTimestamp);
}
$this->timestamp = $time;
}
/**
* Setter to adjust the date/time format output of ___CREATED___
*
* @param string $frmt Date/Time format string
*/
public function setDateTimeFormat($frmt) {
$this->dateformat = $frmt;
}
/**
* Set a variable for use with template code
*
* @param string $name Key name (use as ___key___ in template)
* @param string $value Value to use
*/
public function setVariable($name, $value) {
$this->variables['___'.$name.'___'] = $value;
}
/**
* Resolve relative location of file path to basedir if one is set and fix potential
* broken windows pathnames when run on windows.
*
* @param string $fname
*
* @return string
*/
protected function resolvePath($fname) {
if (empty($this->baseDir)) {
return str_replace('\\', '/', $fname);
}
$basedir = explode(DIRECTORY_SEPARATOR, $this->baseDir);
$filedir = explode(DIRECTORY_SEPARATOR, dirname(realpath($fname)));
$pos = 0;
$max = count($basedir);
while (isset($filedir[$pos]) && $filedir[$pos] == $basedir[$pos]) {
$pos++;
if ($pos == $max) {
break;
}
}
if ($pos == 0) {
return str_replace('\\', '/', $fname);
}
$rel = join('/', array_slice($filedir, $pos));
if (!empty($rel)) {
$rel .= '/';
}
if ($pos<count($basedir)) {
$rel = str_repeat('../', count($basedir)-$pos) . $rel;
}
return '/' . $rel . basename($fname);
}
/**
* Render autoload code into a string
*
* @param string $template
*
* @return string
*/
public function render($template) {
$entries = array();
foreach($this->classes as $class => $file) {
$fname = $this->resolvePath($file);
$entries[] = "'". addslashes($class). "' => '$fname'";
}
$baseDir = '';
if ($this->baseDir) {
$baseDir = $this->compat ? 'dirname(__FILE__) . ' : '__DIR__ . ';
}
$replace = array_merge($this->variables, array(
'___CREATED___' => date( $this->dateformat, $this->timestamp ? $this->timestamp : time()),
'___CLASSLIST___' => join( ',' . $this->linebreak . $this->indent, $entries),
'___BASEDIR___' => $baseDir,
'___AUTOLOAD___' => 'autoload' . md5(serialize($entries)),
'___EXCEPTION___' => $this->throwExceptions ? 'true' : 'false',
'___PREPEND___' => $this->usePrepend ? 'true' : 'false'
));
return str_replace(array_keys($replace), array_values($replace), $template);
}
}
class AutoloadBuilderException extends \Exception {
const TemplateNotFound = 1;
const InvalidTimestamp = 2;
}
}

View file

@ -0,0 +1,607 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*/
namespace TheSeer\Autoload {
/**
* CLI interface to AutoloadRenderer / StaticRenderer
*
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
*/
class CLI {
const RC_OK = 0;
const RC_EXEC_ERROR = 1;
const RC_PARAM_ERROR = 3;
const RC_LINT_ERROR = 4;
const RC_DUPLICATES_ERROR = 5;
private $pharOption;
private $staticOption;
private $helpOption;
private $versionOption;
private $onceOption;
/**
* @var Factory
*/
private $factory;
public function __construct(Factory $factory) {
$this->factory = $factory;
}
/**
* Main executor method
*
* @return void
*/
public function run() {
try {
$this->preBootstrap();
$input = $this->setupInput();
$input->process();
if ($input->getOption('help')->value === TRUE) {
$this->showVersion();
$this->showUsage();
exit(CLI::RC_OK);
}
if ($input->getOption('version')->value === TRUE ) {
$this->showVersion();
exit(CLI::RC_OK);
}
$config = $this->configure($input);
$this->factory->setConfig($config);
if (!$config->isQuietMode()) {
$this->showVersion();
}
$rc = $this->factory->getApplication()->run();
exit($rc);
} catch (CLIEnvironmentException $e) {
$this->showVersion();
fwrite(STDERR, 'Sorry, but your PHP environment is currently not able to run phpab due to');
fwrite(STDERR, "\nthe following issue(s):\n\n" . $e->getMessage() . "\n\n");
fwrite(STDERR, "Please adjust your PHP configuration and try again.\n\n");
exit(CLI::RC_EXEC_ERROR);
} catch (\ezcConsoleException $e) {
$this->showVersion();
echo $e->getMessage() . "\n\n";
$this->showUsage();
exit(CLI::RC_PARAM_ERROR);
} catch (CollectorException $e) {
switch($e->getCode()) {
case CollectorException::InFileRedeclarationFound:
case CollectorException::RedeclarationFound:
case CollectorException::ParseErrror: {
$message = $e->getMessage();
break;
}
default: {
$message = 'Unexpected error in collector process: ' . $e->getMessage() . "\n\nPlease report this as a bug.\n\n";
}
}
$this->showVersion();
fwrite(STDERR, $message . "\n\n");
exit(CLI::RC_EXEC_ERROR);
} catch (\Exception $e) {
$this->showVersion();
fwrite(STDERR, "\nError while processing request:\n - " . $e->getMessage()."\n");
exit(CLI::RC_EXEC_ERROR);
}
}
/**
* @param \ezcConsoleInput $input
*
* @return \TheSeer\Autoload\Config
*/
private function configure(\ezcConsoleInput $input) {
$config = new Config($input->getArguments());
if ($input->getOption('quiet')->value) {
$config->setQuietMode(TRUE);
}
if ($input->getOption('compat')->value) {
$config->setCompatMode(TRUE);
}
if ($input->getOption('tolerant')->value) {
$config->setTolerantMode(TRUE);
}
if ($output = $input->getOption('output')->value) {
$config->setOutputFile($output);
}
if ($input->getOption('phar')->value) {
$compression = \Phar::NONE;
if ($input->getOption('bzip2')->value === TRUE) {
$compression = \Phar::BZ2;
} else if ($input->getOption('gzip')->value === TRUE) {
$compression = \Phar::GZ;
}
$config->enablePharMode(
$compression,
$input->getOption('all')->value,
$input->getOption('key')->value,
$input->getOption('alias')->value
);
$config->setVariable('PHAR',
$input->getOption('alias')->value ? $input->getOption('alias')->value : basename($output)
);
if ($hashAlgorithm = $input->getOption('hash')->value) {
$config->setPharHashAlgorithm($hashAlgorithm);
}
}
if ($input->getOption('cache')->value) {
$config->setCacheFile($input->getOption('cache')->value);
}
if ($basedir = $input->getOption('basedir')->value) {
$config->setBaseDirectory($basedir);
}
$include = $input->getOption('include')->value;
if (!is_array($include)) {
$include = array($include);
}
$config->setInclude($include);
if ($exclude = $input->getOption('exclude')->value) {
if (!is_array($exclude)) {
$exclude = array($exclude);
}
$config->setExclude($exclude);
}
$whitelist = $input->getOption('whitelist')->value;
if (!is_array($whitelist)) {
$whitelist = array($whitelist);
}
$config->setWhitelist($whitelist);
if ($blacklist = $input->getOption('blacklist')->value) {
if (!is_array($blacklist)) {
$blacklist = array($blacklist);
}
$config->setBlacklist($blacklist);
}
if ($input->getOption('static')->value) {
$config->setStaticMode(TRUE);
}
if ($input->getOption('once')->value) {
$config->setOnceMode(TRUE);
}
if ($input->getOption('warm')->value) {
$config->setWarmMode(TRUE);
}
if ($input->getOption('reset')->value) {
$config->setResetMode(TRUE);
}
if ($input->getOption('follow')->value) {
$config->setFollowSymlinks(TRUE);
}
if ($input->getOption('prepend')->value) {
$config->enablePrepend();
}
if ($input->getOption('no-exception')->value) {
$config->disableExceptions();
}
$indent = $input->getOption('indent')->value;
if ($indent !== FALSE) {
$config->setIndent($indent);
}
if ($template = $input->getOption('template')->value) {
$config->setTemplate($template);
}
if ($linebreak = $input->getOption('linebreak')->value) {
$config->setLinebreak($linebreak);
}
if ($input->getOption('nolower')->value) {
$config->setLowercaseMode(FALSE);
}
if ($variables = $input->getOption('var')->value) {
foreach($variables as $var) {
if (strpos($var, '=')===FALSE) {
throw new \RuntimeException("Variable defintion '$var' is invalid and cannot be processed.");
}
list($name, $value) = explode('=', $var, 2);
$config->setVariable($name, $value);
}
}
if ($input->getOption('paranoid')->value || !$input->getOption('trusting')->value) {
$config->setTrusting(FALSE);
}
return $config;
}
/**
* Helper to output version information
*/
protected function showVersion() {
static $shown = false;
if (!$shown) {
$shown = true;
echo Version::getInfoString() . "\n\n";
}
}
/**
* Helper to output usage information
*/
protected function showUsage() {
print <<<EOF
Usage: phpab [switches] <directory1|file1|/path/to/composer.json> [...<directoryN|fileN>]
-i, --include File pattern to include (default: *.php)
-e, --exclude File pattern to exclude
--blacklist Blacklist classname or namespace (wildcards supported)
--whitelist Whitelist classname or namespace (wildcards supported)
-b, --basedir Basedir for filepaths
-t, --template Path to code template to use
-o, --output Output file for generated code (default: STDOUT)
-p, --phar Create a phar archive (requires -o )
--all Include all files in given directory when creating a phar
--alias Specify explicit internal phar alias filename (default: output filename)
--hash Force given hash algorithm (SHA-1, SHA-256 or SHA-512) (requires -p, conflicts with --key)
--bzip2 Compress phar archive using bzip2 (requires -p) (bzip2 required)
--gzip Compress phar archive using gzip (requires -p) (gzip required)
--key OpenSSL key file to use for signing phar archive (requires -p) (openssl required)
-c, --compat Generate PHP 5.2 compatible code
-s, --static Generate a static require file
-w, --warm Generate a static opcache warming file
--reset Add opcache reset call when generating opcache warming file
-1, --prepend Register as first autoloader (prepend to stack, default: append)
-d, --no-exception Do not throw exception on registration problem (default: throw exception)
-n, --nolower Do not lowercase classnames for case insensitivity
-q, --quiet Quiet mode, do not output any processing errors or information
--cache <file> Enable caching and set filename to use for cache storage
--follow Enables following symbolic links (not compatible with phar mode)
--format Dateformat string for timestamp
--linebreak Linebreak style (CR, CRLF or LF, default: LF)
--indent String used for indenting or number of spaces (default: 16 (compat 12) spaces)
--tolerant Ignore Class Redeclarations in the same file
--once Use require_once instead of require when creating a static require file
--trusting Do not check mimetype of files prior to parsing (default)
--paranoid Do check mimetype of files prior to parsing
--var name=foo Assign value 'foo' to variable 'name' to be used in (custom) templates
--lint Run lint on generated code and exit
--lint-php PHP binary to use for linting (default: /usr/bin/php or c:\php\php.exe)
-h, --help Prints this usage information
-v, --version Prints the version and exits
EOF;
}
/**
* @return \ezcConsoleInput
*/
protected function setupInput() {
$input = new \ezcConsoleInput();
$this->versionOption = $input->registerOption( new \ezcConsoleOption( 'v', 'version' ) );
$this->versionOption->shorthelp = 'Prints the version and exits';
$this->versionOption->isHelpOption = TRUE;
$this->helpOption = $input->registerOption( new \ezcConsoleOption( 'h', 'help' ) );
$this->helpOption->isHelpOption = TRUE;
$this->helpOption->shorthelp = 'Prints this usage information';
$input->registerOption( new \ezcConsoleOption(
'', 'cache', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Enable cache and set cache filename'
));
$this->outputOption = $input->registerOption( new \ezcConsoleOption(
'o', 'output', \ezcConsoleInput::TYPE_STRING, 'STDOUT', FALSE,
'Output file for generated code (default: STDOUT)'
));
$this->pharOption = $input->registerOption( new \ezcConsoleOption(
'p', 'phar', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Build a phar archive of directory contents',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'o' ) ) )
));
$input->registerOption( new \ezcConsoleOption(
'', 'all', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Add all files from src dir to phar',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'p' ) ) )
));
$input->registerOption( new \ezcConsoleOption(
'', 'alias', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Provide explicit internal alias filename for phar',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'p' ) ) )
));
$bzip2 = $input->registerOption( new \ezcConsoleOption(
'', 'bzip2', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Compress files phar with bzip2',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'p' ) ) )
));
$gzip = $input->registerOption( new \ezcConsoleOption(
'', 'gzip', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Compress files phar with gzip',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'p' ) ) ),
array( new \ezcConsoleOptionRule( $bzip2 ) )
));
$bzip2->addExclusion(new \ezcConsoleOptionRule($gzip));
$input->registerOption( new \ezcConsoleOption(
'', 'key', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Keyfile to use for signing phar archive',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'p' ) ) )
));
$this->outputOption = $input->registerOption( new \ezcConsoleOption(
'', 'hash', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Force given hash algorithm (SHA-1, SHA-256 or SHA-512) (requires -p)',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'p' ) ) ),
array( new \ezcConsoleOptionRule( $input->getOption( 'key' ) ) )
));
$input->registerOption( new \ezcConsoleOption(
'i', 'include', \ezcConsoleInput::TYPE_STRING, '*.php', TRUE,
'File pattern to include (default: *.php)'
));
$input->registerOption( new \ezcConsoleOption(
'', 'blacklist', \ezcConsoleInput::TYPE_STRING, NULL, TRUE,
'Name pattern to exclude'
));
$input->registerOption( new \ezcConsoleOption(
'', 'whitelist', \ezcConsoleInput::TYPE_STRING, '*', TRUE,
'Name pattern to include (default: *)'
));
$input->registerOption( new \ezcConsoleOption(
'e', 'exclude', \ezcConsoleInput::TYPE_STRING, NULL, TRUE,
'File pattern to exclude'
));
$input->registerOption( new \ezcConsoleOption(
'b', 'basedir', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Basedir for filepaths'
));
$input->registerOption( new \ezcConsoleOption(
't', 'template', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Path to code template to use'
));
$input->registerOption( new \ezcConsoleOption(
'', 'follow', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Enables following symbolic links',
NULL,
array(),
array( new \ezcConsoleOptionRule($this->pharOption) )
));
$input->registerOption( new \ezcConsoleOption(
'', 'format', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Dateformat string for timestamp'
));
$input->registerOption( new \ezcConsoleOption(
'', 'linebreak', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'Linebreak style (CR, CR/LF or LF)'
));
$input->registerOption( new \ezcConsoleOption(
'', 'indent', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'String used for indenting (default: 3 spaces)'
));
$this->lintOption = $input->registerOption( new \ezcConsoleOption(
'', 'lint', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Run lint on generated code'
));
$input->registerOption( new \ezcConsoleOption(
'', 'lint-php', \ezcConsoleInput::TYPE_STRING, NULL, FALSE,
'PHP binary path for linting (default: /usr/bin/php or c:\\php\\php.exe)',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 'lint' ) ) )
));
$compat = $input->registerOption( new \ezcConsoleOption(
'c', 'compat', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Generate PHP 5.2 compliant code'
));
$this->staticOption = $input->registerOption( new \ezcConsoleOption(
's', 'static', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Build a static require file'
));
$input->registerOption( new \ezcConsoleOption(
'', 'tolerant', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Ignore Class Redeclarations in the same file'
));
$trusting = $input->registerOption( new \ezcConsoleOption(
'', 'trusting', \ezcConsoleInput::TYPE_NONE, TRUE, FALSE,
'Do not check mimetype of files prior to parsing'
));
$paranoid = $input->registerOption( new \ezcConsoleOption(
'', 'paranoid', \ezcConsoleInput::TYPE_NONE, FALSE, FALSE,
'Do check mimetype of files prior to parsing',
NULL,
array(),
array( new \ezcConsoleOptionRule($trusting) )
));
$trusting->addExclusion(new \ezcConsoleOptionRule($paranoid));
$this->onceOption = $input->registerOption( new \ezcConsoleOption(
'', 'once', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Use require_once in static require mode',
NULL,
array( new \ezcConsoleOptionRule( $input->getOption( 's' ) ) )
));
$input->registerOption( new \ezcConsoleOption(
'n', 'nolower', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Do not lowercase classnames for case insensitivity'
));
$input->registerOption( new \ezcConsoleOption(
'q', 'quiet', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Run in quiet mode, no output'
));
$input->registerOption( new \ezcConsoleOption(
'1', 'prepend', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Prepend autoloader to stack',
NULL,
array(),
array( new \ezcConsoleOptionRule( $compat ) )
));
$input->registerOption( new \ezcConsoleOption(
'd', 'no-exception', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'Disable exceptions on registration error'
));
$input->registerOption( new \ezcConsoleOption(
'', 'var', \ezcConsoleInput::TYPE_STRING, array(), TRUE,
'Assign variable'
));
$warm = $input->registerOption( new \ezcConsoleOption(
'w', 'warm', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'generate opcache warming file',
NULL,
array(),
array(
new \ezcConsoleOptionRule($this->pharOption),
new \ezcConsoleOptionRule($this->staticOption)
)
));
$input->registerOption( new \ezcConsoleOption(
'', 'reset', \ezcConsoleInput::TYPE_NONE, NULL, FALSE,
'add reset call to generated opcache warming file',
NULL,
array(
new \ezcConsoleOptionRule($warm)
)
));
$input->argumentDefinition = new \ezcConsoleArguments();
$input->argumentDefinition[0] = new \ezcConsoleArgument('directory');
$input->argumentDefinition[0]->shorthelp = 'The directory to process.';
$input->argumentDefinition[0]->multiple = TRUE;
return $input;
}
private function preBootstrap() {
$required = array('tokenizer', 'fileinfo');
$missing = array();
foreach($required as $test) {
if (!extension_loaded($test)) {
$missing[] = sprintf('ext/%s not installed/enabled', $test);
}
}
if (count($missing)) {
throw new CLIEnvironmentException(
join("\n", $missing),
CLIEnvironmentException::ExtensionMissing
);
}
if (extension_loaded('xdebug')) {
ini_set('xdebug.scream', 0);
ini_set('xdebug.max_nesting_level', 8192);
ini_set('xdebug.show_exception_trace', 0);
if (function_exists('xdebug_disable')) { // Xdebug v2
xdebug_disable();
}
}
}
}
class CLIEnvironmentException extends \Exception {
const ExtensionMissing = 1;
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace TheSeer\Autoload {
class Cache {
/**
* @var CacheEntry[]
*/
private $loadedEntries = array();
/**
* @var CacheEntry[]
*/
private $usedEntries = array();
public function __construct(array $initialEntries) {
$this->loadedEntries = $initialEntries;
}
/**
* @param SourceFile $file
*
* @return bool
*/
public function hasResult(SourceFile $file) {
$pathname = $file->getPathname();
if (!isset($this->loadedEntries[$pathname])) {
return false;
}
return $this->loadedEntries[$pathname]->getTimestamp() === $file->getMTime();
}
public function getResult(SourceFile $file) {
if (!$this->hasResult($file)) {
throw new CacheException('Entry not found');
}
$pathname = $file->getPathname();
$entry = $this->loadedEntries[$pathname];
$this->usedEntries[$pathname] = $entry;
return $entry->getResult();
}
public function addResult(SourceFile $file, ParseResult $result) {
$this->usedEntries[$file->getPathname()] = new CacheEntry($file->getMTime(), $result);
}
public function persist($fname) {
if (file_exists($fname)) {
unlink($fname);
}
file_put_contents($fname, serialize($this->usedEntries));
}
}
class CacheException extends \Exception {
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace TheSeer\Autoload {
class CacheEntry {
/**
* @var ParseResult
*/
private $result;
/**
* @var int
*/
private $timestamp;
public function __construct($timestamp, ParseResult $result) {
$this->timestamp = $timestamp;
$this->result = $result;
}
/**
* @return ParseResult
*/
public function getResult() {
return $this->result;
}
/**
* @return int
*/
public function getTimestamp() {
return $this->timestamp;
}
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace TheSeer\Autoload;
class CacheWarmingListRenderer implements StaticListRenderer {
/**
* @var boo
*/
private $addReset;
/**
* @var string
*/
private $indent;
private $linebreak;
/**
* @param boolean $addReset
* @param string $indent
* @param string $getLinebreak
*/
public function __construct($addReset, $indent, $linebreak) {
$this->addReset = $addReset;
$this->indent = $indent;
$this->linebreak = $linebreak;
}
/**
* @return string
*/
public function render(array $list) {
$line = $this->indent . 'opcache_compile_file(___BASEDIR___\'';
$glue = '\');' . $this->linebreak . $line;
$firstLine = $this->addReset ? $this->indent . 'opcache_reset();' . $this->linebreak : '';
return $firstLine . $line . implode($glue, $list) . '\');';
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace TheSeer\Autoload {
class CachingParser implements ParserInterface {
/**
* @var ParserInterface
*/
private $parser;
/**
* @var Cache
*/
private $cache;
public function __construct(Cache $cache, ParserInterface $parser) {
$this->cache = $cache;
$this->parser = $parser;
}
/**
* Parse a given file for defintions of classes, traits and interfaces
*
* @param SourceFile $source file to process
*
* @return ParseResult
*/
public function parse(SourceFile $source) {
if ($this->cache->hasResult($source)) {
return $this->cache->getResult($source);
}
$result = $this->parser->parse($source);
$this->cache->addResult($source, $result);
return $result;
}
}
}

View file

@ -0,0 +1,96 @@
<?php
namespace TheSeer\Autoload {
use TheSeer\DirectoryScanner\PHPFilterIterator;
class Collector {
/**
* @var ParserInterface
*/
private $parser;
/**
* @var CollectorResult
*/
private $collectorResult;
/**
* @var bool
*/
private $tolerantMode;
/**
* @var bool
*/
private $trustingMode;
/**
* Collector constructor.
*
* @param ParserInterface $parser
* @param bool $tolerantMode
* @param bool $trustingMode
* @param array $whitelist
* @param array $blacklist
*/
public function __construct(ParserInterface $parser, $tolerantMode = false, $trustingMode = true, Array $whitelist = array('*'), Array $blacklist = array()) {
$this->parser = $parser;
$this->tolerantMode = $tolerantMode;
$this->trustingMode = $trustingMode;
$this->collectorResult = new CollectorResult($whitelist, $blacklist);
}
public function getResult() {
return $this->collectorResult;
}
public function processDirectory(\Iterator $sources) {
$worker = $this->trustingMode ? $sources : new PHPFilterIterator($sources);
foreach($worker as $file) {
$this->processFile($file);
}
}
public function processFile(\SplFileInfo $file) {
if ($this->collectorResult->hasResultFor($file)) {
return;
}
try {
$parseResult = $this->parser->parse(new SourceFile($file->getRealPath()));
if ($parseResult->hasRedeclarations() && !$this->tolerantMode) {
throw new CollectorException(
sprintf(
"Duplicate (potentially conditional) definitions of the following unit(s) found:\n\n\tUnit(s): %s\n\tFile: %s",
join(', ', $parseResult->getRedeclarations()),
$file->getRealPath()
),
CollectorException::InFileRedeclarationFound
);
}
$this->collectorResult->addParseResult($file, $parseResult);
} catch(ParserException $e) {
throw new CollectorException(
sprintf(
"Could not process file '%s' due to parse errors: %s",
$file->getRealPath(),
$e->getMessage()
),
CollectorException::ParseErrror,
$e
);
} catch(CollectorResultException $e) {
throw new CollectorException(
$e->getMessage(),
CollectorException::RedeclarationFound
);
}
}
}
class CollectorException extends \Exception {
const ParseErrror = 1;
const RedeclarationFound = 2;
const InFileRedeclarationFound = 3;
}
}

View file

@ -0,0 +1,118 @@
<?php
namespace TheSeer\Autoload {
class CollectorResult {
/**
* @var array
*/
private $whitelist;
/**
* @var array
*/
private $blacklist;
/**
* @var array
*/
private $units = array();
/**
* @var array
*/
private $dependencies = array();
/**
* @var array
*/
private $seenFiles = array();
/**
* @var array
*/
private $duplicates = array();
public function __construct(array $whitelist, array $blacklist) {
$this->whitelist = $whitelist;
$this->blacklist = $blacklist;
}
public function hasResultFor(\SplFileInfo $file) {
return isset($this->seenFiles[$file->getRealPath()]);
}
public function addParseResult(\SplFileInfo $file, ParseResult $result) {
if (!$result->hasUnits()) {
return;
}
$filename = $file->getRealPath();
$this->seenFiles[$filename] = true;
foreach($result->getUnits() as $unit) {
if (!$this->accept($unit)) {
continue;
}
if (isset($this->units[$unit])) {
if (!isset($this->duplicates[$unit])) {
$this->duplicates[$unit] = array( $this->units[$unit] );
}
$this->duplicates[$unit][] = $filename;
continue;
}
$this->units[$unit] = $filename;
$this->dependencies[$unit] = $result->getDependenciesForUnit($unit);
}
}
public function hasUnits() {
return count($this->units) > 0;
}
public function hasDuplicates() {
return count($this->duplicates) > 0;
}
/**
* @return array
*/
public function getDependencies() {
return $this->dependencies;
}
/**
* @return array
*/
public function getUnits() {
return $this->units;
}
/**
* @param string $unit
*
* @return bool
*/
private function accept($unit) {
foreach($this->blacklist as $entry) {
if (fnmatch($entry, $unit)) {
return false;
}
}
foreach($this->whitelist as $entry) {
if (fnmatch($entry, $unit)) {
return true;
}
}
return false;
}
public function getDuplicates() {
return $this->duplicates;
}
}
class CollectorResultException extends \Exception {
const DuplicateUnitName = 1;
}
}

View file

@ -0,0 +1,178 @@
<?php
namespace TheSeer\Autoload {
class ComposerIterator implements \Iterator {
/**
* @var array
*/
private $directories = array();
private $seen = array();
private $pos = 0;
public function __construct(\SplFileInfo $composerFile) {
if (!$composerFile->isFile() || !$composerFile->isReadable()) {
throw new ComposerIteratorException(
sprintf('Composer file "%s" not found or not readable', $composerFile->getPathname()),
ComposerIteratorException::InvalidComposerJsonFile
);
}
$composerDir = dirname($composerFile->getRealPath());
$composerData = json_decode(file_get_contents($composerFile->getRealPath()), true);
if (isset($composerData['require'])) {
foreach($composerData['require'] as $require => $version) {
if ($require === 'php' || strpos($require, 'ext-') === 0) {
continue;
}
$this->processRequire($composerDir, $require);
}
}
if (isset($composerData['autoload'])) {
$this->processAutoload($composerDir, $composerData['autoload']);
}
}
private function processAutoload($baseDir, array $map) {
if (isset($map['classmap'])) {
foreach($map['classmap'] as $dir) {
$this->addDirectory($baseDir . '/' . $dir);
}
}
foreach(array('psr-0', 'psr-4') as $psr) {
if (isset($map[$psr])) {
foreach ($map[$psr] as $node => $dir) {
if ($dir === '') {
$this->addDirectory($baseDir);
continue;
}
if (is_array($dir)) {
foreach($dir as $d) {
$this->addDirectory($baseDir . '/' . $d);
}
continue;
}
$this->addDirectory($baseDir . '/' . $dir);
}
}
}
}
private function processRequire($basedir, $require) {
if (isset($this->seen[$require])) {
return;
}
$this->seen[$require] = true;
$requireDir = $basedir . '/vendor/' . $require;
$jsonFile = $this->findComposerJson($requireDir);
if ($jsonFile === null) {
return;
}
$jsonData = json_decode(file_get_contents($jsonFile), true);
if (isset($jsonData['require'])) {
foreach($jsonData['require'] as $entry => $version) {
if ($entry === 'php' || strpos($entry, 'ext-') === 0 || strpos($entry, 'lib-') === 0) {
continue;
}
$this->processRequire($basedir, $entry);
}
}
if (isset($jsonData['autoload'])) {
$this->processAutoload($requireDir, $jsonData['autoload']);
return;
}
$this->addDirectory($requireDir);
}
private function findComposerJson($dir) {
if (file_exists($dir . '/composer.json')) {
return $dir . '/composer.json';
}
foreach(glob($dir . '/*', GLOB_ONLYDIR) as $subDir) {
$result = $this->findComposerJson($subDir);
if ($result !== NULL) {
return $result;
}
}
}
private function addDirectory($dir) {
$dir = rtrim($dir, '/');
if (!in_array($dir, $this->directories)) {
$this->directories[] = $dir;
}
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the current element
*
* @link http://php.net/manual/en/iterator.current.php
* @return mixed Can return any type.
*/
#[\ReturnTypeWillChange]
public function current() {
return $this->directories[$this->pos];
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Move forward to next element
*
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
*/
#[\ReturnTypeWillChange]
public function next() {
$this->pos++;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the key of the current element
*
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
*/
#[\ReturnTypeWillChange]
public function key() {
return $this->pos;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Checks if current position is valid
*
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
#[\ReturnTypeWillChange]
public function valid() {
return $this->pos < count($this->directories);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Rewind the Iterator to the first element
*
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
*/
#[\ReturnTypeWillChange]
public function rewind() {
$this->pos = 0;
}
}
class ComposerIteratorException extends \Exception {
const InvalidComposerJsonFile = 1;
}
}

View file

@ -0,0 +1,435 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*
*/
namespace TheSeer\Autoload {
class Config {
private $quietMode = FALSE;
private $directories = array();
private $outputFile = 'STDOUT';
private $pharMode = FALSE;
private $include = array('*.php');
private $exclude = array();
private $whitelist = array('*');
private $blacklist = array();
private $baseDirectory = NULL;
private $template;
private $linebreak = "\n";
private $indent;
private $lint = FALSE;
private $php;
private $compatMode = FALSE;
private $staticMode = FALSE;
private $warmMode = FALSE;
private $tolerant = FALSE;
private $trusting = TRUE;
private $once = FALSE;
private $reset = FALSE;
private $lowercase = TRUE;
private $dateFormat;
private $variable = array();
private $pharCompression = 'NONE';
private $pharKey;
private $pharAll = false;
private $pharAliasName = '';
private $pharHashAlgorithm;
private $followSymlinks = false;
private $cacheFilename;
private $prepend = false;
private $exceptions = true;
public function __construct(Array $directories) {
$this->directories = $directories;
$this->php = (PHP_OS === 'WIN' ? 'C:\php\php.exe' : '/usr/bin/php');
}
public function setBaseDirectory($baseDirectory) {
$this->baseDirectory = $baseDirectory;
}
public function getBaseDirectory() {
if ($this->baseDirectory !== NULL) {
return realpath($this->baseDirectory);
}
if ($this->isPharMode()) {
$comparator = new PathComparator($this->directories);
return $comparator->getCommonBase();
}
if ($this->outputFile != 'STDOUT') {
return realpath(dirname($this->outputFile) ?: '.');
}
$tmp = $this->getDirectories();
return realpath(is_dir($tmp[0]) ? $tmp[0] : (dirname($tmp[0]) ?: '.'));
}
public function setCompatMode($compatMode) {
$this->compatMode = $compatMode;
}
public function isCompatMode() {
return $this->compatMode === true;
}
public function setDateFormat($dateFormat) {
$this->dateFormat = $dateFormat;
}
public function getDateFormat() {
return $this->dateFormat;
}
public function setExclude(Array $exclude) {
$this->exclude = $exclude;
}
public function getExclude() {
return $this->exclude;
}
public function setInclude(Array $include) {
$this->include = $include;
}
public function getInclude() {
return $this->include;
}
/**
* @return array
*/
public function getBlacklist() {
return $this->blacklist;
}
/**
* @param array $blacklist
*/
public function setBlacklist($blacklist) {
$this->blacklist = $blacklist;
}
/**
* @return array
*/
public function getWhitelist() {
return $this->whitelist;
}
/**
* @param array $whitelist
*/
public function setWhitelist($whitelist) {
$this->whitelist = $whitelist;
}
public function setIndent($indent) {
$this->indent = $indent;
}
public function getIndent() {
if ($this->indent !== NULL) {
if (is_numeric($this->indent) && (int)$this->indent == $this->indent) {
return str_repeat(' ', (int)$this->indent);
}
return $this->indent;
}
if ($this->isStaticMode() || $this->isWarmMode()) {
return '';
}
return str_repeat(' ', $this->isCompatMode() ? 12 : 16);
}
public function setLinebreak($linebreak) {
$lbr = array('LF' => "\n", 'CR' => "\r", 'CRLF' => "\r\n" );
if (isset($lbr[$linebreak])) {
$this->linebreak = $lbr[$linebreak];
} else {
$this->linebreak = $linebreak;
}
}
public function getLinebreak() {
return $this->linebreak;
}
public function setLintMode($lint) {
$this->lint = (boolean)$lint;
}
public function isLintMode() {
return $this->lint;
}
public function setLowercaseMode($lowercase) {
$this->lowercase = (boolean)$lowercase;
}
public function isLowercaseMode() {
return $this->lowercase;
}
public function setOnceMode($once) {
$this->once = (boolean)$once;
}
public function isOnceMode() {
return $this->once;
}
public function setOutputFile($outputFile) {
$this->outputFile = $outputFile;
}
public function getOutputFile() {
return $this->outputFile;
}
public function enablePharMode($compression = 'NONE', $all = true, $key = NULL, $alias = NULL) {
$this->pharMode = true;
$this->pharCompression = $compression;
$this->pharAll = (boolean)$all;
$this->pharKey = $key;
$this->pharAliasName = $alias;
}
public function isPharMode() {
return $this->pharMode;
}
public function isPharAllMode() {
return $this->pharAll;
}
public function getPharCompression() {
return $this->pharCompression;
}
public function getPharKey() {
return $this->pharKey;
}
public function getPharAliasName() {
return $this->pharAliasName;
}
public function hasPharHashAlgorithm() {
return $this->pharHashAlgorithm !== null;
}
/**
* @return string
*/
public function getPharHashAlgorithm() {
return $this->pharHashAlgorithm;
}
/**
* @param string $pharHashAlgorithm
*/
public function setPharHashAlgorithm($pharHashAlgorithm) {
if (!in_array($pharHashAlgorithm, array('SHA-512','SHA-256','SHA-1'))) {
throw new \InvalidArgumentException(
sprintf('Algorithm %s not supported', $pharHashAlgorithm)
);
}
$this->pharHashAlgorithm = $pharHashAlgorithm;
}
public function setPhp($php) {
$this->php = $php;
}
public function getPhp() {
return $this->php;
}
public function setQuietMode($quietMode) {
$this->quietMode = (boolean)$quietMode;
}
public function setStaticMode($staticMode) {
$this->staticMode = (boolean)$staticMode;
$this->warmMode = FALSE;
}
public function isStaticMode() {
return $this->staticMode;
}
public function setWarmMode($warmMode) {
$this->warmMode = (boolean)$warmMode;
$this->staticMode = FALSE;
}
public function isWarmMode() {
return $this->warmMode;
}
public function setResetMode($resetMode) {
$this->reset = (boolean)$resetMode;
}
public function isResetMode() {
return $this->reset;
}
public function setTemplate($template) {
$this->template = $template;
}
public function getTemplate() {
$tplType = $this->isLowercaseMode() ? 'ci' : 'cs';
$template = $this->template;
if ($template !== NULL) {
if (!file_exists($template)) {
$alternative = __DIR__.'/templates/'. $tplType .'/'.$template;
if (file_exists($alternative)) {
$template = $alternative;
}
$alternative .= '.php.tpl';
if (file_exists($alternative)) {
$template = $alternative;
}
}
return $template;
}
// determine auto template to use
$tplFile = 'default.php.tpl';
if ($this->isCompatMode()) {
$tplFile = 'php52.php.tpl';
}
if ($this->isPharMode()) {
if ($this->isStaticMode()) {
$tplFile = 'staticphar.php.tpl';
$tplType = '.';
} else {
$tplFile = 'phar.php.tpl';
}
} elseif ($this->isStaticMode() || $this->isWarmMode()) {
$tplFile = 'static.php.tpl';
$tplType = '.';
}
return __DIR__.'/templates/'.$tplType.'/'.$tplFile;
}
public function setTolerantMode($tolerant) {
$this->tolerant = (boolean)$tolerant;
}
public function isTolerantMode() {
return $this->tolerant;
}
public function setTrusting($trusting) {
$this->trusting = (boolean)$trusting;
}
public function setFollowSymlinks($followSymlinks) {
$this->followSymlinks = (boolean)$followSymlinks;
}
public function isFollowSymlinks() {
return $this->followSymlinks;
}
public function isTrustingMode() {
return $this->trusting;
}
public function setVariable($name, $value) {
$this->variable[$name] = $value;
}
public function getVariables() {
return $this->variable;
}
public function isQuietMode() {
return $this->quietMode;
}
public function getDirectories() {
$list = array();
foreach($this->directories as $dir) {
if (is_file($dir) && basename($dir) == 'composer.json') {
foreach(new ComposerIterator(new \SplFileInfo($dir)) as $d) {
$list[] = $d;
}
} else {
foreach(glob($dir) as $match) {
$list[] = $match;
}
}
}
return $list;
}
public function setCacheFile($filename) {
$this->cacheFilename = $filename;
}
public function isCacheEnabled() {
return $this->cacheFilename !== NULL;
}
public function getCacheFile() {
return $this->cacheFilename;
}
public function enablePrepend() {
$this->prepend = true;
}
public function usePrepend() {
return $this->prepend;
}
public function disableExceptions() {
$this->exceptions = false;
}
public function useExceptions() {
return $this->exceptions;
}
}
}

View file

@ -0,0 +1,100 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*/
namespace TheSeer\Autoload {
/**
* Sorting classes by depdendency for static requires
*
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
*/
class ClassDependencySorter {
private $classList;
private $dependencies;
private $level;
private $sorted = array();
public function __construct(Array $classes, Array $dependencies) {
$this->classList = $classes;
$this->dependencies = $dependencies;
}
public function process() {
$this->level = 0;
foreach($this->classList as $class => $file) {
if (!in_array($class, $this->sorted)) {
$this->resolve($class);
}
}
$res = array();
foreach($this->sorted as $class) {
if (!isset($this->classList[$class])) {
continue;
}
$res[$class] = $this->classList[$class];
}
return $res;
}
private function resolve($class) {
$this->level++;
if ($this->level == 50) {
throw new ClassDependencySorterException("Can't resolve more than 50 levels of dependencies", ClassDependencySorterException::TooManyDependencyLevels);
}
if (isset($this->dependencies[$class])) {
foreach($this->dependencies[$class] as $depclass) {
if (!in_array($depclass, $this->sorted)) {
$this->resolve($depclass);
}
}
}
$this->sorted[] = $class;
$this->level--;
}
}
class ClassDependencySorterException extends \Exception {
const TooManyDependencyLevels = 1;
}
}

View file

@ -0,0 +1,242 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*
*/
namespace TheSeer\Autoload {
use TheSeer\DirectoryScanner\DirectoryScanner;
use TheSeer\DirectoryScanner\IncludeExcludeFilterIterator;
class Factory {
/**
* @var Config
*/
private $config;
/**
* @var Cache
*/
private $cache;
/**
* @param \TheSeer\Autoload\Config $config
*/
public function setConfig(Config $config) {
$this->config = $config;
}
/**
* @return CLI
*/
public function getCLI() {
return new CLI($this);
}
/**
* @return Application
*/
public function getApplication() {
return new Application($this->getLogger(), $this->config, $this);
}
public function getLogger() {
return new Logger($this->config->isQuietMode());
}
/**
* @return Parser
*/
public function getParser() {
$parser = new Parser(
$this->config->isLowercaseMode()
);
if (!$this->config->isCacheEnabled()) {
return $parser;
}
return new CachingParser(
$this->getCache(),
$parser
);
}
/**
* @return Cache
*/
public function getCache() {
if (!$this->cache instanceof Cache) {
$fname = $this->config->getCacheFile();
if (file_exists($fname)) {
$data = unserialize(file_get_contents($fname));
} else {
$data = array();
}
$this->cache = new Cache($data);
}
return $this->cache;
}
public function getCollector() {
return new Collector(
$this->getParser(),
$this->config->isTolerantMode(),
$this->config->isTrustingMode(),
$this->config->getWhitelist(),
$this->config->getBlacklist()
);
}
/**
* Get instance of DirectoryScanner with filter options applied
*
* @param bool $filter
* @return DirectoryScanner
*/
public function getScanner($filter = TRUE) {
$scanner = new DirectoryScanner;
if ($filter) {
$scanner->setIncludes($this->config->getInclude());
$scanner->setExcludes($this->config->getExclude());
}
if ($this->config->isFollowSymlinks()) {
$scanner->setFlag(\FilesystemIterator::FOLLOW_SYMLINKS);
}
return $scanner;
}
public function getFilter(\Iterator $files) {
$filter = new IncludeExcludeFilterIterator($files);
$filter->setInclude($this->config->getInclude());
$filter->setExclude($this->config->getExclude());
return $filter;
}
public function getPharBuilder() {
$builder = new PharBuilder(
$this->getScanner(!$this->config->isPharAllMode()),
$this->config->getBaseDirectory()
);
$builder->setCompressionMode($this->config->getPharCompression());
foreach($this->config->getDirectories() as $directory) {
$builder->addDirectory($directory);
}
return $builder;
}
/**
* Helper to get instance of AutoloadRenderer with cli options applied
*
* @param CollectorResult $result
*
* @throws \RuntimeException
* @return \TheSeer\Autoload\AutoloadRenderer|\TheSeer\Autoload\StaticRenderer
*/
public function getRenderer(CollectorResult $result) {
$isStatic = $this->config->isStaticMode();
$isPhar = $this->config->isPharMode();
$isCompat = $this->config->isCompatMode();
$isOnce = $this->config->isOnceMode();
$isWarm = $this->config->isWarmMode();
$isReset = $this->config->isResetMode();
if ($isWarm === TRUE) {
$renderer = new StaticRenderer(
$result->getUnits(),
$this->getCacheWarmingListRenderer($isReset)
);
$renderer->setDependencies($result->getDependencies());
$renderer->setPharMode($isPhar);
} else if ($isStatic === TRUE) {
$renderer = new StaticRenderer(
$result->getUnits(),
$this->getStaticRequireListRenderer($isOnce)
);
$renderer->setDependencies($result->getDependencies());
$renderer->setPharMode($isPhar);
} else {
$renderer = new AutoloadRenderer($result->getUnits());
if ($this->config->usePrepend()) {
$renderer->prependAutoloader();
}
if ($this->config->useExceptions()) {
$renderer->enableExceptions();
}
}
$renderer->setCompat($isCompat);
$basedir = $this->config->getBaseDirectory();
if (!$basedir || !is_dir($basedir)) {
throw new \RuntimeException("Given basedir '{$basedir}' does not exist or is not a directory");
}
$renderer->setBaseDir($basedir);
$format = $this->config->getDateFormat();
if ($format) {
$renderer->setDateTimeFormat($format);
}
$renderer->setIndent($this->config->getIndent());
$renderer->setLineBreak($this->config->getLinebreak());
foreach($this->config->getVariables() as $name => $value) {
$renderer->setVariable($name, $value);
}
return $renderer;
}
private function getStaticRequireListRenderer($useOnce) {
return new StaticRequireListRenderer(
$useOnce,
$this->config->getIndent(),
$this->config->getLinebreak()
);
}
private function getCacheWarmingListRenderer($addReset) {
return new CacheWarmingListRenderer(
$addReset,
$this->config->getIndent(),
$this->config->getLinebreak()
);
}
}
}

View file

@ -0,0 +1,59 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*
*/
namespace TheSeer\Autoload {
class Logger {
private $quiet = FALSE;
/**
* @param bool $quietMode
*/
public function __construct($quietMode = FALSE) {
$this->quiet = $quietMode;
}
public function log($message, $target = STDOUT) {
if ($this->quiet) {
return;
}
fwrite($target, $message);
}
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace TheSeer\Autoload {
class ParseResult {
/**
* @var string[]
*/
private $units = array();
/**
* @var array
*/
private $dependencies = array();
/**
* @var string[]
*/
private $redeclarations = array();
public function __construct(Array $units, Array $dependencies, Array $redeclarations) {
$this->units = $units;
$this->dependencies = $dependencies;
$this->redeclarations = $redeclarations;
}
public function hasUnits() {
return count($this->units) > 0;
}
public function hasRedeclarations() {
return count($this->redeclarations) > 0;
}
/**
*
* @param string $unit
*
* @return array
*/
public function getDependenciesForUnit($unit) {
if (!isset($this->dependencies[$unit])) {
return array();
}
return $this->dependencies[$unit];
}
/**
* @return \string[]
*/
public function getRedeclarations() {
return $this->redeclarations;
}
/**
* @return \string[]
*/
public function getUnits() {
return $this->units;
}
}
}

View file

@ -0,0 +1,598 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*/
namespace TheSeer\Autoload {
// PHP 5.3 compat
define('T_TRAIT_53', 10355);
if (!defined('T_TRAIT')) {
define('T_TRAIT', -1);
}
// PHP 8.0 forward compat
if (!defined('T_NAME_FULLY_QUALIFIED')) {
define('T_NAME_FULLY_QUALIFIED', -1);
define('T_NAME_QUALIFIED', -1);
}
// PHP 8.1 forward compat
if (!defined('T_ENUM')) {
define('T_ENUM', -1);
}
/**
* Namespace aware parser to find and extract defined classes within php source files
*
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
*/
class Parser implements ParserInterface {
private $methodMap = array(
T_TRAIT => 'processClass',
T_TRAIT_53 => 'processClass',
T_CLASS => 'processClass',
T_ENUM => 'processEnum',
//T_CASE => 'processEnumCase',
T_INTERFACE => 'processInterface',
T_NAMESPACE => 'processNamespace',
T_USE => 'processUse',
'}' => 'processBracketClose',
'{' => 'processBracketOpen',
T_CURLY_OPEN => 'processBracketOpen',
T_DOLLAR_OPEN_CURLY_BRACES => 'processBracketOpen'
);
private $typeMap = array(
T_INTERFACE => 'interface',
T_CLASS => 'class',
T_ENUM => 'enum',
T_TRAIT => 'trait',
T_TRAIT_53 => 'trait'
);
private $caseInsensitive;
private $tokenArray = array();
private $inNamespace = '';
private $inUnit = '';
private $nsBracket = 0;
private $classBracket = 0;
private $bracketLevel = 0;
private $aliases = array();
private $found = array();
private $dependencies = array();
private $redeclarations = array();
public function __construct($caseInsensitive = true) {
$this->caseInsensitive = $caseInsensitive;
}
/**
* Parse a given file for defintions of classes, traits and interfaces
*
* @param SourceFile $source file to process
*
* @return ParseResult
*/
public function parse(SourceFile $source) {
$this->found = array();
$this->redeclarations = array();
$this->inNamespace = '';
$this->aliases = array();
$this->bracketLevel = 0;
$this->inUnit = '';
$this->nsBracket = 0;
$this->classBracket = 0;
$this->tokenArray = $source->getTokens();
$tokenCount = count($this->tokenArray);
$tokList = array_keys($this->methodMap);
for($t=0; $t<$tokenCount; $t++) {
$current = (array)$this->tokenArray[$t];
if ($current[0]===T_STRING && $current[1]==='trait' && T_TRAIT===-1) {
// PHP < 5.4 compat fix
$current[0] = T_TRAIT_53;
$this->tokenArray[$t] = $current;
}
if (!in_array($current[0], $tokList)) {
continue;
}
$t = call_user_func(array($this, $this->methodMap[$current[0]]), $t);
}
return new ParseResult($this->found, $this->dependencies, $this->redeclarations);
}
private function processBracketOpen($pos) {
$this->bracketLevel++;
return $pos + 1;
}
private function processBracketClose($pos) {
$this->bracketLevel--;
if ($this->nsBracket !== 0 && $this->bracketLevel < $this->nsBracket) {
$this->inNamespace = '';
$this->nsBracket = 0;
$this->aliases = array();
}
if ($this->bracketLevel <= $this->classBracket) {
$this->classBracket = 0;
$this->inUnit = '';
}
return $pos + 1;
}
private function processClass($pos) {
if (!$this->classTokenNeedsProcessing($pos)) {
return $pos;
}
$list = array('{');
$stack = $this->getTokensTill($pos, $list);
$stackSize = count($stack);
$classname = $this->inNamespace !== '' ? $this->inNamespace . '\\' : '';
$extends = '';
$extendsFound = false;
$implementsFound = false;
$implementsList = array();
$implements = '';
$mode = 'classname';
foreach(array_slice($stack, 1, -1) as $tok) {
switch ($tok[0]) {
case T_COMMENT:
case T_DOC_COMMENT:
case T_WHITESPACE: {
break;
}
case T_NAME_FULLY_QUALIFIED:
case T_NAME_QUALIFIED:
case T_STRING: {
$$mode .= $tok[1];
break;
}
case T_NS_SEPARATOR: {
$$mode .= '\\';
break;
}
case T_EXTENDS: {
$extendsFound = true;
$mode = 'extends';
break;
}
case T_IMPLEMENTS: {
$implementsFound = true;
$mode = 'implements';
break;
}
case ',': {
if ($mode === 'implements') {
$implementsList[] = $this->resolveDependencyName($implements);
$implements = '';
}
break;
}
default: {
throw new ParserException(sprintf(
'Parse error while trying to process class definition (unexpected token "%s" in name).',
\token_name($tok[0])
), ParserException::ParseError
);
}
}
}
if ($implements != '') {
$implementsList[] = $this->resolveDependencyName($implements);
}
if ($implementsFound && count($implementsList)==0) {
throw new ParserException(sprintf(
'Parse error while trying to process class definition (extends or implements).'
), ParserException::ParseError
);
}
$classname = $this->registerUnit($classname, $stack[0][0]);
$this->dependencies[$classname] = $implementsList;
if ($extendsFound) {
$this->dependencies[$classname][] = $this->resolveDependencyName($extends);
}
$this->inUnit = $classname;
$this->classBracket = $this->bracketLevel + 1;
return $pos + $stackSize - 1;
}
private function processEnum($pos) {
$list = array('{');
$stack = $this->getTokensTill($pos, $list);
$stackSize = count($stack);
$enumName = $this->inNamespace !== '' ? $this->inNamespace . '\\' : '';
$implementsFound = false;
$implementsList = array();
$implements = '';
$backType = '';
$mode = 'enumName';
foreach(array_slice($stack, 1, -1) as $tok) {
switch ($tok[0]) {
case T_COMMENT:
case T_DOC_COMMENT:
case T_WHITESPACE: {
break;
}
case T_NAME_FULLY_QUALIFIED:
case T_NAME_QUALIFIED:
case T_STRING: {
$$mode .= $tok[1];
break;
}
case T_NS_SEPARATOR: {
$$mode .= '\\';
break;
}
case T_IMPLEMENTS: {
$implementsFound = true;
$mode = 'implements';
break;
}
case ':': {
$isBacked = true;
$mode = 'backType';
break;
}
case ',': {
if ($mode === 'implements') {
$implementsList[] = $this->resolveDependencyName($implements);
$implements = '';
}
break;
}
default: {
throw new ParserException(sprintf(
'Parse error while trying to process class definition (unexpected token "%s" in name).',
is_int($tok[0]) ? \token_name($tok[0]) : $tok[0]
), ParserException::ParseError
);
}
}
}
if ($implements != '') {
$implementsList[] = $this->resolveDependencyName($implements);
}
if ($implementsFound && count($implementsList)==0) {
throw new ParserException(sprintf(
'Parse error while trying to process enum definition (implements).'
), ParserException::ParseError
);
}
$enumName = $this->registerUnit($enumName, $stack[0][0]);
$this->dependencies[$enumName] = $implementsList;
return $pos + $stackSize - 1;
}
private function processInterface($pos) {
$list = array('{');
$stack = $this->getTokensTill($pos, $list);
$stackSize = count($stack);
$next = $stack[1];
if (is_array($next) && $next[0] === '(') {
// sort of inline use - ignore
return $pos + $stackSize;
}
$name = $this->inNamespace != '' ? $this->inNamespace . '\\' : '';
$extends = '';
$extendsList = array();
$mode = 'name';
foreach(array_slice($stack, 1, -1) as $tok) {
switch ($tok[0]) {
case T_NS_SEPARATOR:
case T_NAME_QUALIFIED:
case T_NAME_FULLY_QUALIFIED:
case T_STRING: {
$$mode .= $tok[1];
break;
}
case T_EXTENDS: {
$mode = 'extends';
break;
}
case ',': {
if ($mode == 'extends') {
$extendsList[] = $this->resolveDependencyName($extends);
$extends = '';
}
}
}
}
$name = $this->registerUnit($name, T_INTERFACE);
if ($extends != '') {
$extendsList[] = $this->resolveDependencyName($extends);
}
$this->dependencies[$name] = $extendsList;
$this->inUnit = $name;
return $pos + $stackSize - 1;
}
private function resolveDependencyName($name) {
if ($name == '') {
throw new ParserException(sprintf(
'Parse error while trying to process class definition (extends or implements).'
), ParserException::ParseError
);
}
if ($name[0] == '\\') {
$name = substr($name, 1);
} else {
$parts = explode('\\', $name, 2);
$search = $this->caseInsensitive ? strtolower($parts[0]) : $parts[0];
$key = array_search($search, $this->aliases);
if (!$key) {
$name = ($this->inNamespace != '' ? $this->inNamespace . '\\' : ''). $name;
} else {
$name = $key;
if (isset($parts[1])) {
$name .= '\\' . $parts[1];
}
}
}
if ($this->caseInsensitive) {
$name = strtolower($name);
}
return $name;
}
private function registerUnit($name, $type) {
if ($name == '' || substr($name, -1) == '\\') {
throw new ParserException(sprintf(
'Parse error while trying to process %s definition.',
$this->typeMap[$type]
), ParserException::ParseError
);
}
if ($this->caseInsensitive) {
$name = strtolower($name);
}
if (in_array($name, $this->found)) {
$this->redeclarations[] = $name;
} else {
$this->found[] = $name;
}
return $name;
}
private function processNamespace($pos) {
$list = array(';', '{');
$stack = $this->getTokensTill($pos, $list);
$stackSize = count($stack);
$newpos = $pos + $stackSize;
if ($stackSize < 3) { // empty namespace defintion == root namespace
$this->inNamespace = '';
$this->aliases = array();
return $newpos - 1;
}
$next = $stack[1];
if (is_array($next) && ($next[0] === T_NS_SEPARATOR || $next[0] === '(')) {
// sort of inline use - ignore
return $newpos;
}
$this->inNamespace = '';
foreach(array_slice($stack, 1, -1) as $tok) {
$this->inNamespace .= $tok[1];
}
$this->aliases = array();
return $pos + $stackSize - 1;
}
private function processUse($pos) {
$list = array(';','(');
$stack = $this->getTokensTill($pos, $list);
$stackSize = count($stack);
$ignore = array(
'(', // closue use
T_CONST, // use const foo\bar;
T_FUNCTION // use function foo\bar;
);
if (in_array($stack[1][0], $ignore)) {
return $pos + $stackSize - 1;
}
if ($this->classBracket > 0) {
$this->parseUseOfTrait($stackSize, $stack);
} else {
$this->parseUseAsImport($stack);
}
return $pos + $stackSize - 1;
}
private function getTokensTill($start, $list) {
$list = (array)$list;
$stack = array();
$skip = array(
T_WHITESPACE,
T_COMMENT,
T_DOC_COMMENT
);
$limit = count($this->tokenArray);
for ($t=$start; $t<$limit; $t++) {
$current = (array)$this->tokenArray[$t];
if (in_array($current[0], $skip)) {
continue;
}
$stack[] = $current;
if (in_array($current[0], $list)) {
break;
}
}
return $stack;
}
/**
* @param $stackSize
* @param $stack
*/
private function parseUseOfTrait($stackSize, $stack) {
$use = '';
for ($t = 0; $t < $stackSize; $t++) {
$current = (array)$stack[$t];
switch ($current[0]) {
case '{': {
// find closing bracket to skip contents
for ($x = $t + 1; $x < $stackSize; $x++) {
$tok = $stack[$x];
if ($tok[0] == '}') {
$t = $x;
break;
}
}
break;
}
case ';':
case ',': {
$this->dependencies[$this->inUnit][] = $this->resolveDependencyName($use);
$use = '';
break;
}
case T_NS_SEPARATOR:
case T_NAME_QUALIFIED:
case T_NAME_FULLY_QUALIFIED:
case T_STRING: {
$use .= $current[1];
break;
}
}
}
}
/**
* @param $stack
*/
private function parseUseAsImport($stack) {
$use = '';
$alias = '';
$mode = 'use';
$group = '';
$ignore = false;
foreach ($stack as $tok) {
$current = $tok;
switch ($current[0]) {
case T_CONST:
case T_FUNCTION: {
$ignore = true;
break;
}
case '{': {
$group = $use;
break;
}
case ';':
case ',': {
if (!$ignore) {
if ($alias == '') {
$nss = strrpos($use, '\\');
if ($nss !== FALSE) {
$alias = substr($use, $nss + 1);
} else {
$alias = $use;
}
}
if ($this->caseInsensitive) {
$alias = strtolower($alias);
}
$this->aliases[$use] = $alias;
}
$alias = '';
$use = $group;
$mode = 'use';
$ignore = false;
break;
}
case T_NS_SEPARATOR:
case T_NAME_QUALIFIED:
case T_NAME_FULLY_QUALIFIED:
case T_STRING: {
$$mode .= $current[1];
break;
}
case T_AS: {
$mode = 'alias';
break;
}
}
}
}
private function classTokenNeedsProcessing($position) {
// PHP 5.5 has classname::class, reusing T_CLASS
if ($this->tokenArray[$position-1][0] == T_DOUBLE_COLON) {
return false;
}
// PHP 7 has anonymous classes: $x = new class { ... }
if ($position > 2 && $this->tokenArray[$position-2][0] === T_NEW) {
return false;
}
if ($this->tokenArray[$position + 1] === '(' || $this->tokenArray[$position + 2] === '(') {
return false;
}
return true;
}
}
class ParserException extends \Exception {
const ParseError = 1;
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace TheSeer\Autoload;
/**
* Namespace aware parser to find and extract defined classes within php source files
*
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
*/
interface ParserInterface {
/**
* Parse a given file for defintions of classes, traits and interfaces
*
* @param SourceFile $source file to process
*
* @return ParseResult
*/
public function parse(SourceFile $source);
}

View file

@ -0,0 +1,45 @@
<?php
namespace TheSeer\Autoload {
class PathComparator {
/**
* @var string[]
*/
private $directories = array();
/**
* PathComparator constructor.
*
* @param array $directories
*/
public function __construct(array $directories) {
foreach($directories as $dir) {
$this->directories[] = realpath($dir).'/';
}
}
public function getCommonBase() {
if (count($this->directories) == 0) {
return '/';
}
$result = $this->directories[0];
foreach($this->directories as $dir) {
$result = substr($dir, 0, $this->commonPrefix($result, $dir));
}
return ($result ?: '/');
}
private function commonPrefix( $s1, $s2 ) {
$l1 = strlen($s1);
$l2 = strlen($s2);
$i=0;
while($i < $l1 && $i < $l2 && $s1[$i] == $s2[$i]) {
$i++;
}
return strrpos(substr($s1, 0, $i), '/');
}
}
}

View file

@ -0,0 +1,135 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*
*/
namespace TheSeer\Autoload {
use TheSeer\DirectoryScanner\DirectoryScanner;
class PharBuilder {
private $scanner;
private $compression;
private $key;
private $basedir;
private $aliasName;
private $signatureType;
private $directories = array();
private $supportedSignatureTypes = array(
'SHA-512' => \Phar::SHA512,
'SHA-256' => \Phar::SHA256,
'SHA-1' => \Phar::SHA1
);
public function __construct(DirectoryScanner $scanner, $basedir) {
$this->scanner = $scanner;
$this->basedir = $basedir;
}
public function setCompressionMode($mode) {
$this->compression = $mode;
}
public function setSignatureType($type) {
if (!in_array($type, array_keys($this->supportedSignatureTypes))) {
throw new \InvalidArgumentException(
sprintf('Signature type "%s" not known or not supported by this PHP installation.', $type)
);
}
$this->signatureType = $type;
}
public function setSignatureKey($key) {
$this->key = $key;
}
public function addDirectory($directory) {
$this->directories[] = $directory;
}
public function setAliasName($name) {
$this->aliasName = $name;
}
public function build($filename, $stub) {
if (file_exists($filename)) {
unlink($filename);
}
$phar = new \Phar($filename, 0, $this->aliasName != '' ? $this->aliasName : basename($filename));
$phar->startBuffering();
$phar->setStub($stub);
if ($this->key !== NULL) {
$privateKey = '';
openssl_pkey_export($this->key, $privateKey);
$phar->setSignatureAlgorithm(\Phar::OPENSSL, $privateKey);
$keyDetails = openssl_pkey_get_details($this->key);
file_put_contents($filename . '.pubkey', $keyDetails['key']);
} else {
$phar->setSignatureAlgorithm($this->selectSignatureType());
}
$basedir = $this->basedir ? $this->basedir : $this->directories[0];
foreach($this->directories as $directory) {
$phar->buildFromIterator($this->scanner->__invoke($directory), $basedir);
}
if ($this->compression !== \Phar::NONE) {
$phar->compressFiles($this->compression);
}
$phar->stopBuffering();
}
private function selectSignatureType() {
if ($this->signatureType !== NULL) {
return $this->supportedSignatureTypes[$this->signatureType];
}
$supported = \Phar::getSupportedSignatures();
foreach($this->supportedSignatureTypes as $candidate => $type) {
if (in_array($candidate, $supported)) {
return $type;
}
}
// Is there any PHP Version out there that does not support at least SHA-1?
// But hey, fallback to md5, better than nothing
return \Phar::MD5;
}
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace TheSeer\Autoload {
class SourceFile extends \SplFileInfo {
public function getTokens() {
return token_get_all(file_get_contents($this->getRealPath()));
}
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace TheSeer\Autoload;
interface StaticListRenderer {
/**
* @return string
*/
public function render(array $list);
}

View file

@ -0,0 +1,133 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*/
namespace TheSeer\Autoload {
/**
* Builds static require list for inclusion into projects
*
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
*/
class StaticRenderer extends AutoloadRenderer {
private $dependencies;
private $phar;
private $require = 'require';
/**
* @var StaticListRenderer
*/
private $renderHelper;
public function __construct(array $classlist, StaticListRenderer $renderHelper) {
parent::__construct($classlist);
$this->renderHelper = $renderHelper;
}
/**
* Setter for Dependency Array
* @param array $dep Dependency Array from classfinder
*/
public function setDependencies(Array $dep) {
$this->dependencies = $dep;
}
/**
* Toggle phar outut mode
*
* @param boolean $phar
*/
public function setPharMode($phar) {
$this->phar = (boolean)$phar;
}
/**
* Toggle wether or not to use require_once over require
*
* @param boolean $mode
*/
public function setRequireOnce($mode) {
}
/**
* @param string $template
*
* @return string
*/
public function render($template) {
$baseDir = '';
if ($this->phar) {
$baseDir = "'phar://". $this->variables['___PHAR___']."' . ";
} else if ($this->baseDir) {
$baseDir = $this->compat ? 'dirname(__FILE__) . ' : '__DIR__ . ';
}
$entries = array();
foreach($this->sortByDependency() as $fname) {
$entries[] = $this->resolvePath($fname);
}
$replace = array_merge(
$this->variables,
array(
'___CREATED___' => date( $this->dateformat, $this->timestamp ? $this->timestamp : time()),
'___FILELIST___' => $this->renderHelper->render($entries),
'___BASEDIR___' => $baseDir,
'___AUTOLOAD___' => uniqid('autoload', true)
)
);
return str_replace(array_keys($replace), array_values($replace), $template);
}
/**
* Helper to sort classes/interfaces and traits based on their depdendency info
*
* @return array
*/
protected function sortByDependency() {
$sorter = new ClassDependencySorter($this->classes, $this->dependencies);
$list = $sorter->process();
return array_unique($list);
}
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace TheSeer\Autoload;
class StaticRequireListRenderer implements StaticListRenderer {
/** @var boolean */
private $useOnce;
/** @var string */
private $indent;
/** @var string */
private $linebreak;
/**
* @param $useOnce
*/
public function __construct($useOnce, $indent, $linebreak) {
$this->useOnce = $useOnce;
$this->indent = $indent;
$this->linebreak = $linebreak;
}
/**
* @return string
*/
public function render(array $list) {
$require = (boolean)$this->useOnce ? 'require_once' : 'require';
$require .= ' ___BASEDIR___\'';
$glue = '\';' . $this->linebreak . $this->indent . $require;
return $this->indent . $require . implode($glue, $list) . '\';';
}
}

View file

@ -0,0 +1 @@
1.27.1

View file

@ -0,0 +1,66 @@
<?php
/**
* Copyright (c) 2009-2019 Arne Blankerts <arne@blankerts.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Arne Blankerts nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Autoload
* @author Arne Blankerts <arne@blankerts.de>
* @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.
* @license BSD License
*
*/
namespace TheSeer\Autoload {
class Version {
private static $version = NULL;
public static function getVersion() {
if (self::$version === NULL) {
self::$version = PHPAB_VERSION;
if (PHPAB_VERSION == '%development%') {
$cwd = getcwd();
chdir(__DIR__);
$git = exec('command -p git describe --always --dirty 2>/dev/null', $foo, $rc);
chdir($cwd);
if ($rc === 0) {
self::$version = $git;
}
}
}
return self::$version;
}
public static function getInfoString() {
return 'phpab ' . self::getVersion() . ' - Copyright (C) 2009 - ' . date('Y') . ' by Arne Blankerts and Contributors';
}
}
}

View file

@ -0,0 +1,153 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
spl_autoload_register(
function($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
'ezcbase' => '/../vendor/zetacomponents/base/src/base.php',
'ezcbaseautoloadexception' => '/../vendor/zetacomponents/base/src/exceptions/autoload.php',
'ezcbaseautoloadoptions' => '/../vendor/zetacomponents/base/src/options/autoload.php',
'ezcbaseconfigurationinitializer' => '/../vendor/zetacomponents/base/src/interfaces/configuration_initializer.php',
'ezcbasedoubleclassrepositoryprefixexception' => '/../vendor/zetacomponents/base/src/exceptions/double_class_repository_prefix.php',
'ezcbaseexception' => '/../vendor/zetacomponents/base/src/exceptions/exception.php',
'ezcbaseexportable' => '/../vendor/zetacomponents/base/src/interfaces/exportable.php',
'ezcbaseextensionnotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/extension_not_found.php',
'ezcbasefeatures' => '/../vendor/zetacomponents/base/src/features.php',
'ezcbasefile' => '/../vendor/zetacomponents/base/src/file.php',
'ezcbasefileexception' => '/../vendor/zetacomponents/base/src/exceptions/file_exception.php',
'ezcbasefilefindcontext' => '/../vendor/zetacomponents/base/src/structs/file_find_context.php',
'ezcbasefileioexception' => '/../vendor/zetacomponents/base/src/exceptions/file_io.php',
'ezcbasefilenotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/file_not_found.php',
'ezcbasefilepermissionexception' => '/../vendor/zetacomponents/base/src/exceptions/file_permission.php',
'ezcbasefunctionalitynotsupportedexception' => '/../vendor/zetacomponents/base/src/exceptions/functionality_not_supported.php',
'ezcbaseinit' => '/../vendor/zetacomponents/base/src/init.php',
'ezcbaseinitcallbackconfiguredexception' => '/../vendor/zetacomponents/base/src/exceptions/init_callback_configured.php',
'ezcbaseinitinvalidcallbackclassexception' => '/../vendor/zetacomponents/base/src/exceptions/invalid_callback_class.php',
'ezcbaseinvalidparentclassexception' => '/../vendor/zetacomponents/base/src/exceptions/invalid_parent_class.php',
'ezcbasemetadata' => '/../vendor/zetacomponents/base/src/metadata.php',
'ezcbasemetadatapearreader' => '/../vendor/zetacomponents/base/src/metadata/pear.php',
'ezcbasemetadatatarballreader' => '/../vendor/zetacomponents/base/src/metadata/tarball.php',
'ezcbaseoptions' => '/../vendor/zetacomponents/base/src/options.php',
'ezcbasepersistable' => '/../vendor/zetacomponents/base/src/interfaces/persistable.php',
'ezcbasepropertynotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/property_not_found.php',
'ezcbasepropertypermissionexception' => '/../vendor/zetacomponents/base/src/exceptions/property_permission.php',
'ezcbaserepositorydirectory' => '/../vendor/zetacomponents/base/src/structs/repository_directory.php',
'ezcbasesettingnotfoundexception' => '/../vendor/zetacomponents/base/src/exceptions/setting_not_found.php',
'ezcbasesettingvalueexception' => '/../vendor/zetacomponents/base/src/exceptions/setting_value.php',
'ezcbasestruct' => '/../vendor/zetacomponents/base/src/struct.php',
'ezcbasevalueexception' => '/../vendor/zetacomponents/base/src/exceptions/value.php',
'ezcbasewhateverexception' => '/../vendor/zetacomponents/base/src/exceptions/whatever.php',
'ezcconsoleargument' => '/../vendor/zetacomponents/console-tools/src/input/argument.php',
'ezcconsoleargumentalreadyregisteredexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_already_registered.php',
'ezcconsoleargumentexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument.php',
'ezcconsoleargumentmandatoryviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_mandatory_violation.php',
'ezcconsolearguments' => '/../vendor/zetacomponents/console-tools/src/input/arguments.php',
'ezcconsoleargumenttypeviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_type_violation.php',
'ezcconsoledialog' => '/../vendor/zetacomponents/console-tools/src/interfaces/dialog.php',
'ezcconsoledialogabortexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/dialog_abort.php',
'ezcconsoledialogoptions' => '/../vendor/zetacomponents/console-tools/src/options/dialog.php',
'ezcconsoledialogvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/dialog_validator.php',
'ezcconsoledialogviewer' => '/../vendor/zetacomponents/console-tools/src/dialog_viewer.php',
'ezcconsoleexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/exception.php',
'ezcconsoleinput' => '/../vendor/zetacomponents/console-tools/src/input.php',
'ezcconsoleinputhelpgenerator' => '/../vendor/zetacomponents/console-tools/src/interfaces/input_help_generator.php',
'ezcconsoleinputstandardhelpgenerator' => '/../vendor/zetacomponents/console-tools/src/input/help_generators/standard.php',
'ezcconsoleinputvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/input_validator.php',
'ezcconsoleinvalidoptionnameexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/invalid_option_name.php',
'ezcconsoleinvalidoutputtargetexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/invalid_output_target.php',
'ezcconsolemenudialog' => '/../vendor/zetacomponents/console-tools/src/dialog/menu_dialog.php',
'ezcconsolemenudialogdefaultvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/menu_dialog_default.php',
'ezcconsolemenudialogoptions' => '/../vendor/zetacomponents/console-tools/src/options/menu_dialog.php',
'ezcconsolemenudialogvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/menu_dialog_validator.php',
'ezcconsolenopositionstoredexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/no_position_stored.php',
'ezcconsolenovaliddialogresultexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/no_valid_dialog_result.php',
'ezcconsoleoption' => '/../vendor/zetacomponents/console-tools/src/input/option.php',
'ezcconsoleoptionalreadyregisteredexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_already_registered.php',
'ezcconsoleoptionargumentsviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_arguments_violation.php',
'ezcconsoleoptiondependencyviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_dependency_violation.php',
'ezcconsoleoptionexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option.php',
'ezcconsoleoptionexclusionviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_exclusion_violation.php',
'ezcconsoleoptionmandatoryviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_mandatory_violation.php',
'ezcconsoleoptionmissingvalueexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_missing_value.php',
'ezcconsoleoptionnoaliasexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_no_alias.php',
'ezcconsoleoptionnotexistsexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_not_exists.php',
'ezcconsoleoptionrule' => '/../vendor/zetacomponents/console-tools/src/structs/option_rule.php',
'ezcconsoleoptionstringnotwellformedexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_string_not_wellformed.php',
'ezcconsoleoptiontoomanyvaluesexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_too_many_values.php',
'ezcconsoleoptiontypeviolationexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/option_type_violation.php',
'ezcconsoleoutput' => '/../vendor/zetacomponents/console-tools/src/output.php',
'ezcconsoleoutputformat' => '/../vendor/zetacomponents/console-tools/src/structs/output_format.php',
'ezcconsoleoutputformats' => '/../vendor/zetacomponents/console-tools/src/structs/output_formats.php',
'ezcconsoleoutputoptions' => '/../vendor/zetacomponents/console-tools/src/options/output.php',
'ezcconsoleprogressbar' => '/../vendor/zetacomponents/console-tools/src/progressbar.php',
'ezcconsoleprogressbaroptions' => '/../vendor/zetacomponents/console-tools/src/options/progressbar.php',
'ezcconsoleprogressmonitor' => '/../vendor/zetacomponents/console-tools/src/progressmonitor.php',
'ezcconsoleprogressmonitoroptions' => '/../vendor/zetacomponents/console-tools/src/options/progressmonitor.php',
'ezcconsolequestiondialog' => '/../vendor/zetacomponents/console-tools/src/dialog/question_dialog.php',
'ezcconsolequestiondialogcollectionvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_collection.php',
'ezcconsolequestiondialogmappingvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_mapping.php',
'ezcconsolequestiondialogoptions' => '/../vendor/zetacomponents/console-tools/src/options/question_dialog.php',
'ezcconsolequestiondialogregexvalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_regex.php',
'ezcconsolequestiondialogtypevalidator' => '/../vendor/zetacomponents/console-tools/src/dialog/validators/question_dialog_type.php',
'ezcconsolequestiondialogvalidator' => '/../vendor/zetacomponents/console-tools/src/interfaces/question_dialog_validator.php',
'ezcconsolestandardinputvalidator' => '/../vendor/zetacomponents/console-tools/src/input/validators/standard.php',
'ezcconsolestatusbar' => '/../vendor/zetacomponents/console-tools/src/statusbar.php',
'ezcconsolestatusbaroptions' => '/../vendor/zetacomponents/console-tools/src/options/statusbar.php',
'ezcconsolestringtool' => '/../vendor/zetacomponents/console-tools/src/tools/string.php',
'ezcconsoletable' => '/../vendor/zetacomponents/console-tools/src/table.php',
'ezcconsoletablecell' => '/../vendor/zetacomponents/console-tools/src/table/cell.php',
'ezcconsoletableoptions' => '/../vendor/zetacomponents/console-tools/src/options/table.php',
'ezcconsoletablerow' => '/../vendor/zetacomponents/console-tools/src/table/row.php',
'ezcconsoletoomanyargumentsexception' => '/../vendor/zetacomponents/console-tools/src/exceptions/argument_too_many.php',
'theseer\\autoload\\application' => '/Application.php',
'theseer\\autoload\\applicationexception' => '/Application.php',
'theseer\\autoload\\autoloadbuilderexception' => '/AutoloadRenderer.php',
'theseer\\autoload\\autoloadrenderer' => '/AutoloadRenderer.php',
'theseer\\autoload\\cache' => '/Cache.php',
'theseer\\autoload\\cacheentry' => '/CacheEntry.php',
'theseer\\autoload\\cacheexception' => '/Cache.php',
'theseer\\autoload\\cachewarminglistrenderer' => '/CacheWarmingListRenderer.php',
'theseer\\autoload\\cachingparser' => '/CachingParser.php',
'theseer\\autoload\\classdependencysorter' => '/DependencySorter.php',
'theseer\\autoload\\classdependencysorterexception' => '/DependencySorter.php',
'theseer\\autoload\\cli' => '/CLI.php',
'theseer\\autoload\\clienvironmentexception' => '/CLI.php',
'theseer\\autoload\\collector' => '/Collector.php',
'theseer\\autoload\\collectorexception' => '/Collector.php',
'theseer\\autoload\\collectorresult' => '/CollectorResult.php',
'theseer\\autoload\\collectorresultexception' => '/CollectorResult.php',
'theseer\\autoload\\composeriterator' => '/ComposerIterator.php',
'theseer\\autoload\\composeriteratorexception' => '/ComposerIterator.php',
'theseer\\autoload\\config' => '/Config.php',
'theseer\\autoload\\factory' => '/Factory.php',
'theseer\\autoload\\logger' => '/Logger.php',
'theseer\\autoload\\parser' => '/Parser.php',
'theseer\\autoload\\parseresult' => '/ParseResult.php',
'theseer\\autoload\\parserexception' => '/Parser.php',
'theseer\\autoload\\parserinterface' => '/ParserInterface.php',
'theseer\\autoload\\pathcomparator' => '/PathComparator.php',
'theseer\\autoload\\pharbuilder' => '/PharBuilder.php',
'theseer\\autoload\\sourcefile' => '/SourceFile.php',
'theseer\\autoload\\staticlistrenderer' => '/StaticListRenderer.php',
'theseer\\autoload\\staticrenderer' => '/StaticRenderer.php',
'theseer\\autoload\\staticrequirelistrenderer' => '/StaticRequireListRenderer.php',
'theseer\\autoload\\version' => '/Version.php',
'theseer\\directoryscanner\\directoryscanner' => '/../vendor/theseer/directoryscanner/src/directoryscanner.php',
'theseer\\directoryscanner\\exception' => '/../vendor/theseer/directoryscanner/src/directoryscanner.php',
'theseer\\directoryscanner\\filesonlyfilteriterator' => '/../vendor/theseer/directoryscanner/src/filesonlyfilter.php',
'theseer\\directoryscanner\\includeexcludefilteriterator' => '/../vendor/theseer/directoryscanner/src/includeexcludefilter.php',
'theseer\\directoryscanner\\phpfilteriterator' => '/../vendor/theseer/directoryscanner/src/phpfilter.php'
);
}
$cn = strtolower($class);
if (isset($classes[$cn])) {
require __DIR__ . $classes[$cn];
}
},
true,
false
);
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,21 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
spl_autoload_register(
function($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
___CLASSLIST___
);
}
$cn = strtolower($class);
if (isset($classes[$cn])) {
require ___BASEDIR___$classes[$cn];
}
},
___EXCEPTION___,
___PREPEND___
);
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,19 @@
<?php
spl_autoload_register(
function($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
___CLASSLIST___
);
}
$cn = strtolower($class);
if (isset($classes[$cn])) {
require 'phar://___PHAR___' . $classes[$cn];
}
},
___EXCEPTION___,
___PREPEND___
);
Phar::mapPhar('___PHAR___');
__HALT_COMPILER();

View file

@ -0,0 +1,18 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
function ___AUTOLOAD___($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
___CLASSLIST___
);
}
$cn = strtolower($class);
if (isset($classes[$cn])) {
require ___BASEDIR___$classes[$cn];
}
}
spl_autoload_register('___AUTOLOAD___', ___EXCEPTION___);
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,20 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
spl_autoload_register(
function($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
___CLASSLIST___
);
}
if (isset($classes[$class])) {
require ___BASEDIR___$classes[$class];
}
},
___EXCEPTION___,
___PREPEND___
);
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,18 @@
<?php
spl_autoload_register(
function($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
___CLASSLIST___
);
}
if (isset($classes[$class])) {
require 'phar://___PHAR___' . $classes[$class];
}
},
___EXCEPTION___,
___PREPEND___
);
Phar::mapPhar('___PHAR___');
__HALT_COMPILER();

View file

@ -0,0 +1,17 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
function ___AUTOLOAD___($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
___CLASSLIST___
);
}
if (isset($classes[$class])) {
require ___BASEDIR___$classes[$class];
}
}
spl_autoload_register('___AUTOLOAD___', ___EXCEPTION___);
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,6 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
___FILELIST___
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,3 @@
<?php // this is an autogenerated file - do not edit
___FILELIST___
__HALT_COMPILER();