From 25638fe667dad128d20d6934c5c01ae88e07259f Mon Sep 17 00:00:00 2001 From: Paul McCrodden Date: Fri, 1 Jan 2016 06:41:58 +0900 Subject: [PATCH] Converted hook_form_FORM_ID_alter on message edit form and added access handler class. --- message_private.module | 73 +++++--------- src/MessagePrivateAccessControlHandler.php | 111 +++++++++++++++++++++ 2 files changed, 138 insertions(+), 46 deletions(-) create mode 100644 src/MessagePrivateAccessControlHandler.php diff --git a/message_private.module b/message_private.module index 6c87a15..52eef8a 100755 --- a/message_private.module +++ b/message_private.module @@ -58,6 +58,20 @@ function message_private_help($route_name, RouteMatchInterface $arg) { } } +/** + * Implements hook_entity_type_alter. + * + * Extend the message entity type by providing form handlers. + * @todo : can access handler be added to certain bundle only? + */ +function message_ui_entity_type_alter(array &$entity_types) { + if (isset($entity_types['message'])) { + /* @var $message_config \Drupal\Core\Config\Entity\ConfigEntityType */ + $message_config = $entity_types['message']; + $message_config->setAccessClass('Drupal\message_private\MessagePrivateAccessControlHandler'); + } +} + /** * Access callback for Messages tab. * @@ -108,60 +122,27 @@ function message_private_menu_alter(&$items) { * the message_text on the edit and create form, and adds custom validation. */ // @todo - check form ID is matching D8 form id. -function message_private_form_message_ui_instance_message_manage_alter(&$form, &$form_state, $form_id) { - if (!empty($form_state['#entity']) && $form_state['#entity']->type == 'private_message') { + +function message_private_form_message_private_message_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { + $entity = $form_state->getFormObject()->getEntity(); + if ($entity->bundle() == 'private_message') { $user = \Drupal::currentUser(); - $referer = $_SERVER['HTTP_REFERER']; // Get the referrer uri from globals. + /* // There is no cancel link on node form, so this may be unnecessary now. + $referer = $_SERVER['HTTP_REFERER']; // Get the referrer uri from globals. // Redirect back to referer uri is exists, otherwise to user message inbox. // @FIXME // l() expects a Url object, created from a route name or external URI. // $form['actions']['cancel']['#markup'] = - l(t('Cancel'), (!empty($referer) ? $referer : 'user/'. $user->uid . '/messages')); - + l(t('Cancel'), (!empty($referer) ? $referer : 'user/'. $user->uid . '/messages'));*/ if (isset($form['text']['#type'])) { - $form['text']['#type'] = 'hidden'; + $form['text']['#type'] = 'hidden'; // @todo - is this necessary now? } - $form['owner']['#access'] = \Drupal::currentUser()->hasPermission('bypass private message access control'); - $form['#validate'][] = 'message_private_form_message_private_instance_message_manage_validate'; - } -} -/** - * Implements hook_form_FORM_ID_alter(). - * - * Override redirect for private messages. - */ -// @todo - check form ID is matching D8 form id. -function message_private_form_message_ui_instance_delete_alter(&$form, &$form_state, $form_id) { - if (!empty($form_state['#entity']) && $form_state['#entity']->type == 'private_message') { - $user = \Drupal::currentUser(); - $referer = $_SERVER['HTTP_REFERER']; // Get the referrer uri from globals. - // Redirect back to referer uri is exists, otherwise to user message inbox. - $form['actions']['cancel']['#href'] = !empty($referer) ? $referer : 'user/'. $user->uid . '/messages'; - - // Call custom submit callback for private messages. - $form['#submit'] = array('message_private_instance_delete_submit'); - } -} - -/** - * Custom submit callback for deleting private messages. - */ -// @todo - extend MessageForm provided by Message UI and override submitForm(). -function message_private_instance_delete_submit($form, &$form_state) { - if ($form_state['clicked_button']['#type']) { - $user = \Drupal::currentUser(); - - $form_state['#entity']->delete(); - - // Redirect back to user message inbox. - $form_state['redirect'] = 'user/' . $user->uid . '/messages'; - - drupal_set_message(t('The message instance @type deleted successfully', array( - '@type' => $form_state['#entity']->type, - ))); + // @todo - owner access and validation callback needs testing. + $form['owner']['#access'] = \Drupal::currentUser()->hasPermission('bypass private message access control'); + $form['#validate'][] = 'message_private_form_message_private_message_form_validate'; } } @@ -273,8 +254,8 @@ function message_private_menu_local_tasks_alter(&$data, $router_item, $root_path * @param mixed $form_state * The form state including values submitted. */ -// @todo - extend MessageForm in Message UI and override validateForm(). -function message_private_form_message_private_instance_message_manage_validate($form, &$form_state) { +// @todo - test this is called and if form should be passed by reference. +function message_private_form_message_private_message_form_validate($form, \Drupal\Core\Form\FormStateInterface $form_state) { // If there is an imposed message limit set in the admin settings interface. // @FIXME // // @FIXME diff --git a/src/MessagePrivateAccessControlHandler.php b/src/MessagePrivateAccessControlHandler.php new file mode 100644 index 0000000..3511a29 --- /dev/null +++ b/src/MessagePrivateAccessControlHandler.php @@ -0,0 +1,111 @@ +prepareUser($account); + + if ($account->hasPermission('bypass node access')) { + $result = AccessResult::allowed()->cachePerPermissions(); + return $return_as_object ? $result : $result->isAllowed(); + } + if (!$account->hasPermission('access content')) { + $result = AccessResult::forbidden()->cachePerPermissions(); + return $return_as_object ? $result : $result->isAllowed(); + } + $result = parent::access($entity, $operation, $account, TRUE)->cachePerPermissions(); + return $return_as_object ? $result : $result->isAllowed(); + } + + /** + * {@inheritdoc} + */ + public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = array(), $return_as_object = FALSE) { + $account = $this->prepareUser($account); + + if ($account->hasPermission('bypass node access')) { + $result = AccessResult::allowed()->cachePerPermissions(); + return $return_as_object ? $result : $result->isAllowed(); + } + if (!$account->hasPermission('access content')) { + $result = AccessResult::forbidden()->cachePerPermissions(); + return $return_as_object ? $result : $result->isAllowed(); + } + + $result = parent::createAccess($entity_bundle, $account, $context, TRUE)->cachePerPermissions(); + return $return_as_object ? $result : $result->isAllowed(); + } + + /** + * {@inheritdoc} + */ + protected function checkAccess(EntityInterface $message, $operation, AccountInterface $account) { + /** @var \Drupal\message\MessageInterface $message */ + + // Fetch information from the node object if possible. + $status = $message->isPublished(); + $uid = $message->getOwnerId(); + + // Check if authors can view their own unpublished nodes. + if ($operation === 'view' && !$status && $account->hasPermission('view own unpublished content') && $account->isAuthenticated() && $account->id() == $uid) { + return AccessResult::allowed()->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($message); + } + + // Evaluate node grants. + return $this->access($message, $operation, $account); + } + + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return AccessResult::allowedIf($account->hasPermission('create ' . $entity_bundle . ' content'))->cachePerPermissions(); + } +}