class AssignmentConfigureForm in Features 8.3
Same name and namespace in other branches
- 8.4 modules/features_ui/src/Form/AssignmentConfigureForm.php \Drupal\features_ui\Form\AssignmentConfigureForm
Configures the configuration assignment methods for this site.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\features_ui\Form\AssignmentConfigureForm
Expanded class hierarchy of AssignmentConfigureForm
1 string reference to 'AssignmentConfigureForm'
- features_ui.routing.yml in modules/
features_ui/ features_ui.routing.yml - modules/features_ui/features_ui.routing.yml
File
- modules/
features_ui/ src/ Form/ AssignmentConfigureForm.php, line 18
Namespace
Drupal\features_ui\FormView source
class AssignmentConfigureForm extends FormBase {
/**
* Bundle select value that should trigger a new bundle to be created.
*/
const NEW_BUNDLE_SELECT_VALUE = 'new';
/**
* The features manager.
*
* @var \Drupal\features\FeaturesManagerInterface
*/
protected $featuresManager;
/**
* The package assigner.
*
* @var \Drupal\features\FeaturesAssignerInterface
*/
protected $assigner;
/**
* Constructs a AssignmentConfigureForm object.
*
* @param \Drupal\features\FeaturesManagerInterface $features_manager
* The features manager.
* @param \Drupal\features\FeaturesAssignerInterface $assigner
* The configuration assignment methods manager.
*/
public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner) {
$this->featuresManager = $features_manager;
$this->assigner = $assigner;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('features.manager'), $container
->get('features_assigner'));
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'features_assignment_configure_form';
}
/**
* Load the values from the bundle into the user input.
* Used during Ajax callback since updating #default_values is ignored.
*
* @param mixed $bundle_name
* The bundle name.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form values.
*/
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);
}
/**
* Detects if an element triggered the form submission via Ajax.
* TODO: SHOULDN'T NEED THIS! BUT DRUPAL IS CALLING buildForm AFTER THE
* BUNDLE AJAX IS SELECTED AND DOESN'T HAVE getTriggeringElement() SET YET.
*/
protected function elementTriggeredScriptedSubmission(FormStateInterface &$form_state) {
$input = $form_state
->getUserInput();
if (!empty($input['_triggering_element_name'])) {
return $input['_triggering_element_name'];
}
return '';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) {
$load_values = FALSE;
$trigger = $form_state
->getTriggeringElement();
// TODO: See if there is a Drupal Core issue for this.
// Sometimes the first ajax call on the page causes buildForm to be called
// twice! First time form_state->getTriggeringElement is NOT SET, but
// the form_state['input'] shows the _triggering_element_name. Then the
// SECOND time it is called the getTriggeringElement is fine.
$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) {
// If no bundle is selected, use the current one.
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();
// Add missing data to the methods lists.
$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;
}
}
// Order methods list by weight.
asort($methods_weight);
if ($load_values) {
$this
->loadBundleValues($bundle_name, $form_state, $current_bundle, $enabled_methods, $methods_weight);
}
$form = [
'#attached' => [
'library' => [
// Provides the copyFieldValue behavior invoked below.
'system/drupal.system',
'features_ui/drupal.features_ui.admin',
],
],
// '#attributes' => array('class' => 'edit-bundles-wrapper'),
'#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',
],
];
// Don't show the remove button for the default bundle or when adding a new
// bundle.
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,
];
// Don't allow changing the default bundle machine name.
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,
// Show and require only if the profile.add option is selected.
'#states' => $show_and_require_if_profile_checked,
];
// Attach the copyFieldValue behavior to the profile_name field. In
// practice this only works if a user tabs through the bundle machine name
// field or manually edits it.
$form['#attached']['drupalSettings']['copyFieldValue']['edit-bundle-machine-name'] = [
'edit-bundle-profile-name',
];
foreach ($methods_weight as $method_id => $weight) {
// A packaging method might no longer be available if the defining module
// has been uninstalled after the last configuration saving.
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(),
]),
];
// If there is at least one operation enabled, show the operation
// column.
$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;
}
/**
* Ajax callback for handling switching the bundle selector.
*/
public function updateForm($form, FormStateInterface $form_state) {
return $form;
}
/**
* {@inheritdoc}
*/
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.'));
}
}
/**
* {@inheritdoc}
*/
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 this is a new bundle, create it.
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.'));
}
/**
* Callback for machine_name exists()
*
* @param $value
* @param $element
* @param $form_state
*
* @return bool
*/
public function bundleExists($value, $element, $form_state) {
$bundle = $this->assigner
->getBundle($value);
return isset($bundle);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AssignmentConfigureForm:: |
protected | property | The package assigner. | |
AssignmentConfigureForm:: |
protected | property | The features manager. | |
AssignmentConfigureForm:: |
public | function |
Form constructor. Overrides FormInterface:: |
|
AssignmentConfigureForm:: |
public | function | Callback for machine_name exists() | |
AssignmentConfigureForm:: |
public static | function |
Instantiates a new instance of this class. Overrides FormBase:: |
|
AssignmentConfigureForm:: |
protected | function | Detects if an element triggered the form submission via Ajax. TODO: SHOULDN'T NEED THIS! BUT DRUPAL IS CALLING buildForm AFTER THE BUNDLE AJAX IS SELECTED AND DOESN'T HAVE getTriggeringElement() SET YET. | |
AssignmentConfigureForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
AssignmentConfigureForm:: |
protected | function | Load the values from the bundle into the user input. Used during Ajax callback since updating #default_values is ignored. | |
AssignmentConfigureForm:: |
constant | Bundle select value that should trigger a new bundle to be created. | ||
AssignmentConfigureForm:: |
public | function |
Form submission handler. Overrides FormInterface:: |
|
AssignmentConfigureForm:: |
public | function | Ajax callback for handling switching the bundle selector. | |
AssignmentConfigureForm:: |
public | function |
Form validation handler. Overrides FormBase:: |
|
AssignmentConfigureForm:: |
public | function | Constructs a AssignmentConfigureForm object. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |