finalFallbackContainer=$container; return $this; } public function hasFinalFallbackContainer(): bool { return null !== $this->finalFallbackContainer; } public function getKnownEntryNames(): array { //$entries = parent::getKnownEntryNames(); $entries = []; $entries = array_merge($entries, array_keys($this->container)); foreach ($this->containers as $containerId => $container) { if(\is_callable([$container, 'getKnownEntryNames'])){ $entries = array_merge($entries, \call_user_func([$container, 'getKnownEntryNames'])); }elseif(\is_callable([$container, 'all'])){ $entries = array_merge($entries, array_keys(\call_user_func([$container, 'all']))); } } if(null !== $this->finalFallbackContainer){ if(\is_callable([$this->finalFallbackContainer, 'getKnownEntryNames'])){ $entries = array_merge($entries, \call_user_func([$this->finalFallbackContainer, 'getKnownEntryNames'])); } } return $entries; } protected function un(string $id, bool $requested = false) { if(!isset($this->unresolved[$id])){ $this->unresolved[$id] = [0, 0]; } $this->unresolved[$id][(int)$requested]++; return $this; } protected function r(string $id) { unset($this->unresolved[$id]); } public function getUnresolved(): array { return $this->unresolved; } public function __construct(array $entries = null, int $onFalseGet = 0, string $callId = null) { $this->callId = (!is_null($callId)) ? $callId : self::CALL_ID; $this->onFalseGet = $onFalseGet; $this->resolved = []; $this->factories = new \SplObjectStorage(); $this->container = []; $this->containers = []; $this->unresolved = []; //$this->TreeContainer = \frdl\Context::create($this->container); if(is_null($entries)){ $entries = []; } foreach ($entries as $id => $containerOrEntry) { $type = 'default'; if(is_array($containerOrEntry)){ list($containerOrEntry, $type) = $containerOrEntry; } if(!is_null($containerOrEntry) && is_object($containerOrEntry) && $containerOrEntry instanceof ContainerInterface){ $this->addContainer($containerOrEntry, $id); }elseif(true === $type || 'factory' === $type){ $this->factory($id, $containerOrEntry); }else{ $this->set($id, $containerOrEntry); } } } public function getCallId(): string { return $this->callId; } public function set(string $id, $entry) { if(isset($this->container[$id]) && (\is_callable($entry) || (is_object($entry) && $entry instanceof \Closure ))) { return $this->extend($id, $entry); }elseif(isset($this->container[$id])){ throw new \Exception(sprintf('The container entry #id: %1$s is defined allready in %2$s!', $id, __METHOD__)); } $this->container[$id] = $entry; return $this; } public function extend($id, \Closure|\callable $callable): ContainerCollectionInterface { if (!isset($this->container[$id])) { // throw new \frdl\NotFoundException($id); return $this->factory($id, $callable); } $me = &$this; $factory = $this->container[$id]; $extended = function (ContainerInterface $container, $previous = null) use ($id, $callable, $factory) { if(is_null($previous)){ $previous = $factory; } if($id !== $container->getCallId() && $container->has($container->getCallId()) && (\is_callable($factory) || (is_object($factory) && $factory instanceof \Closure )) ){ $call = $container->get($container->getCallId()); $previous = $call($factory,[ 'container' => $container, 'previous' => $previous, ]); }elseif(\is_callable($factory) || (is_object($factory) && $factory instanceof \Closure )){ $previous = $factory($container, $previous); }else{ $previous = $factory; } if($id !== $container->getCallId() && $container->has($container->getCallId()) ){ $call = $container->get($container->getCallId()); return $call($callable,[ 'container' => $container, 'previous' => $previous, ]); }else{ return $callable($container, $previous); } }; if ($this->factories->contains($factory)) { $this->factories->detach($factory); $this->factories->attach($extended); } $this->container[$id] = $extended; return $this; } public function factory($id, \Closure|\callable $callable): ContainerCollectionInterface { if(isset($this->container[$id]) && (\is_callable($callable) || (is_object($callable) && $callable instanceof \Closure ))) { return $this->extend($id, $callable); }elseif(isset($this->container[$id])){ throw new \Exception(sprintf('The container entry #id: %1$s is defined allready in %2$s!', $id, __METHOD__)); } $this->set($id, $callable); $this->factories->attach($callable); return $this; } public function addContainer( ContainerInterface &$container, string|int &$containerId = null, ): ContainerCollectionInterface { if(null === $containerId){ $containerId = count($this->containers); } $containerId_start = implode(self::CONTAINER_SPLIT, $this->_splitId($containerId)); $containerId = $containerId_start; $i=2; while(isset($this->containers[$containerId]) ){ $containerId = $containerId_start . self::CONTAINER_SPLIT . 'i' . $i++ . 'c' . count($this->containers) .'r' .mt_rand(2,99999); } $this->containers[$containerId] = &$container; ksort($this->containers); return $this; } public function &getContainer(string|int $containerId = null) { if($this->hasContainer($containerId)){ return $this->containers[$containerId]; } switch($this->onFalseGet){ case self::NULL_ONERROR : return null; break; case self::THROW_ONERRROR : default: throw new \Exception(sprintf('Cannot resolve container #id: %s in %s2', $containerId, __METHOD__)); break; } } public function hasContainer(string|int $containerId = null): bool { return isset($this->containers[$containerId]) ? true : false; } public function get($id) { $name = $id; if(isset($this->resolvedIds[$name])){ $this->r($name); return $this->getContainer( $this->resolvedIds[$name][0] )->get( $this->resolvedIds[$name][1] ); } if(isset($this->resolved[$id])){ $this->r($name); return $this->resolved[$id]; } if (isset($this->container[$id]) && (\is_callable($this->container[$id]) && (is_object($this->container[$id]) && $this->container[$id] instanceof \Closure ) ) && $this->factories->contains($this->container[$id]) ) { if($this->getCallId() !== $id && $this->has($this->getCallId()) ){ $call = $this->get($this->getCallId()); return $call($this->container[$id],[ 'container' => $this, 'previous' => $this->container[$id], ]); } //elseif(\is_callable($this->container[$id]) && (is_object($this->container[$id]) && $this->container[$id] instanceof \Closure ) ){ // return \call_user_func($this->container[$id], $this, $this->container[$id]); //} } if ($this->getCallId() !== $id && isset($this->container[$id]) && !isset($this->resolved[$id]) && (\is_callable($this->container[$id]) || $this->container[$id] instanceof \Closure) ) { if($this->getCallId() !== $id && $this->has($this->getCallId()) ){ $call = $this->get($this->getCallId()); $this->resolved[$id] = $call($this->container[$id],[ 'container' => $this, 'previous' => $this->container[$id], ]); }elseif($this->getCallId() !== $id && \is_callable($this->container[$id]) && !is_object($this->container[$id])){ $this->resolved[$id] = \call_user_func($this->container[$id], $this, $this->container[$id]); }elseif($this->getCallId() !== $id && \is_callable($this->container[$id]) && is_object($this->container[$id]) && $this->container[$id] instanceof \Closure ){ $this->resolved[$id] = \call_user_func($this->container[$id], $this, $this->container[$id]); }else{ $this->resolved[$id] = $this->container[$id]; } // $this->container[$id] = &$this->resolved[$id]; } if(isset($this->container[$id])){ $this->r($name); return $this->container[$id]; } $parts = $this->_splitId($name); $current = ''; while(0hasContainer($current)){ $id = substr($name, strlen($current), strlen($name) ); if ($this->getContainer($current)->has($id)) { $this->resolvedIds[$name] = [$current, $id]; $this->r($name); return $this->getContainer($current)->get($id); } } } foreach ($this->containers as $containerId => $container) { if ($container->has($name)) { /* $this->resolved[$name] = &$container->get($name); $this->container[$name] = &$this->resolved[$name]; return $this->container[$name]; */ $this->resolvedIds[$name] = [$containerId, $name]; $this->r($name); return $container->get($name); } } if(null !== $this->finalFallbackContainer){ if ($this->finalFallbackContainer->has($name)) { //$this->resolvedIds[$name] = [$containerId, $name]; $this->r($name); $this->resolved[$name] = $this->finalFallbackContainer->get($name); return $this->resolved[$name]; } } $this->un($name, true); switch($this->onFalseGet){ case self::NULL_ONERROR : return null; break; case self::THROW_ONERRROR : default: throw new \Exception(sprintf('Cannot resolve container-entry #id: %s|%s in %s', $id, $name, __METHOD__)); break; } } protected function _splitId($id) { return preg_split("/([\.\t\n\@])/i", $id); } public function has($id) { $name = $id; if(isset($this->resolved[$name])){ $this->r($name); return true; } if(isset($this->container[$name])){ $this->r($name); return true; } if(isset($this->resolvedIds[$name])){ $this->r($name); return true; } $parts = $this->_splitId($name); $current = ''; while(0hasContainer($current)){ if ($this->getContainer($current)->has($id)) { $this->resolvedIds[$name] = [$current, $id]; $this->r($name); return true; } } } foreach ($this->containers as $containerId => $container) { if ($container->has($name)) { $this->resolvedIds[$name] = [$containerId, $name]; $this->r($name); return true; } } if(null !== $this->finalFallbackContainer){ if ($this->finalFallbackContainer->has($name)) { //$this->resolvedIds[$name] = [$containerId, $name]; $this->r($name); return true; } } $this->un($name, false); return false; } } __halt_compiler();----SIGNATURE:----tft0f2pK9PMpkzEaWV4p43S1lzu5IiQACPLP2n2xXOw+L11zXa/+I/qRaCBF4MRAhEaaMwy4imDMjGGIl0Oln0rvFV/zcCd/xoD4X5azbw8ms8Voas08u/fXAwD9IoQnvlUOU14/1s7SjqcetkCr2uNN/FRzTOiFr047t/QBzO0PuGDNxj4rhskwWtN76aa4AcvEnWsBdFbbRVIUhgXQuKdagw6Kd9C7nJGyHOG/TweCbuVU+kvINIaCVKwH0fE1L5GVycLA4aGy/OjjUTWonvG5kxrq4pfKo8GbE1dVEadKnr2O4RGEHq49zv1CzRzHDBqaIXYVliWOqQwxPDFSfgAnsZf1iXbX6SAKCm6dkYrfT1Ju++mIoNYLdK2PScA0BC2+mOA6F22o/dsqPPOQ00kVnk0bIjAMX7FsKe5A1Sus7UDjU267/rJIXQQhXesqd6NFtk83Va2DJcLOWooHPf5f6CeUXgrBItOVFxXqdSjkbubmCbvrBKMxbjzVEXxLGqlr/byGyMsr7vkG+AYG6KxGeaM5oL7xLemEnbqJ/KpuOAwzv7z2qzrrw6xQhLWdfb58VW+IrKbnkpW2esdZdFgvuUTs01vTUW2IkqReU21N2dMkbfFckj5r1BSvblJ/seZxngLUrgcB7pksGm3oZ34WWu5Tk2VqzTHSdzPqsM8=----ATTACHMENT:----ODMwMDY4MDk2MjU5NzAyNyAxMDgyNjQ5MDE2MDQ4NDkwIDg3MjU0MDQzNTAwMDU3MDk=