/** * Build all necessary things for child form (form state, etc.). * * @param \Drupal\Core\Entity\EntityFormInterface $controller * Entity form controller for child form. * @param \Drupal\Core\Form\FormStateInterface $form_state * Parent form state object. * @param \Drupal\Core\Entity\EntityInterface $entity * Entity object. * @param string $operation * Operation that is to be performed in inline form. * @param array $parents * Entity form #parents. * * @return \Drupal\Core\Form\FormStateInterface * Child form state object. */ public static function buildChildFormState(EntityFormInterface $controller, FormStateInterface $form_state, EntityInterface $entity, $operation, $parents) { $child_form_state = new FormState(); $child_form_state->addBuildInfo('callback_object', $controller); $child_form_state->addBuildInfo('base_form_id', $controller->getBaseFormID()); $child_form_state->addBuildInfo('form_id', $controller->getFormID()); $child_form_state->addBuildInfo('args', array()); // Copy values to child form. $child_form_state->setCompleteForm($form_state->getCompleteForm()); $child_form_state->setUserInput($form_state->getUserInput()); // Filter out all submitted values that are not directly relevant for this // IEF. Otherwise they might mess things up. $form_state_values = $form_state->getValues(); $form_state_values = static::extractArraySequence($form_state_values, $parents); $child_form_state->setValues($form_state_values); $child_form_state->setStorage($form_state->getStorage()); $value = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load($entity->getEntityTypeId() . '.' . $entity->bundle() . '.' . $operation); $child_form_state->set('form_display', $value); // Since some of the submit handlers are run, redirects need to be disabled. $child_form_state->disableRedirect(); // When a form is rebuilt after Ajax processing, its #build_id and #action // should not change. // @see drupal_rebuild_form() $rebuild_info = $child_form_state->getRebuildInfo(); $rebuild_info['copy']['#build_id'] = TRUE; $rebuild_info['copy']['#action'] = TRUE; $child_form_state->setRebuildInfo($rebuild_info); $child_form_state->set('inline_entity_form', $form_state->get('inline_entity_form')); $child_form_state->set('langcode', $entity->language()->getId()); $child_form_state->set('field', $form_state->get('field')); $child_form_state->setTriggeringElement($form_state->getTriggeringElement()); $child_form_state->setSubmitHandlers($form_state->getSubmitHandlers()); return $child_form_state; }
/** * Displays the edit feature form. */ public function featureEdit(NodeInterface $node, $fid, $pfid) { $func = uc_product_feature_data($fid, 'callback'); $form_state = new FormState(); $form_state->setBuildInfo(array('args' => array($node, uc_product_feature_load($pfid)))); return $this->formBuilder()->buildForm($func, $form_state); }
/** * @covers ::processMachineName */ public function testProcessMachineName() { $form_state = new FormState(); $element = [ '#id' => 'test', '#field_suffix' => 'test_suffix', '#field_prefix' => 'test_prefix', '#machine_name' => [ 'source' => [ 'test_source', ], 'maxlength' => 32, 'additional_property' => TRUE, '#additional_property_with_hash' => TRUE, ] ]; $complete_form = [ 'test_source' => [ '#type' => 'textfield', '#id' => 'source', ], 'test_machine_name' => $element ]; $form_state->setCompleteForm($complete_form); $language = $this->prophesize(LanguageInterface::class); $language->getId()->willReturn('xx-lolspeak'); $language_manager = $this->prophesize(LanguageManagerInterface::class); $language_manager->getCurrentLanguage()->willReturn($language); $csrf_token = $this->prophesize(CsrfTokenGenerator::class); $csrf_token->get('[^a-z0-9_]+')->willReturn('tis-a-fine-token'); $container = $this->prophesize(ContainerInterface::class); $container->get('language_manager')->willReturn($language_manager->reveal()); $container->get('csrf_token')->willReturn($csrf_token->reveal()); \Drupal::setContainer($container->reveal()); $element = MachineName::processMachineName($element, $form_state, $complete_form); $settings = $element['#attached']['drupalSettings']['machineName']['#source']; $allowed_options = [ 'replace_pattern', 'replace', 'maxlength', 'target', 'label', 'field_prefix', 'field_suffix', 'suffix', 'replace_token', ]; $this->assertEmpty(array_diff_key($settings, array_flip($allowed_options))); foreach ($allowed_options as $key) { $this->assertArrayHasKey($key, $settings); } }
/** * {@inheritdoc} */ public function getForm($formClass) { $args = func_get_args(); array_shift($args); if (!class_exists($formClass)) { $this->logger->log(LogLevel::CRITICAL, "Form class '@class' does not exists", ['@class' => $formClass]); return []; } if (!method_exists($formClass, 'create')) { $this->logger->log(LogLevel::CRITICAL, "Form class '@class' does not implements ::create()", ['@class' => $formClass]); return []; } // God, I do hate Drupal 8... $form = call_user_func([$formClass, 'create'], $this->container); if (!$form instanceof FormInterface) { $this->logger->log(LogLevel::CRITICAL, "Form class '@class' does not implement \\Drupal\\Core\\Form\\FormInterface", ['@class' => $formClass]); return []; } $formId = $form->getFormId(); $data = []; $data['build_info']['args'] = $args; $formState = new FormState($data); $formState->setFormObject($form); $this->formMap[$formId] = [$form, $formState]; return drupal_build_form($formId, $data); }
/** * Page that triggers a programmatic form submission. * * Returns the validation errors triggered by the form submission as json. */ public function submitFormPage() { $form_state = new FormState(); $values = ['name' => 'robo-user', 'mail' => '*****@*****.**', 'op' => t('Submit')]; $form_state->setValues($values); \Drupal::formBuilder()->submitForm('\\Drupal\\user\\Form\\UserPasswordForm', $form_state); return new JsonResponse($form_state->getErrors()); }
/** * Tests the 'validation_complete' $form_state flag. * * @covers ::validateForm * @covers ::finalizeValidation */ public function testValidationComplete() { $form_validator = $this->getMockBuilder('Drupal\\Core\\Form\\FormValidator')->setConstructorArgs([new RequestStack(), $this->getStringTranslationStub(), $this->csrfToken, $this->logger, $this->formErrorHandler])->setMethods(NULL)->getMock(); $form = array(); $form_state = new FormState(); $this->assertFalse($form_state->isValidationComplete()); $form_validator->validateForm('test_form_id', $form, $form_state); $this->assertTrue($form_state->isValidationComplete()); }
/** * Tests the 'validation_complete' $form_state flag. * * @covers ::validateForm * @covers ::finalizeValidation */ public function testValidationComplete() { $form_validator = $this->getMockBuilder('Drupal\\Core\\Form\\FormValidator')->disableOriginalConstructor()->setMethods(NULL)->getMock(); $form = array(); $form_state = new FormState(); $this->assertFalse($form_state->isValidationComplete()); $form_validator->validateForm('test_form_id', $form, $form_state); $this->assertTrue($form_state->isValidationComplete()); }
/** * @covers ::handleFormErrors * @covers ::setElementErrorsFromFormState */ public function testSetElementErrorsFromFormState() { $form_error_handler = $this->getMockBuilder('Drupal\\Core\\Form\\FormErrorHandler')->setMethods(['drupalSetMessage'])->getMock(); $form = ['#parents' => []]; $form['test'] = ['#type' => 'textfield', '#title' => 'Test', '#parents' => ['test'], '#id' => 'edit-test']; $form_state = new FormState(); $form_state->setErrorByName('test', 'invalid'); $form_error_handler->handleFormErrors($form, $form_state); $this->assertSame('invalid', $form['test']['#errors']); }
/** * @covers ::handleFormErrors * @covers ::setElementErrorsFromFormState */ public function testSetElementErrorsFromFormState() { $form_error_handler = $this->getMockBuilder('Drupal\\Core\\Form\\FormErrorHandler')->setConstructorArgs([$this->getStringTranslationStub(), $this->getMock('Drupal\\Core\\Utility\\LinkGeneratorInterface')])->setMethods(['drupalSetMessage'])->getMock(); $form = ['#parents' => []]; $form['test'] = ['#type' => 'textfield', '#title' => 'Test', '#parents' => ['test'], '#id' => 'edit-test']; $form_state = new FormState(); $form_state->setErrorByName('test', 'invalid'); $form_error_handler->handleFormErrors($form, $form_state); $this->assertSame('invalid', $form['test']['#errors']); }
/** * @covers ::getSelected * * @dataProvider providerTestGetSelected */ public function testGetSelected($expected, $element = [], $parents = [], $user_input = [], $not_rebuilding_expected = NULL) { $not_rebuilding_expected = $not_rebuilding_expected ?: $expected; $form_state = new FormState(); $form_state->setUserInput($user_input); $actual = WizardPluginBase::getSelected($form_state, $parents, 'the_default_value', $element); $this->assertSame($not_rebuilding_expected, $actual); $this->assertSame($user_input, $form_state->getUserInput()); $form_state->setRebuild(); $actual = WizardPluginBase::getSelected($form_state, $parents, 'the_default_value', $element); $this->assertSame($expected, $actual); $this->assertSame($user_input, $form_state->getUserInput()); }
/** * Tests that #limit_validation_errors of the only submit button takes effect. */ function testLimitValidationErrors() { // Programmatically submit the form. $form_state = new FormState(); $form_state->setValue('section', 'one'); $form_builder = $this->container->get('form_builder'); $form_builder->submitForm($this, $form_state); // Verify that only the specified section was validated. $errors = $form_state->getErrors(); $this->assertTrue(isset($errors['one']), "Section 'one' was validated."); $this->assertFalse(isset($errors['two']), "Section 'two' was not validated."); // Verify that there are only values for the specified section. $this->assertTrue($form_state->hasValue('one'), "Values for section 'one' found."); $this->assertFalse($form_state->hasValue('two'), "Values for section 'two' not found."); }
/** * Tests the root user account form section in the "Configure site" form. */ function testInstallConfigureForm() { require_once \Drupal::root() . '/core/includes/install.core.inc'; require_once \Drupal::root() . '/core/includes/install.inc'; $install_state = install_state_defaults(); $form_state = new FormState(); $form_state->addBuildInfo('args', [&$install_state]); $form = $this->container->get('form_builder')->buildForm('Drupal\\Core\\Installer\\Form\\SiteConfigureForm', $form_state); // Verify name and pass field order. $this->assertFieldOrder($form['admin_account']['account']); // Verify that web browsers may autocomplete the email value and // autofill/prefill the name and pass values. foreach (array('mail', 'name', 'pass') as $key) { $this->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'{$key}' field: 'autocomplete' attribute not found."); } }
/** * Tests the entity row handler. */ public function testEntityRow() { $vocab = Vocabulary::create(['name' => $this->randomMachineName(), 'vid' => strtolower($this->randomMachineName())]); $vocab->save(); $term = Term::create(['name' => $this->randomMachineName(), 'vid' => $vocab->id()]); $term->save(); $view = Views::getView('test_entity_row'); $build = $view->preview(); $this->render($build); $this->assertText($term->getName(), 'The rendered entity appears as row in the view.'); // Tests the available view mode options. $form = array(); $form_state = new FormState(); $form_state->set('view', $view->storage); $view->rowPlugin->buildOptionsForm($form, $form_state); $this->assertTrue(isset($form['view_mode']['#options']['default']), 'Ensure that the default view mode is available'); }
/** * @covers ::extractFormValues */ public function testExtractFormValues() { $menu_link_manager = $this->prophesize(MenuLinkManagerInterface::class); $menu_parent_form_selector = $this->prophesize(MenuParentFormSelectorInterface::class); $module_handler = $this->prophesize(ModuleHandlerInterface::class); $menu_link_form = new MenuLinkDefaultForm($menu_link_manager->reveal(), $menu_parent_form_selector->reveal(), $this->getStringTranslationStub(), $module_handler->reveal()); $static_override = $this->prophesize(StaticMenuLinkOverridesInterface::class); $menu_link = new MenuLinkDefault([], 'my_plugin_id', [], $static_override->reveal()); $menu_link_form->setMenuLinkInstance($menu_link); $form_state = new FormState(); $form_state->setValue('id', 'my_plugin_id'); $form_state->setValue('enabled', FALSE); $form_state->setValue('weight', 5); $form_state->setValue('expanded', TRUE); $form_state->setValue('menu_parent', 'foo:bar'); $form = []; $result = $menu_link_form->extractFormValues($form, $form_state); $this->assertEquals(['id' => 'my_plugin_id', 'enabled' => 0, 'weight' => 5, 'expanded' => 1, 'parent' => 'bar', 'menu_name' => 'foo'], $result); }
/** * @covers ::setCache */ public function testSetCacheWithSafeStrings() { // A call to SafeMarkup::set() is appropriate in this test as a way to add a // string to the safe list in the simplest way possible. Normally, avoid it. SafeMarkup::set('a_safe_string'); $form_build_id = 'the_form_build_id'; $form = ['#form_id' => 'the_form_id']; $form_state = new FormState(); $this->formCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form, $this->isType('int')); $form_state_data = $form_state->getCacheableArray(); $form_state_data['build_info']['safe_strings'] = ['a_safe_string' => ['html' => TRUE]]; $this->formStateCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form_state_data, $this->isType('int')); $this->formCache->setCache($form_build_id, $form, $form_state); }
/** * Check several empty values for required forms elements. * * Carriage returns, tabs, spaces, and unchecked checkbox elements are not * valid content for a required field. * * If the form field is found in $form_state->getErrors() then the test pass. */ function testRequiredFields() { // Originates from https://www.drupal.org/node/117748. // Sets of empty strings and arrays. $empty_strings = array('""' => "", '"\\n"' => "\n", '" "' => " ", '"\\t"' => "\t", '" \\n\\t "' => " \n\t ", '"\\n\\n\\n\\n\\n"' => "\n\n\n\n\n"); $empty_arrays = array('array()' => array()); $empty_checkbox = array(NULL); $elements['textfield']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'textfield'); $elements['textfield']['empty_values'] = $empty_strings; $elements['telephone']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'tel'); $elements['telephone']['empty_values'] = $empty_strings; $elements['url']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'url'); $elements['url']['empty_values'] = $empty_strings; $elements['search']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'search'); $elements['search']['empty_values'] = $empty_strings; $elements['password']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'password'); $elements['password']['empty_values'] = $empty_strings; $elements['password_confirm']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'password_confirm'); // Provide empty values for both password fields. foreach ($empty_strings as $key => $value) { $elements['password_confirm']['empty_values'][$key] = array('pass1' => $value, 'pass2' => $value); } $elements['textarea']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'textarea'); $elements['textarea']['empty_values'] = $empty_strings; $elements['radios']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'radios', '#options' => array('' => t('None'), $this->randomMachineName(), $this->randomMachineName(), $this->randomMachineName())); $elements['radios']['empty_values'] = $empty_arrays; $elements['checkbox']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'checkbox', '#required' => TRUE); $elements['checkbox']['empty_values'] = $empty_checkbox; $elements['checkboxes']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'checkboxes', '#options' => array($this->randomMachineName(), $this->randomMachineName(), $this->randomMachineName())); $elements['checkboxes']['empty_values'] = $empty_arrays; $elements['select']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'select', '#options' => array('' => t('None'), $this->randomMachineName(), $this->randomMachineName(), $this->randomMachineName())); $elements['select']['empty_values'] = $empty_strings; $elements['file']['element'] = array('#title' => $this->randomMachineName(), '#type' => 'file'); $elements['file']['empty_values'] = $empty_strings; // Regular expression to find the expected marker on required elements. $required_marker_preg = '@<.*?class=".*?form-required.*?">@'; // Go through all the elements and all the empty values for them. foreach ($elements as $type => $data) { foreach ($data['empty_values'] as $key => $empty) { foreach (array(TRUE, FALSE) as $required) { $form_id = $this->randomMachineName(); $form = array(); $form_state = new FormState(); $form['op'] = array('#type' => 'submit', '#value' => t('Submit')); $element = $data['element']['#title']; $form[$element] = $data['element']; $form[$element]['#required'] = $required; $user_input[$element] = $empty; $user_input['form_id'] = $form_id; $form_state->setUserInput($user_input); $form_state->setFormObject(new StubForm($form_id, $form)); $form_state->setMethod('POST'); // The form token CSRF protection should not interfere with this test, // so we bypass it by setting the token to FALSE. $form['#token'] = FALSE; \Drupal::formBuilder()->prepareForm($form_id, $form, $form_state); \Drupal::formBuilder()->processForm($form_id, $form, $form_state); $errors = $form_state->getErrors(); // Form elements of type 'radios' throw all sorts of PHP notices // when you try to render them like this, so we ignore those for // testing the required marker. // @todo Fix this work-around (https://www.drupal.org/node/588438). $form_output = $type == 'radios' ? '' : \Drupal::service('renderer')->renderRoot($form); if ($required) { // Make sure we have a form error for this element. $this->assertTrue(isset($errors[$element]), "Check empty({$key}) '{$type}' field '{$element}'"); if (!empty($form_output)) { // Make sure the form element is marked as required. $this->assertTrue(preg_match($required_marker_preg, $form_output), "Required '{$type}' field is marked as required"); } } else { if (!empty($form_output)) { // Make sure the form element is *not* marked as required. $this->assertFalse(preg_match($required_marker_preg, $form_output), "Optional '{$type}' field is not marked as required"); } if ($type == 'select') { // Select elements are going to have validation errors with empty // input, since those are illegal choices. Just make sure the // error is not "field is required". $this->assertTrue(empty($errors[$element]) || strpos('field is required', $errors[$element]) === FALSE, "Optional '{$type}' field '{$element}' is not treated as a required element"); } else { // Make sure there is *no* form error for this element. $this->assertTrue(empty($errors[$element]), "Optional '{$type}' field '{$element}' has no errors with empty input"); } } } } } // Clear the expected form error messages so they don't appear as exceptions. drupal_get_messages(); }
/** * Helper function for the option check test to submit a form while collecting errors. * * @param $form_element * A form element to test. * @param $edit * An array containing post data. * * @return * An array containing the processed form, the form_state and any errors. */ private function formSubmitHelper($form, $edit) { $form_id = $this->randomMachineName(); $form_state = new FormState(); $form['op'] = array('#type' => 'submit', '#value' => t('Submit')); // The form token CSRF protection should not interfere with this test, so we // bypass it by setting the token to FALSE. $form['#token'] = FALSE; $edit['form_id'] = $form_id; // Disable page redirect for forms submitted programmatically. This is a // solution to skip the redirect step (there are no pages, then the redirect // isn't possible). $form_state->disableRedirect(); $form_state->setUserInput($edit); $form_state->setFormObject(new StubForm($form_id, $form)); \Drupal::formBuilder()->prepareForm($form_id, $form, $form_state); \Drupal::formBuilder()->processForm($form_id, $form, $form_state); $errors = $form_state->getErrors(); // Clear errors and messages. drupal_get_messages(); $form_state->clearErrors(); // Return the processed form together with form_state and errors // to allow the caller lowlevel access to the form. return array($form, $form_state, $errors); }
/** * Tests the handling of a redirect when FormStateInterface::$response exists. */ public function testHandleRedirectWithResponse() { $form_id = 'test_form_id'; $expected_form = $form_id(); // Set up a response that will be used. $response = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\Response')->disableOriginalConstructor()->getMock(); // Set up a redirect that will not be called. $redirect = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RedirectResponse')->disableOriginalConstructor()->getMock(); $form_arg = $this->getMockForm($form_id, $expected_form); $form_arg->expects($this->any())->method('submitForm')->will($this->returnCallback(function ($form, FormStateInterface $form_state) use($response, $redirect) { // Set both the response and the redirect. $form_state->setResponse($response); $form_state->set('redirect', $redirect); })); $form_state = new FormState(); try { $input['form_id'] = $form_id; $form_state->setUserInput($input); $this->simulateFormSubmission($form_id, $form_arg, $form_state, FALSE); $this->fail('EnforcedResponseException was not thrown.'); } catch (EnforcedResponseException $e) { $this->assertSame($response, $e->getResponse()); } $this->assertSame($response, $form_state->getResponse()); }
/** * {@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); } }
/** * Form submit handler to flush Mollom session and form information from cache. * * This is necessary as the entity forms will no longer automatically save * the data with the entity. * * @todo: Possible problems: * - This submit handler is invoked too late; the primary submit handler might * send out e-mails directly after saving the entity (e.g., * user_register_form_submit()), so mollom_mail_alter() is invoked before * Mollom session data has been saved. */ public static function submitForm($form, FormState $form_state) { // Some modules are implementing multi-step forms without separate form // submit handlers. In case we reach here and the form will be rebuilt, we // need to defer our submit handling until final submission. $is_rebuilding = $form_state->isRebuilding(); if ($is_rebuilding) { return; } $mollom = $form_state->getValue('mollom'); $form_object = $form_state->getFormObject(); // If an 'entity' and a 'post_id' mapping was provided via // hook_mollom_form_info(), try to automatically store Mollom session data. if (empty($mollom) || empty($mollom['entity']) || !$form_state->getFormObject() instanceof EntityFormInterface) { return; } /* @var $form_object \Drupal\Core\Entity\EntityFormInterface */ $entity_id = $form_object->getEntity()->id(); $data = (object) $mollom; $data->id = $entity_id; $data->moderate = $mollom['require_moderation'] ? 1 : 0; $stored_data = ResponseDataStorage::save($data); $form_state->setValue(['mollom', 'data'], $stored_data); }
/** * @covers ::actions * @covers ::getPaymentMethodManager */ public function testActionsWithoutAvailablePlugins() { $form = []; $form_state = new FormState(); $form_state->set('plugin_selector', $this->pluginSelector); $this->paymentMethodManager->expects($this->atLeastOnce())->method('getDefinitions')->willReturn([]); $method = new \ReflectionMethod($this->sut, 'actions'); $method->setAccessible(TRUE); $actions = $method->invokeArgs($this->sut, [$form, $form_state]); $this->assertTrue($actions['submit']['#disabled']); }
/** * {@inheritdoc} */ public static function hasAnyErrors() { return FormState::hasAnyErrors(); }
/** * @covers ::copyFormValuesToEntity */ public function testCopyFormValuesToEntity() { $description = $this->randomMachineName(); $id = $this->randomMachineName(); $label = $this->randomMachineName(); $parent_id = $this->randomMachineName(); $this->paymentStatus->expects($this->once())->method('setDescription')->with($description); $this->paymentStatus->expects($this->once())->method('setId')->with($id); $this->paymentStatus->expects($this->once())->method('setLabel')->with($label); $this->paymentStatus->expects($this->once())->method('setParentId')->with($parent_id); $parent_status = $this->getMock(PluginSelectorInterface::class); $parent_status->expects($this->atLeastOnce())->method('getPluginId')->willReturn($parent_id); $parent_selector = $this->getMock(PluginSelectorInterface::class); $parent_selector->expects($this->atLeastOnce())->method('getSelectedPlugin')->willReturn($parent_status); $this->pluginSelectorManager->expects($this->atLeastOnce())->method('createInstance')->willReturn($parent_selector); $form = []; $form_state = new FormState(); $form_state->setValue('description', $description); $form_state->setValue('id', $id); $form_state->setValue('label', $label); $form_state->setValue('parent_id', $parent_id); $method = new \ReflectionMethod($this->sut, 'copyFormValuesToEntity'); $method->setAccessible(TRUE); $method->invokeArgs($this->sut, array($this->paymentStatus, $form, $form_state)); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $pass = $form_state->getValue('filter_pass') ? explode(',', $form_state->getValue('filter_pass')) : array(); $fail = $form_state->getValue('filter_fail') ? explode(',', $form_state->getValue('filter_fail')) : array(); if ($form_state->getValue('filter') == 'all') { $classes = array_merge($pass, $fail); } elseif ($form_state->getValue('filter') == 'pass') { $classes = $pass; } else { $classes = $fail; } if (!$classes) { $form_state->setRedirect('simpletest.test_form'); return; } $form_execute = array(); $form_state_execute = new FormState(); foreach ($classes as $class) { $form_state_execute->setValue(['tests', $class], $class); } // Submit the simpletest test form to rerun the tests. // Under normal circumstances, a form object's submitForm() should never be // called directly, FormBuilder::submitForm() should be called instead. // However, it calls $form_state->setProgrammed(), which disables the Batch API. $simpletest_test_form = SimpletestTestForm::create(\Drupal::getContainer()); $simpletest_test_form->buildForm($form_execute, $form_state_execute); $simpletest_test_form->submitForm($form_execute, $form_state_execute); if ($redirect = $form_state_execute->getRedirect()) { $form_state->setRedirectUrl($redirect); } }
/** * 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; }
/** * @covers ::doBuildForm * * @dataProvider providerTestInvalidToken */ public function testInvalidToken($expected, $valid_token, $user_is_authenticated) { $form_token = 'the_form_token'; $form_id = 'test_form_id'; if (is_bool($valid_token)) { $this->csrfToken->expects($this->any())->method('get')->willReturnArgument(0); $this->csrfToken->expects($this->atLeastOnce())->method('validate')->willReturn($valid_token); } $current_user = $this->prophesize(AccountInterface::class); $current_user->isAuthenticated()->willReturn($user_is_authenticated); $property = new \ReflectionProperty(FormBuilder::class, 'currentUser'); $property->setAccessible(TRUE); $property->setValue($this->formBuilder, $current_user->reveal()); $expected_form = $form_id(); $form_arg = $this->getMockForm($form_id, $expected_form); $form_state = new FormState(); $input['form_id'] = $form_id; $input['form_token'] = $form_token; $form_state->setUserInput($input); $this->simulateFormSubmission($form_id, $form_arg, $form_state, FALSE); $this->assertSame($expected, $form_state->hasInvalidToken()); }
/** * @covers ::setCache */ public function testSetCacheImmutableForm() { $form_build_id = 'the_form_build_id'; $form = ['#form_id' => 'the_form_id']; $form_state = new FormState(); $this->formCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form, $this->isType('int')); $form_state_data = $form_state->getCacheableArray(); $form_state_data['build_info']['safe_strings'] = []; // Ensure that the form is marked immutable. $form_state_data['build_info']['immutable'] = TRUE; $this->formStateCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form_state_data, $this->isType('int')); // Rebuild the FormCache with a config factory that will return a config // object with the internal page cache enabled. $this->configFactory = $this->getConfigFactoryStub(['system.performance' => ['cache.page.use_internal' => TRUE]]); $this->formCache = $this->getMockBuilder('Drupal\\Core\\Form\\FormCache')->setConstructorArgs([$this->keyValueExpirableFactory, $this->moduleHandler, $this->account, $this->csrfToken, $this->logger, $this->configFactory, $this->requestStack, $this->requestPolicy])->setMethods(['isPageCacheable'])->getMock(); $this->formCache->expects($this->once())->method('isPageCacheable')->willReturn(TRUE); $this->formCache->setCache($form_build_id, $form, $form_state); }
/** * @covers ::setCache */ public function testSetCacheAuthUser() { $form_build_id = 'the_form_build_id'; $form = []; $form_state = new FormState(); $cache_token = 'the_cache_token'; $form_data = $form; $form_data['#cache_token'] = $cache_token; $this->formCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form_data, $this->isType('int')); $form_state_data = $form_state->getCacheableArray(); $this->formStateCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form_state_data, $this->isType('int')); $this->csrfToken->expects($this->once())->method('get')->willReturn($cache_token); $this->account->expects($this->once())->method('isAuthenticated')->willReturn(TRUE); $this->formCache->setCache($form_build_id, $form, $form_state); }
/** * @covers ::setCache */ public function testSetCacheWithSafeStrings() { SafeMarkup::set('a_safe_string'); $form_build_id = 'the_form_build_id'; $form = ['#form_id' => 'the_form_id']; $form_state = new FormState(); $this->formCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form, $this->isType('int')); $form_state_data = $form_state->getCacheableArray(); $form_state_data['build_info']['safe_strings'] = ['a_safe_string' => ['html' => TRUE]]; $this->formStateCacheStore->expects($this->once())->method('setWithExpire')->with($form_build_id, $form_state_data, $this->isType('int')); $this->formCache->setCache($form_build_id, $form, $form_state); }
/** * @covers ::submitForm * @covers ::getPluginSelector */ public function testSubmitForm() { $form = ['plugin_selector' => ['foo' => $this->randomMachineName()]]; $form_state = new FormState(); $form_state->setValues(['plugin_selector_id' => $this->configFactoryConfiguration['payment_form.payment_type']['plugin_selector_id'], 'allowed_plugin_ids' => $this->configFactoryConfiguration['payment_form.payment_type']['allowed_plugin_ids'], 'limit_allowed_plugins' => $this->configFactoryConfiguration['payment_form.payment_type']['limit_allowed_plugins']]); $map = [['payment_radios', [], $this->pluginSelector], [$this->configFactoryConfiguration['payment_form.payment_type']['plugin_selector_id'], [], $this->selectedPluginSelector]]; $this->pluginSelectorManager->expects($this->atLeast(count($map)))->method('createInstance')->willReturnMap($map); $this->pluginSelector->expects($this->once())->method('submitSelectorForm')->with($form['plugin_selector'], $form_state); $this->pluginSelector->expects($this->once())->method('getSelectedPlugin')->willReturn($this->selectedPluginSelector); $this->sut->submitForm($form, $form_state); }