Example #1
0
 /**
  * {@inheritdoc}
  */
 public function doSubmitForm(&$form, FormStateInterface &$form_state)
 {
     if (!$form_state->isSubmitted()) {
         return;
     }
     // Execute form submit handlers.
     $this->executeSubmitHandlers($form, $form_state);
     // If batches were set in the submit handlers, we process them now,
     // possibly ending execution. We make sure we do not react to the batch
     // that is already being processed (if a batch operation performs a
     // \Drupal\Core\Form\FormBuilderInterface::submitForm).
     if (($batch =& $this->batchGet()) && !isset($batch['current_set'])) {
         // Store $form_state information in the batch definition.
         $batch['form_state'] = $form_state;
         $batch['progressive'] = !$form_state->isProgrammed();
         $response = batch_process();
         if ($batch['progressive']) {
             return $response;
         }
         // Execution continues only for programmatic forms.
         // For 'regular' forms, we get redirected to the batch processing
         // page. Form redirection will be handled in _batch_finished(),
         // after the batch is processed.
     }
     // Set a flag to indicate the form has been processed and executed.
     $form_state->setExecuted();
     // If no response has been set, process the form redirect.
     if (!$form_state->getResponse() && ($redirect = $this->redirectForm($form_state))) {
         $form_state->setResponse($redirect);
     }
     // If there is a response was set, return it instead of continuing.
     if (($response = $form_state->getResponse()) && $response instanceof Response) {
         return $response;
     }
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state)
 {
     // Only run key provider settings validation if the form is being submitted
     if ($form_state->isSubmitted()) {
         $plugin = $this->manager->createInstance($form_state->getValue('key_provider'), []);
         $plugin->validateConfigurationForm($form, $form_state);
     }
     parent::validateForm($form, $form_state);
 }
Example #3
0
 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state)
 {
     // Only run key settings validation if the form is being submitted
     if ($form_state->isSubmitted()) {
         $plugin_settings = (new FormState())->setValues($form_state->getValue('key_settings'));
         $plugin = $this->manager->createInstance($form_state->getValue('key_provider'), []);
         $plugin->validateConfigurationForm($form, $plugin_settings);
         // Reinject errors from $plugin_settings into $form_state
         foreach ($plugin_settings->getErrors() as $field => $error) {
             $form_state->setErrorByName($field, $error);
         }
     }
     parent::validateForm($form, $form_state);
 }
Example #4
0
 /**
  * {@inheritdoc}
  */
 public function isSubmitted()
 {
     return $this->mainFormState->isSubmitted();
 }
