diff --git a/.gitignore b/.gitignore index bb11b8d..8d5141b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -vendor/ +/vendor/ +/composer.lock composer.phar .DS_Store diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 3ca2d98..20800d1 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -6,6 +6,7 @@ checks: filter: excluded_paths: - "tests/" + - "patchwork-composer/" - "vendor/" coding_style: php: diff --git a/Patchwork.php b/Patchwork.php index bf25f65..9f9349b 100644 --- a/Patchwork.php +++ b/Patchwork.php @@ -7,93 +7,17 @@ */ namespace Patchwork; -if (function_exists('Patchwork\replace')) { +if (defined('Patchwork\PATCHWORK_ALREADY_RAN')) { return; } -require_once __DIR__ . '/src/Exceptions.php'; -require_once __DIR__ . '/src/CallRerouting.php'; -require_once __DIR__ . '/src/CodeManipulation.php'; -require_once __DIR__ . '/src/Utils.php'; -require_once __DIR__ . '/src/Stack.php'; -require_once __DIR__ . '/src/Config.php'; - -function redefine($subject, callable $content) -{ - $handle = null; - foreach (array_slice(func_get_args(), 1) as $content) { - $handle = CallRerouting\connect($subject, $content, $handle); - } - $handle->silence(); - return $handle; -} - -function relay(array $args = null) -{ - return CallRerouting\relay($args); -} +const PATCHWORK_ALREADY_RAN = true; -function fallBack() -{ - throw new Exceptions\NoResult; +// Load all class and function files if Composer is not running. +if (! function_exists('Patchwork\replace')) { + require_once __DIR__ . '/patchwork-composer/autoload.php'; } -function restore(CallRerouting\Handle $handle) -{ - $handle->expire(); -} - -function restoreAll() -{ - CallRerouting\disconnectAll(); -} - -function silence(CallRerouting\Handle $handle) -{ - $handle->silence(); -} - -function assertEventuallyDefined(CallRerouting\Handle $handle) -{ - $handle->unsilence(); -} - -function getClass() -{ - return Stack\top('class'); -} - -function getCalledClass() -{ - return Stack\topCalledClass(); -} - -function getFunction() -{ - return Stack\top('function'); -} - -function getMethod() -{ - return getClass() . '::' . getFunction(); -} - -function configure() -{ - Config\locate(); -} - -function hasMissed($callable) -{ - return Utils\callableWasMissed($callable); -} - -function always($value) -{ - return function() use ($value) { - return $value; - }; -} Utils\alias('Patchwork', [ 'redefine' => ['replace', 'replaceLater'], @@ -137,13 +61,11 @@ function always($value) CallRerouting\createStubsForInternals(); CallRerouting\connectDefaultInternals(); -require __DIR__ . '/src/Redefinitions/LanguageConstructs.php'; - CodeManipulation\register([ CodeManipulation\Actions\RedefinitionOfLanguageConstructs\spliceAllConfiguredLanguageConstructs(), CodeManipulation\Actions\CallRerouting\injectQueueDeploymentCode(), ]); if (Utils\wasRunAsConsoleApp()) { - require __DIR__ . '/src/Console.php'; + require __DIR__ . '/src/Console/console.php'; } diff --git a/composer.json b/composer.json index 2868b88..91e4d6d 100644 --- a/composer.json +++ b/composer.json @@ -16,5 +16,27 @@ }, "require-dev": { "phpunit/phpunit": ">=4" + }, + "autoload": { + "files": [ + "src/functions.php", + "src/CallRerouting/functions.php", + "src/CodeManipulation/Actions/CallRerouting/functions.php", + "src/CodeManipulation/Actions/CodeManipulation/functions.php", + "src/CodeManipulation/Actions/ConflictPrevention/functions.php", + "src/CodeManipulation/Actions/Generic/functions.php", + "src/CodeManipulation/Actions/Namespaces/functions.php", + "src/CodeManipulation/Actions/RedefinitionOfInternals/functions.php", + "src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs/functions.php", + "src/CodeManipulation/Actions/RedefinitionOfNew/functions.php", + "src/CodeManipulation/functions.php", + "src/Config/functions.php", + "src/Redefinitions/LanguageConstructs/functions.php", + "src/Stack/functions.php", + "src/Utils/functions.php" + ], + "psr-4": { + "Patchwork\\": "src/" + } } } diff --git a/patchwork-composer.json b/patchwork-composer.json new file mode 100644 index 0000000..c315420 --- /dev/null +++ b/patchwork-composer.json @@ -0,0 +1,43 @@ +{ + "name": "antecedent/patchwork", + "homepage": "http://patchwork2.org/", + "description": "Method redefinition (monkey-patching) functionality for PHP.", + "keywords": ["testing", "redefinition", "runkit", "monkeypatching", "interception", "aop", "aspect"], + "license": "MIT", + "authors": [ + { + "name": "Ignas Rudaitis", + "email": "ignas.rudaitis@gmail.com" + } + ], + "minimum-stability": "stable", + "require": { + "php": ">=5.4.0" + }, + "autoload": { + "files": [ + "src/functions.php", + "src/CallRerouting/functions.php", + "src/CodeManipulation/Actions/CallRerouting/functions.php", + "src/CodeManipulation/Actions/CodeManipulation/functions.php", + "src/CodeManipulation/Actions/ConflictPrevention/functions.php", + "src/CodeManipulation/Actions/Generic/functions.php", + "src/CodeManipulation/Actions/Namespaces/functions.php", + "src/CodeManipulation/Actions/RedefinitionOfInternals/functions.php", + "src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs/functions.php", + "src/CodeManipulation/Actions/RedefinitionOfNew/functions.php", + "src/CodeManipulation/functions.php", + "src/Config/functions.php", + "src/Redefinitions/LanguageConstructs/functions.php", + "src/Stack/functions.php", + "src/Utils/functions.php" + ], + "psr-4": { + "Patchwork\\": "src/" + } + }, + "config": { + "vendor-dir": "patchwork-composer", + "optimize-autoloader": true + } +} diff --git a/patchwork-composer/autoload.php b/patchwork-composer/autoload.php new file mode 100644 index 0000000..474dbbb --- /dev/null +++ b/patchwork-composer/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/patchwork-composer/composer/LICENSE b/patchwork-composer/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/patchwork-composer/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/patchwork-composer/composer/autoload_classmap.php b/patchwork-composer/composer/autoload_classmap.php new file mode 100644 index 0000000..4bd7bee --- /dev/null +++ b/patchwork-composer/composer/autoload_classmap.php @@ -0,0 +1,34 @@ + $baseDir . '/src/CallRerouting/Decorator.php', + 'Patchwork\\CallRerouting\\Handle' => $baseDir . '/src/CallRerouting/Handle.php', + 'Patchwork\\CallRerouting\\State' => $baseDir . '/src/CallRerouting/State.php', + 'Patchwork\\CodeManipulation\\Actions\\RedefinitionOfNew\\State' => $baseDir . '/src/CodeManipulation/Actions/RedefinitionOfNew/State.php', + 'Patchwork\\CodeManipulation\\Source' => $baseDir . '/src/CodeManipulation/Source.php', + 'Patchwork\\CodeManipulation\\State' => $baseDir . '/src/CodeManipulation/State.php', + 'Patchwork\\CodeManipulation\\Stream' => $baseDir . '/src/CodeManipulation/Stream.php', + 'Patchwork\\Config\\State' => $baseDir . '/src/Config/State.php', + 'Patchwork\\Exceptions\\CachePathConflict' => $baseDir . '/src/Exceptions/CachePathConflict.php', + 'Patchwork\\Exceptions\\CachePathUnavailable' => $baseDir . '/src/Exceptions/CachePathUnavailable.php', + 'Patchwork\\Exceptions\\CallbackException' => $baseDir . '/src/Exceptions/CallbackException.php', + 'Patchwork\\Exceptions\\ConfigException' => $baseDir . '/src/Exceptions/ConfigException.php', + 'Patchwork\\Exceptions\\ConfigKeyNotRecognized' => $baseDir . '/src/Exceptions/ConfigKeyNotRecognized.php', + 'Patchwork\\Exceptions\\ConfigMalformed' => $baseDir . '/src/Exceptions/ConfigMalformed.php', + 'Patchwork\\Exceptions\\DefinedTooEarly' => $baseDir . '/src/Exceptions/DefinedTooEarly.php', + 'Patchwork\\Exceptions\\Exception' => $baseDir . '/src/Exceptions/Exception.php', + 'Patchwork\\Exceptions\\InternalMethodsNotSupported' => $baseDir . '/src/Exceptions/InternalMethodsNotSupported.php', + 'Patchwork\\Exceptions\\InternalsNotSupportedOnHHVM' => $baseDir . '/src/Exceptions/InternalsNotSupportedOnHHVM.php', + 'Patchwork\\Exceptions\\NewKeywordNotRedefinable' => $baseDir . '/src/Exceptions/NewKeywordNotRedefinable.php', + 'Patchwork\\Exceptions\\NoResult' => $baseDir . '/src/Exceptions/NoResult.php', + 'Patchwork\\Exceptions\\NonNullToVoid' => $baseDir . '/src/Exceptions/NonNullToVoid.php', + 'Patchwork\\Exceptions\\NotUserDefined' => $baseDir . '/src/Exceptions/NotUserDefined.php', + 'Patchwork\\Exceptions\\StackEmpty' => $baseDir . '/src/Exceptions/StackEmpty.php', + 'Patchwork\\Stack\\State' => $baseDir . '/src/Stack/State.php', + 'Patchwork\\Utils\\State' => $baseDir . '/src/Utils/State.php', +); diff --git a/patchwork-composer/composer/autoload_files.php b/patchwork-composer/composer/autoload_files.php new file mode 100644 index 0000000..7d7ea32 --- /dev/null +++ b/patchwork-composer/composer/autoload_files.php @@ -0,0 +1,24 @@ + $baseDir . '/src/functions.php', + '797af80c1143897800cef23f803c076f' => $baseDir . '/src/CallRerouting/functions.php', + '3d00ac85237afa0a95418be9d3a3d648' => $baseDir . '/src/CodeManipulation/Actions/CallRerouting/functions.php', + '1d274b725e04b0ac6e013fe3e951c9e7' => $baseDir . '/src/CodeManipulation/Actions/CodeManipulation/functions.php', + 'a43c27a2843edc5ad3b9db9bac89488c' => $baseDir . '/src/CodeManipulation/Actions/ConflictPrevention/functions.php', + '90197d12814b7172e494d6f43b1fe244' => $baseDir . '/src/CodeManipulation/Actions/Generic/functions.php', + 'c4e3053cd7b4dc5a595ad687b7cbef64' => $baseDir . '/src/CodeManipulation/Actions/Namespaces/functions.php', + 'b19e7b29a0ee4825dd0f69974da4ff3f' => $baseDir . '/src/CodeManipulation/Actions/RedefinitionOfInternals/functions.php', + '20db11514444fca048dbed59fc33816e' => $baseDir . '/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs/functions.php', + '7b15434fd0bee2d043a7b1cfcbe1f6b6' => $baseDir . '/src/CodeManipulation/Actions/RedefinitionOfNew/functions.php', + '01c05e4b5de72b2ba165ec0ae0475356' => $baseDir . '/src/CodeManipulation/functions.php', + 'f53fd7e076a00f64495dc3b5c216663c' => $baseDir . '/src/Config/functions.php', + '2c0c9c18b2971b96365f4ccaab50f99d' => $baseDir . '/src/Redefinitions/LanguageConstructs/functions.php', + '204f66c6fa9d6d4fcca84db2b6ce51d5' => $baseDir . '/src/Stack/functions.php', + '7335fc46393476f0de27165dc4aabd3c' => $baseDir . '/src/Utils/functions.php', +); diff --git a/patchwork-composer/composer/autoload_namespaces.php b/patchwork-composer/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/patchwork-composer/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($baseDir . '/src'), +); diff --git a/patchwork-composer/composer/autoload_real.php b/patchwork-composer/composer/autoload_real.php new file mode 100644 index 0000000..08e996d --- /dev/null +++ b/patchwork-composer/composer/autoload_real.php @@ -0,0 +1,70 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInitb7de713a68964186ce39fad9ae1c996a::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInitb7de713a68964186ce39fad9ae1c996a::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequireb7de713a68964186ce39fad9ae1c996a($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequireb7de713a68964186ce39fad9ae1c996a($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/patchwork-composer/composer/autoload_static.php b/patchwork-composer/composer/autoload_static.php new file mode 100644 index 0000000..47384dd --- /dev/null +++ b/patchwork-composer/composer/autoload_static.php @@ -0,0 +1,78 @@ + __DIR__ . '/../..' . '/src/functions.php', + '797af80c1143897800cef23f803c076f' => __DIR__ . '/../..' . '/src/CallRerouting/functions.php', + '3d00ac85237afa0a95418be9d3a3d648' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/CallRerouting/functions.php', + '1d274b725e04b0ac6e013fe3e951c9e7' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/CodeManipulation/functions.php', + 'a43c27a2843edc5ad3b9db9bac89488c' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/ConflictPrevention/functions.php', + '90197d12814b7172e494d6f43b1fe244' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/Generic/functions.php', + 'c4e3053cd7b4dc5a595ad687b7cbef64' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/Namespaces/functions.php', + 'b19e7b29a0ee4825dd0f69974da4ff3f' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/RedefinitionOfInternals/functions.php', + '20db11514444fca048dbed59fc33816e' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs/functions.php', + '7b15434fd0bee2d043a7b1cfcbe1f6b6' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/RedefinitionOfNew/functions.php', + '01c05e4b5de72b2ba165ec0ae0475356' => __DIR__ . '/../..' . '/src/CodeManipulation/functions.php', + 'f53fd7e076a00f64495dc3b5c216663c' => __DIR__ . '/../..' . '/src/Config/functions.php', + '2c0c9c18b2971b96365f4ccaab50f99d' => __DIR__ . '/../..' . '/src/Redefinitions/LanguageConstructs/functions.php', + '204f66c6fa9d6d4fcca84db2b6ce51d5' => __DIR__ . '/../..' . '/src/Stack/functions.php', + '7335fc46393476f0de27165dc4aabd3c' => __DIR__ . '/../..' . '/src/Utils/functions.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'P' => + array ( + 'Patchwork\\' => 10, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Patchwork\\' => + array ( + 0 => __DIR__ . '/../..' . '/src', + ), + ); + + public static $classMap = array ( + 'Patchwork\\CallRerouting\\Decorator' => __DIR__ . '/../..' . '/src/CallRerouting/Decorator.php', + 'Patchwork\\CallRerouting\\Handle' => __DIR__ . '/../..' . '/src/CallRerouting/Handle.php', + 'Patchwork\\CallRerouting\\State' => __DIR__ . '/../..' . '/src/CallRerouting/State.php', + 'Patchwork\\CodeManipulation\\Actions\\RedefinitionOfNew\\State' => __DIR__ . '/../..' . '/src/CodeManipulation/Actions/RedefinitionOfNew/State.php', + 'Patchwork\\CodeManipulation\\Source' => __DIR__ . '/../..' . '/src/CodeManipulation/Source.php', + 'Patchwork\\CodeManipulation\\State' => __DIR__ . '/../..' . '/src/CodeManipulation/State.php', + 'Patchwork\\CodeManipulation\\Stream' => __DIR__ . '/../..' . '/src/CodeManipulation/Stream.php', + 'Patchwork\\Config\\State' => __DIR__ . '/../..' . '/src/Config/State.php', + 'Patchwork\\Exceptions\\CachePathConflict' => __DIR__ . '/../..' . '/src/Exceptions/CachePathConflict.php', + 'Patchwork\\Exceptions\\CachePathUnavailable' => __DIR__ . '/../..' . '/src/Exceptions/CachePathUnavailable.php', + 'Patchwork\\Exceptions\\CallbackException' => __DIR__ . '/../..' . '/src/Exceptions/CallbackException.php', + 'Patchwork\\Exceptions\\ConfigException' => __DIR__ . '/../..' . '/src/Exceptions/ConfigException.php', + 'Patchwork\\Exceptions\\ConfigKeyNotRecognized' => __DIR__ . '/../..' . '/src/Exceptions/ConfigKeyNotRecognized.php', + 'Patchwork\\Exceptions\\ConfigMalformed' => __DIR__ . '/../..' . '/src/Exceptions/ConfigMalformed.php', + 'Patchwork\\Exceptions\\DefinedTooEarly' => __DIR__ . '/../..' . '/src/Exceptions/DefinedTooEarly.php', + 'Patchwork\\Exceptions\\Exception' => __DIR__ . '/../..' . '/src/Exceptions/Exception.php', + 'Patchwork\\Exceptions\\InternalMethodsNotSupported' => __DIR__ . '/../..' . '/src/Exceptions/InternalMethodsNotSupported.php', + 'Patchwork\\Exceptions\\InternalsNotSupportedOnHHVM' => __DIR__ . '/../..' . '/src/Exceptions/InternalsNotSupportedOnHHVM.php', + 'Patchwork\\Exceptions\\NewKeywordNotRedefinable' => __DIR__ . '/../..' . '/src/Exceptions/NewKeywordNotRedefinable.php', + 'Patchwork\\Exceptions\\NoResult' => __DIR__ . '/../..' . '/src/Exceptions/NoResult.php', + 'Patchwork\\Exceptions\\NonNullToVoid' => __DIR__ . '/../..' . '/src/Exceptions/NonNullToVoid.php', + 'Patchwork\\Exceptions\\NotUserDefined' => __DIR__ . '/../..' . '/src/Exceptions/NotUserDefined.php', + 'Patchwork\\Exceptions\\StackEmpty' => __DIR__ . '/../..' . '/src/Exceptions/StackEmpty.php', + 'Patchwork\\Stack\\State' => __DIR__ . '/../..' . '/src/Stack/State.php', + 'Patchwork\\Utils\\State' => __DIR__ . '/../..' . '/src/Utils/State.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitb7de713a68964186ce39fad9ae1c996a::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitb7de713a68964186ce39fad9ae1c996a::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitb7de713a68964186ce39fad9ae1c996a::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/patchwork-composer/composer/installed.json b/patchwork-composer/composer/installed.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/patchwork-composer/composer/installed.json @@ -0,0 +1 @@ +[] diff --git a/src/CallRerouting/State.php b/src/CallRerouting/State.php new file mode 100644 index 0000000..574e7be --- /dev/null +++ b/src/CallRerouting/State.php @@ -0,0 +1,17 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CallRerouting; + +class State +{ + static $routes = []; + static $queue = []; + static $preprocessedFiles = []; + static $routeStack = []; +} diff --git a/src/CallRerouting.php b/src/CallRerouting/functions.php similarity index 98% rename from src/CallRerouting.php rename to src/CallRerouting/functions.php index 98fbea8..2b4d58d 100644 --- a/src/CallRerouting.php +++ b/src/CallRerouting/functions.php @@ -8,9 +8,6 @@ */ namespace Patchwork\CallRerouting; -require __DIR__ . '/CallRerouting/Handle.php'; -require __DIR__ . '/CallRerouting/Decorator.php'; - use Patchwork\Utils; use Patchwork\Stack; use Patchwork\Config; @@ -595,11 +592,3 @@ function getInstantiator($class, $calledClass) $instantiator = "$namespace\\$adaptedName"; return new $instantiator; } - -class State -{ - static $routes = []; - static $queue = []; - static $preprocessedFiles = []; - static $routeStack = []; -} diff --git a/src/CodeManipulation/Actions/CallRerouting.php b/src/CodeManipulation/Actions/CallRerouting/functions.php similarity index 100% rename from src/CodeManipulation/Actions/CallRerouting.php rename to src/CodeManipulation/Actions/CallRerouting/functions.php diff --git a/src/CodeManipulation/Actions/CodeManipulation.php b/src/CodeManipulation/Actions/CodeManipulation/functions.php similarity index 100% rename from src/CodeManipulation/Actions/CodeManipulation.php rename to src/CodeManipulation/Actions/CodeManipulation/functions.php diff --git a/src/CodeManipulation/Actions/ConflictPrevention.php b/src/CodeManipulation/Actions/ConflictPrevention/functions.php similarity index 94% rename from src/CodeManipulation/Actions/ConflictPrevention.php rename to src/CodeManipulation/Actions/ConflictPrevention/functions.php index 634296b..ba5e5e7 100644 --- a/src/CodeManipulation/Actions/ConflictPrevention.php +++ b/src/CodeManipulation/Actions/ConflictPrevention/functions.php @@ -25,7 +25,7 @@ function preventImportingOtherCopiesOfPatchwork() if ($s->read($namespaceKeyword, 4) == 'namespace Patchwork;') { $pattern = '/@copyright\s+2010(-\d+)? Ignas Rudaitis/'; if (preg_match($pattern, $s->read($namespaceKeyword - 2))) { - # Clear the file completely (in memory) + // Clear the file completely (in memory) $s->splice('', 0, count($s->tokens)); } } diff --git a/src/CodeManipulation/Actions/Generic.php b/src/CodeManipulation/Actions/Generic/functions.php similarity index 100% rename from src/CodeManipulation/Actions/Generic.php rename to src/CodeManipulation/Actions/Generic/functions.php diff --git a/src/CodeManipulation/Actions/Namespaces.php b/src/CodeManipulation/Actions/Namespaces/functions.php similarity index 100% rename from src/CodeManipulation/Actions/Namespaces.php rename to src/CodeManipulation/Actions/Namespaces/functions.php diff --git a/src/CodeManipulation/Actions/RedefinitionOfInternals.php b/src/CodeManipulation/Actions/RedefinitionOfInternals/functions.php similarity index 100% rename from src/CodeManipulation/Actions/RedefinitionOfInternals.php rename to src/CodeManipulation/Actions/RedefinitionOfInternals/functions.php diff --git a/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php b/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs/functions.php similarity index 100% rename from src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php rename to src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs/functions.php diff --git a/src/CodeManipulation/Actions/RedefinitionOfNew/State.php b/src/CodeManipulation/Actions/RedefinitionOfNew/State.php new file mode 100644 index 0000000..756ecb3 --- /dev/null +++ b/src/CodeManipulation/Actions/RedefinitionOfNew/State.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\RedefinitionOfNew; + +class State +{ + static $enabled = true; +} diff --git a/src/CodeManipulation/Actions/RedefinitionOfNew.php b/src/CodeManipulation/Actions/RedefinitionOfNew/functions.php similarity index 99% rename from src/CodeManipulation/Actions/RedefinitionOfNew.php rename to src/CodeManipulation/Actions/RedefinitionOfNew/functions.php index 3413e15..a84916e 100644 --- a/src/CodeManipulation/Actions/RedefinitionOfNew.php +++ b/src/CodeManipulation/Actions/RedefinitionOfNew/functions.php @@ -184,8 +184,3 @@ function suspendFor(callable $function) throw $exception; } } - -class State -{ - static $enabled = true; -} diff --git a/src/CodeManipulation/State.php b/src/CodeManipulation/State.php new file mode 100644 index 0000000..6b91d29 --- /dev/null +++ b/src/CodeManipulation/State.php @@ -0,0 +1,17 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation; + +class State +{ + static $actions = []; + static $importListeners = []; + static $cacheIndex = []; + static $cacheIndexFile; +} diff --git a/src/CodeManipulation.php b/src/CodeManipulation/functions.php similarity index 80% rename from src/CodeManipulation.php rename to src/CodeManipulation/functions.php index f36043c..87b8c67 100644 --- a/src/CodeManipulation.php +++ b/src/CodeManipulation/functions.php @@ -8,17 +8,6 @@ */ namespace Patchwork\CodeManipulation; -require __DIR__ . '/CodeManipulation/Source.php'; -require __DIR__ . '/CodeManipulation/Stream.php'; -require __DIR__ . '/CodeManipulation/Actions/Generic.php'; -require __DIR__ . '/CodeManipulation/Actions/CallRerouting.php'; -require __DIR__ . '/CodeManipulation/Actions/CodeManipulation.php'; -require __DIR__ . '/CodeManipulation/Actions/Namespaces.php'; -require __DIR__ . '/CodeManipulation/Actions/RedefinitionOfInternals.php'; -require __DIR__ . '/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php'; -require __DIR__ . '/CodeManipulation/Actions/ConflictPrevention.php'; -require __DIR__ . '/CodeManipulation/Actions/RedefinitionOfNew.php'; - use Patchwork\Exceptions; use Patchwork\Utils; use Patchwork\Config; @@ -138,7 +127,7 @@ function prime($file) function shouldTransform($file) { - return !Config\isBlacklisted($file) || Config\isWhitelisted($file); + return !Config\isPatchworkFile($file) && (!Config\isBlacklisted($file) || Config\isWhitelisted($file)); } function register($actions) @@ -150,11 +139,3 @@ function onImport($listeners) { State::$importListeners = array_merge(State::$importListeners, (array) $listeners); } - -class State -{ - static $actions = []; - static $importListeners = []; - static $cacheIndex = []; - static $cacheIndexFile; -} diff --git a/src/Config/State.php b/src/Config/State.php new file mode 100644 index 0000000..6879671 --- /dev/null +++ b/src/Config/State.php @@ -0,0 +1,20 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Config; + +class State +{ + static $blacklist = []; + static $whitelist = []; + static $cachePath; + static $redefinableInternals = []; + static $redefinableLanguageConstructs = []; + static $newKeywordRedefinable = false; + static $timestamp = 0; +} diff --git a/src/Config.php b/src/Config/functions.php similarity index 95% rename from src/Config.php rename to src/Config/functions.php index 9da67a8..db66b2c 100644 --- a/src/Config.php +++ b/src/Config/functions.php @@ -83,6 +83,12 @@ function isListed($path, array $list) return false; } +function isPatchworkFile($path) +{ + $root = dirname(__DIR__); + return \strpos($path, $root) !== false; +} + function isBlacklisted($path) { return isListed($path, State::$blacklist); @@ -220,14 +226,3 @@ function getTimestamp() { return State::$timestamp; } - -class State -{ - static $blacklist = []; - static $whitelist = []; - static $cachePath; - static $redefinableInternals = []; - static $redefinableLanguageConstructs = []; - static $newKeywordRedefinable = false; - static $timestamp = 0; -} diff --git a/src/Console.php b/src/Console/console.php similarity index 82% rename from src/Console.php rename to src/Console/console.php index 466130d..a24659d 100644 --- a/src/Console.php +++ b/src/Console/console.php @@ -8,7 +8,7 @@ */ namespace Patchwork\Console; -use Patchwork\CodeManipulation as CM; +use Patchwork\CodeManipulation; error_reporting(E_ALL | E_STRICT); @@ -17,7 +17,7 @@ " (to recursively prime all PHP files under given directories)\n\n"); try { - CM\cacheEnabled() + CodeManipulation\cacheEnabled() or exit("\nError: no cache location set.\n\n"); } catch (Patchwork\Exceptions\CachePathUnavailable $e) { exit("\nError: " . $e->getMessage() . "\n\n"); @@ -30,7 +30,7 @@ foreach (array_slice($argv, 2) as $path) { $path = realpath($path); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path)) as $file) { - if (substr($file, -4) == '.php' && !CM\internalToCache($file) && !CM\availableCached($file)) { + if (substr($file, -4) == '.php' && !CodeManipulation\internalToCache($file) && !CodeManipulation\availableCached($file)) { $files[] = $file; } } @@ -47,7 +47,7 @@ $progress = 0; for ($i = 0; $i < $count; $i++) { - CM\prime($files[$i]->getRealPath()); + CodeManipulation\prime($files[$i]->getRealPath()); while ((int) (($i + 1) / $count * CONSOLE_WIDTH) > $progress) { echo '.'; $progress++; diff --git a/src/Exceptions.php b/src/Exceptions.php deleted file mode 100644 index c02c7df..0000000 --- a/src/Exceptions.php +++ /dev/null @@ -1,121 +0,0 @@ - - * @copyright 2010-2018 Ignas Rudaitis - * @license http://www.opensource.org/licenses/mit-license.html - */ -namespace Patchwork\Exceptions; - -use Patchwork\Utils; - -abstract class Exception extends \Exception -{ -} - -class NoResult extends Exception -{ -} - -class StackEmpty extends Exception -{ - protected $message = "There are no calls in the dispatch stack"; -} - -abstract class CallbackException extends Exception -{ - function __construct($callback) - { - parent::__construct(sprintf($this->message, Utils\callableToString($callback))); - } -} - -class NotUserDefined extends CallbackException -{ - protected $message = 'Please include {"redefinable-internals": ["%s"]} in your patchwork.json.'; -} - -class DefinedTooEarly extends CallbackException -{ - - function __construct($callback) - { - $this->message = "The file that defines %s() was included earlier than Patchwork. " . - "This is likely a result of an improper setup; see readme for details."; - parent::__construct($callback); - } -} - -class InternalMethodsNotSupported extends CallbackException -{ - protected $message = "Methods of internal classes (such as %s) are not yet redefinable in Patchwork 2.1."; -} - -class InternalsNotSupportedOnHHVM extends CallbackException -{ - protected $message = "As of version 2.1, Patchwork cannot redefine internal functions and methods (such as %s) on HHVM."; -} - -class CachePathUnavailable extends Exception -{ - function __construct($location) - { - parent::__construct(sprintf( - "The specified cache path is inexistent or read-only: %s", - $location - )); - } -} - -class ConfigException extends Exception -{ -} - -class ConfigMalformed extends ConfigException -{ - function __construct($file, $message) - { - parent::__construct(sprintf( - 'The configuration file %s is malformed: %s', - $file, - $message - )); - } -} - -class ConfigKeyNotRecognized extends ConfigException -{ - function __construct($key, $list, $file) - { - parent::__construct(sprintf( - "The key '%s' in the configuration file %s was not recognized. " . - "You might have meant one of these: %s", - $key, - $file, - join(', ', $list) - )); - } -} - -class CachePathConflict extends ConfigException -{ - function __construct($first, $second) - { - parent::__construct(sprintf( - "Detected configuration files provide conflicting cache paths: %s and %s", - $first, - $second - )); - } -} - -class NewKeywordNotRedefinable extends ConfigException -{ - protected $message = 'Please set {"new-keyword-redefinable": true} to redefine instantiations'; -} - -class NonNullToVoid extends Exception -{ - protected $message = 'A redefinition of a void-typed callable attempted to return a non-null result'; -} diff --git a/src/Exceptions/CachePathConflict.php b/src/Exceptions/CachePathConflict.php new file mode 100644 index 0000000..4e990ee --- /dev/null +++ b/src/Exceptions/CachePathConflict.php @@ -0,0 +1,21 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class CachePathConflict extends ConfigException +{ + function __construct($first, $second) + { + parent::__construct(sprintf( + "Detected configuration files provide conflicting cache paths: %s and %s", + $first, + $second + )); + } +} diff --git a/src/Exceptions/CachePathUnavailable.php b/src/Exceptions/CachePathUnavailable.php new file mode 100644 index 0000000..3c0550f --- /dev/null +++ b/src/Exceptions/CachePathUnavailable.php @@ -0,0 +1,20 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class CachePathUnavailable extends Exception +{ + function __construct($location) + { + parent::__construct(sprintf( + "The specified cache path is inexistent or read-only: %s", + $location + )); + } +} diff --git a/src/Exceptions/CallbackException.php b/src/Exceptions/CallbackException.php new file mode 100644 index 0000000..8551b26 --- /dev/null +++ b/src/Exceptions/CallbackException.php @@ -0,0 +1,19 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +use Patchwork\Utils; + +abstract class CallbackException extends Exception +{ + function __construct($callback) + { + parent::__construct(sprintf($this->message, Utils\callableToString($callback))); + } +} diff --git a/src/Exceptions/ConfigException.php b/src/Exceptions/ConfigException.php new file mode 100644 index 0000000..494ba50 --- /dev/null +++ b/src/Exceptions/ConfigException.php @@ -0,0 +1,13 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class ConfigException extends Exception +{ +} diff --git a/src/Exceptions/ConfigKeyNotRecognized.php b/src/Exceptions/ConfigKeyNotRecognized.php new file mode 100644 index 0000000..2d27214 --- /dev/null +++ b/src/Exceptions/ConfigKeyNotRecognized.php @@ -0,0 +1,23 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class ConfigKeyNotRecognized extends ConfigException +{ + function __construct($key, $list, $file) + { + parent::__construct(sprintf( + "The key '%s' in the configuration file %s was not recognized. " . + "You might have meant one of these: %s", + $key, + $file, + join(', ', $list) + )); + } +} diff --git a/src/Exceptions/ConfigMalformed.php b/src/Exceptions/ConfigMalformed.php new file mode 100644 index 0000000..00b95af --- /dev/null +++ b/src/Exceptions/ConfigMalformed.php @@ -0,0 +1,21 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class ConfigMalformed extends ConfigException +{ + function __construct($file, $message) + { + parent::__construct(sprintf( + 'The configuration file %s is malformed: %s', + $file, + $message + )); + } +} diff --git a/src/Exceptions/DefinedTooEarly.php b/src/Exceptions/DefinedTooEarly.php new file mode 100644 index 0000000..974e724 --- /dev/null +++ b/src/Exceptions/DefinedTooEarly.php @@ -0,0 +1,20 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class DefinedTooEarly extends CallbackException +{ + + function __construct($callback) + { + $this->message = "The file that defines %s() was included earlier than Patchwork. " . + "This is likely a result of an improper setup; see readme for details."; + parent::__construct($callback); + } +} diff --git a/src/Exceptions/Exception.php b/src/Exceptions/Exception.php new file mode 100644 index 0000000..badd231 --- /dev/null +++ b/src/Exceptions/Exception.php @@ -0,0 +1,13 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +abstract class Exception extends \Exception +{ +} diff --git a/src/Exceptions/InternalMethodsNotSupported.php b/src/Exceptions/InternalMethodsNotSupported.php new file mode 100644 index 0000000..18c3cb1 --- /dev/null +++ b/src/Exceptions/InternalMethodsNotSupported.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class InternalMethodsNotSupported extends CallbackException +{ + protected $message = "Methods of internal classes (such as %s) are not yet redefinable in Patchwork 2.1."; +} diff --git a/src/Exceptions/InternalsNotSupportedOnHHVM.php b/src/Exceptions/InternalsNotSupportedOnHHVM.php new file mode 100644 index 0000000..e4c5a0a --- /dev/null +++ b/src/Exceptions/InternalsNotSupportedOnHHVM.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class InternalsNotSupportedOnHHVM extends CallbackException +{ + protected $message = "As of version 2.1, Patchwork cannot redefine internal functions and methods (such as %s) on HHVM."; +} diff --git a/src/Exceptions/NewKeywordNotRedefinable.php b/src/Exceptions/NewKeywordNotRedefinable.php new file mode 100644 index 0000000..9ab5e8a --- /dev/null +++ b/src/Exceptions/NewKeywordNotRedefinable.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class NewKeywordNotRedefinable extends ConfigException +{ + protected $message = 'Please set {"new-keyword-redefinable": true} to redefine instantiations'; +} diff --git a/src/Exceptions/NoResult.php b/src/Exceptions/NoResult.php new file mode 100644 index 0000000..226778e --- /dev/null +++ b/src/Exceptions/NoResult.php @@ -0,0 +1,15 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +use Patchwork\Utils; + +class NoResult extends Exception +{ +} diff --git a/src/Exceptions/NonNullToVoid.php b/src/Exceptions/NonNullToVoid.php new file mode 100644 index 0000000..bd8e50a --- /dev/null +++ b/src/Exceptions/NonNullToVoid.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class NonNullToVoid extends Exception +{ + protected $message = 'A redefinition of a void-typed callable attempted to return a non-null result'; +} diff --git a/src/Exceptions/NotUserDefined.php b/src/Exceptions/NotUserDefined.php new file mode 100644 index 0000000..a1c594a --- /dev/null +++ b/src/Exceptions/NotUserDefined.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class NotUserDefined extends CallbackException +{ + protected $message = 'Please include {"redefinable-internals": ["%s"]} in your patchwork.json.'; +} diff --git a/src/Exceptions/StackEmpty.php b/src/Exceptions/StackEmpty.php new file mode 100644 index 0000000..a055b60 --- /dev/null +++ b/src/Exceptions/StackEmpty.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +class StackEmpty extends Exception +{ + protected $message = "There are no calls in the dispatch stack"; +} diff --git a/src/Redefinitions/LanguageConstructs.php b/src/Redefinitions/LanguageConstructs/functions.php similarity index 100% rename from src/Redefinitions/LanguageConstructs.php rename to src/Redefinitions/LanguageConstructs/functions.php diff --git a/src/Stack/State.php b/src/Stack/State.php new file mode 100644 index 0000000..7b416b0 --- /dev/null +++ b/src/Stack/State.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Stack; + +class State +{ + static $items = []; +} diff --git a/src/Stack.php b/src/Stack/functions.php similarity index 97% rename from src/Stack.php rename to src/Stack/functions.php index aab8f04..b606e8e 100644 --- a/src/Stack.php +++ b/src/Stack/functions.php @@ -88,8 +88,3 @@ function allCalledClasses() return $calledClass; }, State::$items); } - -class State -{ - static $items = []; -} diff --git a/src/Utils/State.php b/src/Utils/State.php new file mode 100644 index 0000000..816669d --- /dev/null +++ b/src/Utils/State.php @@ -0,0 +1,14 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Utils; + +class State +{ + static $missedCallables = []; +} diff --git a/src/Utils.php b/src/Utils/functions.php similarity index 99% rename from src/Utils.php rename to src/Utils/functions.php index a6c8e21..a763a7c 100644 --- a/src/Utils.php +++ b/src/Utils/functions.php @@ -377,8 +377,3 @@ function args() { return func_get_args(); } - -class State -{ - static $missedCallables = []; -} diff --git a/src/functions.php b/src/functions.php new file mode 100644 index 0000000..cbe87ad --- /dev/null +++ b/src/functions.php @@ -0,0 +1,85 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork; + +function redefine($subject, callable $content) +{ + $handle = null; + foreach (array_slice(func_get_args(), 1) as $content) { + $handle = CallRerouting\connect($subject, $content, $handle); + } + $handle->silence(); + return $handle; +} + +function relay(array $args = null) +{ + return CallRerouting\relay($args); +} + +function fallBack() +{ + throw new Exceptions\NoResult; +} + +function restore(CallRerouting\Handle $handle) +{ + $handle->expire(); +} + +function restoreAll() +{ + CallRerouting\disconnectAll(); +} + +function silence(CallRerouting\Handle $handle) +{ + $handle->silence(); +} + +function assertEventuallyDefined(CallRerouting\Handle $handle) +{ + $handle->unsilence(); +} + +function getClass() +{ + return Stack\top('class'); +} + +function getCalledClass() +{ + return Stack\topCalledClass(); +} + +function getFunction() +{ + return Stack\top('function'); +} + +function getMethod() +{ + return getClass() . '::' . getFunction(); +} + +function configure() +{ + Config\locate(); +} + +function hasMissed($callable) +{ + return Utils\callableWasMissed($callable); +} + +function always($value) +{ + return function() use ($value) { + return $value; + }; +}