Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
|||
id: personal
|
||||
label: 'Personal contact form'
|
||||
recipients: { }
|
||||
reply: ''
|
||||
weight: 0
|
||||
status: true
|
||||
langcode: en
|
5
core/modules/contact/config/install/contact.settings.yml
Normal file
5
core/modules/contact/config/install/contact.settings.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
default_form: feedback
|
||||
flood:
|
||||
limit: 5
|
||||
interval: 3600
|
||||
user_default_enabled: true
|
45
core/modules/contact/config/schema/contact.schema.yml
Normal file
45
core/modules/contact/config/schema/contact.schema.yml
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Schema for the configuration files of the Contact module.
|
||||
|
||||
contact.form.*:
|
||||
type: config_entity
|
||||
label: 'Contact form'
|
||||
mapping:
|
||||
id:
|
||||
type: string
|
||||
label: 'ID'
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
recipients:
|
||||
type: sequence
|
||||
label: 'Recipients'
|
||||
sequence:
|
||||
type: email
|
||||
label: 'Email address'
|
||||
reply:
|
||||
type: text
|
||||
label: 'Auto-reply'
|
||||
weight:
|
||||
type: integer
|
||||
label: 'Weight'
|
||||
|
||||
contact.settings:
|
||||
type: config_object
|
||||
label: 'Contact settings'
|
||||
mapping:
|
||||
default_form:
|
||||
type: string
|
||||
label: 'Default form identifier'
|
||||
flood:
|
||||
type: mapping
|
||||
label: 'Flood control'
|
||||
mapping:
|
||||
limit:
|
||||
type: integer
|
||||
label: 'Limit'
|
||||
interval:
|
||||
type: integer
|
||||
label: 'Interval'
|
||||
user_default_enabled:
|
||||
type: boolean
|
||||
label: 'Personal contact form enabled by default'
|
|
@ -0,0 +1,5 @@
|
|||
# Schema for the views plugins of the Contact module.
|
||||
|
||||
views.field.contact_link:
|
||||
type: views.field.user_link
|
||||
label: 'Link to user contact page'
|
7
core/modules/contact/contact.info.yml
Normal file
7
core/modules/contact/contact.info.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
name: Contact
|
||||
type: module
|
||||
description: 'Enables the use of both personal and site-wide contact forms.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
configure: entity.contact_form.collection
|
6
core/modules/contact/contact.links.action.yml
Normal file
6
core/modules/contact/contact.links.action.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
contact.form_add:
|
||||
route_name: contact.form_add
|
||||
title: 'Add contact form'
|
||||
weight: 1
|
||||
appears_on:
|
||||
- entity.contact_form.collection
|
10
core/modules/contact/contact.links.menu.yml
Normal file
10
core/modules/contact/contact.links.menu.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
entity.contact_form.collection:
|
||||
title: 'Contact forms'
|
||||
parent: system.admin_structure
|
||||
description: 'Create and manage contact forms.'
|
||||
route_name: entity.contact_form.collection
|
||||
contact.site_page:
|
||||
title: Contact
|
||||
route_name: contact.site_page
|
||||
menu_name: footer
|
||||
enabled: 0
|
10
core/modules/contact/contact.links.task.yml
Normal file
10
core/modules/contact/contact.links.task.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
entity.contact_form.edit_form:
|
||||
title: 'Edit'
|
||||
route_name: entity.contact_form.edit_form
|
||||
base_route: entity.contact_form.edit_form
|
||||
|
||||
entity.user.contact_form:
|
||||
title: 'Contact'
|
||||
route_name: entity.user.contact_form
|
||||
weight: 2
|
||||
base_route: entity.user.canonical
|
240
core/modules/contact/contact.module
Normal file
240
core/modules/contact/contact.module
Normal file
|
@ -0,0 +1,240 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Enables the use of personal and site-wide contact forms.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function contact_help($route_name, RouteMatchInterface $route_match) {
|
||||
|
||||
switch ($route_name) {
|
||||
case 'help.page.contact':
|
||||
$menu_page = \Drupal::moduleHandler()->moduleExists('menu_ui') ? \Drupal::url('entity.menu.collection') : '#';
|
||||
$block_page = \Drupal::moduleHandler()->moduleExists('block') ? \Drupal::url('block.admin_display') : '#';
|
||||
$contact_page = \Drupal::url('entity.contact_form.collection');
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Contact module allows visitors to contact registered users on your site, using the personal contact form, and also allows you to set up site-wide contact forms. For more information, see the <a href="!contact">online documentation for the Contact module</a>.', array('!contact' => 'https://www.drupal.org/documentation/modules/contact')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Using the personal contact form') . '</dt>';
|
||||
$output .= '<dd>' . t("Site visitors can email registered users on your site by using the personal contact form, without knowing or learning the email address of the recipient. When a site visitor is viewing a user profile, the viewer will see a <em>Contact</em> tab or link, which leads to the personal contact form. The personal contact link is not shown when you are viewing your own profile, and users must have both <em>View user information</em> (to see user profiles) and <em>Use users' personal contact forms</em> permission to see the link. The user whose profile is being viewed must also have their personal contact form enabled (this is a user account setting); viewers with <em>Administer users</em> permission can bypass this setting.") . '</dd>';
|
||||
$output .= '<dt>' . t('Configuring contact forms') . '</dt>';
|
||||
$output .= '<dd>' . t('On the <a href="!contact_admin">Contact forms page</a>, you can configure the fields and display of the personal contact form, and you can set up one or more site-wide contact forms. Each site-wide contact form has a machine name, a label, and one or more defined recipients; when a site visitor submits the form, the field values are sent to those recipients.', array('!contact_admin' => $contact_page)) . '</dd>';
|
||||
$output .= '<dt>' . t('Linking to contact forms') . '</dt>';
|
||||
$output .= '<dd>' . t('One site-wide contact form can be designated as the default contact form. If you choose to designate a default form, the <em>Contact</em> menu link in the <em>Footer</em> menu will link to it. You can modify this link from the <a href="!menu-settings">Menus page</a> if you have the Menu UI module installed. You can also create links to other contact forms; the URL for each form you have set up has format <em>contact/machine_name_of_form</em>.', array('!menu-settings' => $menu_page)) . '</p>';
|
||||
$output .= '<dt>' . t('Adding content to contact forms') . '</dt>';
|
||||
$output .= '<dd>' . t('From the <a href="!contact_admin">Contact forms page</a>, you can configure the fields to be shown on contact forms, including their labels and help text. If you would like other content (such as text or images) to appear on a contact form, use a block. You can create and edit blocks on the <a href="!blocks">Block layout page</a>, if the Block module is installed.', array('!blocks' => $block_page, '!contact_admin' => $contact_page)) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'entity.contact_form.collection':
|
||||
$menu_page = \Drupal::moduleHandler()->moduleExists('menu_ui') ? \Drupal::url('entity.menu.collection') : '#';
|
||||
$block_page = \Drupal::moduleHandler()->moduleExists('block') ? \Drupal::url('block.admin_display') : '#';
|
||||
$output = '';
|
||||
$output .= '<p>' . t('The <em>Personal contact form</em> is the form for site visitors to contact registered users; the name and recipients of this form cannot be edited. Other forms listed here are your configured site-wide contact forms, which site visitors can use to send mail to a centralized email address or addresses. You can edit the name and recipients of site-wide forms by choosing the <em>Edit</em> operation. You can also configure the fields and display of both personal and site-wide forms.') . '</p>';
|
||||
$output .= '<p>' . t('If you have configured a default site-wide contact form, a <em>Contact</em> menu link in the <em>Footer</em> menu will link to it. You can modify this link from the <a href="!menu-settings">Menus page</a> if you have the Menu UI module installed. You can also create links to other contact forms; the URL has format contact/machine_name_of_form.', array('!menu-settings' => $menu_page)) . '</p>';
|
||||
$output .= '<p>' . t('If you would like additional text to appear on a site-wide contact page, beyond field labels, use a block. You can create and edit blocks on the <a href="!blocks">Block layout page</a>, if you have the Block module installed.', array('!blocks' => $block_page)) . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function contact_entity_type_alter(array &$entity_types) {
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
$entity_types['user']->setLinkTemplate('contact-form', '/user/{user}/contact');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_extra_field_info().
|
||||
*/
|
||||
function contact_entity_extra_field_info() {
|
||||
$fields = array();
|
||||
foreach (array_keys(entity_get_bundles('contact_message')) as $bundle) {
|
||||
$fields['contact_message'][$bundle]['form']['name'] = array(
|
||||
'label' => t('Sender name'),
|
||||
'description' => t('Text'),
|
||||
'weight' => -50,
|
||||
);
|
||||
$fields['contact_message'][$bundle]['form']['mail'] = array(
|
||||
'label' => t('Sender email'),
|
||||
'description' => t('Email'),
|
||||
'weight' => -40,
|
||||
);
|
||||
if ($bundle == 'personal') {
|
||||
$fields['contact_message'][$bundle]['form']['recipient'] = array(
|
||||
'label' => t('Recipient username'),
|
||||
'description' => t('User'),
|
||||
'weight' => -30,
|
||||
);
|
||||
}
|
||||
$fields['contact_message'][$bundle]['form']['copy'] = array(
|
||||
'label' => t('Send copy to sender'),
|
||||
'description' => t('Option'),
|
||||
'weight' => 50,
|
||||
);
|
||||
}
|
||||
|
||||
$fields['user']['user']['form']['contact'] = array(
|
||||
'label' => t('Contact settings'),
|
||||
'description' => t('Contact module form element.'),
|
||||
'weight' => 5,
|
||||
);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_local_tasks_alter().
|
||||
*
|
||||
* Hides the 'Contact' tab on the user profile if the user does not have an
|
||||
* email address configured.
|
||||
*/
|
||||
function contact_menu_local_tasks_alter(&$data, $route_name) {
|
||||
if ($route_name == 'entity.user.canonical') {
|
||||
foreach ($data['tabs'][0] as $href => $tab_data) {
|
||||
if ($href == 'entity.user.contact_form') {
|
||||
$link_params = $tab_data['#link']['url']->getRouteParameters();
|
||||
$account = User::load($link_params['user']);
|
||||
if (!$account->getEmail()) {
|
||||
unset($data['tabs'][0]['entity.user.contact_form']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_mail().
|
||||
*/
|
||||
function contact_mail($key, &$message, $params) {
|
||||
$contact_message = $params['contact_message'];
|
||||
/** @var $sender \Drupal\user\UserInterface */
|
||||
$sender = $params['sender'];
|
||||
$language = \Drupal::languageManager()->getLanguage($message['langcode']);
|
||||
|
||||
$variables = array(
|
||||
'!site-name' => \Drupal::config('system.site')->get('name'),
|
||||
'!subject' => $contact_message->getSubject(),
|
||||
'!form' => !empty($params['contact_form']) ? $params['contact_form']->label() : NULL,
|
||||
'!form-url' => \Drupal::url('<current>', [], ['absolute' => TRUE, 'language' => $language]),
|
||||
'!sender-name' => user_format_name($sender),
|
||||
);
|
||||
if ($sender->isAuthenticated()) {
|
||||
$variables['!sender-url'] = $sender->url('canonical', array('absolute' => TRUE, 'language' => $language));
|
||||
}
|
||||
else {
|
||||
$variables['!sender-url'] = $params['sender']->getEmail();
|
||||
}
|
||||
|
||||
$options = array('langcode' => $language->getId());
|
||||
|
||||
switch ($key) {
|
||||
case 'page_mail':
|
||||
case 'page_copy':
|
||||
$message['subject'] .= t('[!form] !subject', $variables, $options);
|
||||
$message['body'][] = t("!sender-name (!sender-url) sent a message using the contact form at !form-url.", $variables, $options);
|
||||
$build = entity_view($contact_message, 'mail', $language->getId());
|
||||
$message['body'][] = \Drupal::service('renderer')->renderPlain($build);
|
||||
break;
|
||||
|
||||
case 'page_autoreply':
|
||||
$message['subject'] .= t('[!form] !subject', $variables, $options);
|
||||
$message['body'][] = $params['contact_form']->getReply();
|
||||
break;
|
||||
|
||||
case 'user_mail':
|
||||
case 'user_copy':
|
||||
$variables += array(
|
||||
'!recipient-name' => user_format_name($params['recipient']),
|
||||
'!recipient-edit-url' => $params['recipient']->url('edit-form', array('absolute' => TRUE, 'language' => $language)),
|
||||
);
|
||||
$message['subject'] .= t('[!site-name] !subject', $variables, $options);
|
||||
$message['body'][] = t('Hello !recipient-name,', $variables, $options);
|
||||
$message['body'][] = t("!sender-name (!sender-url) has sent you a message via your contact form at !site-name.", $variables, $options);
|
||||
$message['body'][] = t("If you don't want to receive such emails, you can change your settings at !recipient-edit-url.", $variables, $options);
|
||||
$build = entity_view($contact_message, 'mail', $language->getId());
|
||||
$message['body'][] = \Drupal::service('renderer')->renderPlain($build);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*
|
||||
* Add the enable personal contact form to an individual user's account page.
|
||||
*
|
||||
* @see \Drupal\user\ProfileForm::form()
|
||||
*/
|
||||
function contact_form_user_form_alter(&$form, FormStateInterface $form_state) {
|
||||
$form['contact'] = array(
|
||||
'#type' => 'details',
|
||||
'#title' => t('Contact settings'),
|
||||
'#open' => TRUE,
|
||||
'#weight' => 5,
|
||||
);
|
||||
$account = $form_state->getFormObject()->getEntity();
|
||||
if (!\Drupal::currentUser()->isAnonymous() && $account->id()) {
|
||||
$account_data = \Drupal::service('user.data')->get('contact', $account->id(), 'enabled');
|
||||
}
|
||||
$form['contact']['contact'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Personal contact form'),
|
||||
'#default_value' => isset($account_data) ? $account_data : \Drupal::config('contact.settings')->get('user_default_enabled'),
|
||||
'#description' => t('Allow other users to contact you via a personal contact form which keeps your email address hidden. Note that some privileged users such as site administrators are still able to contact you even if you choose to disable this feature.'),
|
||||
);
|
||||
$form['actions']['submit']['#submit'][] = 'contact_user_profile_form_submit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for the user profile form to save the contact page setting.
|
||||
*/
|
||||
function contact_user_profile_form_submit($form, FormStateInterface $form_state) {
|
||||
$account = $form_state->getFormObject()->getEntity();
|
||||
if ($account->id() && $form_state->hasValue('contact')) {
|
||||
\Drupal::service('user.data')->set('contact', $account->id(), 'enabled', (int) $form_state->getValue('contact'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*
|
||||
* Add the default personal contact setting on the user settings page.
|
||||
*
|
||||
* @see \Drupal\user\AccountSettingsForm
|
||||
*/
|
||||
function contact_form_user_admin_settings_alter(&$form, FormStateInterface $form_state) {
|
||||
$form['contact'] = array(
|
||||
'#type' => 'details',
|
||||
'#title' => t('Contact settings'),
|
||||
'#open' => TRUE,
|
||||
'#weight' => 0,
|
||||
);
|
||||
$form['contact']['contact_default_status'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Enable the personal contact form by default for new users'),
|
||||
'#description' => t('Changing this setting will not affect existing users.'),
|
||||
'#default_value' => \Drupal::configFactory()->getEditable('contact.settings')->get('user_default_enabled'),
|
||||
);
|
||||
// Add submit handler to save contact configuration.
|
||||
$form['#submit'][] = 'contact_form_user_admin_settings_submit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for user_admin_settings().
|
||||
*
|
||||
* @see contact_form_user_admin_settings_alter()
|
||||
*/
|
||||
function contact_form_user_admin_settings_submit($form, FormStateInterface $form_state) {
|
||||
\Drupal::configFactory()->getEditable('contact.settings')
|
||||
->set('user_default_enabled', $form_state->getValue('contact_default_status'))
|
||||
->save();
|
||||
}
|
6
core/modules/contact/contact.permissions.yml
Normal file
6
core/modules/contact/contact.permissions.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
administer contact forms:
|
||||
title: 'Administer contact forms and contact form settings'
|
||||
access site-wide contact form:
|
||||
title: 'Use the site-wide contact form'
|
||||
access user contact forms:
|
||||
title: 'Use users'' personal contact forms'
|
56
core/modules/contact/contact.routing.yml
Normal file
56
core/modules/contact/contact.routing.yml
Normal file
|
@ -0,0 +1,56 @@
|
|||
entity.contact_form.delete_form:
|
||||
path: '/admin/structure/contact/manage/{contact_form}/delete'
|
||||
defaults:
|
||||
_entity_form: 'contact_form.delete'
|
||||
_title: 'Delete'
|
||||
requirements:
|
||||
_entity_access: 'contact_form.delete'
|
||||
|
||||
entity.contact_form.collection:
|
||||
path: '/admin/structure/contact'
|
||||
defaults:
|
||||
_entity_list: 'contact_form'
|
||||
_title: 'Contact forms'
|
||||
requirements:
|
||||
_permission: 'administer contact forms'
|
||||
|
||||
contact.form_add:
|
||||
path: '/admin/structure/contact/add'
|
||||
defaults:
|
||||
_entity_form: 'contact_form.add'
|
||||
_title: 'Add contact form'
|
||||
requirements:
|
||||
_permission: 'administer contact forms'
|
||||
|
||||
entity.contact_form.edit_form:
|
||||
path: '/admin/structure/contact/manage/{contact_form}'
|
||||
defaults:
|
||||
_entity_form: 'contact_form.edit'
|
||||
_title: 'Edit contact form'
|
||||
requirements:
|
||||
_entity_access: 'contact_form.update'
|
||||
|
||||
contact.site_page:
|
||||
path: '/contact'
|
||||
defaults:
|
||||
_title: 'Contact'
|
||||
_controller: '\Drupal\contact\Controller\ContactController::contactSitePage'
|
||||
contact_form: NULL
|
||||
requirements:
|
||||
_permission: 'access site-wide contact form'
|
||||
|
||||
contact.site_page_form:
|
||||
path: '/contact/{contact_form}'
|
||||
defaults:
|
||||
_title: 'Contact'
|
||||
_controller: '\Drupal\contact\Controller\ContactController::contactSitePage'
|
||||
requirements:
|
||||
_entity_access: 'contact_form.view'
|
||||
|
||||
entity.user.contact_form:
|
||||
path: '/user/{user}/contact'
|
||||
defaults:
|
||||
_title: 'Contact'
|
||||
_controller: '\Drupal\contact\Controller\ContactController::contactPersonalPage'
|
||||
requirements:
|
||||
_access_contact_personal_tab: 'TRUE'
|
13
core/modules/contact/contact.services.yml
Normal file
13
core/modules/contact/contact.services.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
access_check.contact_personal:
|
||||
class: Drupal\contact\Access\ContactPageAccess
|
||||
tags:
|
||||
- { name: access_check, applies_to: _access_contact_personal_tab }
|
||||
arguments: ['@config.factory', '@user.data']
|
||||
contact.mail_handler:
|
||||
class: Drupal\contact\MailHandler
|
||||
arguments: ['@plugin.manager.mail', '@language_manager', '@logger.channel.contact', '@string_translation', '@entity.manager']
|
||||
logger.channel.contact:
|
||||
class: Drupal\Core\Logger\LoggerChannel
|
||||
factory: logger.factory:get
|
||||
arguments: ['contact']
|
19
core/modules/contact/contact.views.inc
Normal file
19
core/modules/contact/contact.views.inc
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provide views data for contact.module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_views_data_alter().
|
||||
*/
|
||||
function contact_views_data_alter(&$data) {
|
||||
$data['users']['contact'] = array(
|
||||
'field' => array(
|
||||
'title' => t('Contact link'),
|
||||
'help' => t('Provide a simple link to the user contact page.'),
|
||||
'id' => 'contact_link',
|
||||
),
|
||||
);
|
||||
}
|
104
core/modules/contact/src/Access/ContactPageAccess.php
Normal file
104
core/modules/contact/src/Access/ContactPageAccess.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Access\ContactPageAccess.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\UserDataInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Access check for contact_personal_page route.
|
||||
*/
|
||||
class ContactPageAccess implements AccessInterface {
|
||||
|
||||
/**
|
||||
* The contact settings config object.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* The user data service.
|
||||
*
|
||||
* @var \Drupal\user\UserDataInterface;
|
||||
*/
|
||||
protected $userData;
|
||||
|
||||
/**
|
||||
* Constructs a ContactPageAccess instance.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory.
|
||||
* @param \Drupal\user\UserDataInterface $user_data
|
||||
* The user data service.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, UserDataInterface $user_data) {
|
||||
$this->configFactory = $config_factory;
|
||||
$this->userData = $user_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks access to the given user's contact page.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* The user being contacted.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The currently logged in account.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
public function access(UserInterface $user, AccountInterface $account) {
|
||||
$contact_account = $user;
|
||||
|
||||
// Anonymous users cannot have contact forms.
|
||||
if ($contact_account->isAnonymous()) {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
// Users may not contact themselves by default, hence this requires user
|
||||
// granularity for caching.
|
||||
$access = AccessResult::neutral()->cachePerUser();
|
||||
if ($account->id() == $contact_account->id()) {
|
||||
return $access;
|
||||
}
|
||||
|
||||
// User administrators should always have access to personal contact forms.
|
||||
$permission_access = AccessResult::allowedIfHasPermission($account, 'administer users');
|
||||
if ($permission_access->isAllowed()) {
|
||||
return $access->orIf($permission_access);
|
||||
}
|
||||
|
||||
// If requested user has been blocked, do not allow users to contact them.
|
||||
$access->cacheUntilEntityChanges($contact_account);
|
||||
if ($contact_account->isBlocked()) {
|
||||
return $access;
|
||||
}
|
||||
|
||||
// Forbid access if the requested user has disabled their contact form.
|
||||
$account_data = $this->userData->get('contact', $contact_account->id(), 'enabled');
|
||||
if (isset($account_data) && !$account_data) {
|
||||
return $access;
|
||||
}
|
||||
|
||||
// If the requested user did not save a preference yet, deny access if the
|
||||
// configured default is disabled.
|
||||
$contact_settings = $this->configFactory->get('contact.settings');
|
||||
$access->cacheUntilConfigurationChanges($contact_settings);
|
||||
if (!isset($account_data) && !$contact_settings->get('user_default_enabled')) {
|
||||
return $access;
|
||||
}
|
||||
|
||||
return $access->orIf(AccessResult::allowedIfHasPermission($account, 'access user contact forms'));
|
||||
}
|
||||
|
||||
}
|
39
core/modules/contact/src/ContactFormAccessControlHandler.php
Normal file
39
core/modules/contact/src/ContactFormAccessControlHandler.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\ContactFormAccessControlHandler.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the contact form entity type.
|
||||
*
|
||||
* @see \Drupal\contact\Entity\ContactForm.
|
||||
*/
|
||||
class ContactFormAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
if ($operation == 'view') {
|
||||
// Do not allow access personal form via site-wide route.
|
||||
return AccessResult::allowedIf($account->hasPermission('access site-wide contact form') && $entity->id() !== 'personal')->cachePerPermissions();
|
||||
}
|
||||
elseif ($operation == 'delete' || $operation == 'update') {
|
||||
// Do not allow the 'personal' form to be deleted, as it's used for
|
||||
// the personal contact form.
|
||||
return AccessResult::allowedIf($account->hasPermission('administer contact forms') && $entity->id() !== 'personal')->cachePerPermissions();
|
||||
}
|
||||
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account);
|
||||
}
|
||||
|
||||
}
|
164
core/modules/contact/src/ContactFormEditForm.php
Normal file
164
core/modules/contact/src/ContactFormEditForm.php
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\ContactFormEditForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\Entity\EntityForm;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Form\ConfigFormBaseTrait;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
|
||||
/**
|
||||
* Base form for contact form edit forms.
|
||||
*/
|
||||
class ContactFormEditForm extends EntityForm implements ContainerInjectionInterface {
|
||||
use ConfigFormBaseTrait;
|
||||
|
||||
/**
|
||||
* The email validator.
|
||||
*
|
||||
* @var \Egulias\EmailValidator\EmailValidator
|
||||
*/
|
||||
protected $emailValidator;
|
||||
|
||||
/**
|
||||
* Constructs a new ContactFormEditForm.
|
||||
*
|
||||
* @param \Egulias\EmailValidator\EmailValidator $email_validator
|
||||
* The email validator.
|
||||
*/
|
||||
public function __construct(EmailValidator $email_validator) {
|
||||
$this->emailValidator = $email_validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('email.validator')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEditableConfigNames() {
|
||||
return ['contact.settings'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::form($form, $form_state);
|
||||
|
||||
$contact_form = $this->entity;
|
||||
$default_form = $this->config('contact.settings')->get('default_form');
|
||||
|
||||
$form['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Label'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $contact_form->label(),
|
||||
'#description' => $this->t("Example: 'website feedback' or 'product information'."),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['id'] = array(
|
||||
'#type' => 'machine_name',
|
||||
'#default_value' => $contact_form->id(),
|
||||
'#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
|
||||
'#machine_name' => array(
|
||||
'exists' => '\Drupal\contact\Entity\ContactForm::load',
|
||||
),
|
||||
'#disabled' => !$contact_form->isNew(),
|
||||
);
|
||||
$form['recipients'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Recipients'),
|
||||
'#default_value' => implode(', ', $contact_form->getRecipients()),
|
||||
'#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,
|
||||
);
|
||||
$form['reply'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Auto-reply'),
|
||||
'#default_value' => $contact_form->getReply(),
|
||||
'#description' => $this->t('Optional auto-reply. Leave empty if you do not want to send the user an auto-reply message.'),
|
||||
);
|
||||
$form['weight'] = array(
|
||||
'#type' => 'weight',
|
||||
'#title' => $this->t('Weight'),
|
||||
'#default_value' => $contact_form->getWeight(),
|
||||
'#description' => $this->t('When listing forms, those with lighter (smaller) weights get listed before forms with heavier (larger) weights. Forms with equal weights are sorted alphabetically.'),
|
||||
);
|
||||
$form['selected'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Make this the default form'),
|
||||
'#default_value' => $default_form === $contact_form->id(),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate(array $form, FormStateInterface $form_state) {
|
||||
parent::validate($form, $form_state);
|
||||
|
||||
// Validate and each email recipient.
|
||||
$recipients = explode(',', $form_state->getValue('recipients'));
|
||||
|
||||
foreach ($recipients as &$recipient) {
|
||||
$recipient = trim($recipient);
|
||||
if (!$this->emailValidator->isValid($recipient)) {
|
||||
$form_state->setErrorByName('recipients', $this->t('%recipient is an invalid email address.', array('%recipient' => $recipient)));
|
||||
}
|
||||
}
|
||||
$form_state->setValue('recipients', $recipients);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
$contact_form = $this->entity;
|
||||
$status = $contact_form->save();
|
||||
$contact_settings = $this->config('contact.settings');
|
||||
|
||||
$edit_link = $this->entity->link($this->t('Edit'));
|
||||
if ($status == SAVED_UPDATED) {
|
||||
drupal_set_message($this->t('Contact form %label has been updated.', array('%label' => $contact_form->label())));
|
||||
$this->logger('contact')->notice('Contact form %label has been updated.', array('%label' => $contact_form->label(), 'link' => $edit_link));
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('Contact form %label has been added.', array('%label' => $contact_form->label())));
|
||||
$this->logger('contact')->notice('Contact form %label has been added.', array('%label' => $contact_form->label(), 'link' => $edit_link));
|
||||
}
|
||||
|
||||
// Update the default form.
|
||||
if ($form_state->getValue('selected')) {
|
||||
$contact_settings
|
||||
->set('default_form', $contact_form->id())
|
||||
->save();
|
||||
}
|
||||
// If it was the default form, empty out the setting.
|
||||
elseif ($contact_settings->get('default_form') == $contact_form->id()) {
|
||||
$contact_settings
|
||||
->set('default_form', NULL)
|
||||
->save();
|
||||
}
|
||||
|
||||
$form_state->setRedirectUrl($contact_form->urlInfo('collection'));
|
||||
}
|
||||
|
||||
}
|
71
core/modules/contact/src/ContactFormInterface.php
Normal file
71
core/modules/contact/src/ContactFormInterface.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\ContactFormInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a contact form entity.
|
||||
*/
|
||||
interface ContactFormInterface extends ConfigEntityInterface {
|
||||
|
||||
/**
|
||||
* Returns list of recipient e-mail addresses.
|
||||
*
|
||||
* @return array
|
||||
* List of recipient e-mail addresses.
|
||||
*/
|
||||
public function getRecipients();
|
||||
|
||||
/**
|
||||
* Returns an auto-reply message to send to the message author.
|
||||
*
|
||||
* @return string
|
||||
* An auto-reply message
|
||||
*/
|
||||
public function getReply();
|
||||
|
||||
/**
|
||||
* Returns the weight of this category (used for sorting).
|
||||
*
|
||||
* @return int
|
||||
* The weight of this category.
|
||||
*/
|
||||
public function getWeight();
|
||||
|
||||
/**
|
||||
* Sets list of recipient e-mail addresses.
|
||||
*
|
||||
* @param array $recipients
|
||||
* The desired list of e-mail addresses of this category.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRecipients($recipients);
|
||||
|
||||
/**
|
||||
* Sets an auto-reply message to send to the message author.
|
||||
*
|
||||
* @param string $reply
|
||||
* The desired reply.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setReply($reply);
|
||||
|
||||
/**
|
||||
* Sets the weight.
|
||||
*
|
||||
* @param int $weight
|
||||
* The desired weight.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWeight($weight);
|
||||
|
||||
}
|
49
core/modules/contact/src/ContactFormListBuilder.php
Normal file
49
core/modules/contact/src/ContactFormListBuilder.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\ContactFormListBuilder.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of contact form entities.
|
||||
*
|
||||
* @see \Drupal\contact\Entity\ContactForm
|
||||
*/
|
||||
class ContactFormListBuilder extends ConfigEntityListBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildHeader() {
|
||||
$header['form'] = t('Form');
|
||||
$header['recipients'] = t('Recipients');
|
||||
$header['selected'] = t('Selected');
|
||||
return $header + parent::buildHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildRow(EntityInterface $entity) {
|
||||
$row['form'] = $this->getLabel($entity);
|
||||
// Special case the personal form.
|
||||
if ($entity->id() == 'personal') {
|
||||
$row['recipients'] = t('Selected user');
|
||||
$row['selected'] = t('No');
|
||||
}
|
||||
else {
|
||||
$row['recipients'] = SafeMarkup::checkPlain(implode(', ', $entity->getRecipients()));
|
||||
$default_form = \Drupal::config('contact.settings')->get('default_form');
|
||||
$row['selected'] = ($default_form == $entity->id() ? t('Yes') : t('No'));
|
||||
}
|
||||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\ContactMessageAccessControlHandler.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the message form entity type.
|
||||
*
|
||||
* @see \Drupal\contact\Entity\Message.
|
||||
*/
|
||||
class ContactMessageAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
|
||||
return AccessResult::allowedIfHasPermission($account, 'access site-wide contact form');
|
||||
}
|
||||
}
|
126
core/modules/contact/src/Controller/ContactController.php
Normal file
126
core/modules/contact/src/Controller/ContactController.php
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Controller\ContactController.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\contact\ContactFormInterface;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Controller routines for contact routes.
|
||||
*/
|
||||
class ContactController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* Constructs a ContactController object.
|
||||
*
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer.
|
||||
*/
|
||||
public function __construct(RendererInterface $renderer) {
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('renderer')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the site-wide contact form.
|
||||
*
|
||||
* @param \Drupal\contact\ContactFormInterface $contact_form
|
||||
* The contact form to use.
|
||||
*
|
||||
* @return array
|
||||
* The form as render array as expected by drupal_render().
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
* Exception is thrown when user tries to access non existing default
|
||||
* contact form.
|
||||
*/
|
||||
public function contactSitePage(ContactFormInterface $contact_form = NULL) {
|
||||
$config = $this->config('contact.settings');
|
||||
|
||||
// Use the default form if no form has been passed.
|
||||
if (empty($contact_form)) {
|
||||
$contact_form = $this->entityManager()
|
||||
->getStorage('contact_form')
|
||||
->load($config->get('default_form'));
|
||||
// If there are no forms, do not display the form.
|
||||
if (empty($contact_form)) {
|
||||
if ($this->currentUser()->hasPermission('administer contact forms')) {
|
||||
drupal_set_message($this->t('The contact form has not been configured. <a href="@add">Add one or more forms</a> .', array(
|
||||
'@add' => $this->url('contact.form_add'))), 'error');
|
||||
return array();
|
||||
}
|
||||
else {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message = $this->entityManager()
|
||||
->getStorage('contact_message')
|
||||
->create(array(
|
||||
'contact_form' => $contact_form->id(),
|
||||
));
|
||||
|
||||
$form = $this->entityFormBuilder()->getForm($message);
|
||||
$form['#title'] = SafeMarkup::checkPlain($contact_form->label());
|
||||
$form['#cache']['contexts'][] = 'user.permissions';
|
||||
$this->renderer->addCacheableDependency($form, $config);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form constructor for the personal contact form.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* The account for which a personal contact form should be generated.
|
||||
*
|
||||
* @return array
|
||||
* The personal contact form as render array as expected by drupal_render().
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
* Exception is thrown when user tries to access a contact form for a
|
||||
* user who does not have an e-mail address configured.
|
||||
*/
|
||||
public function contactPersonalPage(UserInterface $user) {
|
||||
// Do not continue if the user does not have an e-mail address configured.
|
||||
if (!$user->getEmail()) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$message = $this->entityManager()->getStorage('contact_message')->create(array(
|
||||
'contact_form' => 'personal',
|
||||
'recipient' => $user->id(),
|
||||
));
|
||||
|
||||
$form = $this->entityFormBuilder()->getForm($message);
|
||||
$form['#title'] = $this->t('Contact @username', array('@username' => $user->getUsername()));
|
||||
$form['#cache']['contexts'][] = 'user.permissions';
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
131
core/modules/contact/src/Entity/ContactForm.php
Normal file
131
core/modules/contact/src/Entity/ContactForm.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Entity\ContactForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
|
||||
use Drupal\contact\ContactFormInterface;
|
||||
|
||||
/**
|
||||
* Defines the contact form entity.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "contact_form",
|
||||
* label = @Translation("Contact form"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\contact\ContactFormAccessControlHandler",
|
||||
* "list_builder" = "Drupal\contact\ContactFormListBuilder",
|
||||
* "form" = {
|
||||
* "add" = "Drupal\contact\ContactFormEditForm",
|
||||
* "edit" = "Drupal\contact\ContactFormEditForm",
|
||||
* "delete" = "Drupal\Core\Entity\EntityDeleteForm"
|
||||
* }
|
||||
* },
|
||||
* config_prefix = "form",
|
||||
* admin_permission = "administer contact forms",
|
||||
* bundle_of = "contact_message",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "label"
|
||||
* },
|
||||
* links = {
|
||||
* "delete-form" = "/admin/structure/contact/manage/{contact_form}/delete",
|
||||
* "edit-form" = "/admin/structure/contact/manage/{contact_form}",
|
||||
* "collection" = "/admin/structure/contact",
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "label",
|
||||
* "recipients",
|
||||
* "reply",
|
||||
* "weight",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class ContactForm extends ConfigEntityBundleBase implements ContactFormInterface {
|
||||
|
||||
/**
|
||||
* The form ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The human-readable label of the category.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* List of recipient email addresses.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $recipients = array();
|
||||
|
||||
/**
|
||||
* An auto-reply message.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $reply = '';
|
||||
|
||||
/**
|
||||
* The weight of the category.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $weight = 0;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRecipients() {
|
||||
return $this->recipients;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRecipients($recipients) {
|
||||
$this->recipients = $recipients;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReply() {
|
||||
return $this->reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setReply($reply) {
|
||||
$this->reply = $reply;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWeight() {
|
||||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setWeight($weight) {
|
||||
$this->weight = $weight;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
206
core/modules/contact/src/Entity/Message.php
Normal file
206
core/modules/contact/src/Entity/Message.php
Normal file
|
@ -0,0 +1,206 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Entity\Message.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\contact\MessageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines the contact message entity.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "contact_message",
|
||||
* label = @Translation("Contact message"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\contact\ContactMessageAccessControlHandler",
|
||||
* "storage" = "Drupal\Core\Entity\ContentEntityNullStorage",
|
||||
* "view_builder" = "Drupal\contact\MessageViewBuilder",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\contact\MessageForm"
|
||||
* }
|
||||
* },
|
||||
* admin_permission = "administer contact forms",
|
||||
* entity_keys = {
|
||||
* "bundle" = "contact_form",
|
||||
* "uuid" = "uuid"
|
||||
* },
|
||||
* bundle_entity_type = "contact_form",
|
||||
* field_ui_base_route = "entity.contact_form.edit_form",
|
||||
* )
|
||||
*/
|
||||
class Message extends ContentEntityBase implements MessageInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isPersonal() {
|
||||
return $this->bundle() == 'personal';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContactForm() {
|
||||
return $this->get('contact_form')->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSenderName() {
|
||||
return $this->get('name')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSenderName($sender_name) {
|
||||
$this->set('name', $sender_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSenderMail() {
|
||||
return $this->get('mail')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSenderMail($sender_mail) {
|
||||
$this->set('mail', $sender_mail);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSubject() {
|
||||
return $this->get('subject')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSubject($subject) {
|
||||
$this->set('subject', $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMessage() {
|
||||
return $this->get('message')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMessage($message) {
|
||||
$this->set('message', $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function copySender() {
|
||||
return (bool)$this->get('copy')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCopySender($inform) {
|
||||
$this->set('copy', (bool) $inform);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPersonalRecipient() {
|
||||
if ($this->isPersonal()) {
|
||||
return $this->get('recipient')->entity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields['contact_form'] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('Form ID'))
|
||||
->setDescription(t('The ID of the associated form.'))
|
||||
->setSetting('target_type', 'contact_form')
|
||||
->setRequired(TRUE);
|
||||
|
||||
$fields['uuid'] = BaseFieldDefinition::create('uuid')
|
||||
->setLabel(t('UUID'))
|
||||
->setDescription(t('The message UUID.'))
|
||||
->setReadOnly(TRUE);
|
||||
|
||||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The message language code.'))
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'language_select',
|
||||
'weight' => 2,
|
||||
));
|
||||
|
||||
$fields['name'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t("The sender's name"))
|
||||
->setDescription(t('The name of the person that is sending the contact message.'));
|
||||
|
||||
$fields['mail'] = BaseFieldDefinition::create('email')
|
||||
->setLabel(t("The sender's email"))
|
||||
->setDescription(t('The email of the person that is sending the contact message.'));
|
||||
|
||||
// The subject of the contact message.
|
||||
$fields['subject'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Subject'))
|
||||
->setRequired(TRUE)
|
||||
->setSetting('max_length', 100)
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'string_textfield',
|
||||
'weight' => -10,
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
|
||||
// The text of the contact message.
|
||||
$fields['message'] = BaseFieldDefinition::create('string_long')
|
||||
->setLabel(t('Message'))
|
||||
->setRequired(TRUE)
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'string_textarea',
|
||||
'weight' => 0,
|
||||
'settings' => array(
|
||||
'rows' => 12,
|
||||
),
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'string',
|
||||
'weight' => 0,
|
||||
'label' => 'above',
|
||||
))
|
||||
->setDisplayConfigurable('view', TRUE);
|
||||
|
||||
$fields['copy'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Copy'))
|
||||
->setDescription(t('Whether to send a copy of the message to the sender.'));
|
||||
|
||||
$fields['recipient'] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('Recipient ID'))
|
||||
->setDescription(t('The ID of the recipient user for personal contact messages.'))
|
||||
->setSetting('target_type', 'user');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
149
core/modules/contact/src/MailHandler.php
Normal file
149
core/modules/contact/src/MailHandler.php
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\MailHandler.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Mail\MailManagerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Provides a class for handling assembly and dispatch of contact mail messages.
|
||||
*/
|
||||
class MailHandler implements MailHandlerInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Language manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* Logger service.
|
||||
*
|
||||
* @var \Drupal\Core\Logger\LoggerChannelInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Mail manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Mail\MailManagerInterface
|
||||
*/
|
||||
protected $mailManager;
|
||||
|
||||
/**
|
||||
* The user entity storage handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $userStorage;
|
||||
|
||||
/**
|
||||
* Constructs a new \Drupal\contact\MailHandler object.
|
||||
*
|
||||
* @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
|
||||
* Mail manager service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* Language manager service.
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* A logger instance.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* String translation service.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* Entity manager service.
|
||||
*/
|
||||
public function __construct(MailManagerInterface $mail_manager, LanguageManagerInterface $language_manager, LoggerInterface $logger, TranslationInterface $string_translation, EntityManagerInterface $entity_manager) {
|
||||
$this->languageManager = $language_manager;
|
||||
$this->mailManager = $mail_manager;
|
||||
$this->logger = $logger;
|
||||
$this->stringTranslation = $string_translation;
|
||||
$this->userStorage = $entity_manager->getStorage('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sendMailMessages(MessageInterface $message, AccountInterface $sender) {
|
||||
// Clone the sender, as we make changes to mail and name properties.
|
||||
$sender_cloned = clone $this->userStorage->load($sender->id());
|
||||
$params = array();
|
||||
$current_langcode = $this->languageManager->getCurrentLanguage()->getId();
|
||||
$recipient_langcode = $this->languageManager->getDefaultLanguage()->getId();
|
||||
$contact_form = $message->getContactForm();
|
||||
|
||||
if ($sender_cloned->isAnonymous()) {
|
||||
// At this point, $sender contains an anonymous user, so we need to take
|
||||
// over the submitted form values.
|
||||
$sender_cloned->name = $message->getSenderName();
|
||||
$sender_cloned->mail = $message->getSenderMail();
|
||||
|
||||
// For the email message, clarify that the sender name is not verified; it
|
||||
// could potentially clash with a username on this site.
|
||||
$sender_cloned->name = $this->t('!name (not verified)', array('!name' => $message->getSenderName()));
|
||||
}
|
||||
|
||||
// Build email parameters.
|
||||
$params['contact_message'] = $message;
|
||||
$params['sender'] = $sender_cloned;
|
||||
|
||||
if (!$message->isPersonal()) {
|
||||
// Send to the form recipient(s), using the site's default language.
|
||||
$params['contact_form'] = $contact_form;
|
||||
|
||||
$to = implode(', ', $contact_form->getRecipients());
|
||||
}
|
||||
elseif ($recipient = $message->getPersonalRecipient()) {
|
||||
// Send to the user in the user's preferred language.
|
||||
$to = $recipient->getEmail();
|
||||
$recipient_langcode = $recipient->getPreferredLangcode();
|
||||
$params['recipient'] = $recipient;
|
||||
}
|
||||
else {
|
||||
throw new MailHandlerException('Unable to determine message recipient');
|
||||
}
|
||||
|
||||
// Send email to the recipient(s).
|
||||
$key_prefix = $message->isPersonal() ? 'user' : 'page';
|
||||
$this->mailManager->mail('contact', $key_prefix . '_mail', $to, $recipient_langcode, $params, $sender_cloned->getEmail());
|
||||
|
||||
// If requested, send a copy to the user, using the current language.
|
||||
if ($message->copySender()) {
|
||||
$this->mailManager->mail('contact', $key_prefix . '_copy', $sender_cloned->getEmail(), $current_langcode, $params, $sender_cloned->getEmail());
|
||||
}
|
||||
|
||||
// If configured, send an auto-reply, using the current language.
|
||||
if (!$message->isPersonal() && $contact_form->getReply()) {
|
||||
// User contact forms do not support an auto-reply message, so this
|
||||
// message always originates from the site.
|
||||
$this->mailManager->mail('contact', 'page_autoreply', $sender_cloned->getEmail(), $current_langcode, $params);
|
||||
}
|
||||
|
||||
if (!$message->isPersonal()) {
|
||||
$this->logger->notice('%sender-name (@sender-from) sent an email regarding %contact_form.', array(
|
||||
'%sender-name' => $sender_cloned->getUsername(),
|
||||
'@sender-from' => $sender_cloned->getEmail(),
|
||||
'%contact_form' => $contact_form->label(),
|
||||
));
|
||||
}
|
||||
else {
|
||||
$this->logger->notice('%sender-name (@sender-from) sent %recipient-name an email.', array(
|
||||
'%sender-name' => $sender_cloned->getUsername(),
|
||||
'@sender-from' => $sender_cloned->getEmail(),
|
||||
'%recipient-name' => $message->getPersonalRecipient()->getUsername(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
13
core/modules/contact/src/MailHandlerException.php
Normal file
13
core/modules/contact/src/MailHandlerException.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\MailHandlerException.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
/**
|
||||
* Exception thrown by MailHandler when unable to determine message recipient.
|
||||
*/
|
||||
class MailHandlerException extends \RuntimeException {}
|
35
core/modules/contact/src/MailHandlerInterface.php
Normal file
35
core/modules/contact/src/MailHandlerInterface.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\MailHandlerInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for assembly and dispatch of contact mail messages.
|
||||
*/
|
||||
interface MailHandlerInterface {
|
||||
|
||||
/**
|
||||
* Sends mail messages as appropriate for a given Message form submission.
|
||||
*
|
||||
* Can potentially send up to three messages as follows:
|
||||
* - To the configured recipient;
|
||||
* - Auto-reply to the sender; and
|
||||
* - Carbon copy to the sender.
|
||||
*
|
||||
* @param \Drupal\contact\MessageInterface $message
|
||||
* Submitted message entity.
|
||||
* @param \Drupal\Core\Session\AccountInterface $sender
|
||||
* User that submitted the message entity form.
|
||||
*
|
||||
* @throws \Drupal\contact\MailHandlerException
|
||||
* When unable to determine message recipient.
|
||||
*/
|
||||
public function sendMailMessages(MessageInterface $message, AccountInterface $sender);
|
||||
|
||||
}
|
250
core/modules/contact/src/MessageForm.php
Normal file
250
core/modules/contact/src/MessageForm.php
Normal file
|
@ -0,0 +1,250 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\MessageForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Flood\FloodInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Form controller for contact message forms.
|
||||
*/
|
||||
class MessageForm extends ContentEntityForm {
|
||||
|
||||
/**
|
||||
* The message being used by this form.
|
||||
*
|
||||
* @var \Drupal\contact\MessageInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The flood control mechanism.
|
||||
*
|
||||
* @var \Drupal\Core\Flood\FloodInterface
|
||||
*/
|
||||
protected $flood;
|
||||
|
||||
/**
|
||||
* The language manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The contact mail handler service.
|
||||
*
|
||||
* @var \Drupal\contact\MailHandlerInterface
|
||||
*/
|
||||
protected $mailHandler;
|
||||
|
||||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* Constructs a MessageForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Flood\FloodInterface $flood
|
||||
* The flood control mechanism.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager service.
|
||||
* @param \Drupal\contact\MailHandlerInterface $mail_handler
|
||||
* The contact mail handler service.
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* The date service.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, FloodInterface $flood, LanguageManagerInterface $language_manager, MailHandlerInterface $mail_handler, DateFormatter $date_formatter) {
|
||||
parent::__construct($entity_manager);
|
||||
$this->flood = $flood;
|
||||
$this->languageManager = $language_manager;
|
||||
$this->mailHandler = $mail_handler;
|
||||
$this->dateFormatter = $date_formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('flood'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('contact.mail_handler'),
|
||||
$container->get('date.formatter')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$user = $this->currentUser();
|
||||
$message = $this->entity;
|
||||
$form = parent::form($form, $form_state, $message);
|
||||
$form['#attributes']['class'][] = 'contact-form';
|
||||
|
||||
if (!empty($message->preview)) {
|
||||
$form['preview'] = array(
|
||||
'#theme_wrappers' => array('container__preview'),
|
||||
'#attributes' => array('class' => array('preview')),
|
||||
);
|
||||
$form['preview']['message'] = $this->entityManager->getViewBuilder('contact_message')->view($message, 'full');
|
||||
}
|
||||
|
||||
$form['name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Your name'),
|
||||
'#maxlength' => 255,
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['mail'] = array(
|
||||
'#type' => 'email',
|
||||
'#title' => $this->t('Your email address'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
if ($user->isAnonymous()) {
|
||||
$form['#attached']['library'][] = 'core/drupal.form';
|
||||
$form['#attributes']['data-user-info-from-browser'] = TRUE;
|
||||
}
|
||||
// Do not allow authenticated users to alter the name or email values to
|
||||
// prevent the impersonation of other users.
|
||||
else {
|
||||
$form['name']['#type'] = 'item';
|
||||
$form['name']['#value'] = $user->getUsername();
|
||||
$form['name']['#required'] = FALSE;
|
||||
$form['name']['#markup'] = SafeMarkup::checkPlain($user->getUsername());
|
||||
|
||||
$form['mail']['#type'] = 'item';
|
||||
$form['mail']['#value'] = $user->getEmail();
|
||||
$form['mail']['#required'] = FALSE;
|
||||
$form['mail']['#markup'] = SafeMarkup::checkPlain($user->getEmail());
|
||||
}
|
||||
|
||||
// The user contact form has a preset recipient.
|
||||
if ($message->isPersonal()) {
|
||||
$form['recipient'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => $this->t('To'),
|
||||
'#value' => $message->getPersonalRecipient()->id(),
|
||||
'name' => array(
|
||||
'#theme' => 'username',
|
||||
'#account' => $message->getPersonalRecipient(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$form['copy'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Send yourself a copy'),
|
||||
// Do not allow anonymous users to send themselves a copy, because it can
|
||||
// be abused to spam people.
|
||||
'#access' => $user->isAuthenticated(),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function actions(array $form, FormStateInterface $form_state) {
|
||||
$elements = parent::actions($form, $form_state);
|
||||
$elements['submit']['#value'] = $this->t('Send message');
|
||||
$elements['preview'] = array(
|
||||
'#value' => $this->t('Preview'),
|
||||
'#validate' => array('::validate'),
|
||||
'#submit' => array('::submitForm', '::preview'),
|
||||
);
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for the 'preview' action.
|
||||
*/
|
||||
public function preview(array $form, FormStateInterface $form_state) {
|
||||
$message = $this->entity;
|
||||
$message->preview = TRUE;
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate(array $form, FormStateInterface $form_state) {
|
||||
parent::validate($form, $form_state);
|
||||
|
||||
$message = $this->entity;
|
||||
|
||||
// Check if flood control has been activated for sending emails.
|
||||
if (!$this->currentUser()->hasPermission('administer contact forms') && (!$message->isPersonal() || !$this->currentUser()->hasPermission('administer users'))) {
|
||||
$limit = $this->config('contact.settings')->get('flood.limit');
|
||||
$interval = $this->config('contact.settings')->get('flood.interval');
|
||||
|
||||
if (!$this->flood->isAllowed('contact', $limit, $interval)) {
|
||||
$form_state->setErrorByName('', $this->t('You cannot send more than %limit messages in @interval. Try again later.', array(
|
||||
'%limit' => $limit,
|
||||
'@interval' => $this->dateFormatter->formatInterval($interval),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
$message = $this->entity;
|
||||
$user = $this->currentUser();
|
||||
$this->mailHandler->sendMailMessages($message, $user);
|
||||
|
||||
$this->flood->register('contact', $this->config('contact.settings')->get('flood.interval'));
|
||||
drupal_set_message($this->t('Your message has been sent.'));
|
||||
|
||||
// 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.
|
||||
if ($message->isPersonal() && $user->hasPermission('access user profiles')) {
|
||||
$form_state->setRedirectUrl($message->getPersonalRecipient()->urlInfo());
|
||||
}
|
||||
else {
|
||||
$form_state->setRedirect('<front>');
|
||||
}
|
||||
// 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
|
||||
// storage controller straight-forward.
|
||||
$message->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function init(FormStateInterface $form_state) {
|
||||
$message = $this->entity;
|
||||
|
||||
// Make the message inherit the current content language unless specifically
|
||||
// set.
|
||||
if ($message->isNew() && !$message->langcode->value) {
|
||||
$language_content = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
|
||||
$message->langcode->value = $language_content->getId();
|
||||
}
|
||||
|
||||
parent::init($form_state);
|
||||
}
|
||||
|
||||
}
|
121
core/modules/contact/src/MessageInterface.php
Normal file
121
core/modules/contact/src/MessageInterface.php
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\MessageInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a contact message entity.
|
||||
*/
|
||||
interface MessageInterface extends ContentEntityInterface {
|
||||
|
||||
/**
|
||||
* Returns the form this contact message belongs to.
|
||||
*
|
||||
* @return \Drupal\contact\ContactFormInterface
|
||||
* The contact form entity.
|
||||
*/
|
||||
public function getContactForm();
|
||||
|
||||
/**
|
||||
* Returns the name of the sender.
|
||||
*
|
||||
* @return string
|
||||
* The name of the message sender.
|
||||
*/
|
||||
public function getSenderName();
|
||||
|
||||
/**
|
||||
* Sets the name of the message sender.
|
||||
*
|
||||
* @param string $sender_name
|
||||
* The name of the message sender.
|
||||
*/
|
||||
public function setSenderName($sender_name);
|
||||
|
||||
/**
|
||||
* Returns the email address of the sender.
|
||||
*
|
||||
* @return string
|
||||
* The email address of the message sender.
|
||||
*/
|
||||
public function getSenderMail();
|
||||
|
||||
/**
|
||||
* Sets the email address of the sender.
|
||||
*
|
||||
* @param string $sender_mail
|
||||
* The email address of the message sender.
|
||||
*/
|
||||
public function setSenderMail($sender_mail);
|
||||
|
||||
/**
|
||||
* Returns the message subject.
|
||||
*
|
||||
* @return string
|
||||
* The message subject.
|
||||
*/
|
||||
public function getSubject();
|
||||
|
||||
/**
|
||||
* Sets the subject for the email.
|
||||
*
|
||||
* @param string $subject
|
||||
* The message subject.
|
||||
*/
|
||||
public function setSubject($subject);
|
||||
|
||||
/**
|
||||
* Returns the message body.
|
||||
*
|
||||
* @return string
|
||||
* The message body.
|
||||
*/
|
||||
public function getMessage();
|
||||
|
||||
/**
|
||||
* Sets the email message to send.
|
||||
*
|
||||
* @param string $message
|
||||
* The message body.
|
||||
*/
|
||||
public function setMessage($message);
|
||||
|
||||
/**
|
||||
* Returns TRUE if a copy should be sent to the sender.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if a copy should be sent, FALSE if not.
|
||||
*/
|
||||
public function copySender();
|
||||
|
||||
/**
|
||||
* Sets if the sender should receive a copy of this email or not.
|
||||
*
|
||||
* @param bool $inform
|
||||
* TRUE if a copy should be sent, FALSE if not.
|
||||
*/
|
||||
public function setCopySender($inform);
|
||||
|
||||
/**
|
||||
* Returns TRUE if this is the personal contact form.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the message bundle is personal.
|
||||
*/
|
||||
public function isPersonal();
|
||||
|
||||
/**
|
||||
* Returns the user this message is being sent to.
|
||||
*
|
||||
* @return \Drupal\user\UserInterface
|
||||
* The user entity of the recipient, NULL if this is not a personal message.
|
||||
*/
|
||||
public function getPersonalRecipient();
|
||||
|
||||
}
|
75
core/modules/contact/src/MessageViewBuilder.php
Normal file
75
core/modules/contact/src/MessageViewBuilder.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\MessageViewBuilder.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Mail\MailFormatHelper;
|
||||
use Drupal\Core\Render\Element;
|
||||
|
||||
/**
|
||||
* Render controller for contact messages.
|
||||
*/
|
||||
class MessageViewBuilder extends EntityViewBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) {
|
||||
$build = parent::getBuildDefaults($entity, $view_mode, $langcode);
|
||||
// The message fields are individually rendered into email templates, so
|
||||
// the entity has no template itself.
|
||||
unset($build['#theme']);
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) {
|
||||
parent::buildComponents($build, $entities, $displays, $view_mode, $langcode);
|
||||
|
||||
foreach ($entities as $id => $entity) {
|
||||
// Add the message extra field, if enabled.
|
||||
$display = $displays[$entity->bundle()];
|
||||
if ($entity->getMessage() && $display->getComponent('message')) {
|
||||
$build[$id]['message'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Message'),
|
||||
'#markup' => SafeMarkup::checkPlain($entity->getMessage()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
|
||||
$build = parent::view($entity, $view_mode, $langcode);
|
||||
|
||||
if ($view_mode == 'mail') {
|
||||
// Convert field labels into headings.
|
||||
// @todo Improve \Drupal\Core\Mail\MailFormatHelper::htmlToText() to
|
||||
// convert DIVs correctly.
|
||||
foreach (Element::children($build) as $key) {
|
||||
if (isset($build[$key]['#label_display']) && $build[$key]['#label_display'] == 'above') {
|
||||
$build[$key] += array('#prefix' => '');
|
||||
$build[$key]['#prefix'] = $build[$key]['#title'] . ":\n";
|
||||
$build[$key]['#label_display'] = 'hidden';
|
||||
}
|
||||
}
|
||||
$build['#post_render'][] = function ($html, array $elements) {
|
||||
return MailFormatHelper::htmlToText($html);
|
||||
};
|
||||
}
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
69
core/modules/contact/src/Plugin/views/field/ContactLink.php
Normal file
69
core/modules/contact/src/Plugin/views/field/ContactLink.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Plugin\views\field\ContactLink.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Plugin\views\field;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\views\Plugin\views\field\LinkBase;
|
||||
use Drupal\views\ResultRow;
|
||||
|
||||
/**
|
||||
* Defines a field that links to the user contact page, if access is permitted.
|
||||
*
|
||||
* @ingroup views_field_handlers
|
||||
*
|
||||
* @ViewsField("contact_link")
|
||||
*/
|
||||
class ContactLink extends LinkBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
$form['text']['#title'] = $this->t('Link label');
|
||||
$form['text']['#required'] = TRUE;
|
||||
$form['text']['#default_value'] = empty($this->options['text']) ? $this->getDefaultLabel() : $this->options['text'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getUrlInfo(ResultRow $row) {
|
||||
return Url::fromRoute('entity.user.contact_form', ['user' => $this->getEntity($row)->id()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function renderLink(ResultRow $row) {
|
||||
$entity = $this->getEntity($row);
|
||||
|
||||
$this->options['alter']['make_link'] = TRUE;
|
||||
$this->options['alter']['url'] = $this->getUrlInfo($row);
|
||||
|
||||
$title = $this->t('Contact %user', array('%user' => $entity->label()));
|
||||
$this->options['alter']['attributes'] = array('title' => $title);
|
||||
|
||||
if (!empty($this->options['text'])) {
|
||||
return $this->options['text'];
|
||||
}
|
||||
else {
|
||||
return $title;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDefaultLabel() {
|
||||
return $this->t('contact');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\ContactAuthenticatedUserTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests contact form textfields are present if authenticated.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactAuthenticatedUserTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('contact');
|
||||
|
||||
/**
|
||||
* Tests that name and email fields are not present for authenticated users.
|
||||
*/
|
||||
function testContactSiteWideTextfieldsLoggedInTestCase() {
|
||||
$this->drupalLogin($this->drupalCreateUser(array('access site-wide contact form')));
|
||||
$this->drupalGet('contact');
|
||||
|
||||
// Ensure that there is no textfield for name.
|
||||
$this->assertFalse($this->xpath('//input[@name=:name]', array(':name' => 'name')));
|
||||
|
||||
// Ensure that there is no textfield for email.
|
||||
$this->assertFalse($this->xpath('//input[@name=:name]', array(':name' => 'mail')));
|
||||
}
|
||||
}
|
319
core/modules/contact/src/Tests/ContactPersonalTest.php
Normal file
319
core/modules/contact/src/Tests/ContactPersonalTest.php
Normal file
|
@ -0,0 +1,319 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\ContactPersonalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests personal contact form functionality.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactPersonalTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('contact', 'dblog');
|
||||
|
||||
/**
|
||||
* A user with some administrative permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
private $adminUser;
|
||||
|
||||
/**
|
||||
* A user with permission to view profiles and access user contact forms.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
private $webUser;
|
||||
|
||||
/**
|
||||
* A user without any permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
private $contactUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create an admin user.
|
||||
$this->adminUser = $this->drupalCreateUser(array('administer contact forms', 'administer users', 'administer account settings', 'access site reports'));
|
||||
|
||||
// Create some normal users with their contact forms enabled by default.
|
||||
$this->config('contact.settings')->set('user_default_enabled', TRUE)->save();
|
||||
$this->webUser = $this->drupalCreateUser(array('access user profiles', 'access user contact forms'));
|
||||
$this->contactUser = $this->drupalCreateUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that mails for contact messages are correctly sent.
|
||||
*/
|
||||
function testSendPersonalContactMessage() {
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
$message = $this->submitPersonalContact($this->contactUser);
|
||||
$mails = $this->drupalGetMails();
|
||||
$this->assertEqual(1, count($mails));
|
||||
$mail = $mails[0];
|
||||
$this->assertEqual($mail['to'], $this->contactUser->getEmail());
|
||||
$this->assertEqual($mail['from'], $this->config('system.site')->get('mail'));
|
||||
$this->assertEqual($mail['reply-to'], $this->webUser->getEmail());
|
||||
$this->assertEqual($mail['key'], 'user_mail');
|
||||
$variables = array(
|
||||
'!site-name' => $this->config('system.site')->get('name'),
|
||||
'!subject' => $message['subject[0][value]'],
|
||||
'!recipient-name' => $this->contactUser->getUsername(),
|
||||
);
|
||||
$this->assertEqual($mail['subject'], t('[!site-name] !subject', $variables), 'Subject is in sent message.');
|
||||
$this->assertTrue(strpos($mail['body'], t('Hello !recipient-name,', $variables)) !== FALSE, 'Recipient name is in sent message.');
|
||||
$this->assertTrue(strpos($mail['body'], $this->webUser->getUsername()) !== FALSE, 'Sender name is in sent message.');
|
||||
$this->assertTrue(strpos($mail['body'], $message['message[0][value]']) !== FALSE, 'Message body is in sent message.');
|
||||
|
||||
// Check there was no problems raised during sending.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Verify that the correct watchdog message has been logged.
|
||||
$this->drupalGet('/admin/reports/dblog');
|
||||
$placeholders = array(
|
||||
'@sender_name' => $this->webUser->username,
|
||||
'@sender_email' => $this->webUser->getEmail(),
|
||||
'@recipient_name' => $this->contactUser->getUsername()
|
||||
);
|
||||
$this->assertText(SafeMarkup::format('@sender_name (@sender_email) sent @recipient_name an email.', $placeholders));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access to the personal contact form.
|
||||
*/
|
||||
function testPersonalContactAccess() {
|
||||
// Test allowed access to admin user's contact form.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('user/' . $this->adminUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
// Check the page title is properly displayed.
|
||||
$this->assertRaw(t('Contact @username', array('@username' => $this->adminUser->getUsername())));
|
||||
|
||||
// Test denied access to admin user's own contact form.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('user/' . $this->adminUser->id() . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test allowed access to user with contact form enabled.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test that there is no access to personal contact forms for users
|
||||
// without an email address configured.
|
||||
$original_email = $this->contactUser->getEmail();
|
||||
$this->contactUser->setEmail(FALSE)->save();
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(404, 'Not found (404) returned when visiting a personal contact form for a user with no email address');
|
||||
|
||||
// Test that the 'contact tab' does not appear on the user profiles
|
||||
// for users without an email address configured.
|
||||
$this->drupalGet('user/' . $this->contactUser->id());
|
||||
$contact_link = '/user/' . $this->contactUser->id() . '/contact';
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoLinkByHref ($contact_link, 'The "contact" tab is hidden on profiles for users with no email address');
|
||||
|
||||
// Restore original email address.
|
||||
$this->contactUser->setEmail($original_email)->save();
|
||||
|
||||
// Test denied access to the user's own contact form.
|
||||
$this->drupalGet('user/' . $this->webUser->id() . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test always denied access to the anonymous user contact form.
|
||||
$this->drupalGet('user/0/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test that anonymous users can access the contact form.
|
||||
$this->drupalLogout();
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test that anonymous users can access admin user's contact form.
|
||||
$this->drupalGet('user/' . $this->adminUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
$this->assertCacheContext('user');
|
||||
|
||||
// Revoke the personal contact permission for the anonymous user.
|
||||
user_role_revoke_permissions(RoleInterface::ANONYMOUS_ID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(403);
|
||||
$this->assertCacheContext('user');
|
||||
$this->drupalGet('user/' . $this->adminUser->id() . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Disable the personal contact form.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$edit = array('contact_default_status' => FALSE);
|
||||
$this->drupalPostForm('admin/config/people/accounts', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'), 'Setting successfully saved.');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Re-create our contacted user with personal contact forms disabled by
|
||||
// default.
|
||||
$this->contactUser = $this->drupalCreateUser();
|
||||
|
||||
// Test denied access to a user with contact form disabled.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test allowed access for admin user to a user with contact form disabled.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Re-create our contacted user as a blocked user.
|
||||
$this->contactUser = $this->drupalCreateUser();
|
||||
$this->contactUser->block();
|
||||
$this->contactUser->save();
|
||||
|
||||
// Test that blocked users can still be contacted by admin.
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test that blocked users cannot be contacted by non-admins.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test enabling and disabling the contact page through the user profile
|
||||
// form.
|
||||
$this->drupalGet('user/' . $this->webUser->id() . '/edit');
|
||||
$this->assertNoFieldChecked('edit-contact--2');
|
||||
$this->assertFalse(\Drupal::service('user.data')->get('contact', $this->webUser->id(), 'enabled'), 'Personal contact form disabled');
|
||||
$this->drupalPostForm(NULL, array('contact' => TRUE), t('Save'));
|
||||
$this->assertFieldChecked('edit-contact--2');
|
||||
$this->assertTrue(\Drupal::service('user.data')->get('contact', $this->webUser->id(), 'enabled'), 'Personal contact form enabled');
|
||||
|
||||
// Test with disabled global default contact form in combination with a user
|
||||
// that has the contact form enabled.
|
||||
$this->config('contact.settings')->set('user_default_enabled', FALSE)->save();
|
||||
$this->contactUser = $this->drupalCreateUser();
|
||||
\Drupal::service('user.data')->set('contact', $this->contactUser->id(), 'enabled', 1);
|
||||
|
||||
$this->drupalGet('user/' . $this->contactUser->id() . '/contact');
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the personal contact form flood protection.
|
||||
*/
|
||||
function testPersonalContactFlood() {
|
||||
$flood_limit = 3;
|
||||
$this->config('contact.settings')->set('flood.limit', $flood_limit)->save();
|
||||
|
||||
// Clear flood table in preparation for flood test and allow other checks to complete.
|
||||
db_delete('flood')->execute();
|
||||
$num_records_flood = db_query("SELECT COUNT(*) FROM {flood}")->fetchField();
|
||||
$this->assertIdentical($num_records_flood, '0', 'Flood table emptied.');
|
||||
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Submit contact form with correct values and check flood interval.
|
||||
for ($i = 0; $i < $flood_limit; $i++) {
|
||||
$this->submitPersonalContact($this->contactUser);
|
||||
$this->assertText(t('Your message has been sent.'), 'Message sent.');
|
||||
}
|
||||
|
||||
// Submit contact form one over limit.
|
||||
$this->submitPersonalContact($this->contactUser);
|
||||
$this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => $flood_limit, '@interval' => \Drupal::service('date.formatter')->formatInterval($this->config('contact.settings')->get('flood.interval')))), 'Normal user denied access to flooded contact form.');
|
||||
|
||||
// Test that the admin user can still access the contact form even though
|
||||
// the flood limit was reached.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->assertNoText('Try again later.', 'Admin user not denied access to flooded contact form.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the personal contact form based access when an admin adds users.
|
||||
*/
|
||||
function testAdminContact() {
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access user contact forms'));
|
||||
$this->checkContactAccess(200);
|
||||
$this->checkContactAccess(403, FALSE);
|
||||
$config = $this->config('contact.settings');
|
||||
$config->set('user_default_enabled', FALSE);
|
||||
$config->save();
|
||||
$this->checkContactAccess(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a user and then checks contact form access.
|
||||
*
|
||||
* @param int $response
|
||||
* The expected response code.
|
||||
* @param bool $contact_value
|
||||
* (optional) The value the contact field should be set too.
|
||||
*/
|
||||
protected function checkContactAccess($response, $contact_value = NULL) {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/people/create');
|
||||
if ($this->config('contact.settings')->get('user_default_enabled', TRUE)) {
|
||||
$this->assertFieldChecked('edit-contact--2');
|
||||
}
|
||||
else {
|
||||
$this->assertNoFieldChecked('edit-contact--2');
|
||||
}
|
||||
$name = $this->randomMachineName();
|
||||
$edit = array(
|
||||
'name' => $name,
|
||||
'mail' => $this->randomMachineName() . '@example.com',
|
||||
'pass[pass1]' => $pass = $this->randomString(),
|
||||
'pass[pass2]' => $pass,
|
||||
'notify' => FALSE,
|
||||
);
|
||||
if (isset($contact_value)) {
|
||||
$edit['contact'] = $contact_value;
|
||||
}
|
||||
$this->drupalPostForm('admin/people/create', $edit, t('Create new account'));
|
||||
$user = user_load_by_name($name);
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->drupalGet('user/' . $user->id() . '/contact');
|
||||
$this->assertResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills out a user's personal contact form and submits it.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* A user object of the user being contacted.
|
||||
* @param array $message
|
||||
* (optional) An array with the form fields being used. Defaults to an empty
|
||||
* array.
|
||||
*
|
||||
* @return array
|
||||
* An array with the form fields being used.
|
||||
*/
|
||||
protected function submitPersonalContact(AccountInterface $account, array $message = array()) {
|
||||
$message += array(
|
||||
'subject[0][value]' => $this->randomMachineName(16),
|
||||
'message[0][value]' => $this->randomMachineName(64),
|
||||
);
|
||||
$this->drupalPostForm('user/' . $account->id() . '/contact', $message, t('Send message'));
|
||||
return $message;
|
||||
}
|
||||
|
||||
}
|
435
core/modules/contact/src/Tests/ContactSitewideTest.php
Normal file
435
core/modules/contact/src/Tests/ContactSitewideTest.php
Normal file
|
@ -0,0 +1,435 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\ContactSitewideTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\contact\Entity\ContactForm;
|
||||
use Drupal\Core\Mail\MailFormatHelper;
|
||||
use Drupal\field_ui\Tests\FieldUiTestTrait;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests site-wide contact form functionality.
|
||||
*
|
||||
* @see \Drupal\contact\Tests\ContactStorageTest
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactSitewideTest extends WebTestBase {
|
||||
|
||||
use FieldUiTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('text', 'contact', 'field_ui', 'contact_test', 'block');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests configuration options and the site-wide contact form.
|
||||
*/
|
||||
function testSiteWideContact() {
|
||||
// Create and login administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'access site-wide contact form',
|
||||
'administer contact forms',
|
||||
'administer users',
|
||||
'administer account settings',
|
||||
'administer contact_message fields',
|
||||
));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Check the presence of expected cache tags.
|
||||
$this->drupalGet('contact');
|
||||
$this->assertCacheTag('config:contact.settings');
|
||||
|
||||
$flood_limit = 3;
|
||||
$this->config('contact.settings')
|
||||
->set('flood.limit', $flood_limit)
|
||||
->set('flood.interval', 600)
|
||||
->save();
|
||||
|
||||
// Set settings.
|
||||
$edit = array();
|
||||
$edit['contact_default_status'] = TRUE;
|
||||
$this->drupalPostForm('admin/config/people/accounts', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'));
|
||||
|
||||
$this->drupalGet('admin/structure/contact');
|
||||
// Default form exists.
|
||||
$this->assertLinkByHref('admin/structure/contact/manage/feedback/delete');
|
||||
// User form could not be changed or deleted.
|
||||
// Cannot use ::assertNoLinkByHref as it does partial url matching and with
|
||||
// field_ui enabled admin/structure/contact/manage/personal/fields exists.
|
||||
// @todo: See https://www.drupal.org/node/2031223 for the above.
|
||||
$edit_link = $this->xpath('//a[@href=:href]', array(
|
||||
':href' => \Drupal::url('entity.contact_form.edit_form', array('contact_form' => 'personal'))
|
||||
));
|
||||
$this->assertTrue(empty($edit_link), format_string('No link containing href %href found.',
|
||||
array('%href' => 'admin/structure/contact/manage/personal')
|
||||
));
|
||||
$this->assertNoLinkByHref('admin/structure/contact/manage/personal/delete');
|
||||
|
||||
$this->drupalGet('admin/structure/contact/manage/personal');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Delete old forms to ensure that new forms are used.
|
||||
$this->deleteContactForms();
|
||||
$this->drupalGet('admin/structure/contact');
|
||||
$this->assertText('Personal', 'Personal form was not deleted');
|
||||
$this->assertNoLinkByHref('admin/structure/contact/manage/feedback');
|
||||
|
||||
// Ensure that the contact form won't be shown without forms.
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access site-wide contact form'));
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('contact');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('contact');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText(t('The contact form has not been configured.'));
|
||||
// Test access personal form via site-wide contact page.
|
||||
$this->drupalGet('contact/personal');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Add forms.
|
||||
// Test invalid recipients.
|
||||
$invalid_recipients = array('invalid', 'invalid@', 'invalid@site.', '@site.', '@site.com');
|
||||
foreach ($invalid_recipients as $invalid_recipient) {
|
||||
$this->addContactForm($this->randomMachineName(16), $this->randomMachineName(16), $invalid_recipient, '', FALSE);
|
||||
$this->assertRaw(t('%recipient is an invalid email address.', array('%recipient' => $invalid_recipient)));
|
||||
}
|
||||
|
||||
// Test validation of empty form and recipients fields.
|
||||
$this->addContactForm('', '', '', '', TRUE);
|
||||
$this->assertText(t('Label field is required.'));
|
||||
$this->assertText(t('Machine-readable name field is required.'));
|
||||
$this->assertText(t('Recipients field is required.'));
|
||||
|
||||
// Test validation of max_length machine name.
|
||||
$recipients = array('simpletest@example.com', 'simpletest2@example.com', 'simpletest3@example.com');
|
||||
$max_length = EntityTypeInterface::BUNDLE_MAX_LENGTH;
|
||||
$max_length_exceeded = $max_length + 1;
|
||||
$this->addContactForm($id = Unicode::strtolower($this->randomMachineName($max_length_exceeded)), $label = $this->randomMachineName($max_length_exceeded), implode(',', array($recipients[0])), '', TRUE);
|
||||
$this->assertText(format_string('Machine-readable name cannot be longer than !max characters but is currently !exceeded characters long.', array('!max' => $max_length, '!exceeded' => $max_length_exceeded)));
|
||||
$this->addContactForm($id = Unicode::strtolower($this->randomMachineName($max_length)), $label = $this->randomMachineName($max_length), implode(',', array($recipients[0])), '', TRUE);
|
||||
$this->assertRaw(t('Contact form %label has been added.', array('%label' => $label)));
|
||||
|
||||
// Create first valid form.
|
||||
$this->addContactForm($id = Unicode::strtolower($this->randomMachineName(16)), $label = $this->randomMachineName(16), implode(',', array($recipients[0])), '', TRUE);
|
||||
$this->assertRaw(t('Contact form %label has been added.', array('%label' => $label)));
|
||||
|
||||
// Check that the form was created in site default language.
|
||||
$langcode = $this->config('contact.form.' . $id)->get('langcode');
|
||||
$default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
|
||||
$this->assertEqual($langcode, $default_langcode);
|
||||
|
||||
// Make sure the newly created form is included in the list of forms.
|
||||
$this->assertNoUniqueText($label, 'New form included in forms list.');
|
||||
|
||||
// Test update contact form.
|
||||
$this->updateContactForm($id, $label = $this->randomMachineName(16), $recipients_str = implode(',', array($recipients[0], $recipients[1])), $reply = $this->randomMachineName(30), FALSE);
|
||||
$config = $this->config('contact.form.' . $id)->get();
|
||||
$this->assertEqual($config['label'], $label);
|
||||
$this->assertEqual($config['recipients'], array($recipients[0], $recipients[1]));
|
||||
$this->assertEqual($config['reply'], $reply);
|
||||
$this->assertNotEqual($id, $this->config('contact.settings')->get('default_form'));
|
||||
$this->assertRaw(t('Contact form %label has been updated.', array('%label' => $label)));
|
||||
// Ensure the label is displayed on the contact page for this form.
|
||||
$this->drupalGet('contact/' . $id);
|
||||
$this->assertText($label);
|
||||
|
||||
// Reset the form back to be the default form.
|
||||
$this->config('contact.settings')->set('default_form', $id)->save();
|
||||
|
||||
// Ensure that the contact form is shown without a form selection input.
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access site-wide contact form'));
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('contact');
|
||||
$this->assertText(t('Your email address'));
|
||||
$this->assertNoText(t('Form'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add more forms.
|
||||
$this->addContactForm(Unicode::strtolower($this->randomMachineName(16)), $label = $this->randomMachineName(16), implode(',', array($recipients[0], $recipients[1])), '', FALSE);
|
||||
$this->assertRaw(t('Contact form %label has been added.', array('%label' => $label)));
|
||||
|
||||
$this->addContactForm($name = Unicode::strtolower($this->randomMachineName(16)), $label = $this->randomMachineName(16), implode(',', array($recipients[0], $recipients[1], $recipients[2])), '', FALSE);
|
||||
$this->assertRaw(t('Contact form %label has been added.', array('%label' => $label)));
|
||||
|
||||
// Try adding a form that already exists.
|
||||
$this->addContactForm($name, $label, '', '', FALSE);
|
||||
$this->assertNoRaw(t('Contact form %label has been added.', array('%label' => $label)));
|
||||
$this->assertRaw(t('The machine-readable name is already in use. It must be unique.'));
|
||||
|
||||
// Clear flood table in preparation for flood test and allow other checks to complete.
|
||||
db_delete('flood')->execute();
|
||||
$num_records_after = db_query("SELECT COUNT(*) FROM {flood}")->fetchField();
|
||||
$this->assertIdentical($num_records_after, '0', 'Flood table emptied.');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Check to see that anonymous user cannot see contact page without permission.
|
||||
user_role_revoke_permissions(RoleInterface::ANONYMOUS_ID, array('access site-wide contact form'));
|
||||
$this->drupalGet('contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Give anonymous user permission and see that page is viewable.
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access site-wide contact form'));
|
||||
$this->drupalGet('contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Submit contact form with invalid values.
|
||||
$this->submitContact('', $recipients[0], $this->randomMachineName(16), $id, $this->randomMachineName(64));
|
||||
$this->assertText(t('Your name field is required.'));
|
||||
|
||||
$this->submitContact($this->randomMachineName(16), '', $this->randomMachineName(16), $id, $this->randomMachineName(64));
|
||||
$this->assertText(t('Your email address field is required.'));
|
||||
|
||||
$this->submitContact($this->randomMachineName(16), $invalid_recipients[0], $this->randomMachineName(16), $id, $this->randomMachineName(64));
|
||||
$this->assertRaw(t('The email address %mail is not valid.', array('%mail' => 'invalid')));
|
||||
|
||||
$this->submitContact($this->randomMachineName(16), $recipients[0], '', $id, $this->randomMachineName(64));
|
||||
$this->assertText(t('Subject field is required.'));
|
||||
|
||||
$this->submitContact($this->randomMachineName(16), $recipients[0], $this->randomMachineName(16), $id, '');
|
||||
$this->assertText(t('Message field is required.'));
|
||||
|
||||
// Test contact form with no default form selected.
|
||||
$this->config('contact.settings')
|
||||
->set('default_form', '')
|
||||
->save();
|
||||
$this->drupalGet('contact');
|
||||
$this->assertResponse(404);
|
||||
|
||||
// Try to access contact form with non-existing form IDs.
|
||||
$this->drupalGet('contact/0');
|
||||
$this->assertResponse(404);
|
||||
$this->drupalGet('contact/' . $this->randomMachineName());
|
||||
$this->assertResponse(404);
|
||||
|
||||
// Submit contact form with correct values and check flood interval.
|
||||
for ($i = 0; $i < $flood_limit; $i++) {
|
||||
$this->submitContact($this->randomMachineName(16), $recipients[0], $this->randomMachineName(16), $id, $this->randomMachineName(64));
|
||||
$this->assertText(t('Your message has been sent.'));
|
||||
}
|
||||
// Submit contact form one over limit.
|
||||
$this->submitContact($this->randomMachineName(16), $recipients[0], $this->randomMachineName(16), $id, $this->randomMachineName(64));
|
||||
$this->assertRaw(t('You cannot send more than %number messages in 10 min. Try again later.', array('%number' => $this->config('contact.settings')->get('flood.limit'))));
|
||||
|
||||
// Test listing controller.
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->deleteContactForms();
|
||||
|
||||
$label = $this->randomMachineName(16);
|
||||
$recipients = implode(',', array($recipients[0], $recipients[1], $recipients[2]));
|
||||
$contact_form = Unicode::strtolower($this->randomMachineName(16));
|
||||
$this->addContactForm($contact_form, $label, $recipients, '', FALSE);
|
||||
$this->drupalGet('admin/structure/contact');
|
||||
$this->clickLink(t('Edit'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertFieldByName('label', $label);
|
||||
|
||||
// Test field UI and field integration.
|
||||
$this->drupalGet('admin/structure/contact');
|
||||
|
||||
// Find out in which row the form we want to add a field to is.
|
||||
$i = 0;
|
||||
foreach($this->xpath('//table/tbody/tr') as $row) {
|
||||
if (((string)$row->td[0]) == $label) {
|
||||
break;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
$this->clickLink(t('Manage fields'), $i);
|
||||
$this->assertResponse(200);
|
||||
$this->clickLink(t('Add field'));
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Create a simple textfield.
|
||||
$field_name = Unicode::strtolower($this->randomMachineName());
|
||||
$field_label = $this->randomMachineName();
|
||||
$this->fieldUIAddNewField(NULL, $field_name, $field_label, 'text');
|
||||
$field_name = 'field_' . $field_name;
|
||||
|
||||
// Check that the field is displayed.
|
||||
$this->drupalGet('contact/' . $contact_form);
|
||||
$this->assertText($field_label);
|
||||
|
||||
// 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'));
|
||||
$mails = $this->drupalGetMails();
|
||||
$mail = array_pop($mails);
|
||||
$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'], $edit[$field_name . '[0][value]']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests auto-reply on the site-wide contact form.
|
||||
*/
|
||||
function testAutoReply() {
|
||||
// Create and login administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array('access site-wide contact form', 'administer contact forms', 'administer permissions', 'administer users'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Set up three forms, 2 with an auto-reply and one without.
|
||||
$foo_autoreply = $this->randomMachineName(40);
|
||||
$bar_autoreply = $this->randomMachineName(40);
|
||||
$this->addContactForm('foo', 'foo', 'foo@example.com', $foo_autoreply, FALSE);
|
||||
$this->addContactForm('bar', 'bar', 'bar@example.com', $bar_autoreply, FALSE);
|
||||
$this->addContactForm('no_autoreply', 'no_autoreply', 'bar@example.com', '', FALSE);
|
||||
|
||||
// Log the current user out in order to test the name and email fields.
|
||||
$this->drupalLogout();
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access site-wide contact form'));
|
||||
|
||||
// Test the auto-reply for form 'foo'.
|
||||
$email = $this->randomMachineName(32) . '@example.com';
|
||||
$subject = $this->randomMachineName(64);
|
||||
$this->submitContact($this->randomMachineName(16), $email, $subject, 'foo', $this->randomString(128));
|
||||
|
||||
// We are testing the auto-reply, so there should be one email going to the sender.
|
||||
$captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email));
|
||||
$this->assertEqual(count($captured_emails), 1);
|
||||
$this->assertEqual(trim($captured_emails[0]['body']), trim(MailFormatHelper::htmlToText($foo_autoreply)));
|
||||
|
||||
// Test the auto-reply for form 'bar'.
|
||||
$email = $this->randomMachineName(32) . '@example.com';
|
||||
$this->submitContact($this->randomMachineName(16), $email, $this->randomString(64), 'bar', $this->randomString(128));
|
||||
|
||||
// Auto-reply for form 'bar' should result in one auto-reply email to the sender.
|
||||
$captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email));
|
||||
$this->assertEqual(count($captured_emails), 1);
|
||||
$this->assertEqual(trim($captured_emails[0]['body']), trim(MailFormatHelper::htmlToText($bar_autoreply)));
|
||||
|
||||
// Verify that no auto-reply is sent when the auto-reply field is left blank.
|
||||
$email = $this->randomMachineName(32) . '@example.com';
|
||||
$this->submitContact($this->randomMachineName(16), $email, $this->randomString(64), 'no_autoreply', $this->randomString(128));
|
||||
$captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email));
|
||||
$this->assertEqual(count($captured_emails), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a form.
|
||||
*
|
||||
* @param string $id
|
||||
* The form machine name.
|
||||
* @param string $label
|
||||
* The form label.
|
||||
* @param string $recipients
|
||||
* The list of recipient email addresses.
|
||||
* @param string $reply
|
||||
* The auto-reply text that is sent to a user upon completing the contact
|
||||
* form.
|
||||
* @param bool $selected
|
||||
* A Boolean indicating whether the form should be selected by default.
|
||||
* @param array $third_party_settings
|
||||
* Array of third party settings to be added to the posted form data.
|
||||
*/
|
||||
function addContactForm($id, $label, $recipients, $reply, $selected, $third_party_settings = []) {
|
||||
$edit = array();
|
||||
$edit['label'] = $label;
|
||||
$edit['id'] = $id;
|
||||
$edit['recipients'] = $recipients;
|
||||
$edit['reply'] = $reply;
|
||||
$edit['selected'] = ($selected ? TRUE : FALSE);
|
||||
$edit += $third_party_settings;
|
||||
$this->drupalPostForm('admin/structure/contact/add', $edit, t('Save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a form.
|
||||
*
|
||||
* @param string $id
|
||||
* The form machine name.
|
||||
* @param string $label
|
||||
* The form label.
|
||||
* @param string $recipients
|
||||
* The list of recipient email addresses.
|
||||
* @param string $reply
|
||||
* The auto-reply text that is sent to a user upon completing the contact
|
||||
* form.
|
||||
* @param bool $selected
|
||||
* A Boolean indicating whether the form should be selected by default.
|
||||
*/
|
||||
function updateContactForm($id, $label, $recipients, $reply, $selected) {
|
||||
$edit = array();
|
||||
$edit['label'] = $label;
|
||||
$edit['recipients'] = $recipients;
|
||||
$edit['reply'] = $reply;
|
||||
$edit['selected'] = ($selected ? TRUE : FALSE);
|
||||
$this->drupalPostForm("admin/structure/contact/manage/$id", $edit, t('Save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the contact form.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the sender.
|
||||
* @param string $mail
|
||||
* The email address of the sender.
|
||||
* @param string $subject
|
||||
* The subject of the message.
|
||||
* @param string $id
|
||||
* The form ID of the message.
|
||||
* @param string $message
|
||||
* The message body.
|
||||
*/
|
||||
function submitContact($name, $mail, $subject, $id, $message) {
|
||||
$edit = array();
|
||||
$edit['name'] = $name;
|
||||
$edit['mail'] = $mail;
|
||||
$edit['subject[0][value]'] = $subject;
|
||||
$edit['message[0][value]'] = $message;
|
||||
if ($id == $this->config('contact.settings')->get('default_form')) {
|
||||
$this->drupalPostForm('contact', $edit, t('Send message'));
|
||||
}
|
||||
else {
|
||||
$this->drupalPostForm('contact/' . $id, $edit, t('Send message'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all forms.
|
||||
*/
|
||||
function deleteContactForms() {
|
||||
$contact_forms = ContactForm::loadMultiple();;
|
||||
foreach ($contact_forms as $id => $contact_form) {
|
||||
if ($id == 'personal') {
|
||||
// Personal form could not be deleted.
|
||||
$this->drupalGet("admin/structure/contact/manage/$id/delete");
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
else {
|
||||
$this->drupalPostForm("admin/structure/contact/manage/$id/delete", array(), t('Delete'));
|
||||
$this->assertRaw(t('The contact form %label has been deleted.', array('%label' => $contact_form->label())));
|
||||
$this->assertFalse(ContactForm::load($id), format_string('Form %contact_form not found', array('%contact_form' => $contact_form->label())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
81
core/modules/contact/src/Tests/ContactStorageTest.php
Normal file
81
core/modules/contact/src/Tests/ContactStorageTest.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\ContactStorageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\contact\Entity\Message;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests storing contact messages.
|
||||
*
|
||||
* Note that the various test methods in ContactSitewideTest are also run by
|
||||
* this test. This is by design to ensure that regular contact.module functions
|
||||
* continue to work when a storage handler other than ContentEntityNullStorage
|
||||
* is enabled for contact Message entities.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactStorageTest extends ContactSitewideTest {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array(
|
||||
'text',
|
||||
'contact',
|
||||
'field_ui',
|
||||
'contact_storage_test',
|
||||
'contact_test',
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests configuration options and the site-wide contact form.
|
||||
*/
|
||||
public function testContactStorage() {
|
||||
// Create and login administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'access site-wide contact form',
|
||||
'administer contact forms',
|
||||
'administer users',
|
||||
'administer account settings',
|
||||
'administer contact_message fields',
|
||||
));
|
||||
$this->drupalLogin($admin_user);
|
||||
// Create first valid contact form.
|
||||
$mail = 'simpletest@example.com';
|
||||
$this->addContactForm($id = Unicode::strtolower($this->randomMachineName(16)), $label = $this->randomMachineName(16), implode(',', array($mail)), '', TRUE, [
|
||||
'send_a_pony' => 1,
|
||||
]);
|
||||
$this->assertRaw(t('Contact form %label has been added.', array('%label' => $label)));
|
||||
|
||||
// Ensure that anonymous can submit site-wide contact form.
|
||||
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('access site-wide contact form'));
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('contact');
|
||||
$this->assertText(t('Your email address'));
|
||||
$this->assertNoText(t('Form'));
|
||||
$this->submitContact($name = $this->randomMachineName(16), $mail, $subject = $this->randomMachineName(16), $id, $message = $this->randomMachineName(64));
|
||||
$this->assertText(t('Your message has been sent.'));
|
||||
|
||||
$messages = Message::loadMultiple();
|
||||
/** @var \Drupal\contact\Entity\Message $message */
|
||||
$message = reset($messages);
|
||||
$this->assertEqual($message->getContactForm()->id(), $id);
|
||||
$this->assertTrue($message->getContactForm()->getThirdPartySetting('contact_storage_test', 'send_a_pony', FALSE));
|
||||
$this->assertEqual($message->getSenderName(), $name);
|
||||
$this->assertEqual($message->getSubject(), $subject);
|
||||
$this->assertEqual($message->getSenderMail(), $mail);
|
||||
|
||||
$config = $this->config("contact.form.$id");
|
||||
$this->assertEqual($config->get('id'), $id);
|
||||
}
|
||||
|
||||
}
|
76
core/modules/contact/src/Tests/MessageEntityTest.php
Normal file
76
core/modules/contact/src/Tests/MessageEntityTest.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\MessageEntityTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\contact\Entity\Message;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests the message entity class.
|
||||
*
|
||||
* @group contact
|
||||
* @see \Drupal\contact\Entity\Message
|
||||
*/
|
||||
class MessageEntityTest extends EntityUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array(
|
||||
'system',
|
||||
'contact',
|
||||
'field',
|
||||
'user',
|
||||
'contact_test',
|
||||
);
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(array('contact', 'contact_test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test some of the methods.
|
||||
*/
|
||||
public function testMessageMethods() {
|
||||
$message_storage = $this->container->get('entity.manager')->getStorage('contact_message');
|
||||
$message = $message_storage->create(array('contact_form' => 'feedback'));
|
||||
|
||||
// Check for empty values first.
|
||||
$this->assertEqual($message->getMessage(), '');
|
||||
$this->assertEqual($message->getSenderName(), '');
|
||||
$this->assertEqual($message->getSenderMail(), '');
|
||||
$this->assertFalse($message->copySender());
|
||||
|
||||
// Check for default values.
|
||||
$this->assertEqual('feedback', $message->getContactForm()->id());
|
||||
$this->assertFalse($message->isPersonal());
|
||||
|
||||
// Set some values and check for them afterwards.
|
||||
$message->setMessage('welcome_message');
|
||||
$message->setSenderName('sender_name');
|
||||
$message->setSenderMail('sender_mail');
|
||||
$message->setCopySender(TRUE);
|
||||
|
||||
$this->assertEqual($message->getMessage(), 'welcome_message');
|
||||
$this->assertEqual($message->getSenderName(), 'sender_name');
|
||||
$this->assertEqual($message->getSenderMail(), 'sender_mail');
|
||||
$this->assertTrue($message->copySender());
|
||||
|
||||
$no_access_user = $this->createUser(['uid' => 2]);
|
||||
$access_user = $this->createUser(['uid' => 3], ['access site-wide contact form']);
|
||||
$admin = $this->createUser(['uid' => 4], ['administer contact forms']);
|
||||
|
||||
$this->assertFalse(\Drupal::entityManager()->getAccessControlHandler('contact_message')->createAccess(NULL, $no_access_user));
|
||||
$this->assertTrue(\Drupal::entityManager()->getAccessControlHandler('contact_message')->createAccess(NULL, $access_user));
|
||||
$this->assertTrue($message->access('edit', $admin));
|
||||
$this->assertFalse($message->access('edit', $access_user));
|
||||
}
|
||||
|
||||
}
|
67
core/modules/contact/src/Tests/Views/ContactFieldsTest.php
Normal file
67
core/modules/contact/src/Tests/Views/ContactFieldsTest.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\Views\ContactFieldsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests which checks that no fieldapi fields are added on contact.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactFieldsTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('field', 'text', 'contact');
|
||||
|
||||
/**
|
||||
* Contains the field storage definition for contact used for this test.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->fieldStorage = entity_create('field_storage_config', array(
|
||||
'field_name' => strtolower($this->randomMachineName()),
|
||||
'entity_type' => 'contact_message',
|
||||
'type' => 'text'
|
||||
));
|
||||
$this->fieldStorage->save();
|
||||
|
||||
entity_create('contact_form', array(
|
||||
'id' => 'contact_message',
|
||||
'label' => 'Test contact form',
|
||||
))->save();
|
||||
|
||||
entity_create('field_config', array(
|
||||
'field_storage' => $this->fieldStorage,
|
||||
'bundle' => 'contact_message',
|
||||
))->save();
|
||||
|
||||
$this->container->get('views.views_data')->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the views data generation.
|
||||
*/
|
||||
public function testViewsData() {
|
||||
// Test that the field is not exposed to views, since contact_message
|
||||
// entities have no storage.
|
||||
$table_name = 'contact_message__' . $this->fieldStorage->getName();
|
||||
$data = $this->container->get('views.views_data')->get($table_name);
|
||||
$this->assertFalse($data, 'The field is not exposed to Views.');
|
||||
}
|
||||
|
||||
}
|
113
core/modules/contact/src/Tests/Views/ContactLinkTest.php
Normal file
113
core/modules/contact/src/Tests/Views/ContactLinkTest.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\contact\Tests\Views\ContactLinkTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests\Views;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the contact link field.
|
||||
*
|
||||
* @group contact
|
||||
* @see \Drupal\contact\Plugin\views\field\ContactLink.
|
||||
*/
|
||||
class ContactLinkTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Stores the user data service used by the test.
|
||||
*
|
||||
* @var \Drupal\user\UserDataInterface
|
||||
*/
|
||||
public $userData;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('contact_test_views');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_contact_link');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), array('contact_test_views'));
|
||||
|
||||
$this->userData = $this->container->get('user.data');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests contact link.
|
||||
*/
|
||||
public function testContactLink() {
|
||||
$accounts = array();
|
||||
$accounts['root'] = User::load(1);
|
||||
// Create an account with access to all contact pages.
|
||||
$admin_account = $this->drupalCreateUser(array('administer users'));
|
||||
$accounts['admin'] = $admin_account;
|
||||
// Create an account with no access to contact pages.
|
||||
$no_contact_account = $this->drupalCreateUser();
|
||||
$accounts['no_contact'] = $no_contact_account;
|
||||
|
||||
// Create an account with access to contact pages.
|
||||
$contact_account = $this->drupalCreateUser(array('access user contact forms'));
|
||||
$accounts['contact'] = $contact_account;
|
||||
|
||||
$this->drupalLogin($admin_account);
|
||||
$this->drupalGet('test-contact-link');
|
||||
// The admin user has access to all contact links beside his own.
|
||||
$this->assertContactLinks($accounts, array('root', 'no_contact', 'contact'));
|
||||
|
||||
$this->drupalLogin($no_contact_account);
|
||||
$this->drupalGet('test-contact-link');
|
||||
// Ensure that the user without the permission doesn't see any link.
|
||||
$this->assertContactLinks($accounts, array());
|
||||
|
||||
$this->drupalLogin($contact_account);
|
||||
$this->drupalGet('test-contact-link');
|
||||
$this->assertContactLinks($accounts, array('root', 'admin', 'no_contact'));
|
||||
|
||||
// Disable contact link for no_contact.
|
||||
$this->userData->set('contact', $no_contact_account->id(), 'enabled', FALSE);
|
||||
// @todo Remove cache invalidation in https://www.drupal.org/node/2477903.
|
||||
Cache::invalidateTags($no_contact_account->getCacheTags());
|
||||
$this->drupalGet('test-contact-link');
|
||||
$this->assertContactLinks($accounts, array('root', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts whether certain users contact links appear on the page.
|
||||
*
|
||||
* @param array $accounts
|
||||
* All user objects used by the test.
|
||||
* @param array $names
|
||||
* Users which should have contact links.
|
||||
*/
|
||||
public function assertContactLinks(array $accounts, array $names) {
|
||||
$result = $this->xpath('//div[contains(@class, "views-field-contact")]//a');
|
||||
$this->assertEqual(count($result), count($names));
|
||||
foreach ($names as $name) {
|
||||
$account = $accounts[$name];
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "views-field-contact")]//a[contains(@href, :url)]', array(':url' => $account->url('contact-form')));
|
||||
$this->assertTrue(count($result));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
33
core/modules/contact/tests/drupal-7.contact.database.php
Normal file
33
core/modules/contact/tests/drupal-7.contact.database.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Database additions for Drupal\contact\Tests\ContactUpgradePathTest.
|
||||
*
|
||||
* This dump only contains data for the contact module. The
|
||||
* drupal-7.filled.bare.php file is imported before this dump, so the two form
|
||||
* the database structure expected in tests altogether.
|
||||
*/
|
||||
|
||||
// Update the default category to that it is not selected.
|
||||
db_update('contact')
|
||||
->fields(array('selected' => '0'))
|
||||
->condition('cid', '1')
|
||||
->execute();
|
||||
|
||||
// Add a custom contact category.
|
||||
db_insert('contact')->fields(array(
|
||||
'category',
|
||||
'recipients',
|
||||
'reply',
|
||||
'weight',
|
||||
'selected'
|
||||
))
|
||||
->values(array(
|
||||
'category' => 'Upgrade test',
|
||||
'recipients'=> 'test1@example.com,test2@example.com',
|
||||
'reply' => 'Test reply',
|
||||
'weight' => 1,
|
||||
'selected' => 1,
|
||||
))
|
||||
->execute();
|
|
@ -0,0 +1,9 @@
|
|||
# Schema for configuration files of the Contact Storage Test module.
|
||||
|
||||
contact.form.*.third_party.contact_storage_test:
|
||||
type: mapping
|
||||
label: 'Per-contact form storage settings'
|
||||
mapping:
|
||||
send_a_pony:
|
||||
type: boolean
|
||||
label: 'Send a Pony'
|
|
@ -0,0 +1,9 @@
|
|||
name: 'Contact test storage'
|
||||
type: module
|
||||
description: 'Tests that contact messages can be stored.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- contact
|
||||
- user
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains install and update hooks.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function contact_storage_test_install() {
|
||||
$entity_manager = \Drupal::entityManager();
|
||||
$entity_type = $entity_manager->getDefinition('contact_message');
|
||||
|
||||
// Recreate the original entity type definition, in order to notify the
|
||||
// manager of what changed. The change of storage backend will trigger
|
||||
// schema installation.
|
||||
// @see contact_storage_test_entity_type_alter()
|
||||
$original = clone $entity_type;
|
||||
$original->setStorageClass('Drupal\Core\Entity\ContentEntityNullStorage');
|
||||
|
||||
$entity_manager->onEntityTypeUpdate($entity_type, $original);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains custom contact message functionality for ContactStorageTest.
|
||||
*/
|
||||
|
||||
use Drupal\contact\ContactFormInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_base_field_info().
|
||||
*/
|
||||
function contact_storage_test_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->id() == 'contact_message') {
|
||||
$fields = array();
|
||||
|
||||
$fields['id'] = BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('Message ID'))
|
||||
->setDescription(t('The message ID.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function contact_storage_test_entity_type_alter(array &$entity_types) {
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
// Set the controller class for nodes to an alternate implementation of the
|
||||
// Drupal\Core\Entity\EntityStorageInterface interface.
|
||||
$entity_types['contact_message']->setStorageClass('\Drupal\Core\Entity\Sql\SqlContentEntityStorage');
|
||||
$keys = $entity_types['contact_message']->getKeys();
|
||||
$keys['id'] = 'id';
|
||||
$entity_types['contact_message']->set('entity_keys', $keys);
|
||||
$entity_types['contact_message']->set('base_table', 'contact_message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter() for contact_form_form().
|
||||
*/
|
||||
function contact_storage_test_form_contact_form_form_alter(&$form, FormStateInterface $form_state) {
|
||||
/** @var \Drupal\contact\ContactFormInterface $contact_form */
|
||||
$contact_form = $form_state->getFormObject()->getEntity();
|
||||
$form['send_a_pony'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Send submitters a voucher for a free pony.'),
|
||||
'#description' => t('Enable to send an additional email with a free pony voucher to anyone who submits the form.'),
|
||||
'#default_value' => $contact_form->getThirdPartySetting('contact_storage_test', 'send_a_pony', FALSE),
|
||||
);
|
||||
$form['#entity_builders'][] = 'contact_storage_test_contact_form_form_builder';
|
||||
}
|
||||
/**
|
||||
* Entity builder for the contact form edit form with third party options.
|
||||
*
|
||||
* @see contact_storage_test_form_contact_form_edit_form_alter()
|
||||
*/
|
||||
function contact_storage_test_contact_form_form_builder($entity_type, ContactFormInterface $contact_form, &$form, FormStateInterface $form_state) {
|
||||
$contact_form->setThirdPartySetting('contact_storage_test', 'send_a_pony', $form_state->getValue('send_a_pony'));
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
id: feedback
|
||||
label: 'Website feedback'
|
||||
recipients: { }
|
||||
reply: ''
|
||||
weight: 0
|
||||
status: true
|
||||
langcode: en
|
|
@ -0,0 +1,8 @@
|
|||
name: 'Contact test module'
|
||||
type: module
|
||||
description: 'Contains test contact form.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- contact
|
|
@ -0,0 +1,10 @@
|
|||
name: 'Contact test views'
|
||||
type: module
|
||||
description: 'Provides default views for views contact tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- contact
|
||||
- views
|
||||
- user
|
|
@ -0,0 +1,149 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- contact
|
||||
- user
|
||||
id: test_contact_link
|
||||
label: test_contact_link
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: users_field_data
|
||||
base_field: uid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 1
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: full
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 20, 40, 60'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: '‹ previous'
|
||||
next: 'next ›'
|
||||
first: '« first'
|
||||
last: 'last »'
|
||||
quantity: 9
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
name:
|
||||
id: name
|
||||
table: users_field_data
|
||||
field: name
|
||||
label: ''
|
||||
alter:
|
||||
alter_text: false
|
||||
make_link: false
|
||||
absolute: false
|
||||
trim: false
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
strip_tags: false
|
||||
html: false
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exclude: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_alter_empty: true
|
||||
plugin_id: field
|
||||
type: user_name
|
||||
entity_type: user
|
||||
entity_field: name
|
||||
contact:
|
||||
id: contact
|
||||
table: users
|
||||
field: contact
|
||||
plugin_id: contact_link
|
||||
exclude: false
|
||||
entity_type: user
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
table: users_field_data
|
||||
field: status
|
||||
id: status
|
||||
expose:
|
||||
operator: '0'
|
||||
group: 1
|
||||
plugin_id: boolean
|
||||
entity_type: user
|
||||
entity_field: status
|
||||
sorts: { }
|
||||
title: test_contact_link
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
cacheable: false
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: test-contact-link
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
cacheable: false
|
414
core/modules/contact/tests/src/Unit/MailHandlerTest.php
Normal file
414
core/modules/contact/tests/src/Unit/MailHandlerTest.php
Normal file
|
@ -0,0 +1,414 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\contact\Unit\MailHandlerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\contact\Unit;
|
||||
|
||||
use Drupal\contact\MailHandler;
|
||||
use Drupal\contact\MessageInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\contact\MailHandler
|
||||
* @group contact
|
||||
*/
|
||||
class MailHandlerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Language manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* Logger service.
|
||||
*
|
||||
* @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Mail manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Mail\MailManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $mailManager;
|
||||
|
||||
/**
|
||||
* Contact mail messages service.
|
||||
*
|
||||
* @var \Drupal\contact\MailHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $contactMailHandler;
|
||||
|
||||
/**
|
||||
* The contact form entity.
|
||||
*
|
||||
* @var \Drupal\contact\ContactFormInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $contactForm;
|
||||
|
||||
/**
|
||||
* The entity manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The user storage handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $userStorage;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->mailManager = $this->getMock('\Drupal\Core\Mail\MailManagerInterface');
|
||||
$this->languageManager = $this->getMock('\Drupal\Core\Language\LanguageManagerInterface');
|
||||
$this->logger = $this->getMock('\Psr\Log\LoggerInterface');
|
||||
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
|
||||
$this->userStorage = $this->getMock('\Drupal\Core\Entity\EntityStorageInterface');
|
||||
$this->entityManager->expects($this->any())
|
||||
->method('getStorage')
|
||||
->with('user')
|
||||
->willReturn($this->userStorage);
|
||||
|
||||
$string_translation = $this->getStringTranslationStub();
|
||||
$this->contactMailHandler = new MailHandler($this->mailManager, $this->languageManager, $this->logger, $string_translation, $this->entityManager);
|
||||
$language = new Language(array('id' => 'en'));
|
||||
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getDefaultLanguage')
|
||||
->will($this->returnValue($language));
|
||||
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getCurrentLanguage')
|
||||
->will($this->returnValue($language));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the children() method with an invalid key.
|
||||
*
|
||||
* @expectedException \Drupal\contact\MailHandlerException
|
||||
* @expectedExceptionMessage Unable to determine message recipient
|
||||
*
|
||||
* @covers ::sendMailMessages
|
||||
*/
|
||||
public function testInvalidRecipient() {
|
||||
$message = $this->getMock('\Drupal\contact\MessageInterface');
|
||||
$message->expects($this->once())
|
||||
->method('isPersonal')
|
||||
->willReturn(TRUE);
|
||||
$message->expects($this->once())
|
||||
->method('getPersonalRecipient')
|
||||
->willReturn(NULL);
|
||||
$message->expects($this->once())
|
||||
->method('getContactForm')
|
||||
->willReturn($this->getMock('\Drupal\contact\ContactFormInterface'));
|
||||
$sender = $this->getMock('\Drupal\Core\Session\AccountInterface');
|
||||
$this->userStorage->expects($this->any())
|
||||
->method('load')
|
||||
->willReturn($sender);
|
||||
// User IDs 1 and 0 have special implications, use 3 instead.
|
||||
$sender->expects($this->any())
|
||||
->method('id')
|
||||
->willReturn(3);
|
||||
$sender->expects($this->once())
|
||||
->method('isAnonymous')
|
||||
->willReturn(FALSE);
|
||||
$this->contactMailHandler->sendMailMessages($message, $sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the sendMailMessages method.
|
||||
*
|
||||
* @dataProvider getSendMailMessages
|
||||
*
|
||||
* @covers ::sendMailMessages
|
||||
*/
|
||||
public function testSendMailMessages(MessageInterface $message, AccountInterface $sender, $results) {
|
||||
$this->logger->expects($this->once())
|
||||
->method('notice');
|
||||
$this->mailManager->expects($this->any())
|
||||
->method('mail')
|
||||
->willReturnCallback(
|
||||
function($module, $key, $to, $langcode, $params, $from) use (&$results) {
|
||||
$result = array_shift($results);
|
||||
$this->assertEquals($module, $result['module']);
|
||||
$this->assertEquals($key, $result['key']);
|
||||
$this->assertEquals($to, $result['to']);
|
||||
$this->assertEquals($langcode, $result['langcode']);
|
||||
$this->assertArrayEquals($params, $result['params']);
|
||||
$this->assertEquals($from, $result['from']);
|
||||
});
|
||||
$this->userStorage->expects($this->any())
|
||||
->method('load')
|
||||
->willReturn(clone $sender);
|
||||
$this->contactMailHandler->sendMailMessages($message, $sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testSendMailMessages.
|
||||
*/
|
||||
public function getSendMailMessages() {
|
||||
$data = array();
|
||||
$recipients = array('admin@drupal.org', 'user@drupal.org');
|
||||
$default_result = array(
|
||||
'module' => 'contact',
|
||||
'key' => '',
|
||||
'to' => implode(', ', $recipients),
|
||||
'langcode' => 'en',
|
||||
'params' => array(),
|
||||
'from' => 'anonymous@drupal.org',
|
||||
);
|
||||
$results = array();
|
||||
$message = $this->getAnonymousMockMessage($recipients, '');
|
||||
$sender = $this->getMockSender();
|
||||
$result = array(
|
||||
'key' => 'page_mail',
|
||||
'params' => array(
|
||||
'contact_message' => $message,
|
||||
'sender' => $sender,
|
||||
'contact_form' => $message->getContactForm(),
|
||||
),
|
||||
);
|
||||
$results[] = $result + $default_result;
|
||||
$data[] = array($message, $sender, $results);
|
||||
|
||||
$results = array();
|
||||
$message = $this->getAnonymousMockMessage($recipients, 'reply');
|
||||
$sender = $this->getMockSender();
|
||||
$result = array(
|
||||
'key' => 'page_mail',
|
||||
'params' => array(
|
||||
'contact_message' => $message,
|
||||
'sender' => $sender,
|
||||
'contact_form' => $message->getContactForm(),
|
||||
),
|
||||
);
|
||||
$results[] = $result + $default_result;
|
||||
$result['key'] = 'page_autoreply';
|
||||
$result['to'] = 'anonymous@drupal.org';
|
||||
$result['from'] = NULL;
|
||||
$results[] = $result + $default_result;
|
||||
$data[] = array($message, $sender, $results);
|
||||
|
||||
$results = array();
|
||||
$message = $this->getAnonymousMockMessage($recipients, '', TRUE);
|
||||
$sender = $this->getMockSender();
|
||||
$result = array(
|
||||
'key' => 'page_mail',
|
||||
'params' => array(
|
||||
'contact_message' => $message,
|
||||
'sender' => $sender,
|
||||
'contact_form' => $message->getContactForm(),
|
||||
),
|
||||
);
|
||||
$results[] = $result + $default_result;
|
||||
$result['key'] = 'page_copy';
|
||||
$result['to'] = 'anonymous@drupal.org';
|
||||
$results[] = $result + $default_result;
|
||||
$data[] = array($message, $sender, $results);
|
||||
|
||||
$results = array();
|
||||
$message = $this->getAnonymousMockMessage($recipients, 'reply', TRUE);
|
||||
$sender = $this->getMockSender();
|
||||
$result = array(
|
||||
'key' => 'page_mail',
|
||||
'params' => array(
|
||||
'contact_message' => $message,
|
||||
'sender' => $sender,
|
||||
'contact_form' => $message->getContactForm(),
|
||||
),
|
||||
);
|
||||
$results[] = $result + $default_result;
|
||||
$result['key'] = 'page_copy';
|
||||
$result['to'] = 'anonymous@drupal.org';
|
||||
$results[] = $result + $default_result;
|
||||
$result['key'] = 'page_autoreply';
|
||||
$result['from'] = NULL;
|
||||
$results[] = $result + $default_result;
|
||||
$data[] = array($message, $sender, $results);
|
||||
|
||||
//For authenticated user.
|
||||
$results = array();
|
||||
$message = $this->getAuthenticatedMockMessage();
|
||||
$sender = $this->getMockSender(FALSE, 'user@drupal.org');
|
||||
$result = array(
|
||||
'module' => 'contact',
|
||||
'key' => 'user_mail',
|
||||
'to' => 'user2@drupal.org',
|
||||
'langcode' => 'en',
|
||||
'params' => array(
|
||||
'contact_message' => $message,
|
||||
'sender' => $sender,
|
||||
'recipient' => $message->getPersonalRecipient(),
|
||||
),
|
||||
'from' => 'user@drupal.org',
|
||||
);
|
||||
$results[] = $result;
|
||||
$data[] = array($message, $sender, $results);
|
||||
|
||||
$results = array();
|
||||
$message = $this->getAuthenticatedMockMessage(TRUE);
|
||||
$sender = $this->getMockSender(FALSE, 'user@drupal.org');
|
||||
$result = array(
|
||||
'module' => 'contact',
|
||||
'key' => 'user_mail',
|
||||
'to' => 'user2@drupal.org',
|
||||
'langcode' => 'en',
|
||||
'params' => array(
|
||||
'contact_message' => $message,
|
||||
'sender' => $sender,
|
||||
'recipient' => $message->getPersonalRecipient(),
|
||||
),
|
||||
'from' => 'user@drupal.org',
|
||||
);
|
||||
$results[] = $result;
|
||||
|
||||
$result['key'] = 'user_copy';
|
||||
$result['to'] = $result['from'];
|
||||
$results[] = $result;
|
||||
$data[] = array($message, $sender, $results);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a mock sender on given scenario.
|
||||
*
|
||||
* @param bool $anonymous
|
||||
* TRUE if the sender is anonymous.
|
||||
* @param string $mail_address
|
||||
* The mail address of the user.
|
||||
*
|
||||
* @return \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
* Mock sender for testing.
|
||||
*/
|
||||
protected function getMockSender($anonymous = TRUE, $mail_address = 'anonymous@drupal.org') {
|
||||
$sender = $this->getMock('\Drupal\Core\Session\AccountInterface');
|
||||
$sender->expects($this->once())
|
||||
->method('isAnonymous')
|
||||
->willReturn($anonymous);
|
||||
$sender->expects($this->any())
|
||||
->method('getEmail')
|
||||
->willReturn($mail_address);
|
||||
$sender->expects($this->any())
|
||||
->method('getUsername')
|
||||
->willReturn('user');
|
||||
// User ID 1 has special implications, use 3 instead.
|
||||
$sender->expects($this->any())
|
||||
->method('id')
|
||||
->willReturn($anonymous ? 0 : 3);
|
||||
if ($anonymous) {
|
||||
// Anonymous user values set in params include updated values for name and
|
||||
// mail.
|
||||
$sender->name = 'Anonymous (not verified)';
|
||||
$sender->mail = 'anonymous@drupal.org';
|
||||
}
|
||||
return $sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a mock message from anonymous user.
|
||||
*
|
||||
* @param array $recipients
|
||||
* An array of recipient email addresses.
|
||||
* @param bool $auto_reply
|
||||
* TRUE if auto reply is enable.
|
||||
* @param bool $copy_sender
|
||||
* TRUE if a copy should be sent, FALSE if not.
|
||||
*
|
||||
* @return \Drupal\contact\MessageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
* Mock message for testing.
|
||||
*/
|
||||
protected function getAnonymousMockMessage($recipients, $auto_reply, $copy_sender = FALSE) {
|
||||
$message = $this->getMock('\Drupal\contact\MessageInterface');
|
||||
$message->expects($this->any())
|
||||
->method('getSenderName')
|
||||
->willReturn('Anonymous');
|
||||
$message->expects($this->once())
|
||||
->method('getSenderMail')
|
||||
->willReturn('anonymous@drupal.org');
|
||||
$message->expects($this->any())
|
||||
->method('isPersonal')
|
||||
->willReturn(FALSE);
|
||||
$message->expects($this->once())
|
||||
->method('copySender')
|
||||
->willReturn($copy_sender);
|
||||
$message->expects($this->any())
|
||||
->method('getContactForm')
|
||||
->willReturn($this->getMockContactForm($recipients, $auto_reply));
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a mock message from authenticated user.
|
||||
*
|
||||
* @param bool $copy_sender
|
||||
* TRUE if a copy should be sent, FALSE if not.
|
||||
*
|
||||
* @return \Drupal\contact\MessageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
* Mock message for testing.
|
||||
*/
|
||||
protected function getAuthenticatedMockMessage($copy_sender = FALSE) {
|
||||
$message = $this->getMock('\Drupal\contact\MessageInterface');
|
||||
$message->expects($this->any())
|
||||
->method('isPersonal')
|
||||
->willReturn(TRUE);
|
||||
$message->expects($this->once())
|
||||
->method('copySender')
|
||||
->willReturn($copy_sender);
|
||||
$recipient =$this->getMock('\Drupal\user\UserInterface');
|
||||
$recipient->expects($this->once())
|
||||
->method('getEmail')
|
||||
->willReturn('user2@drupal.org');
|
||||
$recipient->expects($this->once())
|
||||
->method('getUsername')
|
||||
->willReturn('user2');
|
||||
$recipient->expects($this->once())
|
||||
->method('getPreferredLangcode')
|
||||
->willReturn('en');
|
||||
$message->expects($this->any())
|
||||
->method('getPersonalRecipient')
|
||||
->willReturn($recipient);
|
||||
$message->expects($this->any())
|
||||
->method('getContactForm')
|
||||
->willReturn($this->getMockContactForm('user2@drupal.org', FALSE));
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a mock message on given scenario.
|
||||
*
|
||||
* @param array $recipients
|
||||
* An array of recipient email addresses.
|
||||
* @param string $auto_reply
|
||||
* An auto-reply message to send to the message author.
|
||||
*
|
||||
* @return \Drupal\contact\ContactFormInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
* Mock message for testing.
|
||||
*/
|
||||
protected function getMockContactForm($recipients, $auto_reply) {
|
||||
$contact_form = $this->getMock('\Drupal\contact\ContactFormInterface');
|
||||
$contact_form->expects($this->once())
|
||||
->method('getRecipients')
|
||||
->willReturn($recipients);
|
||||
$contact_form->expects($this->once())
|
||||
->method('getReply')
|
||||
->willReturn($auto_reply);
|
||||
|
||||
return $contact_form;
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue