Skip to content

Commit

Permalink
Merge pull request #30 from abmmhasan/feature/improvement-n
Browse files Browse the repository at this point in the history
Feature/improvement n
  • Loading branch information
abmmhasan authored Dec 18, 2023
2 parents 46648f1 + 2e4b61d commit 3fb34c1
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 86 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"symfony/cache": "^6.3"
},
"require-dev": {
"captainhook/captainhook": "^5.18",
"captainhook/captainhook": "^5.19",
"laravel/pint": "^1.13",
"pestphp/pest": "^2.24",
"pestphp/pest": "^2.28",
"rector/rector": "^0.18",
"symfony/var-dumper": "^6.3"
},
Expand Down
17 changes: 11 additions & 6 deletions src/DI/Invoker/InjectedCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace AbmmHasan\InterMix\DI\Invoker;

use AbmmHasan\InterMix\DI\Resolver\ClassResolver;
use AbmmHasan\InterMix\DI\Resolver\DefinitionResolver;
use AbmmHasan\InterMix\DI\Resolver\ParameterResolver;
use AbmmHasan\InterMix\DI\Resolver\PropertyResolver;
use AbmmHasan\InterMix\DI\Resolver\Reflector;
Expand All @@ -19,7 +20,7 @@ final class InjectedCall

private ParameterResolver $parameterResolver;
private ClassResolver $classResolver;
private PropertyResolver $propertyResolver;
private DefinitionResolver $definitionResolver;

/**
* Constructor for the class.
Expand All @@ -29,18 +30,22 @@ final class InjectedCall
public function __construct(
private Repository $repository
) {
$this->parameterResolver = new ParameterResolver($this->repository);
$this->propertyResolver = new PropertyResolver(
$this->definitionResolver = new DefinitionResolver($this->repository);
$this->parameterResolver = new ParameterResolver($this->repository, $this->definitionResolver);
$propertyResolver = new PropertyResolver(
$this->repository,
$this->parameterResolver
);
$this->classResolver = new ClassResolver(
$this->repository,
$this->parameterResolver,
$this->propertyResolver
$propertyResolver,
$this->definitionResolver
);

$this->definitionResolver->setResolverInstance($this->classResolver, $this->parameterResolver);
$this->parameterResolver->setClassResolverInstance($this->classResolver);
$this->propertyResolver->setClassResolverInstance($this->classResolver);
$propertyResolver->setClassResolverInstance($this->classResolver);
}

/**
Expand All @@ -52,7 +57,7 @@ public function __construct(
*/
public function resolveByDefinition(string $name): mixed
{
return $this->parameterResolver->getResolvedDefinition($name);
return $this->definitionResolver->resolve($name);
}

/**
Expand Down
37 changes: 25 additions & 12 deletions src/DI/Resolver/ClassResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@
class ClassResolver
{
use Reflector;
private array $entriesResolving = [];

/**
* Constructor for the class.
*
* @param Repository $repository The repository object.
* @param ParameterResolver $parameterResolver The parameter resolver object.
* @param PropertyResolver $propertyResolver The property resolver object.
* @param DefinitionResolver $definitionResolver The definition resolver object.
*/
public function __construct(
private Repository $repository,
private ParameterResolver $parameterResolver,
private PropertyResolver $propertyResolver
private PropertyResolver $propertyResolver,
private DefinitionResolver $definitionResolver
) {
}

Expand All @@ -40,13 +43,12 @@ public function resolveInfuse(Infuse $infuse): mixed
$type = $infuse->getNonMethodData('type');

if (array_key_exists($type, $this->repository->functionReference)) {
return $this->parameterResolver->getResolvedDefinition($type);
return $this->definitionResolver->resolve($type);
}

