Example #1
0
 /**
  * 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 If_a_service_requires_itself_in_its_init_function_this_is_not_considered_as_circular_reference()
 {
     // given
     $ServiceDefinitions = new ServiceDefinitions();
     $ServiceDefinitions->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\A')), ImplementingType::isTheSame(), InitFunction::is(function (A $A) {
     }));
     $Target = new ServiceDefinitionsValidator();
     // when, then
     $Target->validate($ServiceDefinitions);
 }
Example #3
0
 /**
  * @test
  */
 public function The_init_function_can_be_injected()
 {
     // given
     $counter = 0;
     $ServiceDefinitions = new ServiceDefinitions();
     $ServiceDefinitions->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\A')), ImplementingType::isTheSame())->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\B')), ImplementingType::isTheSame(), InitFunction::is(function (A $A, B $B) use(&$counter) {
         $counter++;
     }));
     $Target = new ServiceFactory($ServiceDefinitions);
     $Injector = new Injector($Target);
     // when
     $Target->getService(Type::fromName('tueena\\spec\\core\\stubs\\B'), $Injector);
     // then
     //  We just have to ensure, the init function has been called. A and B must
     // have been injected.
     $this->AssertEquals(1, $counter);
 }
Example #4
0
 /**
  * @test
  */
 public function If_a_service_is_not_defined_with_a_factory_function_the_constructor_of_that_service_gets_injected_with_the_required_services()
 {
     // given
     $serviceDefinitions = new ServiceDefinitions();
     $serviceDefinitions->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\D')), ImplementingType::isTheSame())->add(IdentifyingType::is(Type::fromName('tueena\\spec\\core\\stubs\\E')), ImplementingType::isTheSame());
     $ServiceFactory = new ServiceFactory($serviceDefinitions);
     $Target = new Injector($ServiceFactory);
     $PropertyDOfE = null;
     $Closure = function (\tueena\spec\core\stubs\E $E) use(&$PropertyDOfE) {
         $PropertyDOfE = $E->D;
     };
     // when
     $Target->resolve(new InjectionTargetClosure($Closure));
     // then
     $this->assertInstanceOf('tueena\\spec\\core\\stubs\\D', $PropertyDOfE);
 }
Example #5
0
 /**
  * @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);
     }
 }