View source
<?php
namespace Drupal\features_ui\Form;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\features\FeaturesManagerInterface;
use Drupal\features\FeaturesAssignerInterface;
use Drupal\features\FeaturesBundleInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
class AssignmentConfigureForm extends FormBase {
const NEW_BUNDLE_SELECT_VALUE = 'new';
protected $featuresManager;
protected $assigner;
public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner) {
$this->featuresManager = $features_manager;
$this->assigner = $assigner;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('features.manager'), $container
->get('features_assigner'));
}
public function getFormId() {
return 'features_assignment_configure_form';
}
protected function loadBundleValues($bundle_name, FormStateInterface &$form_state, $current_bundle, $enabled_methods, $methods_weight) {
$input = $form_state
->getUserInput();
if ($bundle_name == self::NEW_BUNDLE_SELECT_VALUE) {
$input['bundle']['name'] = '';
$input['bundle']['machine_name'] = '';
$input['bundle']['description'] = '';
$input['bundle']['is_profile'] = NULL;
$input['bundle']['profile_name'] = '';
}
else {
$input['bundle']['name'] = $current_bundle
->getName();
$input['bundle']['machine_name'] = $current_bundle
->getMachineName();
$input['bundle']['description'] = $current_bundle
->getDescription();
$input['bundle']['is_profile'] = $current_bundle
->isProfile() ? 1 : NULL;
$input['bundle']['profile_name'] = $current_bundle
->isProfile() ? $current_bundle
->getProfileName() : '';
}
foreach ($methods_weight as $method_id => $weight) {
$enabled = isset($enabled_methods[$method_id]);
$input['weight'][$method_id] = $weight;
$input['enabled'][$method_id] = $enabled ? 1 : NULL;
}
$form_state
->setUserInput($input);
}
protected function elementTriggeredScriptedSubmission(FormStateInterface &$form_state) {
$input = $form_state
->getUserInput();
if (!empty($input['_triggering_element_name'])) {
return $input['_triggering_element_name'];
}
return '';
}
public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) {
$load_values = FALSE;
$trigger = $form_state
->getTriggeringElement();
$real_trigger = $this
->elementTriggeredScriptedSubmission($form_state);
if (!isset($trigger) && $real_trigger == 'bundle[bundle_select]') {
$input = $form_state
->getUserInput();
$bundle_name = $input['bundle']['bundle_select'];
if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE) {
$this->assigner
->setCurrent($this->assigner
->getBundle($bundle_name));
}
$load_values = TRUE;
}
elseif (isset($trigger['#name']) && $trigger['#name'] == 'bundle[bundle_select]') {
$bundle_name = $form_state
->getValue([
'bundle',
'bundle_select',
]);
if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE) {
$this->assigner
->setCurrent($this->assigner
->getBundle($bundle_name));
}
$load_values = TRUE;
}
elseif (isset($trigger['#name']) && $trigger['#name'] == 'removebundle') {
$current_bundle = $this->assigner
->loadBundle($bundle_name);
$bundle_name = $current_bundle
->getMachineName();
$this->assigner
->removeBundle($bundle_name);
return $this
->redirect('features.assignment', [
'',
]);
}
if (!isset($current_bundle)) {
switch ($bundle_name) {
case NULL:
$current_bundle = $this->assigner
->loadBundle();
$bundle_name = $current_bundle
->getMachineName();
break;
case self::NEW_BUNDLE_SELECT_VALUE:
$current_bundle = $this->assigner
->loadBundle(FeaturesBundleInterface::DEFAULT_BUNDLE);
break;
default:
$current_bundle = $this->assigner
->loadBundle($bundle_name);
break;
}
}
$enabled_methods = $current_bundle
->getEnabledAssignments();
$methods_weight = $current_bundle
->getAssignmentWeights();
$assignment_info = $this->assigner
->getAssignmentMethods();
foreach ($assignment_info as $method_id => $method) {
if (!isset($methods_weight[$method_id])) {
$methods_weight[$method_id] = isset($method['weight']) ? $method['weight'] : 0;
}
}
asort($methods_weight);
if ($load_values) {
$this
->loadBundleValues($bundle_name, $form_state, $current_bundle, $enabled_methods, $methods_weight);
}
$form = [
'#attached' => [
'library' => [
'system/drupal.system',
'features_ui/drupal.features_ui.admin',
],
],
'#tree' => TRUE,
'#show_operations' => FALSE,
'weight' => [
'#tree' => TRUE,
],
'#prefix' => '<div id="edit-bundles-wrapper">',
'#suffix' => '</div>',
];
$form['bundle'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Bundle'),
'#tree' => TRUE,
'#weight' => -9,
];
if ($bundle_name == self::NEW_BUNDLE_SELECT_VALUE) {
$default_values = [
'bundle_select' => self::NEW_BUNDLE_SELECT_VALUE,
'name' => '',
'machine_name' => '',
'description' => '',
'is_profile' => FALSE,
'profile_name' => '',
];
}
else {
$default_values = [
'bundle_select' => $current_bundle
->getMachineName(),
'name' => $current_bundle
->getName(),
'machine_name' => $current_bundle
->getMachineName(),
'description' => $current_bundle
->getDescription(),
'is_profile' => $current_bundle
->isProfile(),
'profile_name' => $current_bundle
->getProfileName(),
];
}
$form['bundle']['bundle_select'] = [
'#title' => $this
->t('Bundle'),
'#title_display' => 'invisible',
'#type' => 'select',
'#options' => [
self::NEW_BUNDLE_SELECT_VALUE => $this
->t('--New--'),
] + $this->assigner
->getBundleOptions(),
'#default_value' => $default_values['bundle_select'],
'#ajax' => [
'callback' => '::updateForm',
'wrapper' => 'edit-bundles-wrapper',
],
];
if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE && !$current_bundle
->isDefault()) {
$form['bundle']['remove'] = [
'#type' => 'button',
'#name' => 'removebundle',
'#value' => $this
->t('Remove bundle'),
];
}
$form['bundle']['name'] = [
'#title' => $this
->t('Bundle name'),
'#type' => 'textfield',
'#description' => $this
->t('A unique human-readable name of this bundle.'),
'#default_value' => $default_values['name'],
'#required' => TRUE,
'#disabled' => $bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE,
];
if ($bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE) {
$form['bundle']['machine_name'] = [
'#type' => 'value',
'#value' => $default_values['machine_name'],
];
}
else {
$form['bundle']['machine_name'] = [
'#title' => $this
->t('Machine name'),
'#type' => 'machine_name',
'#required' => TRUE,
'#default_value' => $default_values['machine_name'],
'#description' => $this
->t('A unique machine-readable name of this bundle. Used to prefix exported packages. It must only contain lowercase letters, numbers, and underscores.'),
'#machine_name' => [
'source' => [
'bundle',
'name',
],
'exists' => [
$this,
'bundleExists',
],
],
];
}
$form['bundle']['description'] = [
'#title' => $this
->t('Distribution description'),
'#type' => 'textfield',
'#default_value' => $default_values['description'],
'#description' => $this
->t('A description of the bundle.'),
'#size' => 80,
];
$form['bundle']['is_profile'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Include install profile'),
'#default_value' => $default_values['is_profile'],
'#description' => $this
->t('Select this option to have your features packaged into an install profile.'),
'#attributes' => [
'data-add-profile' => 'status',
],
];
$show_and_require_if_profile_checked = [
'visible' => [
':input[data-add-profile="status"]' => [
'checked' => TRUE,
],
],
'required' => [
':input[data-add-profile="status"]' => [
'checked' => TRUE,
],
],
];
$form['bundle']['profile_name'] = [
'#title' => $this
->t('Profile name'),
'#type' => 'textfield',
'#default_value' => $default_values['profile_name'],
'#description' => $this
->t('The machine name (directory name) of your profile.'),
'#size' => 30,
'#states' => $show_and_require_if_profile_checked,
];
$form['#attached']['drupalSettings']['copyFieldValue']['edit-bundle-machine-name'] = [
'edit-bundle-profile-name',
];
foreach ($methods_weight as $method_id => $weight) {
if (!isset($assignment_info[$method_id])) {
continue;
}
$enabled = isset($enabled_methods[$method_id]);
$method = $assignment_info[$method_id];
$method_name = Html::escape($method['name']);
$form['weight'][$method_id] = [
'#type' => 'weight',
'#title' => $this
->t('Weight for @title package assignment method', [
'@title' => mb_strtolower($method_name),
]),
'#title_display' => 'invisible',
'#default_value' => $weight,
'#attributes' => [
'class' => [
'assignment-method-weight',
],
],
'#delta' => 20,
];
$form['title'][$method_id] = [
'#markup' => $method_name,
];
$form['enabled'][$method_id] = [
'#type' => 'checkbox',
'#title' => $this
->t('Enable @title package assignment method', [
'@title' => mb_strtolower($method_name),
]),
'#title_display' => 'invisible',
'#default_value' => $enabled,
];
$form['description'][$method_id] = [
'#markup' => $method['description'],
];
$config_op = [];
if (isset($method['config_route_name'])) {
$config_op['configure'] = [
'title' => $this
->t('Configure'),
'url' => Url::fromRoute($method['config_route_name'], [
'bundle_name' => $current_bundle
->getMachineName(),
]),
];
$form['#show_operations'] = TRUE;
}
$form['operation'][$method_id] = [
'#type' => 'operations',
'#links' => $config_op,
];
}
$form['actions'] = [
'#type' => 'actions',
'#weight' => 9,
];
$form['actions']['submit'] = [
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => $this
->t('Save settings'),
];
return $form;
}
public function updateForm($form, FormStateInterface $form_state) {
return $form;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
if ($form_state
->getValue([
'bundle',
'is_profile',
]) && empty($form_state
->getValue([
'bundle',
'profile_name',
]))) {
$form_state
->setErrorByName('bundle][profile_name', $this
->t('To create a profile, please enter a profile name.'));
}
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$enabled_methods = array_filter($form_state
->getValue('enabled'));
ksort($enabled_methods);
$method_weights = $form_state
->getValue('weight');
ksort($method_weights);
$machine_name = $form_state
->getValue([
'bundle',
'machine_name',
]);
if ($form_state
->getValue([
'bundle',
'bundle_select',
]) == self::NEW_BUNDLE_SELECT_VALUE) {
$bundle = $this->assigner
->createBundleFromDefault($machine_name);
}
else {
$bundle = $this->assigner
->loadBundle();
$old_name = $bundle
->getMachineName();
$new_name = $form_state
->getValue([
'bundle',
'machine_name',
]);
if ($old_name != $new_name) {
$bundle = $this->assigner
->renameBundle($old_name, $new_name);
}
}
$bundle
->setName($form_state
->getValue([
'bundle',
'name',
]));
$bundle
->setDescription($form_state
->getValue([
'bundle',
'description',
]));
$bundle
->setEnabledAssignments(array_keys($enabled_methods));
$bundle
->setAssignmentWeights($method_weights);
$bundle
->setIsProfile($form_state
->getValue([
'bundle',
'is_profile',
]));
$bundle
->setProfileName($form_state
->getValue([
'bundle',
'profile_name',
]));
$bundle
->save();
$this->assigner
->setBundle($bundle);
$this->assigner
->setCurrent($bundle);
$form_state
->setRedirect('features.assignment');
$this
->messenger()
->addStatus($this
->t('Package assignment configuration saved.'));
}
public function bundleExists($value, $element, $form_state) {
$bundle = $this->assigner
->getBundle($value);
return isset($bundle);
}
}