示例#1
0
 /**
  * Render the top of the display so it can be updated during ajax operations.
  */
 public function renderDisplayTop(ViewUI $view)
 {
     $display_id = $this->displayID;
     $element['#theme_wrappers'][] = 'views_ui_container';
     $element['#attributes']['class'] = array('views-display-top', 'clearfix');
     $element['#attributes']['id'] = array('views-display-top');
     // Extra actions for the display
     $element['extra_actions'] = array('#type' => 'dropbutton', '#attributes' => array('id' => 'views-display-extra-actions'), '#links' => array('edit-details' => array('title' => $this->t('Edit view name/description'), 'href' => "admin/structure/views/nojs/edit-details/{$view->id()}/{$display_id}", 'attributes' => array('class' => array('views-ajax-link'))), 'analyze' => array('title' => $this->t('Analyze view'), 'href' => "admin/structure/views/nojs/analyze/{$view->id()}/{$display_id}", 'attributes' => array('class' => array('views-ajax-link'))), 'duplicate' => array('title' => $this->t('Duplicate view')) + $view->urlInfo('duplicate')->toArray(), 'reorder' => array('title' => $this->t('Reorder displays'), 'href' => "admin/structure/views/nojs/reorder-displays/{$view->id()}/{$display_id}", 'attributes' => array('class' => array('views-ajax-link')))));
     if ($view->access('delete')) {
         $element['extra_actions']['#links']['delete'] = array('title' => $this->t('Delete view')) + $view->urlInfo('delete-form')->toArray();
     }
     // Let other modules add additional links here.
     \Drupal::moduleHandler()->alter('views_ui_display_top_links', $element['extra_actions']['#links'], $view, $display_id);
     if (isset($view->type) && $view->type != $this->t('Default')) {
         if ($view->type == $this->t('Overridden')) {
             $element['extra_actions']['#links']['revert'] = array('title' => $this->t('Revert view'), 'href' => "admin/structure/views/view/{$view->id()}/revert", 'query' => array('destination' => "admin/structure/views/view/{$view->id()}"));
         } else {
             $element['extra_actions']['#links']['delete'] = array('title' => $this->t('Delete view'), 'href' => "admin/structure/views/view/{$view->id()}/delete");
         }
     }
     // Determine the displays available for editing.
     if ($tabs = $this->getDisplayTabs($view)) {
         if ($display_id) {
             $tabs[$display_id]['#active'] = TRUE;
         }
         $tabs['#prefix'] = '<h2 class="visually-hidden">' . $this->t('Secondary tabs') . '</h2><ul id = "views-display-menu-tabs" class="tabs secondary">';
         $tabs['#suffix'] = '</ul>';
         $element['tabs'] = $tabs;
     }
     // Buttons for adding a new display.
     foreach (Views::fetchPluginNames('display', NULL, array($view->get('base_table'))) as $type => $label) {
         $element['add_display'][$type] = array('#type' => 'submit', '#value' => $this->t('Add !display', array('!display' => $label)), '#limit_validation_errors' => array(), '#submit' => array(array($this, 'submitDisplayAdd'), array($this, 'submitDelayDestination')), '#attributes' => array('class' => array('add-display')), '#process' => array_merge(array('views_ui_form_button_was_clicked'), element_info_property('submit', '#process', array())), '#values' => array($this->t('Add !display', array('!display' => $label)), $label));
     }
     return $element;
 }