if (function_exists($type)) {
return $type(
...
$this->parameterResolver->resolve(
...$this->parameterResolver->resolve(
new ReflectionFunction($type),
(array)$infuse->getNonMethodData('data'),
'constructor'
Expand Down Expand Up @@ -97,8 +99,10 @@ private function resolveMake(ReflectionClass $class, string $className, string|b
$this->resolveConstructor($class);
$this->propertyResolver->resolve($class);
$this->resolveMethod($class, $callMethod);
$resolved = $this->repository->resolvedResource[$className];
$this->repository->resolvedResource[$className] = $existing;
[$resolved, $this->repository->resolvedResource[$className]] = [
$this->repository->resolvedResource[$className],
$existing
];
return $resolved;
}

Expand All @@ -116,15 +120,24 @@ private function resolveClassResources(
string $className,
string|bool|null $callMethod
): void {
if (!isset($this->repository->resolvedResource[$className]['instance'])) {
$this->resolveConstructor($class);
if (isset($this->entriesResolving[$className])) {
throw new ContainerException("Circular dependency detected while resolving class '$className'");
}
$this->entriesResolving[$className] = true;

if (!isset($this->repository->resolvedResource[$className]['property'])) {
$this->propertyResolver->resolve($class);
}
try {
if (!isset($this->repository->resolvedResource[$className]['instance'])) {
$this->resolveConstructor($class);
}

$this->resolveMethod($class, $callMethod);
if (!isset($this->repository->resolvedResource[$className]['property'])) {
$this->propertyResolver->resolve($class);
}

$this->resolveMethod($class, $callMethod);
} finally {
unset($this->entriesResolving[$className]);
}
}

/**
Expand Down
118 changes: 118 additions & 0 deletions src/DI/Resolver/DefinitionResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

namespace AbmmHasan\InterMix\DI\Resolver;

use AbmmHasan\InterMix\Exceptions\ContainerException;
use Closure;
use Psr\Cache\InvalidArgumentException;
use ReflectionException;
use ReflectionFunction;

class DefinitionResolver
{
use Reflector;

private ClassResolver $classResolver;
private ParameterResolver $parameterResolver;
private array $entriesResolving = [];

/**
* Constructor for the class.
*
* @param Repository $repository The repository object.
*/
public function __construct(
private Repository $repository
) {
}

/**
* Sets the ClassResolver instance for the object.
*
* @param ClassResolver $classResolver The ClassResolver instance to set.
* @param ParameterResolver $parameterResolver The ParameterResolver instance to set.
* @return void
*/
public function setResolverInstance(
ClassResolver $classResolver,
ParameterResolver $parameterResolver
): void {
$this->classResolver = $classResolver;
$this->parameterResolver = $parameterResolver;
}

/**
* Prepare the definition for a given name.
*
* @param string $name The name of the definition.
* @return mixed The prepared definition.
* @throws ReflectionException|ContainerException|InvalidArgumentException
*/
public function resolve(string $name): mixed
{
if (isset($this->entriesResolving[$name])) {
throw new ContainerException("Circular dependency detected while resolving definition '$name'");
}
$this->entriesResolving[$name] = true;

try {
$resolved = $this->getFromCacheOrResolve($name);
} finally {
unset($this->entriesResolving[$name]);
}

return $resolved;
}

/**
* Retrieves the value from the cache if it exists, otherwise resolves the value.
*
* @param string $name The name of the value to retrieve or resolve.
* @return mixed The resolved value.
* @throws ReflectionException|ContainerException|InvalidArgumentException
*/
private function getFromCacheOrResolve(string $name): mixed
{
if (!array_key_exists($name, $this->repository->resolvedDefinition)) {
$this->repository->resolvedDefinition[$name] = match (true) {
isset($this->repository->cacheAdapter) => $this->repository->cacheAdapter->get(
$this->repository->alias . '-' . base64_encode($name),
fn () => $this->resolveDefinition($name)
),
default => $this->resolveDefinition($name)
};
}
return $this->repository->resolvedDefinition[$name];
}

/**
* Prepare the definition for a given name.
*
* @param string $name The name of the definition.
* @return mixed The resolved definition.
* @throws ReflectionException|ContainerException|InvalidArgumentException
*/
private function resolveDefinition(string $name): mixed
{
$definition = $this->repository->functionReference[$name];

return match (true) {
$definition instanceof Closure => $definition(
...$this->parameterResolver->resolve(new ReflectionFunction($definition), [], 'constructor')
),

is_array($definition) && class_exists($definition[0])
=> function () use ($definition) {
$resolved = $this->classResolver->resolve(
...$definition
);
return empty($definition[1]) ? $resolved['instance'] : $resolved['returned'];
},

is_string($definition) && class_exists($definition)
=> $this->classResolver->resolve($this->reflectedClass($definition))['instance'],

default => $definition
};
}
}
Loading

0 comments on commit 3fb34c1

Please sign in to comment.