Issue #1938390 by andypost, disasm, jibran, dawehner, ygerasimov, pfrenssen: Convert contact_site_page and contact_person_page to a new-style Controller.
parent
c120a661e4
commit
94cba6d2d4
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains Drupal\Core\Access\AccessManager.
|
||||
* Contains \Drupal\Core\Access\AccessManager.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Access;
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
* Enables the use of personal and site-wide contact forms.
|
||||
*/
|
||||
|
||||
use Drupal\contact\Entity\Category;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
|
@ -76,26 +73,12 @@ function contact_menu() {
|
|||
);
|
||||
$items['contact/%contact_category'] = array(
|
||||
'title' => 'Contact category form',
|
||||
'title callback' => 'entity_page_label',
|
||||
'title arguments' => array(1),
|
||||
'route_name' => 'contact.site_page_category',
|
||||
'type' => MENU_VISIBLE_IN_BREADCRUMB,
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback: Checks access for a user's personal contact form.
|
||||
*
|
||||
* @param $account
|
||||
* The user object of the user whose contact form is being requested.
|
||||
*
|
||||
* @see contact_menu()
|
||||
*/
|
||||
function _contact_personal_tab_access(UserInterface $account) {
|
||||
return \Drupal::service('access_manager')->checkNamedRoute('contact.personal_page', array('user' => $account->id()), \Drupal::currentUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_info().
|
||||
*/
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Page callbacks for the Contact module.
|
||||
*/
|
||||
|
||||
use Drupal\contact\Entity\Category;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Drupal\Component\Utility\String;
|
||||
|
||||
/**
|
||||
* Page callback: Presents the site-wide contact form.
|
||||
*
|
||||
* @param \Drupal\contact\Entity\Category $category
|
||||
* (optional) The contact category to use.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*
|
||||
* @see contact_menu()
|
||||
* @see contact_site_form_submit()
|
||||
* @ingroup forms
|
||||
*
|
||||
* @deprecated Use \Drupal\contact\Controller\ContactController::contactSitePage()
|
||||
*/
|
||||
function contact_site_page(Category $category = NULL) {
|
||||
// Check if flood control has been activated for sending e-mails.
|
||||
if (!user_access('administer contact forms')) {
|
||||
contact_flood_control();
|
||||
}
|
||||
|
||||
if (!isset($category)) {
|
||||
$categories = entity_load_multiple('contact_category');
|
||||
$default_category = \Drupal::config('contact.settings')->get('default_category');
|
||||
if (isset($categories[$default_category])) {
|
||||
$category = $categories[$default_category];
|
||||
}
|
||||
// If there are no categories, do not display the form.
|
||||
else {
|
||||
if (user_access('administer contact forms')) {
|
||||
drupal_set_message(t('The contact form has not been configured. <a href="@add">Add one or more categories</a> to the form.', array('@add' => url('admin/structure/contact/add'))), 'error');
|
||||
return array();
|
||||
}
|
||||
else {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($category->id() == 'personal') {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$message = entity_create('contact_message', array(
|
||||
'category' => $category->id(),
|
||||
));
|
||||
$form = \Drupal::entityManager()->getForm($message);
|
||||
$form['#title'] = String::checkPlain($category->label());
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback: Form constructor for the personal contact form.
|
||||
*
|
||||
* @param $recipient
|
||||
* The account for which a personal contact form should be generated.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*
|
||||
* @see contact_menu()
|
||||
* @see contact_personal_form_submit()
|
||||
*
|
||||
* @ingroup forms
|
||||
*
|
||||
* @deprecated Use \Drupal\contact\Controller\ContactController::contactPersonalPage()
|
||||
*/
|
||||
function contact_personal_page($recipient) {
|
||||
global $user;
|
||||
|
||||
// Check if flood control has been activated for sending e-mails.
|
||||
if (!user_access('administer contact forms') && !user_access('administer users')) {
|
||||
contact_flood_control();
|
||||
}
|
||||
|
||||
$message = entity_create('contact_message', array(
|
||||
'recipient' => $recipient,
|
||||
'category' => 'personal',
|
||||
));
|
||||
$form = \Drupal::entityManager()->getForm($message);
|
||||
$form['#title'] = t('Contact @username', array('@username' => $recipient->getUsername()));
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the current user is not allowed to submit a contact form.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*
|
||||
* @see contact_site_page()
|
||||
* @see contact_personal_page()
|
||||
*/
|
||||
function contact_flood_control() {
|
||||
$config = \Drupal::config('contact.settings');
|
||||
$limit = $config->get('flood.limit');
|
||||
$interval = $config->get('flood.interval');
|
||||
if (!\Drupal::service('flood')->isAllowed('contact', $limit, $interval)) {
|
||||
drupal_set_message(t("You cannot send more than %limit messages in @interval. Try again later.", array(
|
||||
'%limit' => $limit,
|
||||
'@interval' => format_interval($interval),
|
||||
)), 'error');
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
contact.category_delete:
|
||||
path: '/admin/structure/contact/manage/{contact_category}/delete'
|
||||
defaults:
|
||||
_entity_form: contact_category.delete
|
||||
_entity_form: 'contact_category.delete'
|
||||
_title: 'Delete'
|
||||
requirements:
|
||||
_entity_access: contact_category.delete
|
||||
_entity_access: 'contact_category.delete'
|
||||
|
||||
contact.category_list:
|
||||
path: '/admin/structure/contact'
|
||||
|
@ -17,7 +17,7 @@ contact.category_list:
|
|||
contact.category_add:
|
||||
path: '/admin/structure/contact/add'
|
||||
defaults:
|
||||
_entity_form: contact_category.add
|
||||
_entity_form: 'contact_category.add'
|
||||
_title: 'Add category'
|
||||
requirements:
|
||||
_permission: 'administer contact forms'
|
||||
|
@ -25,10 +25,10 @@ contact.category_add:
|
|||
contact.category_edit:
|
||||
path: '/admin/structure/contact/manage/{contact_category}'
|
||||
defaults:
|
||||
_entity_form: contact_category.edit
|
||||
_entity_form: 'contact_category.edit'
|
||||
_title: 'Edit contact category'
|
||||
requirements:
|
||||
_entity_access: contact_category.update
|
||||
_entity_access: 'contact_category.update'
|
||||
|
||||
contact.site_page:
|
||||
path: '/contact'
|
||||
|
@ -45,7 +45,7 @@ contact.site_page_category:
|
|||
_title: 'Contact category form'
|
||||
_content: '\Drupal\contact\Controller\ContactController::contactSitePage'
|
||||
requirements:
|
||||
_permission: 'access site-wide contact form'
|
||||
_entity_access: 'contact_category.view'
|
||||
|
||||
contact.personal_page:
|
||||
path: '/user/{user}/contact'
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Drupal\contact;
|
|||
use Drupal\Core\Entity\EntityAccessController;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines an access controller for the contact category entity.
|
||||
*
|
||||
|
@ -21,12 +22,17 @@ class CategoryAccessController extends EntityAccessController {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
if ($operation == 'delete' || $operation == 'update') {
|
||||
// Do not allow delete 'personal' category used for personal contact form.
|
||||
return user_access('administer contact forms', $account) && $entity->id() !== 'personal';
|
||||
if ($operation == 'view') {
|
||||
// Do not allow access personal category via site-wide route.
|
||||
return $account->hasPermission('access site-wide contact form') && $entity->id() !== 'personal';
|
||||
}
|
||||
elseif ($operation == 'delete' || $operation == 'update') {
|
||||
// Do not allow the 'personal' category to be deleted, as it's used for
|
||||
// the personal contact form.
|
||||
return $account->hasPermission('administer contact forms') && $entity->id() !== 'personal';
|
||||
}
|
||||
else {
|
||||
return user_access('administer contact forms', $account);
|
||||
return $account->hasPermission('administer contact forms');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,28 +7,135 @@
|
|||
|
||||
namespace Drupal\contact\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Flood\FloodInterface;
|
||||
use Drupal\contact\CategoryInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Drupal\Component\Utility\String;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Controller routines for contact routes.
|
||||
*/
|
||||
class ContactController {
|
||||
class ContactController extends ControllerBase implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* @todo Remove contact_site_page().
|
||||
* The flood service.
|
||||
*
|
||||
* @var \Drupal\Core\Flood\FloodInterface
|
||||
*/
|
||||
public function contactSitePage(CategoryInterface $contact_category = NULL) {
|
||||
module_load_include('pages.inc', 'contact');
|
||||
return contact_site_page($contact_category);
|
||||
protected $flood;
|
||||
|
||||
/**
|
||||
* Constructs a ContactController object.
|
||||
*
|
||||
* @param \Drupal\Core\Flood\FloodInterface $flood
|
||||
* The flood service.
|
||||
*/
|
||||
public function __construct(FloodInterface $flood) {
|
||||
$this->flood = $flood;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Remove contact_personal_page().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('flood')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the site-wide contact form.
|
||||
*
|
||||
* @param \Drupal\contact\CategoryInterface $contact_category
|
||||
* The contact category 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 category form.
|
||||
*/
|
||||
public function contactSitePage(CategoryInterface $contact_category = NULL) {
|
||||
// Check if flood control has been activated for sending e-mails.
|
||||
if (!$this->currentUser()->hasPermission('administer contact forms')) {
|
||||
$this->contactFloodControl();
|
||||
}
|
||||
|
||||
// Use the default category if no category has been passed.
|
||||
if (empty($contact_category)) {
|
||||
$contact_category = $this->entityManager()
|
||||
->getStorageController('contact_category')
|
||||
->load($this->config('contact.settings')->get('default_category'));
|
||||
// If there are no categories, do not display the form.
|
||||
if (empty($contact_category)) {
|
||||
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 categories</a> to the form.', array(
|
||||
'@add' => $this->urlGenerator()->generateFromRoute('contact.category_add'))), 'error');
|
||||
return array();
|
||||
}
|
||||
else {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message = $this->entityManager()
|
||||
->getStorageController('contact_message')
|
||||
->create(array(
|
||||
'category' => $contact_category->id(),
|
||||
));
|
||||
|
||||
$form = $this->entityManager()->getForm($message);
|
||||
$form['#title'] = String::checkPlain($contact_category->label());
|
||||
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().
|
||||
*/
|
||||
public function contactPersonalPage(UserInterface $user) {
|
||||
module_load_include('pages.inc', 'contact');
|
||||
return contact_personal_page($user);
|
||||
// Check if flood control has been activated for sending e-mails.
|
||||
if (!$this->currentUser()->hasPermission('administer contact forms') && !$this->currentUser()->hasPermission('administer users')) {
|
||||
$this->contactFloodControl();
|
||||
}
|
||||
|
||||
$message = $this->entityManager()->getStorageController('contact_message')->create(array(
|
||||
'category' => 'personal',
|
||||
'recipient' => $user->id(),
|
||||
));
|
||||
|
||||
$form = $this->entityManager()->getForm($message);
|
||||
$form['#title'] = $this->t('Contact @username', array('@username' => $user->getUsername()));
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the current user triggers flood control.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
protected function contactFloodControl() {
|
||||
$limit = $this->config('contact.settings')->get('flood.limit');
|
||||
$interval = $this->config('contact.settings')->get('flood.interval');
|
||||
if (!$this->flood->isAllowed('contact', $limit, $interval)) {
|
||||
drupal_set_message($this->t('You cannot send more than %limit messages in @interval. Try again later.', array(
|
||||
'%limit' => $limit,
|
||||
'@interval' => format_interval($interval),
|
||||
)), 'error');
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
|
||||
namespace Drupal\contact\Plugin\views\field;
|
||||
|
||||
use Drupal\Core\Access\AccessManager;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\user\Plugin\views\field\Link;
|
||||
use Drupal\views\ResultRow;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a field that links to the user contact page, if access is permitted.
|
||||
|
@ -20,6 +22,64 @@ use Drupal\views\ResultRow;
|
|||
*/
|
||||
class ContactLink extends Link {
|
||||
|
||||
/**
|
||||
* The access manager.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessManager
|
||||
*/
|
||||
protected $accessManager;
|
||||
|
||||
/**
|
||||
* Current user object.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Gets the current active user.
|
||||
*
|
||||
* @todo: https://drupal.org/node/2105123 put this method in
|
||||
* \Drupal\Core\Plugin\PluginBase instead.
|
||||
*
|
||||
* @return \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected function currentUser() {
|
||||
if (!$this->currentUser) {
|
||||
$this->currentUser = \Drupal::currentUser();
|
||||
}
|
||||
return $this->currentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ContactLink object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the plugin instance.
|
||||
* @param array $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Access\AccessManager $access_manager
|
||||
* The access manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, AccessManager $access_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->accessManager = $access_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('access_manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -50,15 +110,12 @@ class ContactLink extends Link {
|
|||
|
||||
// Check access when we pull up the user account so we know
|
||||
// if the user has made the contact page available.
|
||||
$uid = $entity->id();
|
||||
|
||||
$path = "user/$uid/contact";
|
||||
if (!_contact_personal_tab_access($entity)) {
|
||||
if (!$this->accessManager->checkNamedRoute('contact.personal_page', array('user' => $entity->id()), $this->currentUser())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->options['alter']['make_link'] = TRUE;
|
||||
$this->options['alter']['path'] = $path;
|
||||
$this->options['alter']['path'] = "user/{$entity->id()}/contact";
|
||||
|
||||
$title = t('Contact %user', array('%user' => $entity->name->value));
|
||||
$this->options['alter']['attributes'] = array('title' => $title);
|
||||
|
|
|
@ -90,6 +90,9 @@ class ContactSitewideTest extends WebTestBase {
|
|||
$this->drupalGet('contact');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText(t('The contact form has not been configured.'));
|
||||
// Test access personal category via site-wide contact page.
|
||||
$this->drupalGet('contact/personal');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Add categories.
|
||||
// Test invalid recipients.
|
||||
|
|
Loading…
Reference in New Issue