Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[READ ONLY] Ovos Mod #14

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f20fd0b
Use sourceCache if isSupported check passes, otherwise proceed withou…
falkenhawk Apr 25, 2019
f0a109b
DefinitionGlob to specify a pattern for definition files
falkenhawk Apr 25, 2019
d494750
Prefer composition over inheritance
falkenhawk Apr 26, 2019
ddf0cbd
Optimize compiled string definitions
falkenhawk Apr 27, 2019
4f3fc0d
Optimize compiled factory definitions
falkenhawk Apr 28, 2019
59a2216
AnnotationBasedAutowiring with additional options for performance tweaks
falkenhawk Apr 26, 2019
1cce07a
ServiceLocator
falkenhawk Apr 29, 2019
99305d2
Discard ServiceLocatorRepository::injectOn() method
falkenhawk Apr 30, 2019
7a71a1f
ServiceLocator - rename entry to subscriber, cleanup
falkenhawk May 30, 2019
3938947
ServiceLocatorRepository - replace setService with override method
falkenhawk May 30, 2019
1aa1834
Reference and ServiceLocatorDefinition cleanup
falkenhawk May 30, 2019
d8ea15e
compiler - extract resolveServiceLocator method to CompiledContainer
falkenhawk May 30, 2019
0d1265d
tests for service locators
falkenhawk May 30, 2019
2a10132
code formatting
falkenhawk May 30, 2019
ffad7c9
Merge pull request #2 from ovos/feature/definition-glob
falkenhawk May 30, 2019
851c7c5
Merge pull request #3 from ovos/feature/loosen-apcu-check
falkenhawk May 30, 2019
82af93e
Merge pull request #5 from ovos/feature/compiler-optimize-string-defi…
falkenhawk May 30, 2019
d314100
Merge pull request #6 from ovos/feature/compiler-optimize-factories
falkenhawk May 30, 2019
f2709cd
Merge pull request #4 from ovos/feature/annotations-autowiring-options
falkenhawk May 30, 2019
0fe5cce
Merge pull request #7 from ovos/feature/service-locator
falkenhawk May 30, 2019
4aee110
Merge pull request #7 from ovos/feature/service-locator
falkenhawk May 30, 2019
3fef38a
change package name in composer.json
falkenhawk May 30, 2019
661e59b
Merge branch 'master' into mod
falkenhawk Nov 29, 2019
2466176
Merge pull request #11 from ovos/feature/sourcecache-namespaced
falkenhawk Dec 12, 2019
d7d99f6
Merge pull request #12 from ovos/feature/travis-enable-apcu
falkenhawk Dec 12, 2019
c1a4f7d
Merge branch 'refs/heads/master' into mod
falkenhawk Dec 12, 2019
aa38cca
Merge remote-tracking branch 'ovos/master' into feature/definition-glob
partikus Jan 20, 2021
7b4540a
fix: bump phpunit assertions
partikus Jan 20, 2021
720036d
Merge remote-tracking branch 'ovos/master' into feature/compiler-opti…
partikus Jan 20, 2021
d113eb7
Merge remote-tracking branch 'ovos/master' into feature/compiler-opti…
partikus Jan 20, 2021
4a570b7
adding leading backslash to all native constants
partikus Jan 20, 2021
87b53f1
add psr container exception to the ignored errors
partikus Jan 21, 2021
d474395
csfix
partikus Jan 21, 2021
5219321
Merge branch 'master' into feature/annotations-autowiring-options-wsl
partikus Jan 21, 2021
239a39f
get rid of using deprecated expectException annotations
partikus Jan 21, 2021
80d5ae3
fix a missing default type for Reference::
partikus Jan 21, 2021
33059cf
csfix
partikus Jan 21, 2021
3ab1aab
Merge branch 'feature/annotations-autowiring-options-wsl' into mod
partikus Jan 21, 2021
08bd184
Merge branch 'feature/compiler-optimize-factories' into mod
partikus Jan 21, 2021
25fae83
Merge branch 'feature/compiler-optimize-string-definitions' into mod
partikus Jan 21, 2021
395001c
Merge branch 'feature/definition-glob' into mod
partikus Jan 21, 2021
c119aec
Merge branch 'feature/csfix' into mod
partikus Jan 21, 2021
ce95893
Merge branch 'feature/phpstan-ignore-psr-container-exception' into mod
partikus Jan 21, 2021
2f44a4c
csfix
partikus Jan 21, 2021
a255d11
Merge branch 'feature/annotations-autowiring-options-wsl' into mod
partikus Jan 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"name": "php-di/php-di",
"name": "ovos/php-di",
"replace": {
"php-di/php-di": "^6.0.8"
},
"type": "library",
"description": "The dependency injection container for humans",
"keywords": ["di", "dependency injection", "container", "ioc", "psr-11", "psr11", "container-interop"],
Expand Down Expand Up @@ -45,5 +48,10 @@
"suggest": {
"doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
"ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~2.0)"
},
"extra": {
"branch-alias": {
"dev-mod": "6.x-dev"
}
}
}
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ parameters:
ignoreErrors:
- '#Access to undefined constant DI\\CompiledContainer::METHOD_MAPPING.#'
- '#Function apcu_.* not found.#'
- '#PHPDoc tag @throws with type Psr\\Container\\ContainerExceptionInterface is not subtype of Throwable#'
reportUnmatchedIgnoredErrors: false
inferPrivatePropertyTypeFromConstructor: true
39 changes: 39 additions & 0 deletions src/CompiledContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Invoker\ParameterResolver\DefaultValueResolver;
use Invoker\ParameterResolver\NumericArrayResolver;
use Invoker\ParameterResolver\ResolverChain;
use Psr\Container\NotFoundExceptionInterface;

