Файловый менеджер - Редактировать - /home/tuudkjt/globeasy/wp-includes/ID3/php-di.zip
Назад
PK �x,]Rm��' ' php-di/README.mdnu ��� --- layout: home --- [](https://php-di.org/) [](https://packagist.org/packages/PHP-DI/PHP-DI) [](https://packagist.org/packages/PHP-DI/PHP-DI) [](http://isitmaintained.com/project/PHP-DI/PHP-DI "Average time to resolve an issue") [](http://isitmaintained.com/project/PHP-DI/PHP-DI "Percentage of issues still open") PHP-DI is a dependency injection container meant to be practical, powerful, and framework-agnostic. Read more on the website: **[php-di.org](https://php-di.org)** Get community support in the Gitter chat room: [](https://gitter.im/PHP-DI/PHP-DI) ## For Enterprise *Available as part of the Tidelift Subscription* The maintainers of php-di/php-di and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-php-di-php-di?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) PK �x,]G�W$! ! php-di/support.mdnu ��� --- layout: documentation current_menu: enterprise-support title: Enterprise support for PHP-DI --- # PHP-DI for Enterprise > *Available as part of the Tidelift Subscription* Tidelift is working with the maintainers of PHP-DI and thousands of other open source projects to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. #### [Learn more](https://tidelift.com/subscription/pkg/packagist-php-di-php-di?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) | [**Request a demo**](https://tidelift.com/subscription/request-a-demo?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) ## Enterprise-ready open source software—managed for you The Tidelift Subscription is a managed open source subscription for application dependencies covering millions of open source projects across JavaScript, Python, Java, PHP, Ruby, .NET, and more. Your subscription includes: - **Security updates** Tidelift’s security response team coordinates patches for new breaking security vulnerabilities and alerts immediately through a private channel, so your software supply chain is always secure. - **Licensing verification and indemnification** Tidelift verifies license information to enable easy policy enforcement and adds intellectual property indemnification to cover creators and users in case something goes wrong. You always have a 100% up-to-date bill of materials for your dependencies to share with your legal team, customers, or partners. - **Maintenance and code improvement** Tidelift ensures the software you rely on keeps working as long as you need it to work. Your managed dependencies are actively maintained and we recruit additional maintainers where required. - **Package selection and version guidance** We help you choose the best open source packages from the start—and then guide you through updates to stay on the best releases as new issues arise. - **Roadmap input** Take a seat at the table with the creators behind the software you use. Tidelift’s participating maintainers earn more income as their software is used by more subscribers, so they’re interested in knowing what you need. - **Tooling and cloud integration** Tidelift works with GitHub, GitLab, BitBucket, and more. We support every cloud platform (and other deployment targets, too). The end result? All of the capabilities you expect from commercial-grade software, for the full breadth of open source you use. That means less time grappling with esoteric open source trivia, and more time building your own applications—and your business. [Learn more](https://tidelift.com/subscription/pkg/packagist-php-di-php-di?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) | [**Request a demo**](https://tidelift.com/subscription/request-a-demo?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) PK �x,]'y/�� � php-di/src/FactoryInterface.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI; /** * Describes the basic interface of a factory. * * @api * * @since 4.0 * @author Matthieu Napoli <matthieu@mnapoli.fr> */ interface FactoryInterface { /** * Resolves an entry by its name. If given a class name, it will return a new instance of that class. * * @param string $name Entry name or a class name. * @param array $parameters Optional parameters to use to build the entry. Use this to force specific * parameters to specific values. Parameters not defined in this array will * be automatically resolved. * * @throws \InvalidArgumentException The name parameter must be of type string. * @throws DependencyException Error while resolving the entry. * @throws NotFoundException No entry or class found for the given name. * @return mixed */ public function make($name, array $parameters = []); } PK �x,]�� �� � php-di/src/functions.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI; use Rvx\DI\Definition\ArrayDefinitionExtension; use Rvx\DI\Definition\EnvironmentVariableDefinition; use Rvx\DI\Definition\Helper\AutowireDefinitionHelper; use Rvx\DI\Definition\Helper\CreateDefinitionHelper; use Rvx\DI\Definition\Helper\FactoryDefinitionHelper; use Rvx\DI\Definition\Reference; use Rvx\DI\Definition\StringDefinition; use Rvx\DI\Definition\ValueDefinition; if (!\function_exists('Rvx\\DI\\value')) { /** * Helper for defining a value. * * @param mixed $value */ function value($value) : ValueDefinition { return new ValueDefinition($value); } } if (!\function_exists('Rvx\\DI\\create')) { /** * Helper for defining an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ function create(string $className = null) : CreateDefinitionHelper { return new CreateDefinitionHelper($className); } } if (!\function_exists('Rvx\\DI\\autowire')) { /** * Helper for autowiring an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ function autowire(string $className = null) : AutowireDefinitionHelper { return new AutowireDefinitionHelper($className); } } if (!\function_exists('Rvx\\DI\\factory')) { /** * Helper for defining a container entry using a factory function/callable. * * @param callable $factory The factory is a callable that takes the container as parameter * and returns the value to register in the container. */ function factory($factory) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($factory); } } if (!\function_exists('Rvx\\DI\\decorate')) { /** * Decorate the previous definition using a callable. * * Example: * * 'foo' => decorate(function ($foo, $container) { * return new CachedFoo($foo, $container->get('cache')); * }) * * @param callable $callable The callable takes the decorated object as first parameter and * the container as second. */ function decorate($callable) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($callable, \true); } } if (!\function_exists('Rvx\\DI\\get')) { /** * Helper for referencing another container entry in an object definition. */ function get(string $entryName) : Reference { return new Reference($entryName); } } if (!\function_exists('Rvx\\DI\\env')) { /** * Helper for referencing environment variables. * * @param string $variableName The name of the environment variable. * @param mixed $defaultValue The default value to be used if the environment variable is not defined. */ function env(string $variableName, $defaultValue = null) : EnvironmentVariableDefinition { // Only mark as optional if the default value was *explicitly* provided. $isOptional = 2 === \func_num_args(); return new EnvironmentVariableDefinition($variableName, $isOptional, $defaultValue); } } if (!\function_exists('Rvx\\DI\\add')) { /** * Helper for extending another definition. * * Example: * * 'log.backends' => DI\add(DI\get('My\Custom\LogBackend')) * * or: * * 'log.backends' => DI\add([ * DI\get('My\Custom\LogBackend') * ]) * * @param mixed|array $values A value or an array of values to add to the array. * * @since 5.0 */ function add($values) : ArrayDefinitionExtension { if (!\is_array($values)) { $values = [$values]; } return new ArrayDefinitionExtension($values); } } if (!\function_exists('Rvx\\DI\\string')) { /** * Helper for concatenating strings. * * Example: * * 'log.filename' => DI\string('{app.path}/app.log') * * @param string $expression A string expression. Use the `{}` placeholders to reference other container entries. * * @since 5.0 */ function string(string $expression) : StringDefinition { return new StringDefinition($expression); } } PK �x,]ef���9 �9 php-di/src/Compiler/Compiler.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Compiler; use function chmod; use Rvx\DI\Definition\ArrayDefinition; use Rvx\DI\Definition\DecoratorDefinition; use Rvx\DI\Definition\Definition; use Rvx\DI\Definition\EnvironmentVariableDefinition; use Rvx\DI\Definition\Exception\InvalidDefinition; use Rvx\DI\Definition\FactoryDefinition; use Rvx\DI\Definition\ObjectDefinition; use Rvx\DI\Definition\Reference; use Rvx\DI\Definition\Source\DefinitionSource; use Rvx\DI\Definition\StringDefinition; use Rvx\DI\Definition\ValueDefinition; use Rvx\DI\DependencyException; use Rvx\DI\Proxy\ProxyFactory; use function dirname; use function file_put_contents; use InvalidArgumentException; use Rvx\Laravel\SerializableClosure\Support\ReflectionClosure; use function rename; use function sprintf; use function tempnam; use function unlink; /** * Compiles the container into PHP code much more optimized for performances. * * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class Compiler { /** * @var string */ private $containerClass; /** * @var string */ private $containerParentClass; /** * Definitions indexed by the entry name. The value can be null if the definition needs to be fetched. * * Keys are strings, values are `Definition` objects or null. * * @var \ArrayIterator */ private $entriesToCompile; /** * Progressive counter for definitions. * * Each key in $entriesToCompile is defined as 'SubEntry' + counter * and each definition has always the same key in the CompiledContainer * if PHP-DI configuration does not change. * * @var int */ private $subEntryCounter; /** * Progressive counter for CompiledContainer get methods. * * Each CompiledContainer method name is defined as 'get' + counter * and remains the same after each recompilation * if PHP-DI configuration does not change. * * @var int */ private $methodMappingCounter; /** * Map of entry names to method names. * * @var string[] */ private $entryToMethodMapping = []; /** * @var string[] */ private $methods = []; /** * @var bool */ private $autowiringEnabled; /** * @var ProxyFactory */ private $proxyFactory; public function __construct(ProxyFactory $proxyFactory) { $this->proxyFactory = $proxyFactory; } public function getProxyFactory() : ProxyFactory { return $this->proxyFactory; } /** * Compile the container. * * @return string The compiled container file name. */ public function compile(DefinitionSource $definitionSource, string $directory, string $className, string $parentClassName, bool $autowiringEnabled) : string { $fileName = \rtrim($directory, '/') . '/' . $className . '.php'; if (\file_exists($fileName)) { // The container is already compiled return $fileName; } $this->autowiringEnabled = $autowiringEnabled; // Validate that a valid class name was provided $validClassName = \preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $className); if (!$validClassName) { throw new InvalidArgumentException("The container cannot be compiled: `{$className}` is not a valid PHP class name"); } $this->entriesToCompile = new \ArrayIterator($definitionSource->getDefinitions()); // We use an ArrayIterator so that we can keep adding new items to the list while we compile entries foreach ($this->entriesToCompile as $entryName => $definition) { $silenceErrors = \false; // This is an entry found by reference during autowiring if (!$definition) { $definition = $definitionSource->getDefinition($entryName); // We silence errors for those entries because type-hints may reference interfaces/abstract classes // which could later be defined, or even not used (we don't want to block the compilation for those) $silenceErrors = \true; } if (!$definition) { // We do not throw a `NotFound` exception here because the dependency // could be defined at runtime continue; } // Check that the definition can be compiled $errorMessage = $this->isCompilable($definition); if ($errorMessage !== \true) { continue; } try { $this->compileDefinition($entryName, $definition); } catch (InvalidDefinition $e) { if ($silenceErrors) { // forget the entry unset($this->entryToMethodMapping[$entryName]); } else { throw $e; } } } $this->containerClass = $className; $this->containerParentClass = $parentClassName; \ob_start(); require __DIR__ . '/Template.php'; $fileContent = \ob_get_clean(); $fileContent = "<?php\n" . $fileContent; $this->createCompilationDirectory(dirname($fileName)); $this->writeFileAtomic($fileName, $fileContent); return $fileName; } private function writeFileAtomic(string $fileName, string $content) : int { $tmpFile = @tempnam(dirname($fileName), 'swap-compile'); if ($tmpFile === \false) { throw new InvalidArgumentException(sprintf('Error while creating temporary file in %s', dirname($fileName))); } @chmod($tmpFile, 0666); $written = file_put_contents($tmpFile, $content); if ($written === \false) { @unlink($tmpFile); throw new InvalidArgumentException(sprintf('Error while writing to %s', $tmpFile)); } @chmod($tmpFile, 0666); $renamed = @rename($tmpFile, $fileName); if (!$renamed) { @unlink($tmpFile); throw new InvalidArgumentException(sprintf('Error while renaming %s to %s', $tmpFile, $fileName)); } return $written; } /** * @throws DependencyException * @throws InvalidDefinition * @return string The method name */ private function compileDefinition(string $entryName, Definition $definition) : string { // Generate a unique method name $methodName = 'get' . ++$this->methodMappingCounter; $this->entryToMethodMapping[$entryName] = $methodName; switch (\true) { case $definition instanceof ValueDefinition: $value = $definition->getValue(); $code = 'return ' . $this->compileValue($value) . ';'; break; case $definition instanceof Reference: $targetEntryName = $definition->getTargetEntryName(); $code = 'return $this->delegateContainer->get(' . $this->compileValue($targetEntryName) . ');'; // If this method is not yet compiled we store it for compilation if (!isset($this->entriesToCompile[$targetEntryName])) { $this->entriesToCompile[$targetEntryName] = null; } break; case $definition instanceof StringDefinition: $entryName = $this->compileValue($definition->getName()); $expression = $this->compileValue($definition->getExpression()); $code = 'return \\DI\\Definition\\StringDefinition::resolveExpression(' . $entryName . ', ' . $expression . ', $this->delegateContainer);'; break; case $definition instanceof EnvironmentVariableDefinition: $variableName = $this->compileValue($definition->getVariableName()); $isOptional = $this->compileValue($definition->isOptional()); $defaultValue = $this->compileValue($definition->getDefaultValue()); $code = <<<PHP \$value = \$_ENV[{$variableName}] ?? \$_SERVER[{$variableName}] ?? getenv({$variableName}); if (false !== \$value) return \$value; if (!{$isOptional}) { throw new \\DI\\Definition\\Exception\\InvalidDefinition("The environment variable '{$definition->getVariableName()}' has not been defined"); } return {$defaultValue}; PHP; break; case $definition instanceof ArrayDefinition: try { $code = 'return ' . $this->compileValue($definition->getValues()) . ';'; } catch (\Exception $e) { throw new DependencyException(sprintf('Error while compiling %s. %s', $definition->getName(), $e->getMessage()), 0, $e); } break; case $definition instanceof ObjectDefinition: $compiler = new ObjectCreationCompiler($this); $code = $compiler->compile($definition); $code .= "\n return \$object;"; break; case $definition instanceof DecoratorDefinition: $decoratedDefinition = $definition->getDecoratedDefinition(); if (!$decoratedDefinition instanceof Definition) { if (!$definition->getName()) { throw new InvalidDefinition('Decorators cannot be nested in another definition'); } throw new InvalidDefinition(sprintf('Entry "%s" decorates nothing: no previous definition with the same name was found', $definition->getName())); } $code = sprintf('return call_user_func(%s, %s, $this->delegateContainer);', $this->compileValue($definition->getCallable()), $this->compileValue($decoratedDefinition)); break; case $definition instanceof FactoryDefinition: $value = $definition->getCallable(); // Custom error message to help debugging $isInvokableClass = \is_string($value) && \class_exists($value) && \method_exists($value, '__invoke'); if ($isInvokableClass && !$this->autowiringEnabled) { throw new InvalidDefinition(sprintf('Entry "%s" cannot be compiled. Invokable classes cannot be automatically resolved if autowiring is disabled on the container, you need to enable autowiring or define the entry manually.', $entryName)); } $definitionParameters = ''; if (!empty($definition->getParameters())) { $definitionParameters = ', ' . $this->compileValue($definition->getParameters()); } $code = sprintf('return $this->resolveFactory(%s, %s%s);', $this->compileValue($value), \var_export($entryName, \true), $definitionParameters); break; default: // This case should not happen (so it cannot be tested) throw new \Exception('Cannot compile definition of type ' . \get_class($definition)); } $this->methods[$methodName] = $code; return $methodName; } public function compileValue($value) : string { // Check that the value can be compiled $errorMessage = $this->isCompilable($value); if ($errorMessage !== \true) { throw new InvalidDefinition($errorMessage); } if ($value instanceof Definition) { // Give it an arbitrary unique name $subEntryName = 'subEntry' . ++$this->subEntryCounter; // Compile the sub-definition in another method $methodName = $this->compileDefinition($subEntryName, $value); // The value is now a method call to that method (which returns the value) return "\$this->{$methodName}()"; } if (\is_array($value)) { $value = \array_map(function ($value, $key) { $compiledValue = $this->compileValue($value); $key = \var_export($key, \true); return " {$key} => {$compiledValue},\n"; }, $value, \array_keys($value)); $value = \implode('', $value); return "[\n{$value} ]"; } if ($value instanceof \Closure) { return $this->compileClosure($value); } return \var_export($value, \true); } private function createCompilationDirectory(string $directory) { if (!\is_dir($directory) && !@\mkdir($directory, 0777, \true) && !\is_dir($directory)) { throw new InvalidArgumentException(sprintf('Compilation directory does not exist and cannot be created: %s.', $directory)); } if (!\is_writable($directory)) { throw new InvalidArgumentException(sprintf('Compilation directory is not writable: %s.', $directory)); } } /** * @return string|true If true is returned that means that the value is compilable. */ private function isCompilable($value) { if ($value instanceof ValueDefinition) { return $this->isCompilable($value->getValue()); } if ($value instanceof DecoratorDefinition) { if (empty($value->getName())) { return 'Decorators cannot be nested in another definition'; } } // All other definitions are compilable if ($value instanceof Definition) { return \true; } if ($value instanceof \Closure) { return \true; } if (\is_object($value)) { return 'An object was found but objects cannot be compiled'; } if (\is_resource($value)) { return 'A resource was found but resources cannot be compiled'; } return \true; } /** * @throws \DI\Definition\Exception\InvalidDefinition */ private function compileClosure(\Closure $closure) : string { $reflector = new ReflectionClosure($closure); if ($reflector->getUseVariables()) { throw new InvalidDefinition('Cannot compile closures which import variables using the `use` keyword'); } if ($reflector->isBindingRequired() || $reflector->isScopeRequired()) { throw new InvalidDefinition('Cannot compile closures which use $this or self/static/parent references'); } // Force all closures to be static (add the `static` keyword), i.e. they can't use // $this, which makes sense since their code is copied into another class. $code = ($reflector->isStatic() ? '' : 'static ') . $reflector->getCode(); $code = \trim($code, "\t\n\r;"); return $code; } } PK �x,]�HQ9� � , php-di/src/Compiler/RequestedEntryHolder.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Compiler; use Rvx\DI\Factory\RequestedEntry; /** * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class RequestedEntryHolder implements RequestedEntry { /** * @var string */ private $name; public function __construct(string $name) { $this->name = $name; } public function getName() : string { return $this->name; } } PK �x,]���2Z Z . php-di/src/Compiler/ObjectCreationCompiler.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Compiler; use Rvx\DI\Definition\Exception\InvalidDefinition; use Rvx\DI\Definition\ObjectDefinition; use Rvx\DI\Definition\ObjectDefinition\MethodInjection; use ReflectionClass; use ReflectionMethod; use ReflectionParameter; use ReflectionProperty; /** * Compiles an object definition into native PHP code that, when executed, creates the object. * * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class ObjectCreationCompiler { /** * @var Compiler */ private $compiler; public function __construct(Compiler $compiler) { $this->compiler = $compiler; } public function compile(ObjectDefinition $definition) : string { $this->assertClassIsNotAnonymous($definition); $this->assertClassIsInstantiable($definition); // Lazy? if ($definition->isLazy()) { return $this->compileLazyDefinition($definition); } try { $classReflection = new ReflectionClass($definition->getClassName()); $constructorArguments = $this->resolveParameters($definition->getConstructorInjection(), $classReflection->getConstructor()); $dumpedConstructorArguments = \array_map(function ($value) { return $this->compiler->compileValue($value); }, $constructorArguments); $code = []; $code[] = \sprintf('$object = new %s(%s);', $definition->getClassName(), \implode(', ', $dumpedConstructorArguments)); // Property injections foreach ($definition->getPropertyInjections() as $propertyInjection) { $value = $propertyInjection->getValue(); $value = $this->compiler->compileValue($value); $className = $propertyInjection->getClassName() ?: $definition->getClassName(); $property = new ReflectionProperty($className, $propertyInjection->getPropertyName()); if ($property->isPublic()) { $code[] = \sprintf('$object->%s = %s;', $propertyInjection->getPropertyName(), $value); } else { // Private/protected property $code[] = \sprintf('\\DI\\Definition\\Resolver\\ObjectCreator::setPrivatePropertyValue(%s, $object, \'%s\', %s);', \var_export($propertyInjection->getClassName(), \true), $propertyInjection->getPropertyName(), $value); } } // Method injections foreach ($definition->getMethodInjections() as $methodInjection) { $methodReflection = new \ReflectionMethod($definition->getClassName(), $methodInjection->getMethodName()); $parameters = $this->resolveParameters($methodInjection, $methodReflection); $dumpedParameters = \array_map(function ($value) { return $this->compiler->compileValue($value); }, $parameters); $code[] = \sprintf('$object->%s(%s);', $methodInjection->getMethodName(), \implode(', ', $dumpedParameters)); } } catch (InvalidDefinition $e) { throw InvalidDefinition::create($definition, \sprintf('Entry "%s" cannot be compiled: %s', $definition->getName(), $e->getMessage())); } return \implode("\n ", $code); } public function resolveParameters(MethodInjection $definition = null, ReflectionMethod $method = null) : array { $args = []; if (!$method) { return $args; } $definitionParameters = $definition ? $definition->getParameters() : []; foreach ($method->getParameters() as $index => $parameter) { if (\array_key_exists($index, $definitionParameters)) { // Look in the definition $value =& $definitionParameters[$index]; } elseif ($parameter->isOptional()) { // If the parameter is optional and wasn't specified, we take its default value $args[] = $this->getParameterDefaultValue($parameter, $method); continue; } else { throw new InvalidDefinition(\sprintf('Parameter $%s of %s has no value defined or guessable', $parameter->getName(), $this->getFunctionName($method))); } $args[] =& $value; } return $args; } private function compileLazyDefinition(ObjectDefinition $definition) : string { $subDefinition = clone $definition; $subDefinition->setLazy(\false); $subDefinition = $this->compiler->compileValue($subDefinition); $this->compiler->getProxyFactory()->generateProxyClass($definition->getClassName()); return <<<PHP \$object = \$this->proxyFactory->createProxy( '{$definition->getClassName()}', function (&\$wrappedObject, \$proxy, \$method, \$params, &\$initializer) { \$wrappedObject = {$subDefinition}; \$initializer = null; // turning off further lazy initialization return true; } ); PHP; } /** * Returns the default value of a function parameter. * * @throws InvalidDefinition Can't get default values from PHP internal classes and functions * @return mixed */ private function getParameterDefaultValue(ReflectionParameter $parameter, ReflectionMethod $function) { try { return $parameter->getDefaultValue(); } catch (\ReflectionException $e) { throw new InvalidDefinition(\sprintf('The parameter "%s" of %s has no type defined or guessable. It has a default value, ' . 'but the default value can\'t be read through Reflection because it is a PHP internal class.', $parameter->getName(), $this->getFunctionName($function))); } } private function getFunctionName(ReflectionMethod $method) : string { return $method->getName() . '()'; } private function assertClassIsNotAnonymous(ObjectDefinition $definition) { if (\strpos($definition->getClassName(), '@') !== \false) { throw InvalidDefinition::create($definition, \sprintf('Entry "%s" cannot be compiled: anonymous classes cannot be compiled', $definition->getName())); } } private function assertClassIsInstantiable(ObjectDefinition $definition) { if ($definition->isInstantiable()) { return; } $message = !$definition->classExists() ? 'Entry "%s" cannot be compiled: the class doesn\'t exist' : 'Entry "%s" cannot be compiled: the class is not instantiable'; throw InvalidDefinition::create($definition, \sprintf($message, $definition->getName())); } } PK �x,]j�� � � ! php-di/src/Proxy/ProxyFactory.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Proxy; use Rvx\ProxyManager\Configuration; use Rvx\ProxyManager\Factory\LazyLoadingValueHolderFactory; use Rvx\ProxyManager\FileLocator\FileLocator; use Rvx\ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; use Rvx\ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy; use Rvx\ProxyManager\Proxy\LazyLoadingInterface; /** * Creates proxy classes. * * Wraps Ocramius/ProxyManager LazyLoadingValueHolderFactory. * * @see \ProxyManager\Factory\LazyLoadingValueHolderFactory * * @since 5.0 * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class ProxyFactory { /** * If true, write the proxies to disk to improve performances. * @var bool */ private $writeProxiesToFile; /** * Directory where to write the proxies (if $writeProxiesToFile is enabled). * @var string|null */ private $proxyDirectory; /** * @var LazyLoadingValueHolderFactory|null */ private $proxyManager; public function __construct(bool $writeProxiesToFile = \false, string $proxyDirectory = null) { $this->writeProxiesToFile = $writeProxiesToFile; $this->proxyDirectory = $proxyDirectory; } /** * Creates a new lazy proxy instance of the given class with * the given initializer. * * @param string $className name of the class to be proxied * @param \Closure $initializer initializer to be passed to the proxy */ public function createProxy(string $className, \Closure $initializer) : LazyLoadingInterface { $this->createProxyManager(); return $this->proxyManager->createProxy($className, $initializer); } /** * Generates and writes the proxy class to file. * * @param string $className name of the class to be proxied */ public function generateProxyClass(string $className) { // If proxy classes a written to file then we pre-generate the class // If they are not written to file then there is no point to do this if ($this->writeProxiesToFile) { $this->createProxyManager(); $this->createProxy($className, function () { }); } } private function createProxyManager() { if ($this->proxyManager !== null) { return; } if (!\class_exists(Configuration::class)) { throw new \RuntimeException('The ocramius/proxy-manager library is not installed. Lazy injection requires that library to be installed with Composer in order to work. Run "composer require ocramius/proxy-manager:~2.0".'); } $config = new Configuration(); if ($this->writeProxiesToFile) { $config->setProxiesTargetDir($this->proxyDirectory); $config->setGeneratorStrategy(new FileWriterGeneratorStrategy(new FileLocator($this->proxyDirectory))); // @phpstan-ignore-next-line \spl_autoload_register($config->getProxyAutoloader()); } else { $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); } $this->proxyManager = new LazyLoadingValueHolderFactory($config); } } PK �x,]m��]� � $ php-di/src/Annotation/Injectable.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Annotation; /** * "Injectable" annotation. * * Marks a class as injectable * * @api * * @Annotation * @Target("CLASS") * * @author Domenic Muskulus <domenic@muskulus.eu> * @author Matthieu Napoli <matthieu@mnapoli.fr> */ final class Injectable { /** * Should the object be lazy-loaded. * @var bool|null */ private $lazy; public function __construct(array $values) { if (isset($values['lazy'])) { $this->lazy = (bool) $values['lazy']; } } /** * @return bool|null */ public function isLazy() { return $this->lazy; } } PK �x,]�4�7� � php-di/src/Annotation/Inject.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Annotation; use Rvx\DI\Definition\Exception\InvalidAnnotation; /** * "Inject" annotation. * * Marks a property or method as an injection point * * @api * * @Annotation * @Target({"METHOD","PROPERTY"}) * * @author Matthieu Napoli <matthieu@mnapoli.fr> */ final class Inject { /** * Entry name. * @var string */ private $name; /** * Parameters, indexed by the parameter number (index) or name. * * Used if the annotation is set on a method * @var array */ private $parameters = []; /** * @throws InvalidAnnotation */ public function __construct(array $values) { // Process the parameters as a list AND as a parameter array (we don't know on what the annotation is) // @Inject(name="foo") if (isset($values['name']) && \is_string($values['name'])) { $this->name = $values['name']; return; } // @Inject if (!isset($values['value'])) { return; } $values = $values['value']; // @Inject("foo") if (\is_string($values)) { $this->name = $values; } // @Inject({...}) on a method if (\is_array($values)) { foreach ($values as $key => $value) { if (!\is_string($value)) { throw new InvalidAnnotation(\sprintf('@Inject({"param" = "value"}) expects "value" to be a string, %s given.', \json_encode($value))); } $this->parameters[$key] = $value; } } } /** * @return string|null Name of the entry to inject */ public function getName() { return $this->name; } /** * @return array Parameters, indexed by the parameter number (index) or name */ public function getParameters() : array { return $this->parameters; } } PK �x,]�"��� � % php-di/src/Factory/RequestedEntry.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Factory; /** * Represents the container entry that was requested. * * Implementations of this interface can be injected in factory parameters in order * to know what was the name of the requested entry. * * @api * * @author Matthieu Napoli <matthieu@mnapoli.fr> */ interface RequestedEntry { /** * Returns the name of the entry that was requested by the container. */ public function getName() : string; } PK �x,]}��� � / php-di/src/Invoker/FactoryParameterResolver.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Invoker; use Rvx\Invoker\ParameterResolver\ParameterResolver; use Rvx\Psr\Container\ContainerInterface; use ReflectionFunctionAbstract; use ReflectionNamedType; /** * Inject the container, the definition or any other service using type-hints. * * {@internal This class is similar to TypeHintingResolver and TypeHintingContainerResolver, * we use this instead for performance reasons} * * @author Quim Calpe <quim@kalpe.com> * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class FactoryParameterResolver implements ParameterResolver { /** * @var ContainerInterface */ private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function getParameters(ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters) : array { $parameters = $reflection->getParameters(); // Skip parameters already resolved if (!empty($resolvedParameters)) { $parameters = \array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { $parameterType = $parameter->getType(); if (!$parameterType) { // No type continue; } if (!$parameterType instanceof ReflectionNamedType) { // Union types are not supported continue; } if ($parameterType->isBuiltin()) { // Primitive types are not supported continue; } $parameterClass = $parameterType->getName(); if ($parameterClass === 'Psr\\Container\\ContainerInterface') { $resolvedParameters[$index] = $this->container; } elseif ($parameterClass === 'DI\\Factory\\RequestedEntry') { // By convention the second parameter is the definition $resolvedParameters[$index] = $providedParameters[1]; } elseif ($this->container->has($parameterClass)) { $resolvedParameters[$index] = $this->container->get($parameterClass); } } return $resolvedParameters; } } PK �x,]��FҾ � 2 php-di/src/Invoker/DefinitionParameterResolver.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Invoker; use Rvx\DI\Definition\Definition; use Rvx\DI\Definition\Helper\DefinitionHelper; use Rvx\DI\Definition\Resolver\DefinitionResolver; use Rvx\Invoker\ParameterResolver\ParameterResolver; use ReflectionFunctionAbstract; /** * Resolves callable parameters using definitions. * * @since 5.0 * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class DefinitionParameterResolver implements ParameterResolver { /** * @var DefinitionResolver */ private $definitionResolver; public function __construct(DefinitionResolver $definitionResolver) { $this->definitionResolver = $definitionResolver; } public function getParameters(ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters) : array { // Skip parameters already resolved if (!empty($resolvedParameters)) { $providedParameters = \array_diff_key($providedParameters, $resolvedParameters); } foreach ($providedParameters as $key => $value) { if ($value instanceof DefinitionHelper) { $value = $value->getDefinition(''); } if (!$value instanceof Definition) { continue; } $value = $this->definitionResolver->resolve($value); if (\is_int($key)) { // Indexed by position $resolvedParameters[$key] = $value; } else { // Indexed by parameter name // TODO optimize? $reflectionParameters = $reflection->getParameters(); foreach ($reflectionParameters as $reflectionParameter) { if ($key === $reflectionParameter->name) { $resolvedParameters[$reflectionParameter->getPosition()] = $value; } } } } return $resolvedParameters; } } PK �x,]�5 5 php-di/src/Container.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI; use Rvx\DI\Definition\Definition; use Rvx\DI\Definition\Exception\InvalidDefinition; use Rvx\DI\Definition\FactoryDefinition; use Rvx\DI\Definition\Helper\DefinitionHelper; use Rvx\DI\Definition\InstanceDefinition; use Rvx\DI\Definition\ObjectDefinition; use Rvx\DI\Definition\Resolver\DefinitionResolver; use Rvx\DI\Definition\Resolver\ResolverDispatcher; use Rvx\DI\Definition\Source\DefinitionArray; use Rvx\DI\Definition\Source\MutableDefinitionSource; use Rvx\DI\Definition\Source\ReflectionBasedAutowiring; use Rvx\DI\Definition\Source\SourceChain; use Rvx\DI\Definition\ValueDefinition; use Rvx\DI\Invoker\DefinitionParameterResolver; use Rvx\DI\Proxy\ProxyFactory; use InvalidArgumentException; use Rvx\Invoker\Invoker; use Rvx\Invoker\InvokerInterface; use Rvx\Invoker\ParameterResolver\AssociativeArrayResolver; use Rvx\Invoker\ParameterResolver\Container\TypeHintContainerResolver; use Rvx\Invoker\ParameterResolver\DefaultValueResolver; use Rvx\Invoker\ParameterResolver\NumericArrayResolver; use Rvx\Invoker\ParameterResolver\ResolverChain; use Rvx\Psr\Container\ContainerInterface; /** * Dependency Injection Container. * * @api * * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class Container implements ContainerInterface, FactoryInterface, InvokerInterface { /** * Map of entries that are already resolved. * @var array */ protected $resolvedEntries = []; /** * @var MutableDefinitionSource */ private $definitionSource; /** * @var DefinitionResolver */ private $definitionResolver; /** * Map of definitions that are already fetched (local cache). * * @var (Definition|null)[] */ private $fetchedDefinitions = []; /** * Array of entries being resolved. Used to avoid circular dependencies and infinite loops. * @var array */ protected $entriesBeingResolved = []; /** * @var InvokerInterface|null */ private $invoker; /** * Container that wraps this container. If none, points to $this. * * @var ContainerInterface */ protected $delegateContainer; /** * @var ProxyFactory */ protected $proxyFactory; /** * Use `$container = new Container()` if you want a container with the default configuration. * * If you want to customize the container's behavior, you are discouraged to create and pass the * dependencies yourself, the ContainerBuilder class is here to help you instead. * * @see ContainerBuilder * * @param ContainerInterface $wrapperContainer If the container is wrapped by another container. */ public function __construct(MutableDefinitionSource $definitionSource = null, ProxyFactory $proxyFactory = null, ContainerInterface $wrapperContainer = null) { $this->delegateContainer = $wrapperContainer ?: $this; $this->definitionSource = $definitionSource ?: $this->createDefaultDefinitionSource(); $this->proxyFactory = $proxyFactory ?: new ProxyFactory(\false); $this->definitionResolver = new ResolverDispatcher($this->delegateContainer, $this->proxyFactory); // Auto-register the container $this->resolvedEntries = [self::class => $this, ContainerInterface::class => $this->delegateContainer, FactoryInterface::class => $this, InvokerInterface::class => $this]; } /** * Returns an entry of the container by its name. * * @template T * @param string|class-string<T> $name Entry name or a class name. * * @throws DependencyException Error while resolving the entry. * @throws NotFoundException No entry found for the given name. * @return mixed|T */ public function get($name) { // If the entry is already resolved we return it if (isset($this->resolvedEntries[$name]) || \array_key_exists($name, $this->resolvedEntries)) { return $this->resolvedEntries[$name]; } $definition = $this->getDefinition($name); if (!$definition) { throw new NotFoundException("No entry or class found for '{$name}'"); } $value = $this->resolveDefinition($definition); $this->resolvedEntries[$name] = $value; return $value; } /** * @param string $name * * @return Definition|null */ private function getDefinition($name) { // Local cache that avoids fetching the same definition twice if (!\array_key_exists($name, $this->fetchedDefinitions)) { $this->fetchedDefinitions[$name] = $this->definitionSource->getDefinition($name); } return $this->fetchedDefinitions[$name]; } /** * Build an entry of the container by its name. * * This method behave like get() except resolves the entry again every time. * For example if the entry is a class then a new instance will be created each time. * * This method makes the container behave like a factory. * * @template T * @param string|class-string<T> $name Entry name or a class name. * @param array $parameters Optional parameters to use to build the entry. Use this to force * specific parameters to specific values. Parameters not defined in this * array will be resolved using the container. * * @throws InvalidArgumentException The name parameter must be of type string. * @throws DependencyException Error while resolving the entry. * @throws NotFoundException No entry found for the given name. * @return mixed|T */ public function make($name, array $parameters = []) { if (!\is_string($name)) { throw new InvalidArgumentException(\sprintf('The name parameter must be of type string, %s given', \is_object($name) ? \get_class($name) : \gettype($name))); } $definition = $this->getDefinition($name); if (!$definition) { // If the entry is already resolved we return it if (\array_key_exists($name, $this->resolvedEntries)) { return $this->resolvedEntries[$name]; } throw new NotFoundException("No entry or class found for '{$name}'"); } return $this->resolveDefinition($definition, $parameters); } /** * Test if the container can provide something for the given name. * * @param string $name Entry name or a class name. * * @throws InvalidArgumentException The name parameter must be of type string. * @return bool */ public function has($name) { if (!\is_string($name)) { throw new InvalidArgumentException(\sprintf('The name parameter must be of type string, %s given', \is_object($name) ? \get_class($name) : \gettype($name))); } if (\array_key_exists($name, $this->resolvedEntries)) { return \true; } $definition = $this->getDefinition($name); if ($definition === null) { return \false; } return $this->definitionResolver->isResolvable($definition); } /** * Inject all dependencies on an existing instance. * * @template T * @param object|T $instance Object to perform injection upon * @throws InvalidArgumentException * @throws DependencyException Error while injecting dependencies * @return object|T $instance Returns the same instance */ public function injectOn($instance) { if (!$instance) { return $instance; } $className = \get_class($instance); // If the class is anonymous, don't cache its definition // Checking for anonymous classes is cleaner via Reflection, but also slower $objectDefinition = \false !== \strpos($className, '@anonymous') ? $this->definitionSource->getDefinition($className) : $this->getDefinition($className); if (!$objectDefinition instanceof ObjectDefinition) { return $instance; } $definition = new InstanceDefinition($instance, $objectDefinition); $this->definitionResolver->resolve($definition); return $instance; } /** * Call the given function using the given parameters. * * Missing parameters will be resolved from the container. * * @param callable $callable Function to call. * @param array $parameters Parameters to use. Can be indexed by the parameter names * or not indexed (same order as the parameters). * The array can also contain DI definitions, e.g. DI\get(). * * @return mixed Result of the function. */ public function call($callable, array $parameters = []) { return $this->getInvoker()->call($callable, $parameters); } /** * Define an object or a value in the container. * * @param string $name Entry name * @param mixed|DefinitionHelper $value Value, use definition helpers to define objects */ public function set(string $name, $value) { if ($value instanceof DefinitionHelper) { $value = $value->getDefinition($name); } elseif ($value instanceof \Closure) { $value = new FactoryDefinition($name, $value); } if ($value instanceof ValueDefinition) { $this->resolvedEntries[$name] = $value->getValue(); } elseif ($value instanceof Definition) { $value->setName($name); $this->setDefinition($name, $value); } else { $this->resolvedEntries[$name] = $value; } } /** * Get defined container entries. * * @return string[] */ public function getKnownEntryNames() : array { $entries = \array_unique(\array_merge(\array_keys($this->definitionSource->getDefinitions()), \array_keys($this->resolvedEntries))); \sort($entries); return $entries; } /** * Get entry debug information. * * @param string $name Entry name * * @throws InvalidDefinition * @throws NotFoundException */ public function debugEntry(string $name) : string { $definition = $this->definitionSource->getDefinition($name); if ($definition instanceof Definition) { return (string) $definition; } if (\array_key_exists($name, $this->resolvedEntries)) { return $this->getEntryType($this->resolvedEntries[$name]); } throw new NotFoundException("No entry or class found for '{$name}'"); } /** * Get formatted entry type. * * @param mixed $entry */ private function getEntryType($entry) : string { if (\is_object($entry)) { return \sprintf("Object (\n class = %s\n)", \get_class($entry)); } if (\is_array($entry)) { return \preg_replace(['/^array \\(/', '/\\)$/'], ['[', ']'], \var_export($entry, \true)); } if (\is_string($entry)) { return \sprintf('Value (\'%s\')', $entry); } if (\is_bool($entry)) { return \sprintf('Value (%s)', $entry === \true ? 'true' : 'false'); } return \sprintf('Value (%s)', \is_scalar($entry) ? $entry : \ucfirst(\gettype($entry))); } /** * Resolves a definition. * * Checks for circular dependencies while resolving the definition. * * @throws DependencyException Error while resolving the entry. * @return mixed */ private function resolveDefinition(Definition $definition, array $parameters = []) { $entryName = $definition->getName(); // Check if we are already getting this entry -> circular dependency if (isset($this->entriesBeingResolved[$entryName])) { throw new DependencyException("Circular dependency detected while trying to resolve entry '{$entryName}'"); } $this->entriesBeingResolved[$entryName] = \true; // Resolve the definition try { $value = $this->definitionResolver->resolve($definition, $parameters); } finally { unset($this->entriesBeingResolved[$entryName]); } return $value; } protected function setDefinition(string $name, Definition $definition) { // Clear existing entry if it exists if (\array_key_exists($name, $this->resolvedEntries)) { unset($this->resolvedEntries[$name]); } $this->fetchedDefinitions = []; // Completely clear this local cache $this->definitionSource->addDefinition($definition); } private function getInvoker() : InvokerInterface { if (!$this->invoker) { $parameterResolver = new ResolverChain([new DefinitionParameterResolver($this->definitionResolver), new NumericArrayResolver(), new AssociativeArrayResolver(), new DefaultValueResolver(), new TypeHintContainerResolver($this->delegateContainer)]); $this->invoker = new Invoker($parameterResolver, $this); } return $this->invoker; } private function createDefaultDefinitionSource() : SourceChain { $source = new SourceChain([new ReflectionBasedAutowiring()]); $source->setMutableDefinitionSource(new DefinitionArray([], new ReflectionBasedAutowiring())); return $source; } } PK �x,]*�얔+ �+ php-di/src/ContainerBuilder.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI; use Rvx\DI\Compiler\Compiler; use Rvx\DI\Definition\Source\AnnotationBasedAutowiring; use Rvx\DI\Definition\Source\DefinitionArray; use Rvx\DI\Definition\Source\DefinitionFile; use Rvx\DI\Definition\Source\DefinitionSource; use Rvx\DI\Definition\Source\NoAutowiring; use Rvx\DI\Definition\Source\ReflectionBasedAutowiring; use Rvx\DI\Definition\Source\SourceCache; use Rvx\DI\Definition\Source\SourceChain; use Rvx\DI\Proxy\ProxyFactory; use InvalidArgumentException; use Rvx\Psr\Container\ContainerInterface; /** * Helper to create and configure a Container. * * With the default options, the container created is appropriate for the development environment. * * Example: * * $builder = new ContainerBuilder(); * $container = $builder->build(); * * @api * * @since 3.2 * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class ContainerBuilder { /** * Name of the container class, used to create the container. * @var string */ private $containerClass; /** * Name of the container parent class, used on compiled container. * @var string */ private $containerParentClass; /** * @var bool */ private $useAutowiring = \true; /** * @var bool */ private $useAnnotations = \false; /** * @var bool */ private $ignorePhpDocErrors = \false; /** * If true, write the proxies to disk to improve performances. * @var bool */ private $writeProxiesToFile = \false; /** * Directory where to write the proxies (if $writeProxiesToFile is enabled). * @var string|null */ private $proxyDirectory; /** * If PHP-DI is wrapped in another container, this references the wrapper. * @var ContainerInterface */ private $wrapperContainer; /** * @var DefinitionSource[]|string[]|array[] */ private $definitionSources = []; /** * Whether the container has already been built. * @var bool */ private $locked = \false; /** * @var string|null */ private $compileToDirectory; /** * @var bool */ private $sourceCache = \false; /** * @var string */ protected $sourceCacheNamespace; /** * Build a container configured for the dev environment. */ public static function buildDevContainer() : Container { return new Container(); } /** * @param string $containerClass Name of the container class, used to create the container. */ public function __construct(string $containerClass = Container::class) { $this->containerClass = $containerClass; } /** * Build and return a container. * * @return Container */ public function build() { $sources = \array_reverse($this->definitionSources); if ($this->useAnnotations) { $autowiring = new AnnotationBasedAutowiring($this->ignorePhpDocErrors); $sources[] = $autowiring; } elseif ($this->useAutowiring) { $autowiring = new ReflectionBasedAutowiring(); $sources[] = $autowiring; } else { $autowiring = new NoAutowiring(); } $sources = \array_map(function ($definitions) use($autowiring) { if (\is_string($definitions)) { // File return new DefinitionFile($definitions, $autowiring); } elseif (\is_array($definitions)) { return new DefinitionArray($definitions, $autowiring); } return $definitions; }, $sources); $source = new SourceChain($sources); // Mutable definition source $source->setMutableDefinitionSource(new DefinitionArray([], $autowiring)); if ($this->sourceCache) { if (!SourceCache::isSupported()) { throw new \Exception('APCu is not enabled, PHP-DI cannot use it as a cache'); } // Wrap the source with the cache decorator $source = new SourceCache($source, $this->sourceCacheNamespace); } $proxyFactory = new ProxyFactory($this->writeProxiesToFile, $this->proxyDirectory); $this->locked = \true; $containerClass = $this->containerClass; if ($this->compileToDirectory) { $compiler = new Compiler($proxyFactory); $compiledContainerFile = $compiler->compile($source, $this->compileToDirectory, $containerClass, $this->containerParentClass, $this->useAutowiring || $this->useAnnotations); // Only load the file if it hasn't been already loaded // (the container can be created multiple times in the same process) if (!\class_exists($containerClass, \false)) { require $compiledContainerFile; } } return new $containerClass($source, $proxyFactory, $this->wrapperContainer); } /** * Compile the container for optimum performances. * * Be aware that the container is compiled once and never updated! * * Therefore: * * - in production you should clear that directory every time you deploy * - in development you should not compile the container * * @see https://php-di.org/doc/performances.html * * @param string $directory Directory in which to put the compiled container. * @param string $containerClass Name of the compiled class. Customize only if necessary. * @param string $containerParentClass Name of the compiled container parent class. Customize only if necessary. */ public function enableCompilation(string $directory, string $containerClass = 'CompiledContainer', string $containerParentClass = CompiledContainer::class) : self { $this->ensureNotLocked(); $this->compileToDirectory = $directory; $this->containerClass = $containerClass; $this->containerParentClass = $containerParentClass; return $this; } /** * Enable or disable the use of autowiring to guess injections. * * Enabled by default. * * @return $this */ public function useAutowiring(bool $bool) : self { $this->ensureNotLocked(); $this->useAutowiring = $bool; return $this; } /** * Enable or disable the use of annotations to guess injections. * * Disabled by default. * * @return $this */ public function useAnnotations(bool $bool) : self { $this->ensureNotLocked(); $this->useAnnotations = $bool; return $this; } /** * Enable or disable ignoring phpdoc errors (non-existent classes in `@param` or `@var`). * * @return $this */ public function ignorePhpDocErrors(bool $bool) : self { $this->ensureNotLocked(); $this->ignorePhpDocErrors = $bool; return $this; } /** * Configure the proxy generation. * * For dev environment, use `writeProxiesToFile(false)` (default configuration) * For production environment, use `writeProxiesToFile(true, 'tmp/proxies')` * * @see https://php-di.org/doc/lazy-injection.html * * @param bool $writeToFile If true, write the proxies to disk to improve performances * @param string|null $proxyDirectory Directory where to write the proxies * @throws InvalidArgumentException when writeToFile is set to true and the proxy directory is null * @return $this */ public function writeProxiesToFile(bool $writeToFile, string $proxyDirectory = null) : self { $this->ensureNotLocked(); $this->writeProxiesToFile = $writeToFile; if ($writeToFile && $proxyDirectory === null) { throw new InvalidArgumentException('The proxy directory must be specified if you want to write proxies on disk'); } $this->proxyDirectory = $proxyDirectory; return $this; } /** * If PHP-DI's container is wrapped by another container, we can * set this so that PHP-DI will use the wrapper rather than itself for building objects. * * @return $this */ public function wrapContainer(ContainerInterface $otherContainer) : self { $this->ensureNotLocked(); $this->wrapperContainer = $otherContainer; return $this; } /** * Add definitions to the container. * * @param string|array|DefinitionSource ...$definitions Can be an array of definitions, the * name of a file containing definitions * or a DefinitionSource object. * @return $this */ public function addDefinitions(...$definitions) : self { $this->ensureNotLocked(); foreach ($definitions as $definition) { if (!\is_string($definition) && !\is_array($definition) && !$definition instanceof DefinitionSource) { throw new InvalidArgumentException(\sprintf('%s parameter must be a string, an array or a DefinitionSource object, %s given', 'ContainerBuilder::addDefinitions()', \is_object($definition) ? \get_class($definition) : \gettype($definition))); } $this->definitionSources[] = $definition; } return $this; } /** * Enables the use of APCu to cache definitions. * * You must have APCu enabled to use it. * * Before using this feature, you should try these steps first: * - enable compilation if not already done (see `enableCompilation()`) * - if you use autowiring or annotations, add all the classes you are using into your configuration so that * PHP-DI knows about them and compiles them * Once this is done, you can try to optimize performances further with APCu. It can also be useful if you use * `Container::make()` instead of `get()` (`make()` calls cannot be compiled so they are not optimized). * * Remember to clear APCu on each deploy else your application will have a stale cache. Do not enable the cache * in development environment: any change you will make to the code will be ignored because of the cache. * * @see https://php-di.org/doc/performances.html * * @param string $cacheNamespace use unique namespace per container when sharing a single APC memory pool to prevent cache collisions * @return $this */ public function enableDefinitionCache(string $cacheNamespace = '') : self { $this->ensureNotLocked(); $this->sourceCache = \true; $this->sourceCacheNamespace = $cacheNamespace; return $this; } /** * Are we building a compiled container? */ public function isCompilationEnabled() : bool { return (bool) $this->compileToDirectory; } private function ensureNotLocked() { if ($this->locked) { throw new \LogicException('The ContainerBuilder cannot be modified after the container has been built'); } } } PK �x,]~���� � php-di/src/CompiledContainer.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI; use Rvx\DI\Compiler\RequestedEntryHolder; use Rvx\DI\Definition\Definition; use Rvx\DI\Definition\Exception\InvalidDefinition; use Rvx\DI\Invoker\FactoryParameterResolver; use Rvx\Invoker\Exception\NotCallableException; use Rvx\Invoker\Exception\NotEnoughParametersException; use Rvx\Invoker\Invoker; use Rvx\Invoker\InvokerInterface; use Rvx\Invoker\ParameterResolver\AssociativeArrayResolver; use Rvx\Invoker\ParameterResolver\DefaultValueResolver; use Rvx\Invoker\ParameterResolver\NumericArrayResolver; use Rvx\Invoker\ParameterResolver\ResolverChain; /** * Compiled version of the dependency injection container. * * @author Matthieu Napoli <matthieu@mnapoli.fr> */ abstract class CompiledContainer extends Container { /** * This const is overridden in child classes (compiled containers). * @var array */ protected const METHOD_MAPPING = []; /** * @var InvokerInterface */ private $factoryInvoker; /** * {@inheritdoc} */ public function get($name) { // Try to find the entry in the singleton map if (isset($this->resolvedEntries[$name]) || \array_key_exists($name, $this->resolvedEntries)) { return $this->resolvedEntries[$name]; } $method = static::METHOD_MAPPING[$name] ?? null; // If it's a compiled entry, then there is a method in this class if ($method !== null) { // Check if we are already getting this entry -> circular dependency if (isset($this->entriesBeingResolved[$name])) { throw new DependencyException("Circular dependency detected while trying to resolve entry '{$name}'"); } $this->entriesBeingResolved[$name] = \true; try { $value = $this->{$method}(); } finally { unset($this->entriesBeingResolved[$name]); } // Store the entry to always return it without recomputing it $this->resolvedEntries[$name] = $value; return $value; } return parent::get($name); } /** * {@inheritdoc} */ public function has($name) { if (!\is_string($name)) { throw new \InvalidArgumentException(\sprintf('The name parameter must be of type string, %s given', \is_object($name) ? \get_class($name) : \gettype($name))); } // The parent method is overridden to check in our array, it avoids resolving definitions if (isset(static::METHOD_MAPPING[$name])) { return \true; } return parent::has($name); } protected function setDefinition(string $name, Definition $definition) { // It needs to be forbidden because that would mean get() must go through the definitions // every time, which kinds of defeats the performance gains of the compiled container throw new \LogicException('You cannot set a definition at runtime on a compiled container. You can either put your definitions in a file, disable compilation or ->set() a raw value directly (PHP object, string, int, ...) instead of a PHP-DI definition.'); } /** * Invoke the given callable. */ protected function resolveFactory($callable, $entryName, array $extraParameters = []) { // Initialize the factory resolver if (!$this->factoryInvoker) { $parameterResolver = new ResolverChain([new AssociativeArrayResolver(), new FactoryParameterResolver($this->delegateContainer), new NumericArrayResolver(), new DefaultValueResolver()]); $this->factoryInvoker = new Invoker($parameterResolver, $this->delegateContainer); } $parameters = [$this->delegateContainer, new RequestedEntryHolder($entryName)]; $parameters = \array_merge($parameters, $extraParameters); try { return $this->factoryInvoker->call($callable, $parameters); } catch (NotCallableException $e) { throw new InvalidDefinition("Entry \"{$entryName}\" cannot be resolved: factory " . $e->getMessage()); } catch (NotEnoughParametersException $e) { throw new InvalidDefinition("Entry \"{$entryName}\" cannot be resolved: " . $e->getMessage()); } } } PK �x,]}ۦ� � 7 php-di/src/Definition/Dumper/ObjectDefinitionDumper.phpnu ��� <?php declare (strict_types=1); namespace Rvx\DI\Definition\Dumper; use Rvx\DI\Definition\Definition; use Rvx\DI\Definition\ObjectDefinition; use Rvx\DI\Definition\ObjectDefinition\MethodInjection; use ReflectionException; /** * Dumps object definitions to string for debugging purposes. * * @since 4.1 * @author Matthieu Napoli <matthieu@mnapoli.fr> */ class ObjectDefinitionDumper { /** * Returns the definition as string representation. */ public function dump(ObjectDefinition $definition) : string { $className = $definition->getClassName(); $classExist = \class_exists($className) || \interface_exists($className); // Class if (!$classExist) { $warning = '#UNKNOWN# '; } else { $class = new \ReflectionClass($className); $warning = $class->isInstantiable() ? '' : '#NOT INSTANTIABLE# '; } $str = \sprintf(' class = %s%s', $warning, $className); // Lazy $str .= \PHP_EOL . ' lazy = ' . \var_export($definition->isLazy(), \true); if ($classExist) { // Constructor $str .= $this->dumpConstructor($className, $definition); // Properties $str .= $this->dumpProperties($definition); // Methods $str .= $this->dumpMethods($className, $definition); } return \sprintf('Object (' . \PHP_EOL . '%s' . \PHP_EOL . ')', $str); } private function dumpConstructor(string $className, ObjectDefinition $definition) : string { $str = ''; $constructorInjection = $definition->getConstructorInjection(); if ($constructorInjection !== null) { $parameters = $this->dumpMethodParameters($className, $constructorInjection); $str .= \sprintf(\PHP_EOL . ' __construct(' . \PHP_EOL . ' %s' . \PHP_EOL . ' )', $parameters); } return $str; } private function dumpProperties(ObjectDefinition $definition) : string { $str = ''; foreach ($definition->getPropertyInjections() as $propertyInjection) { $value = $propertyInjection->getValue(); $valueStr = $value instanceof Definition ? (string) $value : \var_export($value, \true); $str .= \sprintf(\PHP_EOL . ' $%s = %s', $propertyInjection->getPropertyName(), $valueStr); } return $str; } private function dumpMethods(string $className, ObjectDefinition $definition) : string { $str = ''; foreach ($definition->getMethodInjections() as $methodInjection) { $parameters = $this->dumpMethodParameters($className, $methodInjection); $str .= \sprintf(\PHP_EOL . ' %s(' . \PHP_EOL . ' %s' . \PHP_EOL . ' )', $methodInjection->getMethodName(), $parameters); } return $str; } private function dumpMethodParameters(string $className, MethodInjection $methodInjection) : string { $methodReflection = new \ReflectionMethod($className, $methodInjection->getMethodName()); $args = []; $definitionParameters = $methodInjection->getParameters(); foreach ($methodReflection->getParameters() as $index => $parameter) { if (\array_key_exists($index, $definitionParameters)) { $value = $definitionParameters[$index]; $valueStr = $value instanceof Definition ? (string) $value : \var_export($value, \true); $args[] = \sprintf('$%s = %s', $parameter->getName(), $valueStr); continue; } // If the parameter is optional and wasn't specified, we take its default value if ($parameter->isOptional()) { try { $value = $parameter->getDefaultValue(); $args[] = \sprintf('$%s = (default value) %s', $parameter->getName(), \var_export($value, \true)); continue; } catch (ReflectionException $e) { // The default value can't be read through Reflection because it is a PHP internal class } } $args[] = \sprintf('$%s = #UNDEFINED#', $parameter->getName()); } return \implode(\PHP_EOL . ' ', $args); } } PK �x,]e�l%� � >