Skip to content

Commit

Permalink
Added Edit Access Check service and RouteSubscriber for MessageUi rou…
Browse files Browse the repository at this point in the history
…te overrides.
  • Loading branch information
mccrodp committed Dec 31, 2015
1 parent d4dc8f1 commit 780cc5e
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 108 deletions.
53 changes: 0 additions & 53 deletions message_private.module
Original file line number Diff line number Diff line change
Expand Up @@ -100,59 +100,6 @@ function message_private_menu_alter(&$items) {
return $items;
}

/**
* Override instance list provided by Message UI.
*
* Create links to all message create forms by type, allowing for creation of
* link to custom Private Message create form URI.
*
* @return null|string
* @throws Exception
*/
// @todo - remove in place of getAllowedInstanceList() override in Message UI.
function message_private_create_new_message_instance_list() {
$items = array();
$allowed_types = message_ui_user_can_create_message();

if ($types = message_ui_get_types()) {
foreach ($types as $type => $title) {
if ($allowed_types || (is_array($allowed_types) && $allowed_types[$type])) {
// Create links to message create forms.
if ($type != 'private_message') {
// @FIXME
// l() expects a Url object, created from a route name or external URI.
// $items[] = l($title, 'admin/content/message/create/' . str_replace('_', '-', $type));

}
else {
// Create link to customised menu item for private_message create.
// @FIXME
// l() expects a Url object, created from a route name or external URI.
// $items[] = l($title, 'message/create/' . str_replace('_', '-', $type));

}
}
}
}
else {
// @FIXME
// url() expects a route name or an external URI.
// return t("There are no messages types. You can create a new message type <a href='@url'>here</a>.", array('@url' => url('admin/structure/messages/add')));

}

// @FIXME
// theme() has been renamed to _theme() and should NEVER be called directly.
// Calling _theme() directly can alter the expected output and potentially
// introduce security issues (see https://www.drupal.org/node/2195739). You
// should use renderable arrays instead.
//
//
// @see https://www.drupal.org/node/2195739
// return theme('item_list', array('items' => $items));

}

/**
* Implements hook_form_FORM_ID_alter().
*
Expand Down
11 changes: 10 additions & 1 deletion message_private.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@ services:
class: Drupal\message_private\Access\MessagePrivateAddAccessCheck
arguments: ['@entity.manager']
tags:
- { name: access_check, applies_to: _message_private_add_access }
- { name: access_check, applies_to: _message_private_add_access }
access_check.message_private.edit:
class: Drupal\message_private\Access\MessagePrivateEditAccessCheck
arguments: ['@entity.manager']
tags:
- { name: access_check, applies_to: _message_private_edit_access }
message_private.route_subscriber:
class: Drupal\message_private\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
57 changes: 3 additions & 54 deletions src/Access/MessagePrivateAddAccessCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public function __construct(EntityManagerInterface $entity_manager) {
* @param \Drupal\Core\Session\AccountInterface $account
* The currently logged in account.
* @param \Drupal\message\MessageTypeInterface $message_type
* (optional) The node type. If not specified, access is allowed if there
* exists at least one node type for which the user may create a node.
* (optional) The message type. If not specified, access is allowed if there
* exists at least one message type for which the user may create a message.
*
* @return string
* A \Drupal\Core\Access\AccessInterface constant value.
Expand All @@ -59,64 +59,13 @@ public function access(AccountInterface $account, MessageTypeInterface $message_
if ($message_type) {
return $access_control_handler->createAccess($message_type->id(), $account, [], TRUE);
}
// If checking whether a node of any type may be created.
// If checking whether a message of any type may be created.
foreach ($this->entityManager->getStorage('message_type')->loadMultiple() as $message_type) {
if (($access = $access_control_handler->createAccess($message_type->id(), $account, [], TRUE)) && $access->isAllowed()) {
return $access;
}
}

// @todo: go through the below, previously message_private_access_control().
/**
if (empty($user_obj)) {
$user = \Drupal::currentUser();
$account = \Drupal::entityManager()->getStorage('user')->load($user->uid);
}
else {
$user = $user_obj;
$account = \Drupal::entityManager()->getStorage('user')->load($user->uid);
}
// Get the message type from the function argument or from the message object.
$type = is_object($message) ? $message->type : $message;
// If this is not a private message then use the message callback provided by
// message_ui module.
if ($type != 'private_message') {
return message_ui_access_control($operation, $message);
}
else {
if ($account->hasPermission('bypass private message access control')) {
return TRUE;
}
// Verify that the user can apply the op.
if ($account->hasPermission($operation . ' any message instance')
|| $account->hasPermission($operation . ' a ' . $type . ' message instance')
) {
if ($type == 'private_message' && $operation != 'create') {
// Check if the user is message author.
if ($message->uid == $account->uid) {
return TRUE;
}
$users = field_get_items('message', $message, 'field_message_user_ref');
if ($users && is_array($users)) {
foreach ($users as $user_ref) {
if ($user_ref['target_id'] == $account->uid) {
return TRUE;
}
}
}
}
else {
return TRUE;
}
}
}
return FALSE;
*/