/**
* Compiled version of the dependency injection container.
Expand Down Expand Up @@ -120,4 +121,42 @@ protected function resolveFactory($callable, $entryName, array $extraParameters
throw new InvalidDefinition("Entry \"$entryName\" cannot be resolved: " . $e->getMessage());
}
}

/**
* Resolve a placeholder in string definition
* - wrap possible NotFound exception to conform to the one from StringDefinition::resolveExpression.
*/
protected function resolveStringPlaceholder($placeholder, $entryName)
{
try {
return $this->delegateContainer->get($placeholder);
} catch (NotFoundExceptionInterface $e) {
throw new DependencyException(sprintf(
"Error while parsing string expression for entry '%s': %s",
$entryName,
$e->getMessage()
), 0, $e);
}
}

/**
* Resolve ServiceLocator for given subscriber class (based on \DI\Definition\ServiceLocatorDefinition::resolve).
*
* @param string $requestingName class name of a subscriber, implementing ServiceSubscriberInterface
* @param string $repositoryClass ServiceLocatorRepository
* @return ServiceLocator
* @throws ServiceSubscriberException
*/
protected function resolveServiceLocator($requestingName, $repositoryClass)
{
if (!method_exists($requestingName, 'getSubscribedServices')) {
throw new ServiceSubscriberException(sprintf('The class %s does not implement ServiceSubscriberInterface.', $requestingName));
}

/** @var ServiceLocatorRepository $repository */
$repository = $this->delegateContainer->get($repositoryClass);
$services = $requestingName::getSubscribedServices();

return $repository->create($requestingName, $services);
}
}
92 changes: 89 additions & 3 deletions src/Compiler/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace DI\Compiler;

use function chmod;
use DI\Container;
use DI\Definition\ArrayDefinition;
use DI\Definition\DecoratorDefinition;
use DI\Definition\Definition;
Expand All @@ -22,6 +23,8 @@
use function file_put_contents;
use InvalidArgumentException;
use Opis\Closure\SerializableClosure;
use ReflectionFunction;
use ReflectionFunctionAbstract;
use function rename;
use function sprintf;
use function tempnam;
Expand Down Expand Up @@ -227,6 +230,13 @@ private function compileDefinition(string $entryName, Definition $definition) :
$code = 'return ' . $this->compileValue($value) . ';';
break;
case $definition instanceof Reference:
if ($definition->isServiceLocatorEntry()) {
$requestingEntry = $definition->getRequestingName();
$serviceLocatorDefinition = $definition->getServiceLocatorDefinition();
$code = 'return $this->resolveServiceLocator(' . $this->compileValue($requestingEntry) . ', ' . $this->compileValue($serviceLocatorDefinition::$serviceLocatorRepositoryClass) . ');';
break;
}

$targetEntryName = $definition->getTargetEntryName();
$code = 'return $this->delegateContainer->get(' . $this->compileValue($targetEntryName) . ');';
// If this method is not yet compiled we store it for compilation
Expand All @@ -235,9 +245,12 @@ private function compileDefinition(string $entryName, Definition $definition) :
}
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);';
$expression = $definition->getExpression();
$callback = function (array $matches) use ($definition) {
return '\'.$this->resolveStringPlaceholder(' . $this->compileValue($matches[1]) . ', ' . $this->compileValue($definition->getName()) . ').\'';
};
$value = preg_replace_callback('#\{([^\{\}]+)\}#', $callback, $expression);
$code = 'return \'' . $value . '\';';
break;
case $definition instanceof EnvironmentVariableDefinition:
$variableName = $this->compileValue($definition->getVariableName());
Expand Down Expand Up @@ -297,6 +310,35 @@ private function compileDefinition(string $entryName, Definition $definition) :
));
}