示例#2
0
 /**
  * Provide a standard set of Apply/Cancel/OK buttons for the forms. Also provide
  * a hidden op operator because the forms plugin doesn't seem to properly
  * provide which button was clicked.
  *
  * TODO: Is the hidden op operator still here somewhere, or is that part of the
  * docblock outdated?
  */
 public function getStandardButtons(&$form, FormStateInterface $form_state, $form_id, $name = NULL)
 {
     $form['actions'] = array('#type' => 'actions');
     if (empty($name)) {
         $name = t('Apply');
         if (!empty($this->stack) && count($this->stack) > 1) {
             $name = t('Apply and continue');
         }
         $names = array(t('Apply'), t('Apply and continue'));
     }
     // Views provides its own custom handling of AJAX form submissions. Usually
     // this happens at the same path, but custom paths may be specified in
     // $form_state.
     $form_path = $form_state->get('path') ?: current_path();
     // Forms that are purely informational set an ok_button flag, so we know not
     // to create an "Apply" button for them.
     if (!$form_state->get('ok_button')) {
         $form['actions']['submit'] = array('#type' => 'submit', '#value' => $name, '#id' => 'edit-submit-' . drupal_html_id($form_id), '#submit' => array(array($this, 'standardSubmit')), '#button_type' => 'primary', '#ajax' => array('path' => $form_path));
         // Form API button click detection requires the button's #value to be the
         // same between the form build of the initial page request, and the
         // initial form build of the request processing the form submission.
         // Ideally, the button's #value shouldn't change until the form rebuild
         // step. However, \Drupal\views_ui\Form\Ajax\ViewsFormBase::getForm()
         // implements a different multistep form workflow than the Form API does,
         // and adjusts $view->stack prior to form processing, so we compensate by
         // extending button click detection code to support any of the possible
         // button labels.
         if (isset($names)) {
             $form['actions']['submit']['#values'] = $names;
             $form['actions']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), element_info_property($form['actions']['submit']['#type'], '#process', array()));
         }
         // If a validation handler exists for the form, assign it to this button.
         $form['actions']['submit']['#validate'][] = [$form_state->getFormObject(), 'validateForm'];
     }
     // Create a "Cancel" button. For purely informational forms, label it "OK".
     $cancel_submit = function_exists($form_id . '_cancel') ? $form_id . '_cancel' : array($this, 'standardCancel');
     $form['actions']['cancel'] = array('#type' => 'submit', '#value' => !$form_state->get('ok_button') ? t('Cancel') : t('Ok'), '#submit' => array($cancel_submit), '#validate' => array(), '#ajax' => array('path' => $form_path), '#limit_validation_errors' => array());
     // Compatibility, to be removed later: // TODO: When is "later"?
     // We used to set these items on the form, but now we want them on the $form_state:
     if (isset($form['#title'])) {
         $form_state->set('title', $form['#title']);
     }
     if (isset($form['#section'])) {
         $form_state->set('#section', $form['#section']);
     }
     // Finally, we never want these cached -- our object cache does that for us.
     $form['#no_cache'] = TRUE;
 }
 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state)
 {
     $account = \Drupal::currentUser();
     $form = ['#attached' => ['library' => ['webform/webform']]];
     $form_state->loadInclude('webform', 'inc', 'includes/webform.components');
     $form_state->loadInclude('webform', 'inc', 'includes/webform.submissions');
     // For ajax requests, $form_state->getValue('details') is missing. Restore
     // from storage, if available, for multi-page forms.
     if (empty($form_state->getValue('details')) && !empty($form_state->getValue(['storage', 'details']))) {
         $form_state->setValue('details', $form_state->getValue(['storage', 'details']));
     }
     $node = $this->node;
     $submission = $this->node;
     $resume_draft = $this->resume_draft;
     $filter = $this->filter;
     // If in a multi-step form, a submission ID may be specified in form state.
     // Load this submission. This allows anonymous users to use auto-save.
     if (empty($submission) && !empty($form_state->getValue(['details', 'sid']))) {
         $submission = webform_get_submission($node->id(), $form_state->getValue(['details', 'sid']));
     }
     $finished = isset($submission->is_draft) ? !$submission->is_draft : 0;
     $submit_button_text = $finished ? $this->t('Save') : (empty($node->webform['submit_text']) ? $this->t('Submit') : $node->webform['submit_text']);
     // Bind arguments to $form to make them available in theming and form_alter.
     $form['#node'] = $node;
     $form['#submission'] = $submission;
     $form['#filter'] = $filter;
     // Add a theme function for this form.
     $form['#theme'] = ['webform_form_' . $node->id(), 'webform_form'];
     // Add a CSS class for all client forms.
     $form['#attributes']['class'][] = 'webform-client-form';
     $form['#attributes']['class'][] = 'webform-client-form-' . $node->id();
     // Set the encoding type (necessary for file uploads).
     $form['#attributes']['enctype'] = 'multipart/form-data';
     // Sometimes when displaying a webform as a teaser or block, a custom action
     // property is set to direct the user to the node page.
     if (!empty($node->webform['action'])) {
         $form['#action'] = $node->webform['action'];
     }
     // @todo Convert these to methods.
     $form['#submit'] = ['webform_client_form_pages', 'webform_client_form_submit'];
     $form['#validate'] = ['webform_client_form_validate'];
     // Add includes for used component types and pre/post validation handlers
     $form['#process'] = ['webform_client_form_process'];
     if (is_array($node->webform['components']) && !empty($node->webform['components'])) {
         // Prepare a new form array.
         $form['submitted'] = ['#tree' => TRUE];
         $form['details'] = ['#tree' => TRUE];
         // Put the components into a tree structure.
         if (!isset($form_state->getStorage()['component_tree'])) {
             $form_state->set(['webform', 'component_tree'], []);
             $form_state->set(['webform', 'page_count'], 1);
             $form_state->set(['webform', 'page_num'], 1);
             _webform_components_tree_build($node->webform['components'], $form_state->get(['webform', 'component_tree']), 0, $form_state->get(['webform', 'page_count']));
             // If preview is enabled, increase the page count by one.
             if ($node->webform['preview']) {
                 $form_state->set(['webform', 'page_count'], $form_state->get(['webform', 'page_count']) + 1);
             }
             $form_state->set(['webform', 'preview'], $node->webform['preview']);
             // If this is the first time this draft has been restore and presented
             // to the user, let them know that they are looking at a draft, rather
             // than a new form. This applies to the node view page, but not to a
             // submission edit page (where they presumably know what submission they
             // are editing).
             if ($resume_draft && empty($form_state->getUserInput())) {
                 drupal_set_message($this->t('A partially-completed form was found. Please complete the remaining portions.'));
             }
         } else {
             $form_state->set(['webform', 'component_tree'], $form_state->getStorage()['component_tree']);
             $form_state->set(['webform', 'page_count'], $form_state->getStorage()['page_count']);
             $form_state->set(['webform', 'page_num'], $form_state->getStorage()['page_num']);
             $form_state->set(['webform', 'preview'], $form_state->getStorage()['preview']);
         }
         // Set the input values based on whether we're editing an existing
         // submission or not.
         $input_values = isset($submission->data) ? $submission->data : [];
         // Form state storage override any default submission information. Convert
         // the value structure to always be an array, matching $submission->data.
         if (isset($form_state->getStorage()['submitted'])) {
             foreach ($form_state->getStorage()['submitted'] as $cid => $data) {
                 $input_values[$cid] = is_array($data) ? $data : [$data];
             }
         }
         // Form state values override any default submission information. Convert
         // the value structure to always be an array, matching $submission->data.
         if ($form_state->getValue('submitted')) {
             foreach ($form_state->getValue('submitted') as $cid => $data) {
                 $input_values[$cid] = is_array($data) ? $data : [$data];
             }
         }
         // Generate conditional topological order & report any errors.
         $sorter = webform_get_conditional_sorter($node);
         $sorter->reportErrors();
         // Execute the conditionals on the current input values
         $input_values = $sorter->executeConditionals($input_values);
         // Allow values from other pages to be sent to browser for conditionals.
         $form['#conditional_values'] = $input_values;
         // Allow components access to most up-to-date values.
         $form_state['#conditional_values'] = $input_values;
         // For resuming a previous draft, find the next page after the last
         // validated page.
         if (!isset($form_state->getStorage()['page_num']) && $submission && $submission->is_draft && $submission->highest_valid_page) {
             // Find the
             //    1) previous/next non-empty page, or
             //    2) the preview page, or
             //    3) the preview page, forcing its display if the form would
             //       unexpectedly submit, or
             //    4) page 1 even if empty, if no other previous page would be shown
             $form_state->set(['webform', 'page_num'], $submission->highest_valid_page);
             do {
                 $form_state->set(['webform', 'page_num'], $form_state->get(['webform', 'page_num']) + 1);
             } while (!webform_get_conditional_sorter($node)->pageVisibility($form_state->get(['webform', 'page_num'])));
             if (!$form_state->get(['webform', 'preview']) && $form_state->get(['webform', 'page_num']) == $form_state->get(['webform', 'page_count']) + (int) (!$form_state->get(['webform', 'preview']))) {
                 // Force a preview to avert an unintended submission via Next.
                 $form_state->set(['webform', 'preview'], TRUE);
                 $form_state->set(['webform', 'page_count'], $form_state->get(['webform', 'page_count']) + 1);
             }
             // The form hasn't been submitted (ever) and the preview code will
             // expect $form_state['values']['submitted'] to be set from a previous
             // submission, so provide these values here.
             $form_state->setValue('submitted', $input_values);
             $form_state->setStorage(['submitted' => $input_values]);
         }
         // Shorten up our variable names.
         $component_tree = $form_state->get(['webform', 'component_tree']);
         $page_count = $form_state->get(['webform', 'page_count']);
         $page_num = $form_state->get(['webform', 'page_num']);
         $preview = $form_state->get(['webform', 'preview']);
         if ($page_count > 1) {
             $page_labels = webform_page_labels($node, $form_state);
             $form['progressbar'] = ['#theme' => 'webform_progressbar', '#node' => $node, '#page_num' => $page_num, '#page_count' => count($page_labels), '#page_labels' => $page_labels, '#weight' => -100];
         }
         // Check whether a previous submission was truncated. The length of the
         // client form is not estimated before submission because a) the
         // determination may not be accurate for some webform components and b)
         // the error will be apparent upon submission.
         webform_input_vars_check($form, $form_state, 'submitted');
         // Recursively add components to the form. The unfiltered version of the
         // form (typically used in Form Builder), includes all components.
         foreach ($component_tree['children'] as $cid => $component) {
             if ($component['type'] == 'pagebreak') {
                 $next_page_labels[$component['page_num'] - 1] = !empty($component['extra']['next_page_label']) ? $component['extra']['next_page_label'] : $this->t('Next Page >');
                 $prev_page_labels[$component['page_num']] = !empty($component['extra']['prev_page_label']) ? $component['extra']['prev_page_label'] : $this->t('< Previous Page');
             }
             if (!$filter || $sorter->componentVisibility($cid, $page_num)) {
                 $component_value = isset($input_values[$cid]) ? $input_values[$cid] : NULL;
                 _webform_client_form_add_component($node, $component, $component_value, $form['submitted'], $form, $input_values, 'form', $page_num, $filter);
             }
         }
         if ($preview) {
             $next_page_labels[$page_count - 1] = $node->webform['preview_next_button_label'] ? $node->webform['preview_next_button_label'] : $this->t('Preview');
             $prev_page_labels[$page_count] = $node->webform['preview_prev_button_label'] ? $node->webform['preview_prev_button_label'] : $this->t('< Previous');
         }
         // Add the preview if needed.
         if ($preview && $page_num === $page_count) {
             $preview_submission = webform_submission_create($node, $account, $form_state, TRUE, $submission);
             $preview_message = $node->webform['preview_message'];
             if (strlen(trim(strip_tags($preview_message))) === 0) {
                 $preview_message = $this->t('Please review your submission. Your submission is not complete until you press the "!button" button!', ['!button' => $submit_button_text]);
             }
             $form['preview_message'] = ['#type' => 'markup', '#markup' => webform_replace_tokens($preview_message, $node, $preview_submission, NULL, $node->webform['preview_message_format'])];
             $form['preview'] = webform_submission_render($node, $preview_submission, NULL, 'html', $node->webform['preview_excluded_components']);
             $form['#attributes']['class'][] = 'preview';
         }
         // These form details help managing data upon submission.
         $form['details']['nid'] = ['#type' => 'value', '#value' => $node->id()];
         $form['details']['sid'] = ['#type' => 'hidden', '#value' => isset($submission->sid) ? $submission->sid : NULL];
         $form['details']['uid'] = ['#type' => 'value', '#value' => isset($submission->uid) ? $submission->uid : $account->id()];
         $form['details']['page_num'] = ['#type' => 'hidden', '#value' => $page_num];
         $form['details']['page_count'] = ['#type' => 'hidden', '#value' => $page_count];
         $form['details']['finished'] = ['#type' => 'hidden', '#value' => $finished];
         // Add process functions to remove the IDs forced upon buttons and wrappers.
         $actions_pre_render = array_merge(element_info_property('actions', '#pre_render', []), ['webform_pre_render_remove_id']);
         $buttons_pre_render = array_merge(element_info_property('submit', '#pre_render', []), ['webform_pre_render_remove_id']);
         // Add buttons for pages, drafts, and submissions.
         $form['actions'] = ['#type' => 'actions', '#weight' => 1000, '#pre_render' => $actions_pre_render];
         // Add the draft button.
         if ($node->webform['allow_draft'] && (empty($submission) || $submission->is_draft) && $account->id() != 0) {
             $form['actions']['draft'] = ['#type' => 'submit', '#value' => $this->t('Save Draft'), '#weight' => -2, '#validate' => ['webform_client_form_prevalidate'], '#attributes' => ['formnovalidate' => 'formnovalidate', 'class' => ['webform-draft']], '#pre_render' => $buttons_pre_render];
         }
         // Add the submit button(s).
         if ($page_num > 1) {
             $form['actions']['previous'] = ['#type' => 'submit', '#value' => $prev_page_labels[$page_num], '#weight' => 5, '#validate' => [], '#attributes' => ['formnovalidate' => 'formnovalidate', 'class' => ['webform-previous']], '#pre_render' => $buttons_pre_render];
         }
         if ($page_num == $page_count) {
             $form['actions']['submit'] = ['#type' => 'submit', '#value' => $submit_button_text, '#weight' => 10, '#attributes' => ['class' => ['webform-submit', 'button-primary']], '#pre_render' => $buttons_pre_render];
         } elseif ($page_num < $page_count) {
             $form['actions']['next'] = ['#type' => 'submit', '#value' => $next_page_labels[$page_num], '#weight' => 10, '#attributes' => ['class' => ['webform-next', 'button-primary']], '#pre_render' => $buttons_pre_render];
         }
     }
     return $form;
 }