Example #5
0
 /**
  * Determines if validation errors should be limited.
  *
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   The current state of the form.
  *
  * @return array|null
  */
 protected function determineLimitValidationErrors(FormStateInterface &$form_state)
 {
     // While this element is being validated, it may be desired that some
     // calls to \Drupal\Core\Form\FormStateInterface::setErrorByName() be
     // suppressed and not result in a form error, so that a button that
     // implements low-risk functionality (such as "Previous" or "Add more") that
     // doesn't require all user input to be valid can still have its submit
     // handlers triggered. The triggering element's #limit_validation_errors
     // property contains the information for which errors are needed, and all
     // other errors are to be suppressed. The #limit_validation_errors property
     // is ignored if submit handlers will run, but the element doesn't have a
     // #submit property, because it's too large a security risk to have any
     // invalid user input when executing form-level submit handlers.
     $triggering_element = $form_state->getTriggeringElement();
     if (isset($triggering_element['#limit_validation_errors']) && $triggering_element['#limit_validation_errors'] !== FALSE && !($form_state->isSubmitted() && !isset($triggering_element['#submit']))) {
         return $triggering_element['#limit_validation_errors'];
     } elseif ($triggering_element && !isset($triggering_element['#limit_validation_errors']) && !$form_state->isSubmitted()) {
         return array();
     } else {
         return NULL;
     }
 }
 /**
  * Returns the full feature export array based upon user selections in
  * form_state.
  *
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   Optional form_state information for user selections. Can be updated to
  *   reflect new selection status.
  *
  * @return \Drupal\features\Package
  *   New export array to be exported
  *   array['components'][$component_name] = $component_info
  *     $component_info['_features_options'][$section] is list of available options
  *     $component_info['_features_selected'][$section] is option state TRUE/FALSE
  *   $section = array('sources', included', 'detected', 'added')
  *     sources - options that are available to be added to the feature
  *     included - options that have been previously exported to the feature
  *     detected - options that have been auto-detected
  *     added - newly added options to the feature
  *
  * NOTE: This routine gets a bit complex to handle all of the different
  * possible user checkbox selections and de-selections.
  * Cases to test:
  *   1a) uncheck Included item -> mark as Added but unchecked
  *   1b) re-check unchecked Added item -> return it to Included check item
  *   2a) check Sources item -> mark as Added and checked
  *   2b) uncheck Added item -> return it to Sources as unchecked
  *   3a) uncheck Included item that still exists as auto-detect -> mark as
  *       Detected but unchecked
  *   3b) re-check Detected item -> return it to Included and checked
  *   4a) check Sources item should also add any auto-detect items as Detected
  *       and checked
  *   4b) uncheck Sources item with auto-detect and auto-detect items should
  *       return to Sources and unchecked
  *   5a) uncheck a Detected item -> refreshing page should keep it as
  *       unchecked Detected
  *   6)  when nothing changes, refresh should not change any state
  *   7)  should never see an unchecked Included item
  */
 protected function getComponentList(FormStateInterface $form_state)
 {
     $config = $this->featuresManager->getConfigCollection();
     $package_name = $this->package->getMachineName();
     // Auto-detect dependencies for included config.
     $package_config = $this->package->getConfig();
     if (!empty($this->package->getConfigOrig())) {
         $package_config = array_unique(array_merge($package_config, $this->package->getConfigOrig()));
     }
     if (!empty($package_config)) {
         $this->featuresManager->assignConfigDependents($package_config, $package_name);
     }
     $packages = $this->featuresManager->getPackages();
     // Re-fetch the package in case config was updated with Dependents above.
     $this->package = $packages[$package_name];
     // Make a map of all config data.
     $components = array();
     $this->conflicts = array();
     foreach ($config as $item_name => $item) {
         if ($item->getPackage() != $package_name && !empty($packages[$item->getPackage()]) && $packages[$item->getPackage()]->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT) {
             $this->conflicts[$item->getType()][$item->getShortName()] = $item->getLabel();
         }
         if ($this->allowConflicts || !isset($this->conflicts[$item->getType()][$item->getShortName()]) || $this->package->getConfigOrig() && in_array($item_name, $this->package->getConfigOrig())) {
             $components[$item->getType()][$item->getShortName()] = $item->getLabel();
         }
     }
     // Make a map of the config data already exported to the Feature.
     $exported_features_info = array();
     foreach ($this->package->getConfigOrig() as $item_name) {
         // Make sure the extension provided item exists in the active
         // configuration storage.
         if (isset($config[$item_name])) {
             $item = $config[$item_name];
             // Remove any conflicts if those are not being allowed.
             // if ($this->allowConflicts || !isset($this->conflicts[$item['type']][$item['name_short']])) {
             $exported_features_info[$item->getType()][$item->getShortName()] = $item->getLabel();
             // }
         }
     }
     $exported_features_info['dependencies'] = $this->package->getDependencyInfo();
     // Make a map of any config specifically excluded and/or required.
     foreach (array('excluded', 'required') as $constraint) {
         $this->{$constraint} = array();
         $info = !empty($this->package->getFeaturesInfo()[$constraint]) ? $this->package->getFeaturesInfo()[$constraint] : array();
         foreach ($info as $item_name) {
             $item = $config[$item_name];
             $this->{$constraint}[$item->getType()][$item->getShortName()] = $item->getLabel();
         }
     }
     // Make a map of the config data to be exported within the Feature.
     $new_features_info = array();
     foreach ($this->package->getConfig() as $item_name) {
         $item = $config[$item_name];
         $new_features_info[$item->getType()][$item->getShortName()] = $item->getLabel();
     }
     $new_features_info['dependencies'] = $this->package->getDependencies();
     // Assemble the combined component list.
     $config_new = array();
     $sections = array('sources', 'included', 'detected', 'added');
     // Generate list of config to be exported.
     $config_count = array();
     foreach ($components as $component => $component_info) {
         // User-selected components take precedence.
         $config_new[$component] = array();
         $config_count[$component] = 0;
         // Add selected items from Sources checkboxes.
         if (!$form_state->isValueEmpty(array($component, 'sources', 'selected'))) {
             $config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue(array($component, 'sources', 'selected')))));
             $config_count[$component]++;
         }
         // Add selected items from already Included, newly Added, auto-detected
         // checkboxes.
         foreach (array('included', 'added', 'detected') as $section) {
             if (!$form_state->isValueEmpty(array($component, $section))) {
                 $config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue(array($component, $section)))));
                 $config_count[$component]++;
             }
         }
         // Only fallback to an existing feature's values if there are no export
         // options for the component.
         if ($component == 'dependencies') {
             if ($config_count[$component] == 0 && !empty($exported_features_info['dependencies'])) {
                 $config_new[$component] = array_combine($exported_features_info['dependencies'], $exported_features_info['dependencies']);
             }
         } elseif ($config_count[$component] == 0 && !empty($exported_features_info[$component])) {
             $config_names = array_keys($exported_features_info[$component]);
             $config_new[$component] = array_combine($config_names, $config_names);
         }
     }
     // Generate new populated feature.
     $export['package'] = $this->package;
     $export['config_new'] = $config_new;
     // Now fill the $export with categorized sections of component options
     // based upon user selections and de-selections.
     foreach ($components as $component => $component_info) {
         $component_export = $component_info;
         foreach ($sections as $section) {
             $component_export['_features_options'][$section] = array();
             $component_export['_features_selected'][$section] = array();
         }
         if (!empty($component_info)) {
             $exported_components = !empty($exported_features_info[$component]) ? $exported_features_info[$component] : array();
             $new_components = !empty($new_features_info[$component]) ? $new_features_info[$component] : array();
             foreach ($component_info as $key => $label) {
                 $config_name = $this->featuresManager->getFullName($component, $key);
                 // If checkbox in Sources is checked, move it to Added section.
                 if (!$form_state->isValueEmpty(array($component, 'sources', 'selected', $key))) {
                     $form_state->setValue(array($component, 'sources', 'selected', $key), FALSE);
                     $form_state->setValue(array($component, 'added', $key), 1);
                     $component_export['_features_options']['added'][$key] = $this->configLabel($component, $key, $label);
                     $component_export['_features_selected']['added'][$key] = $key;
                     // If this was previously excluded, we don't need to set it as
                     // required because it was automatically assigned.
                     if (isset($this->excluded[$component][$key])) {
                         unset($this->excluded[$component][$key]);
                     } else {
                         $this->required[$component][$key] = $key;
                     }
                 } elseif (isset($new_components[$key])) {
                     // Option is in the New exported array.
                     if (isset($exported_components[$key])) {
                         // Option was already previously exported so it's part of the
                         // Included checkboxes.
                         $section = 'included';
                         $default_value = $key;
                         // If Included item was un-selected (removed from export
                         // $config_new) but was re-detected in the $new_components
                         // means it was an auto-detect that was previously part of the
                         // export and is now de-selected in UI.
                         if ($form_state->isSubmitted() && ($form_state->hasValue(array($component, 'included', $key)) || $form_state->isValueEmpty(array($component, 'detected', $key))) && empty($config_new[$component][$key])) {
                             $section = 'detected';
                             $default_value = FALSE;
                         } elseif ($form_state->isSubmitted() && $form_state->isValueEmpty(array($component, 'added', $key)) && $form_state->isValueEmpty(array($component, 'detected', $key)) && $form_state->isValueEmpty(array($component, 'included', $key))) {
                             $section = 'added';
                             $default_value = FALSE;
                         }
                     } else {
                         // Option was in New exported array, but NOT in already exported
                         // so it's a user-selected or an auto-detect item.
                         $section = 'detected';
                         $default_value = NULL;
                         // Check for item explicitly excluded.
                         if (isset($this->excluded[$component][$key]) && !$form_state->hasValue(array($component, 'detected', $key))) {
                             $default_value = FALSE;
                         } else {
                             $default_value = $key;
                         }
                         // If it's already checked in Added or Sources, leave it in Added
                         // as checked.
                         if ($form_state->isSubmitted() && (!$form_state->isValueEmpty(array($component, 'added', $key)) || !$form_state->isValueEmpty(array($component, 'sources', 'selected', $key)))) {
                             $section = 'added';
                             $default_value = $key;
                         } elseif ($form_state->isSubmitted() && $form_state->isValueEmpty(array($component, 'sources', 'selected', $key)) && $form_state->isValueEmpty(array($component, 'detected', $key)) && !$form_state->hasValue(array($component, 'added', $key))) {
                             $section = 'detected';
                             $default_value = FALSE;
                         }
                     }
                     $component_export['_features_options'][$section][$key] = $this->configLabel($component, $key, $label);
                     $component_export['_features_selected'][$section][$key] = $default_value;
                     // Save which dependencies are specifically excluded from
                     // auto-detection.
                     if ($section == 'detected' && $default_value === FALSE) {
                         // If this was previously required, we don't need to set it as
                         // excluded because it wasn't automatically assigned.
                         if (isset($this->required[$component][$key])) {
                             unset($this->required[$component][$key]);
                         } else {
                             $this->excluded[$component][$key] = $key;
                         }
                         // Remove excluded item from export.
                         if ($component == 'dependencies') {
                             $export['package']->removeDependency($key);
                         } else {
                             $export['package']->removeConfig($config_name);
                         }
                     } else {
                         unset($this->excluded[$component][$key]);
                     }
                     // Remove the 'input' and set the 'values' so Drupal stops looking
                     // at 'input'.
                     if ($form_state->isSubmitted()) {
                         if (!$default_value) {
                             $form_state->setValue(array($component, $section, $key), FALSE);
                         } else {
                             $form_state->setValue(array($component, $section, $key), 1);
                         }
                     }
                 } elseif (!$form_state->isSubmitted() && isset($exported_components[$key])) {
                     // Component is not part of new export, but was in original export.
                     // Mark component as Added when creating initial form.
                     $component_export['_features_options']['added'][$key] = $this->configLabel($component, $key, $label);
                     $component_export['_features_selected']['added'][$key] = $key;
                 } else {
                     // Option was not part of the new export.
                     $added = FALSE;
                     foreach (array('included', 'added') as $section) {
                         // Restore any user-selected checkboxes.
                         if (!$form_state->isValueEmpty(array($component, $section, $key))) {
                             $component_export['_features_options'][$section][$key] = $this->configLabel($component, $key, $label);
                             $component_export['_features_selected'][$section][$key] = $key;
                             $added = TRUE;
                         }
                     }
                     if (!$added) {
                         // If not Included or Added, then put it back in the unchecked
                         // Sources checkboxes.
                         $component_export['_features_options']['sources'][$key] = $this->configLabel($component, $key, $label);
                         $component_export['_features_selected']['sources'][$key] = FALSE;
                     }
                 }
             }
         }
         $export['components'][$component] = $component_export;
     }
     $export['features_exclude'] = $this->excluded;
     $export['features_require'] = $this->required;
     $export['conflicts'] = $this->conflicts;
     return $export;
 }
 /**
  * {@inheritdoc}
  */
 public function isSubmitted()
 {
     return $this->decoratedFormState->isSubmitted();
 }
 /**
  * @covers ::isSubmitted
  *
  * @dataProvider providerSingleBooleanArgument
  *
  * @param bool $submitted
  */
 public function testIsSubmitted($submitted)
 {
     $this->decoratedFormState->isSubmitted()->willReturn($submitted);
     $this->assertSame($submitted, $this->formStateDecoratorBase->isSubmitted());
 }