/**
  * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentDependency
  */
 public function testAssignDependency()
 {
     $method_id = 'dependency';
     // Enable the method.
     $this->enableAssignmentMethod($method_id);
     // Test the default options for the base assignment method.
     // Test node type assignments.
     // Declare the node_type entity 'article'.
     $this->addConfigurationItem('node.type.article', [], ['shortName' => 'article', 'label' => 'Article', 'type' => 'node_type', 'dependents' => ['field.field.node.article.body']]);
     // Add a piece of dependent configuration.
     $this->addConfigurationItem('field.field.node.article.body', [], ['shortName' => 'node.article.body', 'label' => 'Body', 'type' => 'field_config', 'dependents' => []]);
     $this->featuresManager->initPackage(self::PACKAGE_NAME, 'My test package');
     $this->featuresManager->assignConfigPackage(self::PACKAGE_NAME, ['node.type.article']);
     $this->assigner->applyAssignmentMethod($method_id);
     $packages = $this->featuresManager->getPackages();
     $expected_package_names = [self::PACKAGE_NAME];
     $this->assertEquals($expected_package_names, array_keys($packages), 'Expected packages not created.');
     $expected_config_items = ['node.type.article', 'field.field.node.article.body'];
     $this->assertEquals($expected_config_items, $packages[self::PACKAGE_NAME]->getConfig(), 'Expected configuration items not present in article package.');
 }
 /**
  * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentForwardDependency
  */
 public function testAssignForwardDependency()
 {
     $method_id = 'forward_dependency';
     // Enable the method.
     $this->enableAssignmentMethod($method_id);
     // Add some configuration.
     // Two parent items.
     $this->addConfigurationItem('parent1', [], ['type' => 'node_type', 'dependents' => ['grandparent']]);
     $this->addConfigurationItem('parent2', [], ['type' => 'node_type', 'dependents' => []]);
     // Something that belongs to just one parent.
     $this->addConfigurationItem('child1', [], ['type' => 'node_type', 'dependents' => ['parent1']]);
     // Something that belongs to both parents.
     $this->addConfigurationItem('child2', [], ['type' => 'node_type', 'dependents' => ['parent1', 'parent2']]);
     // Something that indirectly belongs to parent1.
     $this->addConfigurationItem('grandchild', [], ['type' => 'node_type', 'dependents' => ['child1']]);
     // A dependent, not a dependency.
     $this->addConfigurationItem('grandparent', [], ['type' => 'node_type', 'dependents' => []]);
     // Something completely unrelated.
     $this->addConfigurationItem('stranger', [], ['type' => 'node_type', 'dependents' => []]);
     $this->featuresManager->initPackage(self::PACKAGE_NAME, 'My test package');
     $this->featuresManager->assignConfigPackage(self::PACKAGE_NAME, ['parent1']);
     $other_package_name = 'other_package';
     $this->featuresManager->initPackage($other_package_name, 'Other package');
     $this->featuresManager->assignConfigPackage($other_package_name, ['parent2']);
     $this->assigner->applyAssignmentMethod($method_id);
     $packages = $this->featuresManager->getPackages();
     $expected_package_names = [self::PACKAGE_NAME, $other_package_name];
     sort($expected_package_names);
     $actual_package_names = array_keys($packages);
     sort($actual_package_names);
     $this->assertEquals($expected_package_names, $actual_package_names, 'Expected packages not created.');
     $expected_config_items = ['parent1', 'child1', 'grandchild'];
     sort($expected_config_items);
     $actual_config_items = $packages[self::PACKAGE_NAME]->getConfig();
     sort($actual_config_items);
     $this->assertEquals($expected_config_items, $actual_config_items, 'Expected configuration items not present in article package.');
 }
  /**
   * Generates and adds .info.yml files to a package.
   *
   * @param array $package
   *   The package.
   */
  protected function addInfoFile(array &$package) {
    // Filter to standard keys of the profiles that we will use in info files.
    $info_keys = [
      'name',
      'description',
      'type',
      'core',
      'dependencies',
      'themes',
      'version'
    ];
    $info = array_intersect_key($package, array_fill_keys($info_keys, NULL));

    // Assign to a "package" named for the profile.
    if (isset($package['bundle'])) {
      $bundle = $this->assigner->getBundle($package['bundle']);
    }
    if (isset($bundle) && !$bundle->isDefault()) {
      $info['package'] = $bundle->getName();
    }

    if (!empty($package['config'])) {
      // Save the current bundle in the info file so the package
      // can be reloaded later by the AssignmentPackages plugin.
      if (isset($bundle) && !$bundle->isDefault()) {
        $info['features']['bundle'] = $bundle->getMachineName();
      }
      else {
        unset($info['features']['bundle']);
      }
      if (!empty($package['excluded'])) {
        $info['features']['excluded'] = $package['excluded'];
      }
      else {
        unset($info['features']['excluded']);
      }
      if (empty($info['features'])) {
        $info['features'] = TRUE;
      }
    }

    // Add profile-specific info data.
    if ($info['type'] == 'profile') {
      // Set the distribution name.
      $info['distribution'] = [
        'name' => $info['name']
      ];
    }

    $package['files']['info'] = [
      'filename' => $package['machine_name'] . '.info.yml',
      'subdirectory' => NULL,
      // Filter to remove any empty keys, e.g., an empty themes array.
      'string' => Yaml::encode(array_filter($info))
    ];
  }
 /**
  * Reset the config to reapply assignment plugins
  */
 protected function reset()
 {
     $this->assigner->reset();
     // Start with an empty configuration collection.
     $this->featuresManager->setConfigCollection([]);
 }