// No opinion.
return AccessResult::neutral();
}
Expand Down
102 changes: 102 additions & 0 deletions src/Access/MessagePrivateEditAccessCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/**
* @file
* Contains \Drupal\message_private\Access\MessagePrivateEditAccessCheck.
*/

namespace Drupal\message_private\Access;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\message\MessageInterface;

/**
* Determines access to for message edit pages for private messages.
*
* @ingroup message_access
*/
class MessagePrivateEditAccessCheck implements AccessInterface {

/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;

/**
* Constructs a EntityCreateAccessCheck object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
*/
public function __construct(EntityManagerInterface $entity_manager) {
$this->entityManager = $entity_manager;
}

/**
* Checks access to the message edit page for the message entity.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The currently logged in account.
* @param \Drupal\message\MessageInterface $message
*
* @return string
* A \Drupal\Core\Access\AccessInterface constant value.
*/
public function access(AccountInterface $account, MessageInterface $message = NULL) {
$access_control_handler = $this->entityManager->getAccessControlHandler('message');
// If checking whether a node of a particular type may be created.
if ($account->hasPermission('administer message private')
|| $account->hasPermission('bypass private message access control')) {
return AccessResult::allowed()->cachePerPermissions();
}

// @todo: go through the below, previously message_private_access_control().

// Get the message type from the function argument or from the message object.
$type = $message->bundle();

// If this is not a private message then use the message callback provided
// by message_ui module.
if ($type != 'private_message') {
// No opinion.
return AccessResult::neutral();
}
else {
if ($account->hasPermission('bypass private message access control')) {
return TRUE;
}

$operation = 'edit';

// Verify that the user can apply the op.
if ($account->hasPermission($operation . ' any message instance')
|| $account->hasPermission($operation . ' a ' . $type . ' message instance')
) {
if ($type == 'private_message' && $operation != 'create') {
// Check if the user is message author.
/* @var $message \Drupal\message\Entity\Message */
if ($message->getAuthorId() == $account->id()) {
return TRUE;
}
$users = $message->get('field_message_user_ref');
if ($users && is_array($users)) {
foreach ($users as $user_ref) {
if ($user_ref['target_id'] == $account->id()) {
return TRUE;
}
}
}
}
else {
return TRUE;
}
}
}
return FALSE;
}
}
140 changes: 140 additions & 0 deletions src/Controller/MessagePrivateController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php
/**
* @file
* Contains \Drupal\message_ui\Controller\MessagePrivateController.
*/

namespace Drupal\message_private\Controller;

use Drupal\Core\Url;
use Drupal\Core\Controller\ControllerBase;
use Drupal\message\MessageInterface;
use Drupal\message\Entity\MessageType;
use Drupal\message\Entity\Message;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;


