From 81dc679a4da40bf0fe49e39d327fe15c6c9b7e52 Mon Sep 17 00:00:00 2001 From: Paul McCrodden Date: Mon, 4 Jan 2016 19:57:33 +0900 Subject: [PATCH] Added access classes, actions and local tasks yaml files. --- message_private.links.action.yml | 74 +++++++++++ message_private.links.task.yml | 37 ++++++ message_private.module | 125 +----------------- message_private.routing.yml | 12 +- message_private.services.yml | 10 ++ .../MessagePrivateDeleteAccessCheck.php | 73 ++++++++++ src/Access/MessagePrivateViewAccessCheck.php | 73 ++++++++++ src/Controller/MessagePrivateController.php | 1 + src/Routing/RouteSubscriber.php | 28 +++- 9 files changed, 295 insertions(+), 138 deletions(-) create mode 100644 message_private.links.action.yml create mode 100644 message_private.links.task.yml create mode 100644 src/Access/MessagePrivateDeleteAccessCheck.php create mode 100644 src/Access/MessagePrivateViewAccessCheck.php diff --git a/message_private.links.action.yml b/message_private.links.action.yml new file mode 100644 index 0000000..5ef44c7 --- /dev/null +++ b/message_private.links.action.yml @@ -0,0 +1,74 @@ +#message_ui.create_message: +# route_name: message_ui.create_message +# title: 'Add message' +# appears_on: +# - view.message.page_1 + +#case 'user/%': +# // Add a 'Create a new message for %user' action link. +# if (is_array($router_item['page_arguments'])) { +# // Get the user object from page arguments. +# foreach ($router_item['page_arguments'] as $arg) { +# if (is_object($arg) && !empty($arg->uid)) { +# $to_user = $arg; +# } +# } +# } +# // Only display the local task on other users profile, not current user's. +# if (!empty($to_user) && $user->uid != $to_user->uid) { +# // @FIXME +#// menu_get_item() has been removed. To retrieve route information, use the +#// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). +#// +#// +#// @see https://www.drupal.org/node/2203305 +#// $item = menu_get_item('message/create/private-message'); +# +# $item['title'] = t('Create a new message for') . ' ' . $to_user->name; +# $item['localized_options']['query'] = array('field_message_user_ref' => $to_user->uid); +# $data['actions']['output'][] = array( +# '#theme' => 'menu_local_action', +# '#link' => $item, +# ); +# +# } +# break; + +#case 'user/%/messages': +# // Add a 'Create a new message' action link above message_private view. +# // @FIXME +#// menu_get_item() has been removed. To retrieve route information, use the +#// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). +#// +#// +#// @see https://www.drupal.org/node/2203305 +#// $item = menu_get_item('message/create/private-message'); +# +# $item['title'] = t('Create a new message'); +# $data['actions']['output'][] = array( +# '#theme' => 'menu_local_action', +# '#link' => $item, +# ); +# +# break; +# +#// Get from user to Add a 'Create a new message for %user' action link. +# $to_user = \Drupal::entityManager()->getStorage('user')->load($message->uid); +# // Display the local task on other users profile, not current user's. +# if (!empty($to_user) && $user->uid != $to_user->uid) { +# // @FIXME +#// menu_get_item() has been removed. To retrieve route information, use the +#// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). +#// +#// +#// @see https://www.drupal.org/node/2203305 +#// $item = menu_get_item('message/create/private-message'); +# +# $item['title'] = t('Create a new message for') . ' ' . $to_user->name; +# $item['localized_options']['query'] = array('field_message_user_ref' => $to_user->uid); +# $data['actions']['output'][] = array( +# '#theme' => 'menu_local_action', +# '#link' => $item, +# ); +# +# } \ No newline at end of file diff --git a/message_private.links.task.yml b/message_private.links.task.yml new file mode 100644 index 0000000..adb36de --- /dev/null +++ b/message_private.links.task.yml @@ -0,0 +1,37 @@ +# MENU_DEFAULT_LOCAL_TASK for 'message/%message/view'. +#message_ui.show_message.view: +# route_name: message_ui.show_message +# title: 'View' +# parent_id: message_ui.show_message +# weight: -10 +# +#message_ui.edit_message: +# route_name: message_ui.edit_message +# base_route: message_ui.show_message +# title: 'Edit' +# weight: 0 +# +#message_ui.delete_message: +# route_name: message_ui.delete_message +# base_route: message_ui.show_message +# title: 'Delete' +# weight: 10 + +# case 'message/%': +# $message = \Drupal::routeMatch()->getParameter('message', 1, $router_item['href']); +# if (isset($message->type) && $message->type == 'private_message') { +# // Add a Messages tab to the private_message Message entities. +# // @FIXME +#// menu_get_item() has been removed. To retrieve route information, use the +#// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). +#// +#// +#// @see https://www.drupal.org/node/2203305 +#// $item = menu_get_item('user/' . $user->uid . '/messages'); +# +# $item['title'] = t('Messages'); +# $data['tabs'][0]['output'][] = array( +# '#theme' => 'menu_local_task', +# '#link' => $item, +# ); +# } diff --git a/message_private.module b/message_private.module index 52eef8a..5f86262 100755 --- a/message_private.module +++ b/message_private.module @@ -91,29 +91,6 @@ function message_private_access_callback($message) { return FALSE; } -/** - * Implements hook_menu_alter(). - * - * Override some of the menu paths set in message ui module. - */ -function message_private_menu_alter(&$items) { - - // Override access callbacks. - // @todo: add appropriate callbacks to services refering to node.services.yml. - $items['message/%message']['access callback'] = 'message_private_access_control'; - $items['message/%message/view']['access callback'] = 'message_private_access_control'; - $items['message/%message/edit']['access callback'] = 'message_private_access_control'; - $items['message/%message/delete']['access callback'] = 'message_private_access_control'; - - // Override page created by message_ui to allow custom "Private Message" URI. - $items['admin/content/message/create']['page callback'] = 'message_private_create_new_message_instance_list'; - - // Unset menu item created by message_ui for private_message type. - unset($items['admin/content/message/create/private-message']); - - return $items; -} - /** * Implements hook_form_FORM_ID_alter(). * @@ -146,106 +123,6 @@ function message_private_form_message_private_message_form_alter(&$form, \Drupal } } -/** - * Implements hook_menu_local_tasks_alter(). - */ -// @todo - remove in place of a dynamic local task class. -function message_private_menu_local_tasks_alter(&$data, $router_item, $root_path) { - $user = \Drupal::currentUser(); - - switch ($root_path) { - case 'user/%': - // Add a 'Create a new message for %user' action link. - if (is_array($router_item['page_arguments'])) { - // Get the user object from page arguments. - foreach ($router_item['page_arguments'] as $arg) { - if (is_object($arg) && !empty($arg->uid)) { - $to_user = $arg; - } - } - } - // Only display the local task on other users profile, not current user's. - if (!empty($to_user) && $user->uid != $to_user->uid) { - // @FIXME -// menu_get_item() has been removed. To retrieve route information, use the -// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). -// -// -// @see https://www.drupal.org/node/2203305 -// $item = menu_get_item('message/create/private-message'); - - $item['title'] = t('Create a new message for') . ' ' . $to_user->name; - $item['localized_options']['query'] = array('field_message_user_ref' => $to_user->uid); - $data['actions']['output'][] = array( - '#theme' => 'menu_local_action', - '#link' => $item, - ); - - } - break; - - case 'user/%/messages': - // Add a 'Create a new message' action link above message_private view. - // @FIXME -// menu_get_item() has been removed. To retrieve route information, use the -// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). -// -// -// @see https://www.drupal.org/node/2203305 -// $item = menu_get_item('message/create/private-message'); - - $item['title'] = t('Create a new message'); - $data['actions']['output'][] = array( - '#theme' => 'menu_local_action', - '#link' => $item, - ); - - break; - - case 'message/%': - $message = \Drupal::routeMatch()->getParameter('message', 1, $router_item['href']); - if (isset($message->type) && $message->type == 'private_message') { - // Add a Messages tab to the private_message Message entities. - // @FIXME -// menu_get_item() has been removed. To retrieve route information, use the -// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). -// -// -// @see https://www.drupal.org/node/2203305 -// $item = menu_get_item('user/' . $user->uid . '/messages'); - - $item['title'] = t('Messages'); - $data['tabs'][0]['output'][] = array( - '#theme' => 'menu_local_task', - '#link' => $item, - ); - - // Get from user to Add a 'Create a new message for %user' action link. - $to_user = \Drupal::entityManager()->getStorage('user')->load($message->uid); - // Display the local task on other users profile, not current user's. - if (!empty($to_user) && $user->uid != $to_user->uid) { - // @FIXME -// menu_get_item() has been removed. To retrieve route information, use the -// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch(). -// -// -// @see https://www.drupal.org/node/2203305 -// $item = menu_get_item('message/create/private-message'); - - $item['title'] = t('Create a new message for') . ' ' . $to_user->name; - $item['localized_options']['query'] = array('field_message_user_ref' => $to_user->uid); - $data['actions']['output'][] = array( - '#theme' => 'menu_local_action', - '#link' => $item, - ); - - } - } - break; - - } -} - /** * Validation for Private Message form. * @@ -349,7 +226,7 @@ function message_private_message_insert(\Drupal\message\MessageInterface $messag * If email notifications are disabled, hide the per user setting on user * profiles, unless the user is in role with bypass access control permission. */ -// @todo - check form ID is matching D8 form id. +// @todo - check form ID matches D8 form id & add config for user notify field. function message_private_form_user_profile_form_alter(&$form, &$form_state, $form_id) { // @FIXME // // @FIXME diff --git a/message_private.routing.yml b/message_private.routing.yml index 086caa6..7711e00 100644 --- a/message_private.routing.yml +++ b/message_private.routing.yml @@ -19,14 +19,4 @@ message_private.messages: message_private.messages.inbox: route_name: message_private.messages title: 'Inbox' - parent_id: message_private.messages - -message_private.create_message: - route_name: message_ui.create_message_by_type - title: 'Create Private Message' - description: 'Create a new message Private Message instance' - options: - parameters: - message_type: 'private-message' - requirements: - _message_private_add_access: 'message:private_message' \ No newline at end of file + parent_id: message_private.messages \ No newline at end of file diff --git a/message_private.services.yml b/message_private.services.yml index 786a1f5..c1856e8 100644 --- a/message_private.services.yml +++ b/message_private.services.yml @@ -1,4 +1,9 @@ services: + access_check.message_private.view: + class: Drupal\message_private\Access\MessagePrivateViewAccessCheck + arguments: ['@entity.manager'] + tags: + - { name: access_check, applies_to: _message_private_view_access } access_check.message_private.add: class: Drupal\message_private\Access\MessagePrivateAddAccessCheck arguments: ['@entity.manager'] @@ -9,6 +14,11 @@ services: arguments: ['@entity.manager'] tags: - { name: access_check, applies_to: _message_private_edit_access } + access_check.message_private.delete: + class: Drupal\message_private\Access\MessagePrivateDeleteAccessCheck + arguments: ['@entity.manager'] + tags: + - { name: access_check, applies_to: _message_private_delete_access } message_private.route_subscriber: class: Drupal\message_private\Routing\RouteSubscriber tags: diff --git a/src/Access/MessagePrivateDeleteAccessCheck.php b/src/Access/MessagePrivateDeleteAccessCheck.php new file mode 100644 index 0000000..451074f --- /dev/null +++ b/src/Access/MessagePrivateDeleteAccessCheck.php @@ -0,0 +1,73 @@ +entityManager = $entity_manager; + } + + /** + * Checks access to the message add page for the message type. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The currently logged in account. + * @param \Drupal\message\MessageTypeInterface $message_type + * (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. + */ + public function access(AccountInterface $account, MessageTypeInterface $message_type = 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(); + } + if ($message_type) { + return $access_control_handler->createAccess($message_type->id(), $account, [], TRUE); + } + // 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; + } + } + + // No opinion. + return AccessResult::neutral(); + } + +} diff --git a/src/Access/MessagePrivateViewAccessCheck.php b/src/Access/MessagePrivateViewAccessCheck.php new file mode 100644 index 0000000..320919f --- /dev/null +++ b/src/Access/MessagePrivateViewAccessCheck.php @@ -0,0 +1,73 @@ +entityManager = $entity_manager; + } + + /** + * Checks access to the message add page for the message type. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The currently logged in account. + * @param \Drupal\message\MessageTypeInterface $message_type + * (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. + */ + public function access(AccountInterface $account, MessageTypeInterface $message_type = 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(); + } + if ($message_type) { + return $access_control_handler->createAccess($message_type->id(), $account, [], TRUE); + } + // 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; + } + } + + // No opinion. + return AccessResult::neutral(); + } + +} diff --git a/src/Controller/MessagePrivateController.php b/src/Controller/MessagePrivateController.php index ac2f7a6..68e6a2c 100644 --- a/src/Controller/MessagePrivateController.php +++ b/src/Controller/MessagePrivateController.php @@ -12,6 +12,7 @@ use Drupal\message\Entity\MessageType; use Drupal\message\Entity\Message; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\message_ui\Controller\MessageViewController; class MessagePrivateController extends ControllerBase implements ContainerInjectionInterface { diff --git a/src/Routing/RouteSubscriber.php b/src/Routing/RouteSubscriber.php index 7b9e4fb..827b0b1 100644 --- a/src/Routing/RouteSubscriber.php +++ b/src/Routing/RouteSubscriber.php @@ -19,6 +19,26 @@ class RouteSubscriber extends RouteSubscriberBase { * {@inheritdoc} */ protected function alterRoutes(RouteCollection $collection) { + // @todo - check for message_type of 'private_message' and if so, set. + // Message viewing. + $route = $collection->get('message_ui.show_message'); + if ($route) { + $route->setRequirements(array( + '_message_private_view_access' => '{message}', + )); + } + // Message creation types list. + $route = $collection->get('message_ui.create_message'); + if ($route) { + // $route->setDefault('controller', '\Drupal\message_private\Controller\MessagePrivateController::showTypes'); + } + // Message create by private message type. + $route = $collection->get('message_ui.create_message_by_type'); + if ($route) { + $route->setRequirements(array( + '_message_private_add_access:' => 'message:private_message', + )); + } // Modify Message edit form to have private message access permissions. $route = $collection->get('message_ui.edit_message'); if ($route) { @@ -26,10 +46,12 @@ protected function alterRoutes(RouteCollection $collection) { '_message_private_edit_access' => '{message}', )); } - $route = $collection->get('message_ui.create_message'); + // Message deletion. + $route = $collection->get('message_ui.delete_message'); if ($route) { - // @todo - check for message_type of 'private_message' and if so, set. - // $route->setDefault('controller', '\Drupal\message_private\Controller\MessagePrivateController::showTypes'); + $route->setRequirements(array( + '_message_private_delete_access' => '{message}', + )); } } }