diff --git a/core/lib/Drupal/Core/Wizard/WizardFormController.php b/core/lib/Drupal/Core/Wizard/WizardFormController.php new file mode 100644 index 0000000..38171af --- /dev/null +++ b/core/lib/Drupal/Core/Wizard/WizardFormController.php @@ -0,0 +1,127 @@ +entityInfo(); + drupal_set_title($definition['steps'][$this->getOperation()]); + return parent::form($form, $form_state, $entity); + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::actions(). + * + * Digs through the entity definition's steps to determine if previous or + * next steps exist in order to display the appropriate buttons and text on + * those buttons. + */ + protected function actions(array $form, array &$form_state) { + $actions = parent::actions($form, $form_state); + $entity = $this->buildEntity($form, $form_state += array('values' => array())); + $definition = $entity->entityInfo(); + $steps = array_keys($definition['steps']); + $before = array_slice($definition['steps'], 0, array_search($this->getOperation(), $steps)); + $after = array_slice($definition['steps'], array_search($this->getOperation(), $steps) + 1); + // If there are steps after this one, label the button "Next" otherwise + // label it "Finish". + if ($after) { + $actions['submit']['#value'] = t('Next'); + } + else { + $actions['submit']['#value'] = t('Finish'); + $actions['submit']['#submit'][] = array($this, 'finish'); + } + + // If there are steps before this one, label the button "previous" + // otherwise do not display a button. + if ($before) { + $actions['previous'] = array( + '#value' => t('Previous'), + '#submit' => array( + array($this, 'previous'), + ), + '#limit_validation_errors' => array(), + '#weight' => -10, + ); + } + + return $actions; + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::submit(). + * + * Instead of saving the entity at each step, we populate a tempstore with + * the entity for the next step. + */ + public function submit(array $form, array &$form_state) { + if ($form_state['values']['op'] == 'Next') { + $entity = $this->buildEntity($form, $form_state); + $definition = $entity->entityInfo(); + drupal_container()->get('user.tempstore')->get($definition['id'])->set($entity->id(), $entity); + $steps = array_keys($definition['steps']); + $after = array_slice($definition['steps'], array_search($this->getOperation(), $steps) + 1); + $after = array_keys($after); + $after = array_reverse($after); + + $form_state['redirect'] = 'admin/config/system/conditions/' . $entity->id() . '/' . $after[0]; + } + } + + /** + * Form submission handler for the 'previous' action. + * + * This method finds the previous step and redirects us to it. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A reference to a keyed array containing the current state of the form. + */ + public function previous(array $form, array &$form_state) { + $entity = $this->buildEntity($form, $form_state); + $definition = $entity->entityInfo(); + $steps = array_keys($definition['steps']); + $before = array_slice($definition['steps'], 0, array_search($this->getOperation(), $steps)); + $before = array_keys($before); + $before = array_reverse($before); + + $form_state['redirect'] = 'admin/config/system/conditions/' . $entity->id() . '/' . $before[0]; + } + + /** + * Form submission handler for the 'previous' action. + * + * Retrieves the entity, saves it and deletes the values in the tempstore. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A reference to a keyed array containing the current state of the form. + */ + public function finish(array $form, array &$form_state) { + $entity = parent::submit($form, $form_state); + $definition = $entity->entityInfo(); + $entity->save(); + drupal_container()->get('user.tempstore')->get($definition['id'])->delete($entity->id()); + $form_state['redirect'] = 'admin/config/system/conditions'; + } +} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 60cd4e0..b129070 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1147,6 +1147,35 @@ function system_plugin_ui_access($plugin, $facet = NULL) { return $plugin_ui->access($facet); } + +/** + * Provides a generic wrapper for multi page entity wizard forms. + * + * @param $entity_type + * The type of entity we are working with. This will be used for + * entity_create() calls as well as unique storage within tempstore. + * @param $step + * The current step in the form wizard process. + * @param $id + * The unique identifier of the entity the form wizard is building. + * + * @return array + * The renderable array from the current step of the entity's available form + * controllers. + */ +function system_wizard_form($entity_type, $step, $id = NULL) { + if (empty($id)) { + $entity = entity_create($entity_type, array()); + } + else { + $entity = drupal_container()->get('user.tempstore')->get($entity_type)->get($id); + if (!method_exists($entity, 'entityType')) { + $entity = entity_load($entity_type, $id); + } + } + return entity_get_form($entity, $step); +} + /** * Implements hook_forms(). */