if ($value instanceof \Closure) {
$reflection = new ReflectionFunction($value);
$requestedEntry = new RequestedEntryHolder($entryName);
$parametersByClassName = [
'DI\Factory\RequestedEntry' => $requestedEntry,
];
// default non-typehinted parameters
$defaultParameters = [new Reference(Container::class), $requestedEntry];

$resolvedParameters = $this->resolveFactoryParameters(
$reflection,
$definition->getParameters(),
$parametersByClassName,
$defaultParameters
);

$definitionParameters = array_map(function ($value) {
return $this->compileValue($value);
}, $resolvedParameters);

$code = sprintf(
'return (%s)(%s);',
$this->compileValue($value),
implode(', ', $definitionParameters)
);
break;
}

// todo optimize other (non-closure) factories
$definitionParameters = '';
if (!empty($definition->getParameters())) {
$definitionParameters = ', ' . $this->compileValue($definition->getParameters());
Expand Down Expand Up @@ -328,6 +370,11 @@ public function compileValue($value) : string
throw new InvalidDefinition($errorMessage);
}

// one step ahead to skip CompiledContainer->resolveFactory
if ($value instanceof RequestedEntryHolder) {
return 'new DI\Compiler\RequestedEntryHolder(\'' . $value->getName() . '\')';
}

if ($value instanceof Definition) {
// Give it an arbitrary unique name
$subEntryName = 'subEntry' . (++$this->subEntryCounter);
Expand Down Expand Up @@ -386,6 +433,10 @@ private function isCompilable($value)
if ($value instanceof \Closure) {
return true;
}
// added for skipping CompiledContainer->resolveFactory - there is a special case for this in compileValue method
if ($value instanceof RequestedEntryHolder) {
return true;
}
if (is_object($value)) {
return 'An object was found but objects cannot be compiled';
}
Expand Down Expand Up @@ -420,4 +471,39 @@ private function compileClosure(\Closure $closure) : string

return $code;
}

public function resolveFactoryParameters(
ReflectionFunctionAbstract $reflection,
array $definitionParameters = [],
array $parametersByClassName = [],
array $defaultParameters = []
) {
$resolvedParameters = [];
$parameters = $reflection->getParameters();

foreach ($parameters as $index => $parameter) {
$name = $parameter->getName();
if (array_key_exists($name, $definitionParameters)) {
$resolvedParameters[$index] = $definitionParameters[$name];
continue;
}

$parameterClass = $parameter->getClass();
if (!$parameterClass) {
if (array_key_exists($index, $defaultParameters)) {
// take default parameters, when no typehint
$resolvedParameters[$index] = $defaultParameters[$index];
}
continue;
}

if (isset($parametersByClassName[$parameterClass->name])) {
$resolvedParameters[$index] = $parametersByClassName[$parameterClass->name];
} else {
$resolvedParameters[$index] = new Reference($parameterClass->name);
}
}

return $resolvedParameters;
}
}
19 changes: 13 additions & 6 deletions src/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use DI\Definition\Source\AnnotationBasedAutowiring;
use DI\Definition\Source\DefinitionArray;
use DI\Definition\Source\DefinitionFile;
use DI\Definition\Source\DefinitionGlob;
use DI\Definition\Source\DefinitionSource;
use DI\Definition\Source\NoAutowiring;
use DI\Definition\Source\ReflectionBasedAutowiring;
Expand Down Expand Up @@ -56,6 +57,11 @@ class ContainerBuilder
*/
private $useAnnotations = false;

/**
* @var int
*/
private $annotationsFlags = 0;

/**
* @var bool
*/
Expand Down Expand Up @@ -131,7 +137,7 @@ public function build()
$sources = array_reverse($this->definitionSources);

if ($this->useAnnotations) {
$autowiring = new AnnotationBasedAutowiring($this->ignorePhpDocErrors);
$autowiring = new AnnotationBasedAutowiring($this->ignorePhpDocErrors, $this->annotationsFlags);
$sources[] = $autowiring;
} elseif ($this->useAutowiring) {
$autowiring = new ReflectionBasedAutowiring;
Expand All @@ -146,6 +152,8 @@ public function build()
return new DefinitionFile($definitions, $autowiring);
} elseif (is_array($definitions)) {
return new DefinitionArray($definitions, $autowiring);
} elseif ($definitions instanceof DefinitionGlob) {
$definitions->setAutowiring($autowiring);
}

