diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 7e54581..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -/.github export-ignore -.gitattributes export-ignore diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml deleted file mode 100644 index 6cbfcf0..0000000 --- a/.github/workflows/close-pull-request.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Close Pull Request - -on: - pull_request_target: - types: [opened] - -jobs: - run: - runs-on: ubuntu-24.04 - steps: - - uses: superbrothers/close-pull-request@v3 - with: - comment: "Thank you for your pull request. However, you have submitted this PR on the Illuminate organization which is a read-only sub split of `laravel/framework`. Please submit your PR on the https://github.com/laravel/framework repository.

Thanks!" diff --git a/Attributes/Auth.php b/Attributes/Auth.php deleted file mode 100644 index 4cf0c1a..0000000 --- a/Attributes/Auth.php +++ /dev/null @@ -1,30 +0,0 @@ -make('auth')->guard($attribute->guard); - } -} diff --git a/Attributes/Authenticated.php b/Attributes/Authenticated.php deleted file mode 100644 index ffbba45..0000000 --- a/Attributes/Authenticated.php +++ /dev/null @@ -1,30 +0,0 @@ -make('auth')->userResolver(), $attribute->guard); - } -} diff --git a/Attributes/Bind.php b/Attributes/Bind.php deleted file mode 100644 index 3e74b94..0000000 --- a/Attributes/Bind.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - public array $environments = []; - - /** - * Create a new attribute instance. - * - * @param class-string $concrete - * @param non-empty-array|non-empty-string|\UnitEnum $environments - * - * @throws \InvalidArgumentException - */ - public function __construct( - string $concrete, - string|array|UnitEnum $environments = ['*'], - ) { - $environments = array_filter(is_array($environments) ? $environments : [$environments]); - - if ($environments === []) { - throw new InvalidArgumentException('The environment property must be set and cannot be empty.'); - } - - $this->concrete = $concrete; - - $this->environments = array_map( - fn ($environment) => enum_value($environment), - $environments, - ); - } -} diff --git a/Attributes/Cache.php b/Attributes/Cache.php deleted file mode 100644 index 2b7b1f7..0000000 --- a/Attributes/Cache.php +++ /dev/null @@ -1,30 +0,0 @@ -make('cache')->store($attribute->store); - } -} diff --git a/Attributes/Config.php b/Attributes/Config.php deleted file mode 100644 index 0133708..0000000 --- a/Attributes/Config.php +++ /dev/null @@ -1,30 +0,0 @@ -make('config')->get($attribute->key, $attribute->default); - } -} diff --git a/Attributes/Context.php b/Attributes/Context.php deleted file mode 100644 index 1c85807..0000000 --- a/Attributes/Context.php +++ /dev/null @@ -1,36 +0,0 @@ -make(Repository::class); - - return match ($attribute->hidden) { - true => $repository->getHidden($attribute->key, $attribute->default), - false => $repository->get($attribute->key, $attribute->default), - }; - } -} diff --git a/Attributes/CurrentUser.php b/Attributes/CurrentUser.php deleted file mode 100644 index 7c13b4e..0000000 --- a/Attributes/CurrentUser.php +++ /dev/null @@ -1,11 +0,0 @@ -make('db')->connection($attribute->connection); - } -} diff --git a/Attributes/Give.php b/Attributes/Give.php deleted file mode 100644 index 35891a2..0000000 --- a/Attributes/Give.php +++ /dev/null @@ -1,35 +0,0 @@ -make($attribute->class, $attribute->params); - } -} diff --git a/Attributes/Log.php b/Attributes/Log.php deleted file mode 100644 index 07673e7..0000000 --- a/Attributes/Log.php +++ /dev/null @@ -1,30 +0,0 @@ -make('log')->channel($attribute->channel); - } -} diff --git a/Attributes/RouteParameter.php b/Attributes/RouteParameter.php deleted file mode 100644 index 32afced..0000000 --- a/Attributes/RouteParameter.php +++ /dev/null @@ -1,30 +0,0 @@ -make('request')->route($attribute->parameter); - } -} diff --git a/Attributes/Scoped.php b/Attributes/Scoped.php deleted file mode 100644 index 1cf04e0..0000000 --- a/Attributes/Scoped.php +++ /dev/null @@ -1,10 +0,0 @@ -make('filesystem')->disk($attribute->disk); - } -} diff --git a/Attributes/Tag.php b/Attributes/Tag.php deleted file mode 100644 index 944fcd9..0000000 --- a/Attributes/Tag.php +++ /dev/null @@ -1,30 +0,0 @@ -tagged($attribute->tag); - } -} diff --git a/BoundMethod.php b/BoundMethod.php index 6bedef0..0dfd6fd 100644 --- a/BoundMethod.php +++ b/BoundMethod.php @@ -3,10 +3,9 @@ namespace Illuminate\Container; use Closure; -use Illuminate\Contracts\Container\BindingResolutionException; -use InvalidArgumentException; -use ReflectionFunction; use ReflectionMethod; +use ReflectionFunction; +use InvalidArgumentException; class BoundMethod { @@ -18,22 +17,17 @@ class BoundMethod * @param array $parameters * @param string|null $defaultMethod * @return mixed - * - * @throws \ReflectionException - * @throws \InvalidArgumentException */ public static function call($container, $callback, array $parameters = [], $defaultMethod = null) { - if (is_string($callback) && ! $defaultMethod && method_exists($callback, '__invoke')) { - $defaultMethod = '__invoke'; - } - if (static::isCallableWithAtSign($callback) || $defaultMethod) { return static::callClass($container, $callback, $parameters, $defaultMethod); } return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) { - return $callback(...array_values(static::getMethodDependencies($container, $callback, $parameters))); + return call_user_func_array( + $callback, static::getMethodDependencies($container, $callback, $parameters) + ); }); } @@ -55,18 +49,15 @@ protected static function callClass($container, $target, array $parameters = [], // We will assume an @ sign is used to delimit the class name from the method // name. We will split on this @ sign and then build a callable array that // we can pass right back into the "call" method for dependency binding. - $method = count($segments) === 2 - ? $segments[1] - : $defaultMethod; + $method = count($segments) == 2 + ? $segments[1] : $defaultMethod; if (is_null($method)) { throw new InvalidArgumentException('Method not provided.'); } return static::call( - $container, - [$container->make($segments[0]), $method], - $parameters + $container, [$container->make($segments[0]), $method], $parameters ); } @@ -81,7 +72,7 @@ protected static function callClass($container, $target, array $parameters = [], protected static function callBoundMethod($container, $callback, $default) { if (! is_array($callback)) { - return Util::unwrapIfClosure($default); + return $default instanceof Closure ? $default() : $default; } // Here we need to turn the array callable into a Class@method string we can use to @@ -93,7 +84,7 @@ protected static function callBoundMethod($container, $callback, $default) return $container->callMethodBinding($method, $callback[0]); } - return Util::unwrapIfClosure($default); + return $default instanceof Closure ? $default() : $default; } /** @@ -116,8 +107,6 @@ protected static function normalizeMethod($callback) * @param callable|string $callback * @param array $parameters * @return array - * - * @throws \ReflectionException */ protected static function getMethodDependencies($container, $callback, array $parameters = []) { @@ -127,7 +116,7 @@ protected static function getMethodDependencies($container, $callback, array $pa static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies); } - return array_merge($dependencies, array_values($parameters)); + return array_merge($dependencies, $parameters); } /** @@ -135,20 +124,16 @@ protected static function getMethodDependencies($container, $callback, array $pa * * @param callable|string $callback * @return \ReflectionFunctionAbstract - * - * @throws \ReflectionException */ protected static function getCallReflector($callback) { - if (is_string($callback) && str_contains($callback, '::')) { + if (is_string($callback) && strpos($callback, '::') !== false) { $callback = explode('::', $callback); - } elseif (is_object($callback) && ! $callback instanceof Closure) { - $callback = [$callback, '__invoke']; } return is_array($callback) - ? new ReflectionMethod($callback[0], $callback[1]) - : new ReflectionFunction($callback); + ? new ReflectionMethod($callback[0], $callback[1]) + : new ReflectionFunction($callback); } /** @@ -158,53 +143,20 @@ protected static function getCallReflector($callback) * @param \ReflectionParameter $parameter * @param array $parameters * @param array $dependencies - * @return void - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException + * @return mixed */ - protected static function addDependencyForCallParameter( - $container, - $parameter, - array &$parameters, - &$dependencies, - ) { - $pendingDependencies = []; - - if (array_key_exists($paramName = $parameter->getName(), $parameters)) { - $pendingDependencies[] = $parameters[$paramName]; - - unset($parameters[$paramName]); - } elseif ($attribute = Util::getContextualAttributeFromDependency($parameter)) { - $pendingDependencies[] = $container->resolveFromAttribute($attribute); - } elseif (! is_null($className = Util::getParameterClassName($parameter))) { - if (array_key_exists($className, $parameters)) { - $pendingDependencies[] = $parameters[$className]; - - unset($parameters[$className]); - } elseif ($parameter->isVariadic()) { - $variadicDependencies = $container->make($className); - - $pendingDependencies = array_merge($pendingDependencies, is_array($variadicDependencies) - ? $variadicDependencies - : [$variadicDependencies]); - } elseif ($parameter->isDefaultValueAvailable() && ! $container->bound($className)) { - $pendingDependencies[] = $parameter->getDefaultValue(); - } else { - $pendingDependencies[] = $container->make($className); - } - } elseif ($parameter->isDefaultValueAvailable()) { - $pendingDependencies[] = $parameter->getDefaultValue(); - } elseif (! $parameter->isOptional() && ! array_key_exists($paramName, $parameters)) { - $message = "Unable to resolve dependency [{$parameter}] in class {$parameter->getDeclaringClass()->getName()}"; - - throw new BindingResolutionException($message); - } + protected static function addDependencyForCallParameter($container, $parameter, + array &$parameters, &$dependencies) + { + if (array_key_exists($parameter->name, $parameters)) { + $dependencies[] = $parameters[$parameter->name]; - foreach ($pendingDependencies as $dependency) { - $container->fireAfterResolvingAttributeCallbacks($parameter->getAttributes(), $dependency); + unset($parameters[$parameter->name]); + } elseif ($parameter->getClass()) { + $dependencies[] = $container->make($parameter->getClass()->name); + } elseif ($parameter->isDefaultValueAvailable()) { + $dependencies[] = $parameter->getDefaultValue(); } - - $dependencies = array_merge($dependencies, $pendingDependencies); } /** @@ -215,6 +167,6 @@ protected static function addDependencyForCallParameter( */ protected static function isCallableWithAtSign($callback) { - return is_string($callback) && str_contains($callback, '@'); + return is_string($callback) && strpos($callback, '@') !== false; } } diff --git a/Container.php b/Container.php index 0134178..a4b479a 100755 --- a/Container.php +++ b/Container.php @@ -2,30 +2,16 @@ namespace Illuminate\Container; -use ArrayAccess; use Closure; -use Exception; -use Illuminate\Container\Attributes\Bind; -use Illuminate\Container\Attributes\Scoped; -use Illuminate\Container\Attributes\Singleton; -use Illuminate\Contracts\Container\BindingResolutionException; -use Illuminate\Contracts\Container\CircularDependencyException; -use Illuminate\Contracts\Container\Container as ContainerContract; -use Illuminate\Contracts\Container\ContextualAttribute; -use Illuminate\Contracts\Container\SelfBuilding; -use Illuminate\Support\Traits\ReflectsClosures; +use ArrayAccess; use LogicException; -use ReflectionAttribute; use ReflectionClass; -use ReflectionException; -use ReflectionFunction; use ReflectionParameter; -use TypeError; +use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Contracts\Container\Container as ContainerContract; class Container implements ArrayAccess, ContainerContract { - use ReflectsClosures; - /** * The current globally available container (if any). * @@ -36,196 +22,124 @@ class Container implements ArrayAccess, ContainerContract /** * An array of the types that have been resolved. * - * @var bool[] + * @var array */ protected $resolved = []; /** * The container's bindings. * - * @var array[] + * @var array */ protected $bindings = []; /** * The container's method bindings. * - * @var \Closure[] + * @var array */ protected $methodBindings = []; /** * The container's shared instances. * - * @var object[] - */ - protected $instances = []; - - /** - * The container's scoped instances. - * * @var array */ - protected $scopedInstances = []; + protected $instances = []; /** * The registered type aliases. * - * @var string[] + * @var array */ protected $aliases = []; /** * The registered aliases keyed by the abstract name. * - * @var array[] + * @var array */ protected $abstractAliases = []; /** * The extension closures for services. * - * @var array[] + * @var array */ protected $extenders = []; /** * All of the registered tags. * - * @var array[] + * @var array */ protected $tags = []; /** * The stack of concretions currently being built. * - * @var array[] + * @var array */ protected $buildStack = []; /** * The parameter override stack. * - * @var array[] + * @var array */ protected $with = []; /** * The contextual binding map. * - * @var array[] + * @var array */ public $contextual = []; - /** - * The contextual attribute handlers. - * - * @var array[] - */ - public $contextualAttributes = []; - - /** - * Whether an abstract class has already had its attributes checked for bindings. - * - * @var array - */ - protected $checkedForAttributeBindings = []; - - /** - * Whether a class has already been checked for Singleton or Scoped attributes. - * - * @var array - */ - protected $checkedForSingletonOrScopedAttributes = []; - /** * All of the registered rebound callbacks. * - * @var array[] + * @var array */ protected $reboundCallbacks = []; - /** - * All of the global before resolving callbacks. - * - * @var \Closure[] - */ - protected $globalBeforeResolvingCallbacks = []; - /** * All of the global resolving callbacks. * - * @var \Closure[] + * @var array */ protected $globalResolvingCallbacks = []; /** * All of the global after resolving callbacks. * - * @var \Closure[] + * @var array */ protected $globalAfterResolvingCallbacks = []; - /** - * All of the before resolving callbacks by class type. - * - * @var array[] - */ - protected $beforeResolvingCallbacks = []; - /** * All of the resolving callbacks by class type. * - * @var array[] + * @var array */ protected $resolvingCallbacks = []; /** * All of the after resolving callbacks by class type. * - * @var array[] + * @var array */ protected $afterResolvingCallbacks = []; - /** - * All of the after resolving attribute callbacks by class type. - * - * @var array[] - */ - protected $afterResolvingAttributeCallbacks = []; - - /** - * The callback used to determine the container's environment. - * - * @var (callable(array|string): bool|string)|null - */ - protected $environmentResolver = null; - /** * Define a contextual binding. * - * @param array|string $concrete + * @param string $concrete * @return \Illuminate\Contracts\Container\ContextualBindingBuilder */ public function when($concrete) { - $aliases = []; - - foreach (Util::arrayWrap($concrete) as $c) { - $aliases[] = $this->getAlias($c); - } - - return new ContextualBindingBuilder($this, $aliases); - } - - /** - * Define a contextual binding based on an attribute. - * - * @return void - */ - public function whenHasAttribute(string $attribute, Closure $handler) - { - $this->contextualAttributes[$attribute] = $handler; + return new ContextualBindingBuilder($this, $this->getAlias($concrete)); } /** @@ -242,9 +156,9 @@ public function bound($abstract) } /** - * {@inheritdoc} + * {@inheritdoc} */ - public function has(string $id): bool + public function has($id) { return $this->bound($id); } @@ -273,64 +187,9 @@ public function resolved($abstract) */ public function isShared($abstract) { - if (isset($this->instances[$abstract])) { - return true; - } - - if (isset($this->bindings[$abstract]['shared']) && $this->bindings[$abstract]['shared'] === true) { - return true; - } - - if (! class_exists($abstract)) { - return false; - } - - if (($scopedType = $this->getScopedTyped($abstract)) === null) { - return false; - } - - if ($scopedType === 'scoped') { - if (! in_array($abstract, $this->scopedInstances, true)) { - $this->scopedInstances[] = $abstract; - } - } - - return true; - } - - /** - * Determine if a ReflectionClass has scoping attributes applied. - * - * @param ReflectionClass|class-string $reflection - * @return "singleton"|"scoped"|null - */ - protected function getScopedTyped(ReflectionClass|string $reflection): ?string - { - $className = $reflection instanceof ReflectionClass - ? $reflection->getName() - : $reflection; - - if (array_key_exists($className, $this->checkedForSingletonOrScopedAttributes)) { - return $this->checkedForSingletonOrScopedAttributes[$className]; - } - - try { - $reflection = $reflection instanceof ReflectionClass - ? $reflection - : new ReflectionClass($reflection); - } catch (ReflectionException) { - return $this->checkedForSingletonOrScopedAttributes[$className] = null; - } - - $type = null; - - if (! empty($reflection->getAttributes(Singleton::class))) { - $type = 'singleton'; - } elseif (! empty($reflection->getAttributes(Scoped::class))) { - $type = 'scoped'; - } - - return $this->checkedForSingletonOrScopedAttributes[$className] = $type; + return isset($this->instances[$abstract]) || + (isset($this->bindings[$abstract]['shared']) && + $this->bindings[$abstract]['shared'] === true); } /** @@ -347,27 +206,18 @@ public function isAlias($name) /** * Register a binding with the container. * - * @param \Closure|string $abstract + * @param string|array $abstract * @param \Closure|string|null $concrete * @param bool $shared * @return void - * - * @throws \TypeError - * @throws ReflectionException */ public function bind($abstract, $concrete = null, $shared = false) { - if ($abstract instanceof Closure) { - return $this->bindBasedOnClosureReturnTypes( - $abstract, $concrete, $shared - ); - } - - $this->dropStaleInstances($abstract); - // If no concrete type was given, we will simply set the concrete type to the // abstract type. After that, the concrete type to be registered as shared // without being forced to state their classes in both of the parameters. + $this->dropStaleInstances($abstract); + if (is_null($concrete)) { $concrete = $abstract; } @@ -376,14 +226,10 @@ public function bind($abstract, $concrete = null, $shared = false) // bound into this container to the abstract type and we will just wrap it // up inside its own Closure to give us more convenience when extending. if (! $concrete instanceof Closure) { - if (! is_string($concrete)) { - throw new TypeError(self::class.'::bind(): Argument #2 ($concrete) must be of type Closure|string|null'); - } - $concrete = $this->getClosure($abstract, $concrete); } - $this->bindings[$abstract] = ['concrete' => $concrete, 'shared' => $shared]; + $this->bindings[$abstract] = compact('concrete', 'shared'); // If the abstract type was already resolved in this container we'll fire the // rebound listener so that any objects which have already gotten resolved @@ -407,9 +253,7 @@ protected function getClosure($abstract, $concrete) return $container->build($concrete); } - return $container->resolve( - $concrete, $parameters, raiseEvents: false - ); + return $container->make($concrete, $parameters); }; } @@ -439,7 +283,7 @@ public function bindMethod($method, $callback) /** * Get the method to be bound in class@method format. * - * @param array|string $method + * @param array|string $method * @return string */ protected function parseBindMethod($method) @@ -467,7 +311,7 @@ public function callMethodBinding($method, $instance) * Add a contextual binding to the container. * * @param string $concrete - * @param \Closure|string $abstract + * @param string $abstract * @param \Closure|string $implementation * @return void */ @@ -479,7 +323,7 @@ public function addContextualBinding($concrete, $abstract, $implementation) /** * Register a binding if it hasn't already been registered. * - * @param \Closure|string $abstract + * @param string $abstract * @param \Closure|string|null $concrete * @param bool $shared * @return void @@ -494,7 +338,7 @@ public function bindIf($abstract, $concrete = null, $shared = false) /** * Register a shared binding in the container. * - * @param \Closure|string $abstract + * @param string|array $abstract * @param \Closure|string|null $concrete * @return void */ @@ -503,71 +347,11 @@ public function singleton($abstract, $concrete = null) $this->bind($abstract, $concrete, true); } - /** - * Register a shared binding if it hasn't already been registered. - * - * @param \Closure|string $abstract - * @param \Closure|string|null $concrete - * @return void - */ - public function singletonIf($abstract, $concrete = null) - { - if (! $this->bound($abstract)) { - $this->singleton($abstract, $concrete); - } - } - - /** - * Register a scoped binding in the container. - * - * @param \Closure|string $abstract - * @param \Closure|string|null $concrete - * @return void - */ - public function scoped($abstract, $concrete = null) - { - $this->scopedInstances[] = $abstract; - - $this->singleton($abstract, $concrete); - } - - /** - * Register a scoped binding if it hasn't already been registered. - * - * @param \Closure|string $abstract - * @param \Closure|string|null $concrete - * @return void - */ - public function scopedIf($abstract, $concrete = null) - { - if (! $this->bound($abstract)) { - $this->scoped($abstract, $concrete); - } - } - - /** - * Register a binding with the container based on the given Closure's return types. - * - * @param \Closure|string $abstract - * @param \Closure|string|null $concrete - * @param bool $shared - * @return void - */ - protected function bindBasedOnClosureReturnTypes($abstract, $concrete = null, $shared = false) - { - $abstracts = $this->closureReturnTypes($abstract); - - $concrete = $abstract; - - foreach ($abstracts as $abstract) { - $this->bind($abstract, $concrete, $shared); - } - } - /** * "Extend" an abstract type in the container. * - * @param string $abstract + * @param string $abstract + * @param \Closure $closure * @return void * * @throws \InvalidArgumentException @@ -592,11 +376,9 @@ public function extend($abstract, Closure $closure) /** * Register an existing instance as shared in the container. * - * @template TInstance of mixed - * * @param string $abstract - * @param TInstance $instance - * @return TInstance + * @param mixed $instance + * @return mixed */ public function instance($abstract, $instance) { @@ -643,7 +425,7 @@ protected function removeAbstractAlias($searched) * Assign a set of tags to a given binding. * * @param array|string $abstracts - * @param mixed ...$tags + * @param array|mixed ...$tags * @return void */ public function tag($abstracts, $tags) @@ -665,19 +447,19 @@ public function tag($abstracts, $tags) * Resolve all of the bindings for a given tag. * * @param string $tag - * @return iterable + * @return array */ public function tagged($tag) { - if (! isset($this->tags[$tag])) { - return []; - } + $results = []; - return new RewindableGenerator(function () use ($tag) { + if (isset($this->tags[$tag])) { foreach ($this->tags[$tag] as $abstract) { - yield $this->make($abstract); + $results[] = $this->make($abstract); } - }, count($this->tags[$tag])); + } + + return $results; } /** @@ -686,17 +468,9 @@ public function tagged($tag) * @param string $abstract * @param string $alias * @return void - * - * @throws \LogicException */ public function alias($abstract, $alias) { - if ($alias === $abstract) { - throw new LogicException("[{$abstract}] is aliased to itself."); - } - - $this->removeAbstractAlias($alias); - $this->aliases[$alias] = $abstract; $this->abstractAliases[$abstract][] = $alias; @@ -705,7 +479,8 @@ public function alias($abstract, $alias) /** * Bind a new callback to an abstract's rebind event. * - * @param string $abstract + * @param string $abstract + * @param \Closure $callback * @return mixed */ public function rebinding($abstract, Closure $callback) @@ -721,7 +496,7 @@ public function rebinding($abstract, Closure $callback) * Refresh an instance on the given target and method. * * @param string $abstract - * @param mixed $target + * @param mixed $target * @param string $method * @return mixed */ @@ -740,14 +515,10 @@ public function refresh($abstract, $target, $method) */ protected function rebound($abstract) { - if (! $callbacks = $this->getReboundCallbacks($abstract)) { - return; - } - $instance = $this->make($abstract); - foreach ($callbacks as $callback) { - $callback($this, $instance); + foreach ($this->getReboundCallbacks($abstract) as $callback) { + call_user_func($callback, $this, $instance); } } @@ -759,90 +530,59 @@ protected function rebound($abstract) */ protected function getReboundCallbacks($abstract) { - return $this->reboundCallbacks[$abstract] ?? []; + if (isset($this->reboundCallbacks[$abstract])) { + return $this->reboundCallbacks[$abstract]; + } + + return []; } /** * Wrap the given closure such that its dependencies will be injected when executed. * + * @param \Closure $callback + * @param array $parameters * @return \Closure */ public function wrap(Closure $callback, array $parameters = []) { - return fn () => $this->call($callback, $parameters); + return function () use ($callback, $parameters) { + return $this->call($callback, $parameters); + }; } /** * Call the given Closure / class@method and inject its dependencies. * * @param callable|string $callback - * @param array $parameters + * @param array $parameters * @param string|null $defaultMethod * @return mixed - * - * @throws \InvalidArgumentException */ public function call($callback, array $parameters = [], $defaultMethod = null) { - $pushedToBuildStack = false; - - if (($className = $this->getClassForCallable($callback)) && ! in_array( - $className, - $this->buildStack, - true - )) { - $this->buildStack[] = $className; - - $pushedToBuildStack = true; - } - - $result = BoundMethod::call($this, $callback, $parameters, $defaultMethod); - - if ($pushedToBuildStack) { - array_pop($this->buildStack); - } - - return $result; - } - - /** - * Get the class name for the given callback, if one can be determined. - * - * @param callable|string $callback - * @return string|false - */ - protected function getClassForCallable($callback) - { - if (is_callable($callback) && - ! ($reflector = new ReflectionFunction($callback(...)))->isAnonymous()) { - return $reflector->getClosureScopeClass()->name ?? false; - } - - return false; + return BoundMethod::call($this, $callback, $parameters, $defaultMethod); } /** * Get a closure to resolve the given type from the container. * - * @template TClass of object - * - * @param string|class-string $abstract - * @return ($abstract is class-string ? \Closure(): TClass : \Closure(): mixed) + * @param string $abstract + * @return \Closure */ public function factory($abstract) { - return fn () => $this->make($abstract); + return function () use ($abstract) { + return $this->make($abstract); + }; } /** * An alias function name for make(). * - * @template TClass of object - * - * @param string|class-string|callable $abstract - * @return ($abstract is class-string ? TClass : mixed) - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException + * @param string $abstract + * @param array $parameters + * @return mixed */ public function makeWith($abstract, array $parameters = []) { @@ -852,12 +592,9 @@ public function makeWith($abstract, array $parameters = []) /** * Resolve the given type from the container. * - * @template TClass of object - * - * @param string|class-string $abstract - * @return ($abstract is class-string ? TClass : mixed) - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException + * @param string $abstract + * @param array $parameters + * @return mixed */ public function make($abstract, array $parameters = []) { @@ -865,56 +602,31 @@ public function make($abstract, array $parameters = []) } /** - * {@inheritdoc} - * - * @template TClass of object - * - * @param string|class-string $id - * @return ($id is class-string ? TClass : mixed) - * - * @throws \Illuminate\Contracts\Container\CircularDependencyException - * @throws \Illuminate\Container\EntryNotFoundException + * {@inheritdoc} */ - public function get(string $id) + public function get($id) { - try { + if ($this->has($id)) { return $this->resolve($id); - } catch (Exception $e) { - if ($this->has($id) || $e instanceof CircularDependencyException) { - throw $e; - } - - throw new EntryNotFoundException($id, is_int($e->getCode()) ? $e->getCode() : 0, $e); } + + throw new EntryNotFoundException; } /** * Resolve the given type from the container. * - * @template TClass of object - * - * @param string|class-string|callable $abstract + * @param string $abstract * @param array $parameters - * @param bool $raiseEvents - * @return ($abstract is class-string ? TClass : mixed) - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException - * @throws \Illuminate\Contracts\Container\CircularDependencyException + * @return mixed */ - protected function resolve($abstract, $parameters = [], $raiseEvents = true) + protected function resolve($abstract, $parameters = []) { $abstract = $this->getAlias($abstract); - // First we'll fire any event handlers which handle the "before" resolving of - // specific types. This gives some hooks the chance to add various extends - // calls to change the resolution of objects that they're interested in. - if ($raiseEvents) { - $this->fireBeforeResolvingCallbacks($abstract, $parameters); - } - - $concrete = $this->getContextualConcrete($abstract); - - $needsContextualBuild = ! empty($parameters) || ! is_null($concrete); + $needsContextualBuild = ! empty($parameters) || ! is_null( + $this->getContextualConcrete($abstract) + ); // If an instance of the type is currently being managed as a singleton we'll // just return an existing instance instead of instantiating new instances @@ -925,16 +637,16 @@ protected function resolve($abstract, $parameters = [], $raiseEvents = true) $this->with[] = $parameters; - if (is_null($concrete)) { - $concrete = $this->getConcrete($abstract); - } + $concrete = $this->getConcrete($abstract); // We're ready to instantiate an instance of the concrete type registered for // the binding. This will instantiate the types, as well as resolve any of // its "nested" dependencies recursively until all have gotten resolved. - $object = $this->isBuildable($concrete, $abstract) - ? $this->build($concrete) - : $this->make($concrete); + if ($this->isBuildable($concrete, $abstract)) { + $object = $this->build($concrete); + } else { + $object = $this->make($concrete); + } // If we defined any extenders for this type, we'll need to spin through them // and apply them to the object being built. This allows for the extension @@ -950,16 +662,12 @@ protected function resolve($abstract, $parameters = [], $raiseEvents = true) $this->instances[$abstract] = $object; } - if ($raiseEvents) { - $this->fireResolvingCallbacks($abstract, $object); - } + $this->fireResolvingCallbacks($abstract, $object); // Before returning, we will also set the resolved flag to "true" and pop off // the parameter overrides for this build. After those two things are done // we will be ready to return back the fully constructed class instance. - if (! $needsContextualBuild) { - $this->resolved[$abstract] = true; - } + $this->resolved[$abstract] = true; array_pop($this->with); @@ -969,11 +677,15 @@ protected function resolve($abstract, $parameters = [], $raiseEvents = true) /** * Get the concrete type for a given abstract. * - * @param string|callable $abstract - * @return mixed + * @param string $abstract + * @return mixed $concrete */ protected function getConcrete($abstract) { + if (! is_null($concrete = $this->getContextualConcrete($abstract))) { + return $concrete; + } + // If we don't have a registered resolver or concrete for the type, we'll just // assume each type is a concrete name and will attempt to resolve it as is // since the container should be able to resolve concretes automatically. @@ -981,76 +693,14 @@ protected function getConcrete($abstract) return $this->bindings[$abstract]['concrete']; } - if ($this->environmentResolver === null || - ($this->checkedForAttributeBindings[$abstract] ?? false) || ! is_string($abstract)) { - return $abstract; - } - - return $this->getConcreteBindingFromAttributes($abstract); - } - - /** - * Get the concrete binding for an abstract from the Bind attribute. - * - * @param string $abstract - * @return mixed - */ - protected function getConcreteBindingFromAttributes($abstract) - { - $this->checkedForAttributeBindings[$abstract] = true; - - try { - $reflected = new ReflectionClass($abstract); - } catch (ReflectionException) { - return $abstract; - } - - $bindAttributes = $reflected->getAttributes(Bind::class); - - if ($bindAttributes === []) { - return $abstract; - } - - $concrete = $maybeConcrete = null; - - foreach ($bindAttributes as $reflectedAttribute) { - $instance = $reflectedAttribute->newInstance(); - - if ($instance->environments === ['*']) { - $maybeConcrete = $instance->concrete; - - continue; - } - - if ($this->currentEnvironmentIs($instance->environments)) { - $concrete = $instance->concrete; - - break; - } - } - - if ($maybeConcrete !== null && $concrete === null) { - $concrete = $maybeConcrete; - } - - if ($concrete === null) { - return $abstract; - } - - match ($this->getScopedTyped($reflected)) { - 'scoped' => $this->scoped($abstract, $concrete), - 'singleton' => $this->singleton($abstract, $concrete), - null => $this->bind($abstract, $concrete), - }; - - return $this->bindings[$abstract]['concrete']; + return $abstract; } /** * Get the contextual concrete binding for the given abstract. * - * @param string|callable $abstract - * @return \Closure|string|array|null + * @param string $abstract + * @return string|null */ protected function getContextualConcrete($abstract) { @@ -1075,18 +725,20 @@ protected function getContextualConcrete($abstract) /** * Find the concrete binding for the given abstract in the contextual binding array. * - * @param string|callable $abstract - * @return \Closure|string|null + * @param string $abstract + * @return string|null */ protected function findInContextualBindings($abstract) { - return $this->contextual[end($this->buildStack)][$abstract] ?? null; + if (isset($this->contextual[end($this->buildStack)][$abstract])) { + return $this->contextual[end($this->buildStack)][$abstract]; + } } /** * Determine if the given concrete is buildable. * - * @param mixed $concrete + * @param mixed $concrete * @param string $abstract * @return bool */ @@ -1098,13 +750,10 @@ protected function isBuildable($concrete, $abstract) /** * Instantiate a concrete instance of the given type. * - * @template TClass of object - * - * @param \Closure(static, array): TClass|class-string $concrete - * @return TClass + * @param string $concrete + * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException - * @throws \Illuminate\Contracts\Container\CircularDependencyException */ public function build($concrete) { @@ -1112,33 +761,18 @@ public function build($concrete) // hand back the results of the functions, which allows functions to be // used as resolvers for more fine-tuned resolution of these objects. if ($concrete instanceof Closure) { - $this->buildStack[] = spl_object_hash($concrete); - - try { - return $concrete($this, $this->getLastParameterOverride()); - } finally { - array_pop($this->buildStack); - } + return $concrete($this, $this->getLastParameterOverride()); } - try { - $reflector = new ReflectionClass($concrete); - } catch (ReflectionException $e) { - throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e); - } + $reflector = new ReflectionClass($concrete); // If the type is not instantiable, the developer is attempting to resolve - // an abstract type such as an Interface or Abstract Class and there is + // an abstract type such as an Interface of Abstract Class and there is // no binding registered for the abstractions so we need to bail out. if (! $reflector->isInstantiable()) { return $this->notInstantiable($concrete); } - if (is_a($concrete, SelfBuilding::class, true) && - ! in_array($concrete, $this->buildStack, true)) { - return $this->buildSelfBuildingInstance($concrete, $reflector); - } - $this->buildStack[] = $concrete; $constructor = $reflector->getConstructor(); @@ -1149,11 +783,7 @@ public function build($concrete) if (is_null($constructor)) { array_pop($this->buildStack); - $this->fireAfterResolvingAttributeCallbacks( - $reflector->getAttributes(), $instance = new $concrete - ); - - return $instance; + return new $concrete; } $dependencies = $constructor->getParameters(); @@ -1161,63 +791,27 @@ public function build($concrete) // Once we have all the constructor's parameters we can create each of the // dependency instances and then use the reflection instances to make a // new instance of this class, injecting the created dependencies in. - try { - $instances = $this->resolveDependencies($dependencies); - } finally { - array_pop($this->buildStack); - } - - $this->fireAfterResolvingAttributeCallbacks( - $reflector->getAttributes(), $instance = new $concrete(...$instances) + $instances = $this->resolveDependencies( + $dependencies ); - return $instance; - } - - /** - * Instantiate a concrete instance of the given self building type. - * - * @template TClass of object - * - * @param object{'newInstance': \Closure(static, array): TClass|class-string} $concrete - * @param \ReflectionClass $reflector - * @return TClass - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException - */ - protected function buildSelfBuildingInstance($concrete, $reflector) - { - if (! method_exists($concrete, 'newInstance')) { - throw new BindingResolutionException("No newInstance method exists for [$concrete]."); - } - - $this->buildStack[] = $concrete; - - $instance = $this->call([$concrete, 'newInstance']); - array_pop($this->buildStack); - $this->fireAfterResolvingAttributeCallbacks( - $reflector->getAttributes(), $instance - ); - - return $instance; + return $reflector->newInstanceArgs($instances); } /** * Resolve all of the dependencies from the ReflectionParameters. * - * @param \ReflectionParameter[] $dependencies + * @param array $dependencies * @return array - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException */ protected function resolveDependencies(array $dependencies) { $results = []; foreach ($dependencies as $dependency) { - // If the dependency has an override for this particular build we will use + // If this dependency has a override for this particular build we will use // that instead as the value. Otherwise, we will continue with this run // of resolutions and let reflection attempt to determine the result. if ($this->hasParameterOverride($dependency)) { @@ -1226,26 +820,12 @@ protected function resolveDependencies(array $dependencies) continue; } - $result = null; - - if (! is_null($attribute = Util::getContextualAttributeFromDependency($dependency))) { - $result = $this->resolveFromAttribute($attribute); - } - // If the class is null, it means the dependency is a string or some other // primitive type which we can not resolve since it is not a class and // we will just bomb out with an error since we have no-where to go. - $result ??= is_null(Util::getParameterClassName($dependency)) - ? $this->resolvePrimitive($dependency) - : $this->resolveClass($dependency); - - $this->fireAfterResolvingAttributeCallbacks($dependency->getAttributes(), $result); - - if ($dependency->isVariadic()) { - $results = array_merge($results, $result); - } else { - $results[] = $result; - } + $results[] = is_null($dependency->getClass()) + ? $this->resolvePrimitive($dependency) + : $this->resolveClass($dependency); } return $results; @@ -1282,119 +862,56 @@ protected function getParameterOverride($dependency) */ protected function getLastParameterOverride() { - return count($this->with) ? array_last($this->with) : []; + return count($this->with) ? end($this->with) : []; } /** * Resolve a non-class hinted primitive dependency. * + * @param \ReflectionParameter $parameter * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ protected function resolvePrimitive(ReflectionParameter $parameter) { - if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->getName()))) { - return Util::unwrapIfClosure($concrete, $this); + if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) { + return $concrete instanceof Closure ? $concrete($this) : $concrete; } if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } - if ($parameter->isVariadic()) { - return []; - } - - if ($parameter->hasType() && $parameter->allowsNull()) { - return null; - } - $this->unresolvablePrimitive($parameter); } /** * Resolve a class based dependency from the container. * + * @param \ReflectionParameter $parameter * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ protected function resolveClass(ReflectionParameter $parameter) { - $className = Util::getParameterClassName($parameter); - - // First we will check if a default value has been defined for the parameter. - // If it has, and no explicit binding exists, we should return it to avoid - // overriding any of the developer specified defaults for the parameters. - if ($parameter->isDefaultValueAvailable() && - ! $this->bound($className) && - $this->findInContextualBindings($className) === null) { - return $parameter->getDefaultValue(); - } - try { - return $parameter->isVariadic() - ? $this->resolveVariadicClass($parameter) - : $this->make($className); + return $this->make($parameter->getClass()->name); } // If we can not resolve the class instance, we will check to see if the value - // is variadic. If it is, we will return an empty array as the value of the - // dependency similarly to how we handle scalar values in this situation. + // is optional, and if it is we will return the optional parameter value as + // the value of the dependency, similarly to how we do this with scalars. catch (BindingResolutionException $e) { - if ($parameter->isVariadic()) { - array_pop($this->with); - - return []; + if ($parameter->isOptional()) { + return $parameter->getDefaultValue(); } throw $e; } } - /** - * Resolve a class based variadic dependency from the container. - * - * @return mixed - */ - protected function resolveVariadicClass(ReflectionParameter $parameter) - { - $className = Util::getParameterClassName($parameter); - - $abstract = $this->getAlias($className); - - if (! is_array($concrete = $this->getContextualConcrete($abstract))) { - return $this->make($className); - } - - return array_map(fn ($abstract) => $this->resolve($abstract), $concrete); - } - - /** - * Resolve a dependency based on an attribute. - * - * @return mixed - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException - */ - public function resolveFromAttribute(ReflectionAttribute $attribute) - { - $handler = $this->contextualAttributes[$attribute->getName()] ?? null; - - $instance = $attribute->newInstance(); - - if (is_null($handler) && method_exists($instance, 'resolve')) { - $handler = $instance->resolve(...); - } - - if (is_null($handler)) { - throw new BindingResolutionException("Contextual binding attribute [{$attribute->getName()}] has no registered handler."); - } - - return $handler($instance, $this); - } - /** * Throw an exception that the concrete is not instantiable. * @@ -1419,6 +936,7 @@ protected function notInstantiable($concrete) /** * Throw an exception for an unresolvable primitive. * + * @param \ReflectionParameter $parameter * @return void * * @throws \Illuminate\Contracts\Container\BindingResolutionException @@ -1430,32 +948,14 @@ protected function unresolvablePrimitive(ReflectionParameter $parameter) throw new BindingResolutionException($message); } - /** - * Register a new before resolving callback for all types. - * - * @param \Closure|string $abstract - * @return void - */ - public function beforeResolving($abstract, ?Closure $callback = null) - { - if (is_string($abstract)) { - $abstract = $this->getAlias($abstract); - } - - if ($abstract instanceof Closure && is_null($callback)) { - $this->globalBeforeResolvingCallbacks[] = $abstract; - } else { - $this->beforeResolvingCallbacks[$abstract][] = $callback; - } - } - /** * Register a new resolving callback. * - * @param \Closure|string $abstract + * @param string $abstract + * @param \Closure|null $callback * @return void */ - public function resolving($abstract, ?Closure $callback = null) + public function resolving($abstract, Closure $callback = null) { if (is_string($abstract)) { $abstract = $this->getAlias($abstract); @@ -1471,10 +971,11 @@ public function resolving($abstract, ?Closure $callback = null) /** * Register a new after resolving callback for all types. * - * @param \Closure|string $abstract + * @param string $abstract + * @param \Closure|null $callback * @return void */ - public function afterResolving($abstract, ?Closure $callback = null) + public function afterResolving($abstract, Closure $callback = null) { if (is_string($abstract)) { $abstract = $this->getAlias($abstract); @@ -1487,53 +988,11 @@ public function afterResolving($abstract, ?Closure $callback = null) } } - /** - * Register a new after resolving attribute callback for all types. - * - * @return void - */ - public function afterResolvingAttribute(string $attribute, \Closure $callback) - { - $this->afterResolvingAttributeCallbacks[$attribute][] = $callback; - } - - /** - * Fire all of the before resolving callbacks. - * - * @param string $abstract - * @param array $parameters - * @return void - */ - protected function fireBeforeResolvingCallbacks($abstract, $parameters = []) - { - $this->fireBeforeCallbackArray($abstract, $parameters, $this->globalBeforeResolvingCallbacks); - - foreach ($this->beforeResolvingCallbacks as $type => $callbacks) { - if ($type === $abstract || is_subclass_of($abstract, $type)) { - $this->fireBeforeCallbackArray($abstract, $parameters, $callbacks); - } - } - } - - /** - * Fire an array of callbacks with an object. - * - * @param string $abstract - * @param array $parameters - * @return void - */ - protected function fireBeforeCallbackArray($abstract, $parameters, array $callbacks) - { - foreach ($callbacks as $callback) { - $callback($abstract, $parameters, $this); - } - } - /** * Fire all of the resolving callbacks. * * @param string $abstract - * @param mixed $object + * @param mixed $object * @return void */ protected function fireResolvingCallbacks($abstract, $object) @@ -1551,7 +1010,7 @@ protected function fireResolvingCallbacks($abstract, $object) * Fire all of the after resolving callbacks. * * @param string $abstract - * @param mixed $object + * @param mixed $object * @return void */ protected function fireAfterResolvingCallbacks($abstract, $object) @@ -1563,39 +1022,13 @@ protected function fireAfterResolvingCallbacks($abstract, $object) ); } - /** - * Fire all of the after resolving attribute callbacks. - * - * @param \ReflectionAttribute[] $attributes - * @param mixed $object - * @return void - */ - public function fireAfterResolvingAttributeCallbacks(array $attributes, $object) - { - foreach ($attributes as $attribute) { - if (is_a($attribute->getName(), ContextualAttribute::class, true)) { - $instance = $attribute->newInstance(); - - if (method_exists($instance, 'after')) { - $instance->after($instance, $object, $this); - } - } - - $callbacks = $this->getCallbacksForType( - $attribute->getName(), $object, $this->afterResolvingAttributeCallbacks - ); - - foreach ($callbacks as $callback) { - $callback($attribute->newInstance(), $object, $this); - } - } - } - /** * Get all callbacks for a given type. * * @param string $abstract * @param object $object + * @param array $callbacksPerType + * * @return array */ protected function getCallbacksForType($abstract, $object, array $callbacksPerType) @@ -1615,6 +1048,7 @@ protected function getCallbacksForType($abstract, $object, array $callbacksPerTy * Fire an array of callbacks with an object. * * @param mixed $object + * @param array $callbacks * @return void */ protected function fireCallbackArray($object, array $callbacks) @@ -1624,16 +1058,6 @@ protected function fireCallbackArray($object, array $callbacks) } } - /** - * Get the name of the binding the container is currently resolving. - * - * @return class-string|string|null - */ - public function currentlyResolving() - { - return array_last($this->buildStack) ?: null; - } - /** * Get the container's bindings. * @@ -1649,12 +1073,20 @@ public function getBindings() * * @param string $abstract * @return string + * + * @throws \LogicException */ public function getAlias($abstract) { - return isset($this->aliases[$abstract]) - ? $this->getAlias($this->aliases[$abstract]) - : $abstract; + if (! isset($this->aliases[$abstract])) { + return $abstract; + } + + if ($this->aliases[$abstract] === $abstract) { + throw new LogicException("[{$abstract}] is aliased to itself."); + } + + return $this->getAlias($this->aliases[$abstract]); } /** @@ -1665,7 +1097,13 @@ public function getAlias($abstract) */ protected function getExtenders($abstract) { - return $this->extenders[$this->getAlias($abstract)] ?? []; + $abstract = $this->getAlias($abstract); + + if (isset($this->extenders[$abstract])) { + return $this->extenders[$abstract]; + } + + return []; } /** @@ -1711,48 +1149,6 @@ public function forgetInstances() $this->instances = []; } - /** - * Clear all of the scoped instances from the container. - * - * @return void - */ - public function forgetScopedInstances() - { - foreach ($this->scopedInstances as $scoped) { - if ($scoped instanceof Closure) { - foreach ($this->closureReturnTypes($scoped) as $type) { - unset($this->instances[$type]); - } - } else { - unset($this->instances[$scoped]); - } - } - } - - /** - * Set the callback which determines the current container environment. - * - * @param (callable(array|string): bool|string)|null $callback - * @return void - */ - public function resolveEnvironmentUsing(?callable $callback) - { - $this->environmentResolver = $callback; - } - - /** - * Determine the environment for the container. - * - * @param array|string $environments - * @return bool - */ - public function currentEnvironmentIs($environments) - { - return $this->environmentResolver === null - ? false - : call_user_func($this->environmentResolver, $environments); - } - /** * Flush the container of all bindings and resolved instances. * @@ -1765,27 +1161,29 @@ public function flush() $this->bindings = []; $this->instances = []; $this->abstractAliases = []; - $this->scopedInstances = []; - $this->checkedForAttributeBindings = []; - $this->checkedForSingletonOrScopedAttributes = []; } /** - * Get the globally available instance of the container. + * Set the globally available instance of the container. * * @return static */ public static function getInstance() { - return static::$instance ??= new static; + if (is_null(static::$instance)) { + static::$instance = new static; + } + + return static::$instance; } /** * Set the shared instance of the container. * - * @return \Illuminate\Contracts\Container\Container|static + * @param \Illuminate\Contracts\Container\Container|null $container + * @return static */ - public static function setInstance(?ContainerContract $container = null) + public static function setInstance(ContainerContract $container = null) { return static::$instance = $container; } @@ -1793,42 +1191,48 @@ public static function setInstance(?ContainerContract $container = null) /** * Determine if a given offset exists. * - * @param string $offset + * @param string $key + * @return bool */ - public function offsetExists($offset): bool + public function offsetExists($key) { - return $this->bound($offset); + return $this->bound($key); } /** * Get the value at a given offset. * - * @param string $offset + * @param string $key + * @return mixed */ - public function offsetGet($offset): mixed + public function offsetGet($key) { - return $this->make($offset); + return $this->make($key); } /** * Set the value at a given offset. * - * @param string $offset - * @param mixed $value + * @param string $key + * @param mixed $value + * @return void */ - public function offsetSet($offset, $value): void + public function offsetSet($key, $value) { - $this->bind($offset, $value instanceof Closure ? $value : fn () => $value); + $this->bind($key, $value instanceof Closure ? $value : function () use ($value) { + return $value; + }); } /** * Unset the value at a given offset. * - * @param string $offset + * @param string $key + * @return void */ - public function offsetUnset($offset): void + public function offsetUnset($key) { - unset($this->bindings[$offset], $this->instances[$offset], $this->resolved[$offset]); + unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]); } /** @@ -1846,7 +1250,7 @@ public function __get($key) * Dynamically set container services. * * @param string $key - * @param mixed $value + * @param mixed $value * @return void */ public function __set($key, $value) diff --git a/ContextualBindingBuilder.php b/ContextualBindingBuilder.php index aeed0cf..58b70ce 100644 --- a/ContextualBindingBuilder.php +++ b/ContextualBindingBuilder.php @@ -2,7 +2,6 @@ namespace Illuminate\Container; -use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Container\ContextualBindingBuilder as ContextualBindingBuilderContract; class ContextualBindingBuilder implements ContextualBindingBuilderContract @@ -10,14 +9,14 @@ class ContextualBindingBuilder implements ContextualBindingBuilderContract /** * The underlying container instance. * - * @var \Illuminate\Contracts\Container\Container + * @var \Illuminate\Container\Container */ protected $container; /** * The concrete instance. * - * @var string|array + * @var string */ protected $concrete; @@ -31,8 +30,9 @@ class ContextualBindingBuilder implements ContextualBindingBuilderContract /** * Create a new contextual binding builder. * - * @param \Illuminate\Contracts\Container\Container $container - * @param string|array $concrete + * @param \Illuminate\Container\Container $container + * @param string $concrete + * @return void */ public function __construct(Container $container, $concrete) { @@ -56,42 +56,13 @@ public function needs($abstract) /** * Define the implementation for the contextual binding. * - * @param \Closure|string|array $implementation - * @return $this + * @param \Closure|string $implementation + * @return void */ public function give($implementation) { - foreach (Util::arrayWrap($this->concrete) as $concrete) { - $this->container->addContextualBinding($concrete, $this->needs, $implementation); - } - - return $this; - } - - /** - * Define tagged services to be used as the implementation for the contextual binding. - * - * @param string $tag - * @return $this - */ - public function giveTagged($tag) - { - return $this->give(function ($container) use ($tag) { - $taggedServices = $container->tagged($tag); - - return is_array($taggedServices) ? $taggedServices : iterator_to_array($taggedServices); - }); - } - - /** - * Specify the configuration item to bind as a primitive. - * - * @param string $key - * @param mixed $default - * @return $this - */ - public function giveConfig($key, $default = null) - { - return $this->give(fn ($container) => $container->get('config')->get($key, $default)); + $this->container->addContextualBinding( + $this->concrete, $this->needs, $implementation + ); } } diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 79810c8..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) Taylor Otwell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/RewindableGenerator.php b/RewindableGenerator.php deleted file mode 100644 index 53013f8..0000000 --- a/RewindableGenerator.php +++ /dev/null @@ -1,60 +0,0 @@ -count = $count; - $this->generator = $generator; - } - - /** - * Get an iterator from the generator. - * - * @return \Traversable - */ - public function getIterator(): Traversable - { - return ($this->generator)(); - } - - /** - * Get the total number of tagged services. - * - * @return int - */ - public function count(): int - { - if (is_callable($count = $this->count)) { - $this->count = $count(); - } - - return $this->count; - } -} diff --git a/Util.php b/Util.php deleted file mode 100644 index ebd345e..0000000 --- a/Util.php +++ /dev/null @@ -1,87 +0,0 @@ -getType(); - - if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) { - return null; - } - - $name = $type->getName(); - - if (! is_null($class = $parameter->getDeclaringClass())) { - if ($name === 'self') { - return $class->getName(); - } - - if ($name === 'parent' && $parent = $class->getParentClass()) { - return $parent->getName(); - } - } - - return $name; - } - - /** - * Get a contextual attribute from a dependency. - * - * @param \ReflectionParameter $dependency - * @return \ReflectionAttribute|null - */ - public static function getContextualAttributeFromDependency($dependency) - { - return $dependency->getAttributes(ContextualAttribute::class, ReflectionAttribute::IS_INSTANCEOF)[0] ?? null; - } -} diff --git a/composer.json b/composer.json index eb6c93b..46f3d1e 100755 --- a/composer.json +++ b/composer.json @@ -2,48 +2,34 @@ "name": "illuminate/container", "description": "The Illuminate Container package.", "license": "MIT", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], - "homepage": "https://laravel.com", - "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" - }, "require": { - "php": "^8.3", - "illuminate/contracts": "^13.0", - "illuminate/reflection": "^13.0", - "psr/container": "^1.1.1 || ^2.0.1", - "symfony/polyfill-php84": "^1.33", - "symfony/polyfill-php85": "^1.33" + "php": ">=7.0", + "illuminate/contracts": "5.6.*", + "psr/container": "~1.0" }, - "provide": { - "psr/container-implementation": "1.1 || 2.0" - }, - "suggest": { - "illuminate/auth": "Required to use the Auth attribute", - "illuminate/cache": "Required to use the Cache attribute", - "illuminate/config": "Required to use the Config attribute", - "illuminate/database": "Required to use the DB attribute", - "illuminate/filesystem": "Required to use the Storage attribute", - "illuminate/log": "Required to use the Log or Context attributes" - }, - "minimum-stability": "dev", "autoload": { "psr-4": { "Illuminate\\Container\\": "" } }, - "config": { - "sort-packages": true - }, "extra": { "branch-alias": { - "dev-master": "13.0.x-dev" + "dev-master": "5.6-dev" } - } + }, + "config": { + "sort-packages": true + }, + "minimum-stability": "dev" }