/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $bundle = $this->assigner->getBundle($this->bundle); $this->assigner->assignConfigPackages(); $this->package->setName($form_state->getValue('name')); $this->package->setMachineName($form_state->getValue('machine_name')); $this->package->setDescription($form_state->getValue('description')); $this->package->setVersion($form_state->getValue('version')); $this->package->setBundle($bundle->getMachineName()); // Save it first just to create it in case it's a new package. $this->featuresManager->setPackage($this->package); $this->package->setConfig($this->updatePackageConfig($form_state)); $this->package->setExcluded($this->updateExcluded()); $this->package->setRequired($this->updateRequired()); // Now save it with the selected config data. $this->featuresManager->setPackage($this->package); $method_id = NULL; $trigger = $form_state->getTriggeringElement(); $op = $form_state->getValue('op'); if (!empty($trigger) && empty($op)) { $method_id = $trigger['#name']; } // Set default redirect, but allow generators to change it later. $form_state->setRedirect('features.edit', array('featurename' => $this->package->getMachineName())); if (!empty($method_id)) { $packages = array($this->package->getMachineName()); $this->generator->generatePackages($method_id, $packages, $bundle); $this->generator->applyExportFormSubmit($method_id, $form, $form_state); } $this->assigner->setCurrent($bundle); }
/** * Registers a failed package or profile archive operation. * * @param array &$return * The return value, passed by reference. * @param \Drupal\features\Package $package * The package or profile. * @param \Exception $exception * The exception object. * @param string $message * Error message when there isn't an Exception object. */ protected function failure(array &$return, Package $package, \Exception $exception = NULL, $message = '') { $type = $package->getType() == 'module' ? $this->t('Package') : $this->t('Profile'); $return[] = ['success' => FALSE, 'display' => FALSE, 'message' => '@type @package not written to archive. Error: @error.', 'variables' => ['@type' => $type, '@package' => $package->getName(), '@error' => isset($exception) ? $exception->getMessage() : $message]]; }
/** * 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; }
/** * @depends testAppendConfig * @covers ::removeConfig */ public function testRemoveConfig(Package $package) { $package->removeConfig('test_config_a'); $this->assertEquals(['test_config_b', 'test_config_c'], array_values($package->getConfig())); }
/** * {@inheritdoc} */ public function detectMissing(Package $feature) { $config = $this->getConfigCollection(); $result = array(); foreach ($feature->getConfigOrig() as $name) { if (!isset($config[$name])) { $result[] = $name; } } return $result; }
/** * Returns a form element for the given overrides. * * @param \Drupal\features\Package $package * A package. * @param array $overrides * An array of overrides. * @param array $missing * An array of missing config. * * @return array * A form element. */ protected function diffOutput(Package $package, $overrides, $missing = array()) { $element = array(); $config = $this->featuresManager->getConfigCollection(); $components = array_merge($missing, $overrides); $header = array(array('data' => '', 'class' => 'diff-marker'), array('data' => $this->t('Active site config'), 'class' => 'diff-context'), array('data' => '', 'class' => 'diff-marker'), array('data' => $this->t('Feature code config'), 'class' => 'diff-context')); foreach ($components as $name) { $rows[] = array(array('data' => $name, 'colspan' => 4, 'header' => TRUE)); if (!isset($config[$name])) { $details = array('#markup' => $this->t('Component in feature missing from active config.')); } else { $active = $this->featuresManager->getActiveStorage()->read($name); $extension = $this->featuresManager->getExtensionStorages()->read($name); if (empty($extension)) { $details = array('#markup' => $this->t('Dependency detected in active config but not exported to the feature.')); } else { $diff = $this->configDiff->diff($active, $extension); $details = array('#type' => 'table', '#header' => $header, '#rows' => $this->diffFormatter->format($diff), '#attributes' => array('class' => array('diff', 'features-diff'))); } } $element[$name] = array('row' => array('data' => array('#type' => 'details', '#title' => Html::escape($name), '#open' => TRUE, '#description' => array('data' => $details))), '#attributes' => array('class' => 'diff-' . $package->getMachineName())); } return $element; }