示例#1
0
 public function run(App $previousApp = null)
 {
     //Make sure all correct feature aliases are registered
     $this->_registerFeatureAliases();
     //We will sort the features by dependency on other features
     //and initialize them in the correct order
     //First we create an instance of all features.
     /**
      * @var \Tale\App\FeatureBase[] $features
      */
     $features = [];
     foreach ($this->getOption('features') as $name => $options) {
         //Aliases are resolved.
         $className = $this->_featureFactory->resolveClassName($name);
         //We don't want duplicate instances. Rather create a new feature
         //It's better for unique identification
         if (isset($features[$className])) {
             throw new RuntimeException("Failed to add feature {$name}({$className}): Feature does already exist");
         }
         //This creates the actual instance via Tale\Factory
         $feature = $this->_featureFactory->createInstance($className, [$this]);
         //We can pass a string as the options to use a config file
         if (is_string($options)) {
             $feature->appendOptionFile($options, true);
         } else {
             if (is_array($options)) {
                 $feature->appendOptions($options, true);
             } else {
                 throw new RuntimeException("Failed to initialize feature {$name}({$className}): " . "Config needs to be a path to a file or an option array");
             }
         }
         $features[] = $feature;
     }
     //All features are instanced and got all the options they will get
     //at this point.
     //Now we sort the features by dependencies.
     //TODO: Circular dependencies probably f**k up.
     ArrayUtil::mergeSort($features, [__CLASS__, 'compareFeatures']);
     $classes = array_map('get_class', $features);
     $features = array_combine($classes, $features);
     //Now we can initialize the features
     //Since our deps are ordered now, we can just iterate
     foreach ($features as $feature) {
         //First append our dependencies
         foreach ($feature->getDependencies() as $name => $className) {
             if (isset($features[$className])) {
                 $feature->setDependency($name, $features[$className]);
             }
         }
         //Now initialize the feature
         //This is the possibility to add events etc.
         $feature->init();
     }
     //This is only sorting! We dont ensure, that the feature exists.
     //The feature has to do that by itself (through an easy way, look at it)
     //Put together our event args
     $args = ['app' => $this, 'previousApp' => $previousApp];
     //First, we prepare (and let features prepare)
     if ($this->emit('beforeRun', new Event\Args($args))) {
         $this->_setPhpOptions();
         //Then we run
         if ($this->emit('run', new Event\Args($args))) {
             //Clear our features
             $this->_features = null;
             //Allow clean-up at the end (Notice that the "true"
             //makes it reverse
             $this->emit('afterRun', new Event\Args($args), true);
         }
     }
     return $this;
 }