/** * Returns a service instance for the passed in identifying type name. If the * instance does not exist, it creates one. * * @param Type $IdentifyingType * @param Injector $Injector * @return object * @throws ServiceNotDefined */ public function getService(Type $IdentifyingType, Injector $Injector) { $identifyingTypeName = $IdentifyingType->getName(); if (isset($this->builtServices[$identifyingTypeName])) { return $this->builtServices[$identifyingTypeName]; } $ServiceDefinition = $this->ServiceDefinitions->get($IdentifyingType); if (is_null($ServiceDefinition)) { $callerFilePath = debug_backtrace()[0]['file']; $callerLineNumber = debug_backtrace()[0]['line']; throw new ServiceNotDefined($IdentifyingType->getName(), $callerFilePath, $callerLineNumber); } if ($ServiceDefinition->hasFactoryFunction()) { $InjectionTarget = new InjectionTargetClosure($ServiceDefinition->getFactoryFunction()); $Service = $Injector->resolve($InjectionTarget); $this->ensureValueImplementsIdentifyingType($ServiceDefinition, $Service); } else { $InjectionTarget = new InjectionTargetConstructor($ServiceDefinition->getImplementingType()); $Service = $Injector->resolve($InjectionTarget); } $this->builtServices[$identifyingTypeName] = $Service; if ($ServiceDefinition->hasInitFunction()) { $InjectionTarget = new InjectionTargetClosure($ServiceDefinition->getInitFunction()); $Injector->resolve($InjectionTarget); } return $Service; }
/** * @test */ public function The_getAll_method_returns_all_service_definitions() { // given $Target = new ServiceDefinitions(); $Target->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\IMyService')), ImplementingType::isTheSame())->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\MyService')), ImplementingType::isTheSame()); // when $result = $Target->getAll(); // then $this->assertEquals(['tueena\\spec\\core\\stubs\\IMyService' => $Target->get(Type::fromName('tueena\\spec\\core\\stubs\\IMyService')), 'tueena\\spec\\core\\stubs\\MyService' => $Target->get(Type::fromName('tueena\\spec\\core\\stubs\\MyService'))], $result); }
/** * @param ServiceDefinition $ServiceDefinition * @param ServiceDefinitions $ServiceDefinitions * @param ServiceDefinition $InitialServiceDefinition * @param ServiceDefinition[] $alreadyCheckedRequirements * @param array[] $trace * @param \Closure $Closure */ private static function throwOnCircularReferenceOfRequiresServicesHelper(ServiceDefinition $ServiceDefinition, ServiceDefinitions $ServiceDefinitions, ServiceDefinition $InitialServiceDefinition, array &$alreadyCheckedRequirements, array $trace, \Closure $Closure = null) { if ($Closure === null) { return; } $InjectionTarget = new InjectionTargetClosure($Closure); foreach ($InjectionTarget->getRequiredTypes() as $requiredType) { $ServiceDefinition = $ServiceDefinitions->get($requiredType); if (in_array($ServiceDefinition, $alreadyCheckedRequirements)) { continue; } // The second part of the condition ensures, that no exception is thrown // if an init function of a service requires the service itself. This // is absolutely valid. if ($ServiceDefinition === $InitialServiceDefinition && $trace[0][1] !== 'init') { self::throwCircularReferenceException($InitialServiceDefinition, $trace); } $alreadyCheckedRequirements[] = $ServiceDefinition; self::throwOnCircularReferenceOfRequiredServices($ServiceDefinition, $ServiceDefinitions, $InitialServiceDefinition, $alreadyCheckedRequirements, $trace); } }