/** * Build the query for the view. */ public function build($display_id = NULL) { if (!empty($this->built)) { return; } if (empty($this->current_display) || $display_id) { if (!$this->setDisplay($display_id)) { return FALSE; } } // Let modules modify the view just prior to building it. $module_handler = \Drupal::moduleHandler(); $module_handler->invokeAll('views_pre_build', array($this)); // Attempt to load from cache. // @todo Load a build_info from cache. $start = microtime(TRUE); // If that fails, let's build! $this->build_info = array('query' => '', 'count_query' => '', 'query_args' => array()); $this->initQuery(); // Call a module hook and see if it wants to present us with a // pre-built query or instruct us not to build the query for // some reason. // @todo: Implement this. Use the same mechanism Panels uses. // Run through our handlers and ensure they have necessary information. $this->initHandlers(); // Let the handlers interact with each other if they really want. $this->_preQuery(); if ($this->display_handler->usesExposed()) { $exposed_form = $this->display_handler->getPlugin('exposed_form'); $this->exposed_widgets = $exposed_form->renderExposedForm(); if (FormState::hasAnyErrors() || !empty($this->build_info['abort'])) { $this->built = TRUE; // Don't execute the query, $form_state, but rendering will still be executed to display the empty text. $this->executed = TRUE; return empty($this->build_info['fail']); } } // Build all the relationships first thing. $this->_build('relationship'); // Set the filtering groups. if (!empty($this->filter)) { $filter_groups = $this->display_handler->getOption('filter_groups'); if ($filter_groups) { $this->query->setGroupOperator($filter_groups['operator']); foreach ($filter_groups['groups'] as $id => $operator) { $this->query->setWhereGroup($operator, $id); } } } // Build all the filters. $this->_build('filter'); $this->build_sort = TRUE; // Arguments can, in fact, cause this whole thing to abort. if (!$this->_buildArguments()) { $this->build_time = microtime(TRUE) - $start; $this->attachDisplays(); return $this->built; } // Initialize the style; arguments may have changed which style we use, // so waiting as long as possible is important. But we need to know // about the style when we go to build fields. if (!$this->initStyle()) { $this->build_info['fail'] = TRUE; return FALSE; } if ($this->style_plugin->usesFields()) { $this->_build('field'); } // Build our sort criteria if we were instructed to do so. if (!empty($this->build_sort)) { // Allow the style handler to deal with sorting. if ($this->style_plugin->buildSort()) { $this->_build('sort'); } // allow the plugin to build second sorts as well. $this->style_plugin->buildSortPost(); } // Allow area handlers to affect the query. $this->_build('header'); $this->_build('footer'); $this->_build('empty'); // Allow display handler to affect the query: $this->display_handler->query($this->display_handler->useGroupBy()); // Allow style handler to affect the query: $this->style_plugin->query($this->display_handler->useGroupBy()); // Allow exposed form to affect the query: if (isset($exposed_form)) { $exposed_form->query(); } if (\Drupal::config('views.settings')->get('sql_signature')) { $this->query->addSignature($this); } // Let modules modify the query just prior to finalizing it. $this->query->alter($this); // Only build the query if we weren't interrupted. if (empty($this->built)) { // Build the necessary info to execute the query. $this->query->build($this); } $this->built = TRUE; $this->build_time = microtime(TRUE) - $start; // Attach displays $this->attachDisplays(); // Let modules modify the view just after building it. $module_handler->invokeAll('views_post_build', array($this)); return TRUE; }
/** * {@inheritdoc} */ public static function hasAnyErrors() { return FormState::hasAnyErrors(); }
/** * {@inheritdoc} */ public function processForm($form_id, &$form, FormStateInterface &$form_state) { $form_state->setValues([]); // With GET, these forms are always submitted if requested. if ($form_state->isMethodType('get') && $form_state->getAlwaysProcess()) { $input = $form_state->getUserInput(); if (!isset($input['form_build_id'])) { $input['form_build_id'] = $form['#build_id']; } if (!isset($input['form_id'])) { $input['form_id'] = $form_id; } if (!isset($input['form_token']) && isset($form['#token'])) { $input['form_token'] = $this->csrfToken->get($form['#token']); } $form_state->setUserInput($input); } // self::doBuildForm() finishes building the form by calling element // #process functions and mapping user input, if any, to #value properties, // and also storing the values in $form_state->getValues(). We need to // retain the unprocessed $form in case it needs to be cached. $unprocessed_form = $form; $form = $this->doBuildForm($form_id, $form, $form_state); // Only process the input if we have a correct form submission. if ($form_state->isProcessingInput()) { // Form values for programmed form submissions typically do not include a // value for the submit button. But without a triggering element, a // potentially existing #limit_validation_errors property on the primary // submit button is not taken account. Therefore, check whether there is // exactly one submit button in the form, and if so, automatically use it // as triggering_element. $buttons = $form_state->getButtons(); if ($form_state->isProgrammed() && !$form_state->getTriggeringElement() && count($buttons) == 1) { $form_state->setTriggeringElement(reset($buttons)); } $this->formValidator->validateForm($form_id, $form, $form_state); // \Drupal\Component\Utility\Html::getUniqueId() maintains a cache of // element IDs it has seen, so it can prevent duplicates. We want to be // sure we reset that cache when a form is processed, so scenarios that // result in the form being built behind the scenes and again for the // browser don't increment all the element IDs needlessly. if (!FormState::hasAnyErrors()) { // In case of errors, do not break HTML IDs of other forms. Html::resetSeenIds(); } // If there are no errors and the form is not rebuilding, submit the form. if (!$form_state->isRebuilding() && !FormState::hasAnyErrors()) { $submit_response = $this->formSubmitter->doSubmitForm($form, $form_state); // If this form was cached, delete it from the cache after submission. if ($form_state->isCached()) { $this->deleteCache($form['#build_id']); } // If the form submission directly returned a response, return it now. if ($submit_response) { return $submit_response; } } // Don't rebuild or cache form submissions invoked via self::submitForm(). if ($form_state->isProgrammed()) { return; } // If $form_state->isRebuilding() has been set and input has been // processed without validation errors, we are in a multi-step workflow // that is not yet complete. A new $form needs to be constructed based on // the changes made to $form_state during this request. Normally, a submit // handler sets $form_state->isRebuilding() if a fully executed form // requires another step. However, for forms that have not been fully // executed (e.g., Ajax submissions triggered by non-buttons), there is no // submit handler to set $form_state->isRebuilding(). It would not make // sense to redisplay the identical form without an error for the user to // correct, so we also rebuild error-free non-executed forms, regardless // of $form_state->isRebuilding(). // @todo Simplify this logic; considering Ajax and non-HTML front-ends, // along with element-level #submit properties, it makes no sense to // have divergent form execution based on whether the triggering element // has #executes_submit_callback set to TRUE. if (($form_state->isRebuilding() || !$form_state->isExecuted()) && !FormState::hasAnyErrors()) { // Form building functions (e.g., self::handleInputElement()) may use // $form_state->isRebuilding() to determine if they are running in the // context of a rebuild, so ensure it is set. $form_state->setRebuild(); $form = $this->rebuildForm($form_id, $form_state, $form); } } // After processing the form, the form builder or a #process callback may // have called $form_state->setCached() to indicate that the form and form // state shall be cached. But the form may only be cached if // $form_state->disableCache() is not called. Only cache $form as it was // prior to self::doBuildForm(), because self::doBuildForm() must run for // each request to accommodate new user input. Rebuilt forms are not cached // here, because self::rebuildForm() already takes care of that. if (!$form_state->isRebuilding() && $form_state->isCached()) { $this->setCache($form['#build_id'], $unprocessed_form, $form_state); } }
/** * {@inheritdoc} */ public function processForm($form_id, &$form, FormStateInterface &$form_state) { $form_state->set('values', array()); // With GET, these forms are always submitted if requested. if ($form_state['method'] == 'get' && !empty($form_state['always_process'])) { $input = $form_state->get('input'); if (!isset($input['form_build_id'])) { $input['form_build_id'] = $form['#build_id']; } if (!isset($input['form_id'])) { $input['form_id'] = $form_id; } if (!isset($input['form_token']) && isset($form['#token'])) { $input['form_token'] = $this->csrfToken->get($form['#token']); } $form_state->set('input', $input); } // self::doBuildForm() finishes building the form by calling element // #process functions and mapping user input, if any, to #value properties, // and also storing the values in $form_state['values']. We need to retain // the unprocessed $form in case it needs to be cached. $unprocessed_form = $form; $form = $this->doBuildForm($form_id, $form, $form_state); // Only process the input if we have a correct form submission. if ($form_state['process_input']) { // Form constructors may explicitly set #token to FALSE when cross site // request forgery is irrelevant to the form, such as search forms. if (isset($form['#token']) && $form['#token'] === FALSE) { unset($form['#token']); } // Form values for programmed form submissions typically do not include a // value for the submit button. But without a triggering element, a // potentially existing #limit_validation_errors property on the primary // submit button is not taken account. Therefore, check whether there is // exactly one submit button in the form, and if so, automatically use it // as triggering_element. if ($form_state['programmed'] && !isset($form_state['triggering_element']) && count($form_state['buttons']) == 1) { $form_state->set('triggering_element', reset($form_state['buttons'])); } $this->formValidator->validateForm($form_id, $form, $form_state); // drupal_html_id() maintains a cache of element IDs it has seen, so it // can prevent duplicates. We want to be sure we reset that cache when a // form is processed, so scenarios that result in the form being built // behind the scenes and again for the browser don't increment all the // element IDs needlessly. if (!FormState::hasAnyErrors()) { // In case of errors, do not break HTML IDs of other forms. $this->drupalStaticReset('drupal_html_id'); } if (!$form_state['rebuild'] && !FormState::hasAnyErrors()) { if ($submit_response = $this->formSubmitter->doSubmitForm($form, $form_state)) { return $submit_response; } } // Don't rebuild or cache form submissions invoked via self::submitForm(). if (!empty($form_state['programmed'])) { return; } // If $form_state['rebuild'] has been set and input has been processed // without validation errors, we are in a multi-step workflow that is not // yet complete. A new $form needs to be constructed based on the changes // made to $form_state during this request. Normally, a submit handler // sets $form_state['rebuild'] if a fully executed form requires another // step. However, for forms that have not been fully executed (e.g., Ajax // submissions triggered by non-buttons), there is no submit handler to // set $form_state['rebuild']. It would not make sense to redisplay the // identical form without an error for the user to correct, so we also // rebuild error-free non-executed forms, regardless of // $form_state['rebuild']. // @todo Simplify this logic; considering Ajax and non-HTML front-ends, // along with element-level #submit properties, it makes no sense to // have divergent form execution based on whether the triggering element // has #executes_submit_callback set to TRUE. if (($form_state['rebuild'] || !$form_state['executed']) && !FormState::hasAnyErrors()) { // Form building functions (e.g., self::handleInputElement()) may use // $form_state['rebuild'] to determine if they are running in the // context of a rebuild, so ensure it is set. $form_state->setRebuild(); $form = $this->rebuildForm($form_id, $form_state, $form); } } // After processing the form, the form builder or a #process callback may // have set $form_state['cache'] to indicate that the form and form state // shall be cached. But the form may only be cached if the 'no_cache' // property is not set to TRUE. Only cache $form as it was prior to // self::doBuildForm(), because self::doBuildForm() must run for each // request to accommodate new user input. Rebuilt forms are not cached here, // because self::rebuildForm() already takes care of that. if (!$form_state['rebuild'] && $form_state['cache'] && empty($form_state['no_cache'])) { $this->setCache($form['#build_id'], $unprocessed_form, $form_state); } }