Commit 06caf9c7 authored by catch's avatar catch

Issue #306662 by naveenvalecha, andypost, larowlan, tim-e, mr.baileys,...

Issue #306662 by naveenvalecha, andypost, larowlan, tim-e, mr.baileys, pguillard, alexpott, hussainweb, frankcarey, Tor Arne Thune, deepakaryan1988, jibran, tstoeckler: Add redirect option to site-wide contact forms
parent e5664869
...@@ -6,3 +6,5 @@ label: 'Personal contact form' ...@@ -6,3 +6,5 @@ label: 'Personal contact form'
recipients: { } recipients: { }
reply: '' reply: ''
weight: 0 weight: 0
message: 'Your message has been sent.'
redirect: ''
...@@ -22,6 +22,12 @@ contact.form.*: ...@@ -22,6 +22,12 @@ contact.form.*:
weight: weight:
type: integer type: integer
label: 'Weight' label: 'Weight'
message:
type: label
label: 'Message displayed to user on submission'
redirect:
type: path
label: 'Redirect path on submission'
contact.settings: contact.settings:
type: config_object type: config_object
......
<?php
/**
* @file
* Post update functions for Contact.
*/
use Drupal\contact\Entity\ContactForm;
/**
* @addtogroup updates-8.1.x-to-8.2.x
* @{
*/
/**
* Initialize 'message' and 'redirect' field values to 'contact_form' entities.
*/
function contact_post_update_add_message_redirect_field_to_contact_form() {
/** @var \Drupal\contact\ContactFormInterface $contact */
foreach (ContactForm::loadMultiple() as $contact) {
$contact
->setMessage('Your message has been sent.')
->setRedirectPath('')
->save();
}
}
/**
* @} End of "addtogroup updates-8.1.x-to-8.2.x".
*/
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Drupal\contact; namespace Drupal\contact;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityForm;
...@@ -9,6 +10,8 @@ ...@@ -9,6 +10,8 @@
use Drupal\Core\Form\ConfigFormBaseTrait; use Drupal\Core\Form\ConfigFormBaseTrait;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Egulias\EmailValidator\EmailValidator; use Egulias\EmailValidator\EmailValidator;
use Drupal\Core\Path\PathValidatorInterface;
use Drupal\Core\Render\Element\PathElement;
/** /**
* Base form for contact form edit forms. * Base form for contact form edit forms.
...@@ -23,14 +26,22 @@ class ContactFormEditForm extends EntityForm implements ContainerInjectionInterf ...@@ -23,14 +26,22 @@ class ContactFormEditForm extends EntityForm implements ContainerInjectionInterf
*/ */
protected $emailValidator; protected $emailValidator;
/**
* The path validator.
*
* @var \Drupal\Core\Path\PathValidatorInterface
*/
protected $pathValidator;
/** /**
* Constructs a new ContactFormEditForm. * Constructs a new ContactFormEditForm.
* *
* @param \Egulias\EmailValidator\EmailValidator $email_validator * @param \Egulias\EmailValidator\EmailValidator $email_validator
* The email validator. * The email validator.
*/ */
public function __construct(EmailValidator $email_validator) { public function __construct(EmailValidator $email_validator, PathValidatorInterface $path_validator) {
$this->emailValidator = $email_validator; $this->emailValidator = $email_validator;
$this->pathValidator = $path_validator;
} }
/** /**
...@@ -38,7 +49,8 @@ public function __construct(EmailValidator $email_validator) { ...@@ -38,7 +49,8 @@ public function __construct(EmailValidator $email_validator) {
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('email.validator') $container->get('email.validator'),
$container->get('path.validator')
); );
} }
...@@ -82,6 +94,19 @@ public function form(array $form, FormStateInterface $form_state) { ...@@ -82,6 +94,19 @@ public function form(array $form, FormStateInterface $form_state) {
'#description' => $this->t("Example: 'webmaster@example.com' or 'sales@example.com,support@example.com' . To specify multiple recipients, separate each email address with a comma."), '#description' => $this->t("Example: 'webmaster@example.com' or 'sales@example.com,support@example.com' . To specify multiple recipients, separate each email address with a comma."),
'#required' => TRUE, '#required' => TRUE,
); );
$form['message'] = array(
'#type' => 'textarea',
'#title' => $this->t('Message'),
'#default_value' => $contact_form->getMessage(),
'#description' => $this->t('The message to display to the user after submission of this form. Leave blank for no message.'),
);
$form['redirect'] = array(
'#type' => 'path',
'#title' => $this->t('Redirect path'),
'#convert_path' => PathElement::CONVERT_NONE,
'#default_value' => $contact_form->getRedirectPath(),
'#description' => $this->t('Path to redirect the user to after submission of this form. For example, type "/about" to redirect to that page. Use a relative path with a slash in front.'),
);
$form['reply'] = array( $form['reply'] = array(
'#type' => 'textarea', '#type' => 'textarea',
'#title' => $this->t('Auto-reply'), '#title' => $this->t('Auto-reply'),
...@@ -119,6 +144,12 @@ public function validateForm(array &$form, FormStateInterface $form_state) { ...@@ -119,6 +144,12 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
} }
} }
$form_state->setValue('recipients', $recipients); $form_state->setValue('recipients', $recipients);
$redirect_url = $form_state->getValue('redirect');
if ($redirect_url && $this->pathValidator->isValid($redirect_url)) {
if (Unicode::substr($redirect_url, 0, 1) !== '/') {
$form_state->setErrorByName('redirect', $this->t('The path should start with /.'));
}
}
} }
/** /**
......
...@@ -9,6 +9,14 @@ ...@@ -9,6 +9,14 @@
*/ */
interface ContactFormInterface extends ConfigEntityInterface { interface ContactFormInterface extends ConfigEntityInterface {
/**
* Returns the message to be displayed to user.
*
* @return string
* A user message.
*/
public function getMessage();
/** /**
* Returns list of recipient email addresses. * Returns list of recipient email addresses.
* *
...@@ -17,6 +25,24 @@ interface ContactFormInterface extends ConfigEntityInterface { ...@@ -17,6 +25,24 @@ interface ContactFormInterface extends ConfigEntityInterface {
*/ */
public function getRecipients(); public function getRecipients();
/**
* Returns the path for redirect.
*
* @return string
* The redirect path.
*/
public function getRedirectPath();
/**
* Returns the url object for redirect path.
*
* Empty redirect property results a url object of front page.
*
* @return \Drupal\core\Url
* The redirect url object.
*/
public function getRedirectUrl();
/** /**
* Returns an auto-reply message to send to the message author. * Returns an auto-reply message to send to the message author.
* *
...@@ -33,6 +59,16 @@ public function getReply(); ...@@ -33,6 +59,16 @@ public function getReply();
*/ */
public function getWeight(); public function getWeight();
/**
* Sets the message to be displayed to the user.
*
* @param string $message
* The message to display after form is submitted.
*
* @return $this
*/
public function setMessage($message);
/** /**
* Sets list of recipient email addresses. * Sets list of recipient email addresses.
* *
...@@ -43,6 +79,16 @@ public function getWeight(); ...@@ -43,6 +79,16 @@ public function getWeight();
*/ */
public function setRecipients($recipients); public function setRecipients($recipients);
/**
* Sets the redirect path.
*
* @param string $redirect
* The desired path.
*
* @return $this
*/
public function setRedirectPath($redirect);
/** /**
* Sets an auto-reply message to send to the message author. * Sets an auto-reply message to send to the message author.
* *
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
use Drupal\Core\Config\Entity\ConfigEntityBundleBase; use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
use Drupal\contact\ContactFormInterface; use Drupal\contact\ContactFormInterface;
use Drupal\Core\Url;
/** /**
* Defines the contact form entity. * Defines the contact form entity.
...@@ -39,6 +40,8 @@ ...@@ -39,6 +40,8 @@
* "recipients", * "recipients",
* "reply", * "reply",
* "weight", * "weight",
* "message",
* "redirect",
* } * }
* ) * )
*/ */
...@@ -58,6 +61,13 @@ class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface ...@@ -58,6 +61,13 @@ class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface
*/ */
protected $label; protected $label;
/**
* The message displayed to user on form submission.
*
* @var string
*/
protected $message;
/** /**
* List of recipient email addresses. * List of recipient email addresses.
* *
...@@ -65,6 +75,13 @@ class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface ...@@ -65,6 +75,13 @@ class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface
*/ */
protected $recipients = array(); protected $recipients = array();
/**
* The path to redirect to on form submission.
*
* @var string
*/
protected $redirect;
/** /**
* An auto-reply message. * An auto-reply message.
* *
...@@ -79,6 +96,21 @@ class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface ...@@ -79,6 +96,21 @@ class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface
*/ */
protected $weight = 0; protected $weight = 0;
/**
* {@inheritdoc}
*/
public function getMessage() {
return $this->message;
}
/**
* {@inheritdoc}
*/
public function setMessage($message) {
$this->message = $message;
return $this;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -94,6 +126,34 @@ public function setRecipients($recipients) { ...@@ -94,6 +126,34 @@ public function setRecipients($recipients) {
return $this; return $this;
} }
/**
* {@inheritdoc}
*/
public function getRedirectPath() {
return $this->redirect;
}
/**
* {@inheritdoc}
*/
public function getRedirectUrl() {
if ($this->redirect) {
$url = Url::fromUserInput($this->redirect);
}
else {
$url = Url::fromRoute('<front>');
}
return $url;
}
/**
* {@inheritdoc}
*/
public function setRedirectPath($redirect) {
$this->redirect = $redirect;
return $this;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -206,9 +206,12 @@ public function save(array $form, FormStateInterface $form_state) { ...@@ -206,9 +206,12 @@ public function save(array $form, FormStateInterface $form_state) {
$message = $this->entity; $message = $this->entity;
$user = $this->currentUser(); $user = $this->currentUser();
$this->mailHandler->sendMailMessages($message, $user); $this->mailHandler->sendMailMessages($message, $user);
$contact_form = $message->getContactForm();
$this->flood->register('contact', $this->config('contact.settings')->get('flood.interval')); $this->flood->register('contact', $this->config('contact.settings')->get('flood.interval'));
drupal_set_message($this->t('Your message has been sent.')); if ($submission_message = $contact_form->getMessage()) {
drupal_set_message($submission_message);
}
// To avoid false error messages caused by flood control, redirect away from // To avoid false error messages caused by flood control, redirect away from
// the contact form; either to the contacted user account or the front page. // the contact form; either to the contacted user account or the front page.
...@@ -216,7 +219,7 @@ public function save(array $form, FormStateInterface $form_state) { ...@@ -216,7 +219,7 @@ public function save(array $form, FormStateInterface $form_state) {
$form_state->setRedirectUrl($message->getPersonalRecipient()->urlInfo()); $form_state->setRedirectUrl($message->getPersonalRecipient()->urlInfo());
} }
else { else {
$form_state->setRedirect('<front>'); $form_state->setRedirectUrl($contact_form->getRedirectUrl());
} }
// Save the message. In core this is a no-op but should contrib wish to // Save the message. In core this is a no-op but should contrib wish to
// implement message storage, this will make the task of swapping in a real // implement message storage, this will make the task of swapping in a real
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\Unicode;
use Drupal\contact\Entity\ContactForm; use Drupal\contact\Entity\ContactForm;
use Drupal\Core\Mail\MailFormatHelper; use Drupal\Core\Mail\MailFormatHelper;
use Drupal\Core\Url;
use Drupal\field_ui\Tests\FieldUiTestTrait; use Drupal\field_ui\Tests\FieldUiTestTrait;
use Drupal\simpletest\WebTestBase; use Drupal\simpletest\WebTestBase;
use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeInterface;
...@@ -154,7 +155,7 @@ function testSiteWideContact() { ...@@ -154,7 +155,7 @@ function testSiteWideContact() {
$this->assertEscaped($recipients[0]); $this->assertEscaped($recipients[0]);
// Test update contact form. // Test update contact form.
$this->updateContactForm($id, $label = $this->randomMachineName(16), $recipients_str = implode(',', array($recipients[0], $recipients[1])), $reply = $this->randomMachineName(30), FALSE); $this->updateContactForm($id, $label = $this->randomMachineName(16), $recipients_str = implode(',', array($recipients[0], $recipients[1])), $reply = $this->randomMachineName(30), FALSE, 'Your message has been sent.', '/user');
$config = $this->config('contact.form.' . $id)->get(); $config = $this->config('contact.form.' . $id)->get();
$this->assertEqual($config['label'], $label); $this->assertEqual($config['label'], $label);
$this->assertEqual($config['recipients'], array($recipients[0], $recipients[1])); $this->assertEqual($config['recipients'], array($recipients[0], $recipients[1]));
...@@ -298,6 +299,46 @@ function testSiteWideContact() { ...@@ -298,6 +299,46 @@ function testSiteWideContact() {
$this->assertEqual($mail['subject'], t('[@label] @subject', array('@label' => $label, '@subject' => $edit['subject[0][value]']))); $this->assertEqual($mail['subject'], t('[@label] @subject', array('@label' => $label, '@subject' => $edit['subject[0][value]'])));
$this->assertTrue(strpos($mail['body'], $field_label)); $this->assertTrue(strpos($mail['body'], $field_label));
$this->assertTrue(strpos($mail['body'], $edit[$field_name . '[0][value]'])); $this->assertTrue(strpos($mail['body'], $edit[$field_name . '[0][value]']));
// Test messages and redirect.
/** @var \Drupal\contact\ContactFormInterface $form */
$form = ContactForm::load($contact_form);
$form->setMessage('Thanks for your submission.');
$form->setRedirectPath('/user/' . $admin_user->id());
$form->save();
// Check that the field is displayed.
$this->drupalGet('contact/' . $contact_form);
// Submit the contact form and verify the content.
$edit = array(
'subject[0][value]' => $this->randomMachineName(),
'message[0][value]' => $this->randomMachineName(),
$field_name . '[0][value]' => $this->randomMachineName(),
);
$this->drupalPostForm(NULL, $edit, t('Send message'));
$this->assertText('Thanks for your submission.');
$this->assertUrl('user/' . $admin_user->id());
// Test Empty message.
/** @var \Drupal\contact\ContactFormInterface $form */
$form = ContactForm::load($contact_form);
$form->setMessage('');
$form->setRedirectPath('/user/' . $admin_user->id());
$form->save();
$this->drupalGet('admin/structure/contact/manage/' . $contact_form);
// Check that the field is displayed.
$this->drupalGet('contact/' . $contact_form);
// Submit the contact form and verify the content.
$edit = array(
'subject[0][value]' => $this->randomMachineName(),
'message[0][value]' => $this->randomMachineName(),
$field_name . '[0][value]' => $this->randomMachineName(),
);
$this->drupalPostForm(NULL, $edit, t('Send message'));
$result = $this->xpath('//div[@role=:role]', array(':role' => 'contentinfo'));
$this->assertEqual(count($result), 0, 'Messages not found.');
$this->assertUrl('user/' . $admin_user->id());
} }
/** /**
...@@ -359,13 +400,17 @@ function testAutoReply() { ...@@ -359,13 +400,17 @@ function testAutoReply() {
* form. * form.
* @param bool $selected * @param bool $selected
* A Boolean indicating whether the form should be selected by default. * A Boolean indicating whether the form should be selected by default.
* @param string $message
* The message that will be displayed to a user upon completing the contact
* form.
* @param array $third_party_settings * @param array $third_party_settings
* Array of third party settings to be added to the posted form data. * Array of third party settings to be added to the posted form data.
*/ */
function addContactForm($id, $label, $recipients, $reply, $selected, $third_party_settings = []) { function addContactForm($id, $label, $recipients, $reply, $selected, $message = 'Your message has been sent.', $third_party_settings = []) {
$edit = array(); $edit = array();
$edit['label'] = $label; $edit['label'] = $label;
$edit['id'] = $id; $edit['id'] = $id;
$edit['message'] = $message;
$edit['recipients'] = $recipients; $edit['recipients'] = $recipients;
$edit['reply'] = $reply; $edit['reply'] = $reply;
$edit['selected'] = ($selected ? TRUE : FALSE); $edit['selected'] = ($selected ? TRUE : FALSE);
...@@ -387,13 +432,20 @@ function addContactForm($id, $label, $recipients, $reply, $selected, $third_part ...@@ -387,13 +432,20 @@ function addContactForm($id, $label, $recipients, $reply, $selected, $third_part
* form. * form.
* @param bool $selected * @param bool $selected
* A Boolean indicating whether the form should be selected by default. * A Boolean indicating whether the form should be selected by default.
* @param string $message
* The message that will be displayed to a user upon completing the contact
* form.
* @param string $redirect
* The path where user will be redirect after this form has been submitted..
*/ */
function updateContactForm($id, $label, $recipients, $reply, $selected) { function updateContactForm($id, $label, $recipients, $reply, $selected, $message = 'Your message has been sent.', $redirect = '/') {
$edit = array(); $edit = array();
$edit['label'] = $label; $edit['label'] = $label;
$edit['recipients'] = $recipients; $edit['recipients'] = $recipients;
$edit['reply'] = $reply; $edit['reply'] = $reply;
$edit['selected'] = ($selected ? TRUE : FALSE); $edit['selected'] = ($selected ? TRUE : FALSE);
$edit['message'] = $message;
$edit['redirect'] = $redirect;
$this->drupalPostForm("admin/structure/contact/manage/$id", $edit, t('Save')); $this->drupalPostForm("admin/structure/contact/manage/$id", $edit, t('Save'));
} }
......
...@@ -47,7 +47,7 @@ public function testContactStorage() { ...@@ -47,7 +47,7 @@ public function testContactStorage() {
$this->drupalLogin($admin_user); $this->drupalLogin($admin_user);
// Create first valid contact form. // Create first valid contact form.
$mail = 'simpletest@example.com'; $mail = 'simpletest@example.com';
$this->addContactForm($id = Unicode::strtolower($this->randomMachineName(16)), $label = $this->randomMachineName(16), implode(',', array($mail)), '', TRUE, [ $this->addContactForm($id = Unicode::strtolower($this->randomMachineName(16)), $label = $this->randomMachineName(16), implode(',', array($mail)), '', TRUE, 'Your message has been sent.', [
'send_a_pony' => 1, 'send_a_pony' => 1,
]); ]);
$this->assertText(t('Contact form @label has been added.', array('@label' => $label))); $this->assertText(t('Contact form @label has been added.', array('@label' => $label)));
......
<?php
namespace Drupal\contact\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests contact update path.
*
* @group contact
*/
class ContactUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
/**
* Tests contact_form updates.
*
* @see contact_post_update_add_message_redirect_field_to_contact_form()
*/
public function testPostUpdateContactFormFields() {
// Check that contact_form does not have fields redirect and message.
$config_factory = \Drupal::configFactory();
// Check that contact_form entities are more than zero.
$contact_forms = $config_factory->listAll('contact.form.');
$this->assertTrue(count($contact_forms), 'There are contact forms to update.');
foreach ($contact_forms as $contact_config_name) {
$contact_form_data = $config_factory->get($contact_config_name)->get();
$this->assertFalse(isset($contact_form_data['message']), 'Prior to running the update the "message" key does not exist.');
$this->assertFalse(isset($contact_form_data['redirect']), 'Prior to running the update the "redirect" key does not exist.');
}
// Run updates.
$this->runUpdates();
// Check that the contact_form entities have been updated.
foreach ($contact_forms as $contact_config_name) {
$contact_form_data = $config_factory->get($contact_config_name)->get();
$this->assertTrue(isset($contact_form_data['message']), 'After running the update the "message" key exists.');
$this->assertEqual('Your message has been sent.', $contact_form_data['message']);
$this->assertTrue(isset($contact_form_data['redirect']), 'After running the update the "redirect" key exists.');
$this->assertEqual('', $contact_form_data['redirect']);
}
}
}
...@@ -5,3 +5,5 @@ reply: '' ...@@ -5,3 +5,5 @@ reply: ''
weight: 0 weight: 0
status: true status: true
langcode: en langcode: en
message: 'Your message has been sent.'
redirect: ''
...@@ -7,3 +7,5 @@ recipients: ...@@ -7,3 +7,5 @@ recipients:
- admin@example.com - admin@example.com
reply: '' reply: ''
weight: 0 weight: 0
message: 'Your message has been sent.'
redirect: ''
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment