/** * {@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); }
/** * 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); }
/** * @covers ::prepareCallback */ public function testPrepareCallbackArray() { $form_state = new FormState(); $form_state->setFormObject(new PrepareCallbackTestForm()); $callback = [$form_state->getFormObject(), 'buildForm']; $processed_callback = $form_state->prepareCallback($callback); $this->assertEquals($callback, $processed_callback); }