class MessagePrivateController extends ControllerBase implements ContainerInjectionInterface {

/**
* Constructs a MessageUiController object.
*/
public function __construct() {
// @todo: should I be using Dependency Injection here?
$this->entityManager = \Drupal::entityManager();
}

/**
* Display list of message types to create an instance for them.
*
*/
// @todo - remove note: message_ui_create_new_message_instance_list in D7.
public function getAllowedInstanceList() {
// $access_controller = new MessageAccessControlHandler('message');
// $allowed_types = $access_controller->userCreateMessageAccess();

/*
// From D7 message_private instance list override fn:
$items = array();
$allowed_types = message_ui_user_can_create_message();
if ($types = message_ui_get_types()) {
foreach ($types as $type => $title) {
if ($allowed_types || (is_array($allowed_types) && $allowed_types[$type])) {
// Create links to message create forms.
if ($type != 'private_message') {
// @FIXME
// l() expects a Url object, created from a route name or external URI.
// $items[] = l($title, 'admin/content/message/create/' . str_replace('_', '-', $type));
}
else {
// Create link to customised menu item for private_message create.
// @FIXME
// l() expects a Url object, created from a route name or external URI.
// $items[] = l($title, 'message/create/' . str_replace('_', '-', $type));
}
}
}
}
else {
// @FIXME
// url() expects a route name or an external URI.
// return t("There are no messages types. You can create a new message type <a href='@url'>here</a>.", array('@url' => url('admin/structure/messages/add')));
}
// @FIXME
// theme() has been renamed to _theme() and should NEVER be called directly.
// Calling _theme() directly can alter the expected output and potentially
// introduce security issues (see https://www.drupal.org/node/2195739). You
// should use renderable arrays instead.
//
//
// @see https://www.drupal.org/node/2195739
// return theme('item_list', array('items' => $items));
*/

// @todo - replace this line with access controlled type list:
$allowed_types = MessageType::loadMultiple();

if ($types = MessageType::loadMultiple()) {
foreach ($types as $type) {
if ($allowed_types || (is_array($allowed_types) && array_key_exists($type, $allowed_types))) {
return $allowed_types;
}
}
}
return FALSE;
}

/**
* Generates output of all message type entities with permission to create.
*
* @return array
* An array as expected by drupal_render().
*/
public function showTypes() {
// $account = $this->currentUser();

// @todo add access control for message_type, see message_ui_access_control.

$items = array();
// @todo : Use the following or MessageType's method? $this->entityManager()->getStorage('message_type')->loadMultiple()
// Only use node types the user has access to.
// @todo - override the path for private messages, or is there a better way?
foreach ($this->getAllowedInstanceList() as $type => $entity) {
// @todo - get access control working below.
// \Doctrine\Common\Util\Debug::dump($this->entityManager()->getAccessControlHandler('message')->createAccess($type->id()));
// if ($this->entityManager()->getAccessControlHandler('message')->createAccess($type->id())) {
/* @var $entity MessageType */
$url = Url::fromUri('internal:/admin/content/messages/create/' . str_replace('_', '-', $type));
$items[] = array(
'type' => $type,
'name' => $entity->label(),
'internal_link' => \Drupal::l(ucfirst(str_replace('_', ' ', $type)), $url),
);
//\Doctrine\Common\Util\Debug::dump($content);
// }
}

// Bypass the admin/content/messages/create listing if only one content type is available.
/* if (count($content) == 1) {
$type = array_shift($content);
return $this->redirect('message_ui.create_message_by_type', array('message_type' => $type->id()));
} */

if ($items) {
return array(
'#theme' => 'instance_item_list',
'#items' => $items,
'#type' => 'ul'
);
}
else {
$url = Url::fromRoute('message.type_add');
return t("There are no messages types. You can create a new message type <a href='$url'>here</a>.");
}
}
}
Loading

0 comments on commit 780cc5e

Please sign in to comment.