/** * Builds the details of a package. * * @param \Drupal\features\Package $package * The package. * * @return array * A render array of a form element. */ protected function buildPackageDetail(Package $package) { $config_collection = $this->featuresManager->getConfigCollection(); $url = Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())); $element['name'] = array('data' => \Drupal::l($package->getName(), $url), 'class' => array('feature-name')); $machine_name = $package->getMachineName(); // Except for the 'unpackaged' pseudo-package, display the full name, since // that's what will be generated. if ($machine_name !== 'unpackaged') { $machine_name = $this->assigner->getBundle($package->getBundle())->getFullName($machine_name); } $element['machine_name'] = $machine_name; $element['status'] = array('data' => $this->featuresManager->statusLabel($package->getStatus()), 'class' => array('column-nowrap')); // Use 'data' instead of plain string value so a blank version doesn't // remove column from table. $element['version'] = array('data' => SafeMarkup::checkPlain($package->getVersion()), 'class' => array('column-nowrap')); $overrides = $this->featuresManager->detectOverrides($package); $new_config = $this->featuresManager->detectNew($package); $conflicts = array(); $missing = array(); if ($package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) { $overrides = array(); $new_config = array(); } // Bundle package configuration by type. $package_config = array(); foreach ($package->getConfig() as $item_name) { $item = $config_collection[$item_name]; $package_config[$item->getType()][] = array('name' => SafeMarkup::checkPlain($item_name), 'label' => SafeMarkup::checkPlain($item->getLabel()), 'class' => in_array($item_name, $overrides) ? 'features-override' : (in_array($item_name, $new_config) ? 'features-detected' : '')); } // Conflict config from other modules. foreach ($package->getConfigOrig() as $item_name) { if (!isset($config_collection[$item_name])) { $missing[] = $item_name; $package_config['missing'][] = array('name' => SafeMarkup::checkPlain($item_name), 'label' => SafeMarkup::checkPlain($item_name), 'class' => 'features-conflict'); } elseif (!in_array($item_name, $package->getConfig())) { $item = $config_collection[$item_name]; $conflicts[] = $item_name; $package_config[$item->getType()][] = array('name' => SafeMarkup::checkPlain($item_name), 'label' => SafeMarkup::checkPlain($item->getLabel()), 'class' => 'features-conflict'); } } // Add dependencies. $package_config['dependencies'] = array(); foreach ($package->getDependencies() as $dependency) { $package_config['dependencies'][] = array('name' => $dependency, 'label' => $this->moduleHandler->getName($dependency), 'class' => ''); } $class = ''; $label = ''; if (!empty($conflicts)) { $url = Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())); $class = 'features-conflict'; $label = $this->t('Conflicts'); } elseif (!empty($overrides)) { $url = Url::fromRoute('features.diff', array('featurename' => $package->getMachineName())); $class = 'features-override'; $label = $this->featuresManager->stateLabel(FeaturesManagerInterface::STATE_OVERRIDDEN); } elseif (!empty($new_config)) { $url = Url::fromRoute('features.diff', array('featurename' => $package->getMachineName())); $class = 'features-detected'; $label = $this->t('New detected'); } elseif (!empty($missing)) { $url = Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())); $class = 'features-conflict'; $label = $this->t('Missing'); } if (!empty($class)) { $element['state'] = array('data' => \Drupal::l($label, $url), 'class' => array($class, 'column-nowrap')); } else { $element['state'] = ''; } $config_types = $this->featuresManager->listConfigTypes(); // Add dependencies. $config_types['dependencies'] = $this->t('Dependencies'); $config_types['missing'] = $this->t('Missing'); uasort($config_types, 'strnatcasecmp'); $rows = array(); // Use sorted array for order. foreach ($config_types as $type => $label) { // For each component type, offer alternating rows. $row = array(); if (isset($package_config[$type])) { $row[] = array('data' => array('#type' => 'html_tag', '#tag' => 'span', '#value' => SafeMarkup::checkPlain($label), '#attributes' => array('title' => SafeMarkup::checkPlain($type), 'class' => 'features-item-label'))); $row[] = array('data' => array('#theme' => 'features_items', '#items' => $package_config[$type], '#value' => SafeMarkup::checkPlain($label), '#title' => SafeMarkup::checkPlain($type)), 'class' => 'item'); $rows[] = $row; } } $element['table'] = array('#type' => 'table', '#rows' => $rows); $details = array(); $details['description'] = array('#markup' => Xss::filterAdmin($package->getDescription())); $details['table'] = array('#type' => 'details', '#title' => array('#markup' => $this->t('Included configuration')), '#description' => array('data' => $element['table'])); $element['details'] = array('class' => array('description', 'expand'), 'data' => $details); return $element; }