return $definitions;
Expand All @@ -155,10 +163,8 @@ public function build()
// 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');
}
// use cache if isSupported check passes, otherwise proceed without cache and do not throw an exception
if ($this->sourceCache && SourceCache::isSupported()) {
// Wrap the source with the cache decorator
$source = new SourceCache($source, $this->sourceCacheNamespace);
}
Expand Down Expand Up @@ -244,11 +250,12 @@ public function useAutowiring(bool $bool) : self
*
* @return $this
*/
public function useAnnotations(bool $bool) : self
public function useAnnotations(bool $bool, int $flags = 0) : self
{
$this->ensureNotLocked();

$this->useAnnotations = $bool;
$this->annotationsFlags = $flags;

return $this;
}
Expand Down
6 changes: 3 additions & 3 deletions src/Definition/ArrayDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function replaceNestedDefinitions(callable $replacer)

public function __toString()
{
$str = '[' . PHP_EOL;
$str = '[' . \PHP_EOL;

foreach ($this->values as $key => $value) {
if (is_string($key)) {
Expand All @@ -60,12 +60,12 @@ public function __toString()
$str .= ' ' . $key . ' => ';

if ($value instanceof Definition) {
$str .= str_replace(PHP_EOL, PHP_EOL . ' ', (string) $value);
$str .= str_replace(\PHP_EOL, \PHP_EOL . ' ', (string) $value);
} else {
$str .= var_export($value, true);
}

$str .= ',' . PHP_EOL;
$str .= ',' . \PHP_EOL;
}

return $str . ']';
Expand Down
21 changes: 21 additions & 0 deletions src/Definition/AutowireDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,25 @@
*/
class AutowireDefinition extends ObjectDefinition
{
/**
* @var bool|null
*/
protected $useAnnotations;

/**
* Enable/disable reading annotations for this definition, regardless of a container configuration.
*/
public function useAnnotations(bool $flag = true)
{
$this->useAnnotations = $flag;
}

/**
* Returns boolean if the useAnnotation flag was explicitly set, otherwise null.
* @return bool|null
*/
public function isUsingAnnotations()
{
return $this->useAnnotations;
}
}
12 changes: 6 additions & 6 deletions src/Definition/Dumper/ObjectDefinitionDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function dump(ObjectDefinition $definition) : string
$str = sprintf(' class = %s%s', $warning, $className);

// Lazy
$str .= PHP_EOL . ' lazy = ' . var_export($definition->isLazy(), true);
$str .= \PHP_EOL . ' lazy = ' . var_export($definition->isLazy(), true);

if ($classExist) {
// Constructor
Expand All @@ -48,7 +48,7 @@ public function dump(ObjectDefinition $definition) : string
$str .= $this->dumpMethods($className, $definition);
}

return sprintf('Object (' . PHP_EOL . '%s' . PHP_EOL . ')', $str);
return sprintf('Object (' . \PHP_EOL . '%s' . \PHP_EOL . ')', $str);
}

private function dumpConstructor(string $className, ObjectDefinition $definition) : string
Expand All @@ -60,7 +60,7 @@ private function dumpConstructor(string $className, ObjectDefinition $definition
if ($constructorInjection !== null) {
$parameters = $this->dumpMethodParameters($className, $constructorInjection);

$str .= sprintf(PHP_EOL . ' __construct(' . PHP_EOL . ' %s' . PHP_EOL . ' )', $parameters);
$str .= sprintf(\PHP_EOL . ' __construct(' . \PHP_EOL . ' %s' . \PHP_EOL . ' )', $parameters);
}

return $str;
Expand All @@ -74,7 +74,7 @@ private function dumpProperties(ObjectDefinition $definition) : string
$value = $propertyInjection->getValue();
$valueStr = $value instanceof Definition ? (string) $value : var_export($value, true);

$str .= sprintf(PHP_EOL . ' $%s = %s', $propertyInjection->getPropertyName(), $valueStr);
$str .= sprintf(\PHP_EOL . ' $%s = %s', $propertyInjection->getPropertyName(), $valueStr);
}

return $str;
Expand All @@ -87,7 +87,7 @@ private function dumpMethods(string $className, ObjectDefinition $definition) :
foreach ($definition->getMethodInjections() as $methodInjection) {
$parameters = $this->dumpMethodParameters($className, $methodInjection);

$str .= sprintf(PHP_EOL . ' %s(' . PHP_EOL . ' %s' . PHP_EOL . ' )', $methodInjection->getMethodName(), $parameters);
$str .= sprintf(\PHP_EOL . ' %s(' . \PHP_EOL . ' %s' . \PHP_EOL . ' )', $methodInjection->getMethodName(), $parameters);
}

return $str;
Expand Down Expand Up @@ -130,6 +130,6 @@ private function dumpMethodParameters(string $className, MethodInjection $method
$args[] = sprintf('$%s = #UNDEFINED#', $parameter->getName());
}

return implode(PHP_EOL . ' ', $args);
return implode(\PHP_EOL . ' ', $args);
}
}
Loading
Loading