From ce8dcd40d1bc9315c803425633b585d414a676c9 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Tue, 9 Sep 2014 16:26:50 +0100 Subject: [PATCH] Issue #2321745 by larowlan, tim.plunkett: Add #type => 'path' that accepts path but optionally stores URL object or route name and parameters. --- .../Core/Render/Element/PathElement.php | 98 ++++++++ .../src/Tests/Element/PathElementFormTest.php | 213 ++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 core/lib/Drupal/Core/Render/Element/PathElement.php create mode 100644 core/modules/system/src/Tests/Element/PathElementFormTest.php diff --git a/core/lib/Drupal/Core/Render/Element/PathElement.php b/core/lib/Drupal/Core/Render/Element/PathElement.php new file mode 100644 index 0000000000..f4ea306693 --- /dev/null +++ b/core/lib/Drupal/Core/Render/Element/PathElement.php @@ -0,0 +1,98 @@ +getUrlIfValid($element['#value'])) { + if ($url->isExternal()) { + $form_state->setError($element, t('You cannot use an external URL, please enter a relative path.')); + return; + } + if ($element['#convert_path'] == self::CONVERT_NONE) { + // Url is valid, no conversion required. + return; + } + // We do the value conversion here whilst the Url object is in scope + // after validation has occurred. + if ($element['#convert_path'] == self::CONVERT_ROUTE) { + $form_state->setValueForElement($element, array( + 'route_name' => $url->getRouteName(), + 'route_parameters' => $url->getRouteParameters(), + )); + return; + } + elseif ($element['#convert_path'] == self::CONVERT_URL) { + $form_state->setValueForElement($element, $url); + return; + } + } + $form_state->setError($element, t('This path does not exist or you do not have permission to link to %path.', array( + '%path' => $element['#value'], + ))); + } + } + +} diff --git a/core/modules/system/src/Tests/Element/PathElementFormTest.php b/core/modules/system/src/Tests/Element/PathElementFormTest.php new file mode 100644 index 0000000000..0683b97b10 --- /dev/null +++ b/core/modules/system/src/Tests/Element/PathElementFormTest.php @@ -0,0 +1,213 @@ +installSchema('system', array('router', 'sequences')); + $this->installEntitySchema('user'); + \Drupal::service('router.builder')->rebuild(); + /** @var \Drupal\user\RoleInterface $role */ + $role = Role::create(array( + 'id' => 'admin', + 'label' => 'admin', + )); + $role->grantPermission('link to any page'); + $role->save(); + $this->testUser = User::create(array( + 'name' => 'foobar', + 'mail' => 'foobar@example.com', + )); + $this->testUser->addRole($role->id()); + $this->testUser->save(); + \Drupal::service('current_user')->setAccount($this->testUser); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'test_path_element'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + // A required validated path. + $form['required_validate'] = array( + '#type' => 'path', + '#required' => TRUE, + '#title' => 'required_validate', + '#convert_path' => PathElement::CONVERT_NONE, + ); + + // A non validated required path. + $form['required_non_validate'] = array( + '#type' => 'path', + '#required' => TRUE, + '#title' => 'required_non_validate', + '#convert_path' => PathElement::CONVERT_NONE, + '#validate_path' => FALSE, + ); + + // A non required validated path. + $form['optional_validate'] = array( + '#type' => 'path', + '#required' => FALSE, + '#title' => 'optional_validate', + '#convert_path' => PathElement::CONVERT_NONE, + ); + + // A non required converted path. + $form['optional_validate'] = array( + '#type' => 'path', + '#required' => FALSE, + '#title' => 'optional_validate', + '#convert_path' => PathElement::CONVERT_ROUTE, + ); + + // A converted required validated path. + $form['required_validate_route'] = array( + '#type' => 'path', + '#required' => TRUE, + '#title' => 'required_validate_route', + ); + + // A converted required validated path. + $form['required_validate_url'] = array( + '#type' => 'path', + '#required' => TRUE, + '#title' => 'required_validate_url', + '#convert_path' => PathElement::CONVERT_URL, + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) {} + + /** + * Form validation handler. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + */ + public function validateForm(array &$form, FormStateInterface $form_state) {} + + /** + * Tests that default handlers are added even if custom are specified. + */ + public function testPathElement() { + $form_state = new FormState(array( + 'values' => array( + 'required_validate' => 'user/' . $this->testUser->id(), + 'required_non_validate' => 'magic-ponies', + 'required_validate_route' => 'user/' . $this->testUser->id(), + 'required_validate_url' => 'user/' . $this->testUser->id(), + ), + )); + $form_builder = $this->container->get('form_builder'); + $form_builder->submitForm($this, $form_state); + + // Valid form state. + $this->assertEqual(count($form_state->getErrors()), 0); + $this->assertEqual($form_state->getValue('required_validate_route'), array( + 'route_name' => 'entity.user.canonical', + 'route_parameters' => array( + 'user' => $this->testUser->id(), + ), + )); + /** @var \Drupal\Core\Url $url */ + $url = $form_state->getValue('required_validate_url'); + $this->assertTrue($url instanceof Url); + $this->assertEqual($url->getRouteName(), 'entity.user.canonical'); + $this->assertEqual($url->getRouteParameters(), array( + 'user' => $this->testUser->id(), + )); + + // Test #required. + $form_state = new FormState(array( + 'values' => array( + 'required_non_validate' => 'magic-ponies', + 'required_validate_route' => 'user/' . $this->testUser->id(), + 'required_validate_url' => 'user/' . $this->testUser->id(), + ), + )); + $form_builder->submitForm($this, $form_state); + $errors = $form_state->getErrors(); + // Should be missing 'required_validate' field. + $this->assertEqual(count($errors), 1); + $this->assertEqual($errors, array('required_validate' => t('!name field is required.', array('!name' => 'required_validate')))); + + // Test invalid parameters. + $form_state = new FormState(array( + 'values' => array( + 'required_validate' => 'user/74', + 'required_non_validate' => 'magic-ponies', + 'required_validate_route' => 'user/74', + 'required_validate_url' => 'user/74', + ), + )); + $form_builder = $this->container->get('form_builder'); + $form_builder->submitForm($this, $form_state); + + // Valid form state. + $errors = $form_state->getErrors(); + $this->assertEqual(count($errors), 3); + $this->assertEqual($errors, array( + 'required_validate' => t('This path does not exist or you do not have permission to link to %path.', array('%path' => 'user/74')), + 'required_validate_route' => t('This path does not exist or you do not have permission to link to %path.', array('%path' => 'user/74')), + 'required_validate_url' => t('This path does not exist or you do not have permission to link to %path.', array('%path' => 'user/74')), + )); + } + +} -- GitLab