From f20dc7929da1e0543fbb63b4ff9e685e65592850 Mon Sep 17 00:00:00 2001 From: "Matthew Wire (MJW Consulting)" Date: Thu, 16 Aug 2018 17:51:03 +0100 Subject: [PATCH] Extension of https://github.com/civicrm/civicrm-core/pull/12424 --- CRM/Event/BAO/Event.php | 116 ++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 22 deletions(-) diff --git a/CRM/Event/BAO/Event.php b/CRM/Event/BAO/Event.php index 2e6c5e0bd70e..ccdf5834c42f 100644 --- a/CRM/Event/BAO/Event.php +++ b/CRM/Event/BAO/Event.php @@ -2063,30 +2063,106 @@ public static function checkRegistration($params) { * @param int $eventId * @param int $type * - * @return string - * the permission that the user has (or null) + * @return bool|array + * Whether the user has permission for this event (or if eventId=NULL an array of permissions) + * @throws \CiviCRM_API3_Exception */ public static function checkPermission($eventId = NULL, $type = CRM_Core_Permission::VIEW) { - if (!isset(Civi::$statics[__CLASS__]['permissions'])) { - $params = array( - 'check_permissions' => 1, - 'return' => 'title', - 'options' => array( - 'limit' => 0, - ), - ); + if (empty($eventId)) { + return self::getAllPermissions($type); + } + + if ($type == CRM_Core_Permission::VIEW) { + if (!isset(Civi::$statics[__CLASS__]['permission']['view'][$eventId])) { + Civi::$statics[__CLASS__]['permission']['view'][$eventId] = FALSE; - if ($eventId) { - $params['id'] = $eventId; + list($allEvents, $createdEvents) = self::checkPermissionGetInfo($eventId); + if (CRM_Core_Permission::check('access CiviEvent') && CRM_Core_Permission::check('view event participants')) { + // use case: allow "view all events" but NOT "edit all events" + // so for a normal site allow users with these two permissions to view all events AND + // at the same time also allow any hook to override if needed. + if (in_array($eventId, CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_event', $allEvents, array_keys($allEvents)))) { + Civi::$statics[__CLASS__]['permission']['view'][$eventId] = TRUE; + } + } } + return Civi::$statics[__CLASS__]['permission']['view'][$eventId]; + } - $result = civicrm_api3('Event', 'get', $params); - $allEvents = CRM_Utils_Array::collect('title', $result['values']); + if ($type == CRM_Core_Permission::EDIT) { + if (!isset(Civi::$statics[__CLASS__]['permission']['edit'][$eventId])) { + Civi::$statics[__CLASS__]['permission']['edit'][$eventId] = FALSE; - // Search again, but only events created by the user. - $params['created_id'] = 'user_contact_id'; - $result = civicrm_api3('Event', 'get', $params); - $createdEvents = array_keys($result['values']); + list($allEvents, $createdEvents) = self::checkPermissionGetInfo($eventId); + // Note: for a multisite setup, a user with edit all events, can edit all events + // including those from other sites + if (($type == CRM_Core_Permission::EDIT) && CRM_Core_Permission::check('edit all events')) { + Civi::$statics[__CLASS__]['permission']['edit'][$eventId] = TRUE; + } + elseif (in_array($eventId, CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_event', $allEvents, $createdEvents))) { + Civi::$statics[__CLASS__]['permission']['edit'][$eventId] = TRUE; + } + } + return Civi::$statics[__CLASS__]['permission']['edit'][$eventId]; + } + + if ($type == CRM_Core_Permission::DELETE) { + if (!isset(Civi::$statics[__CLASS__]['permission']['delete'][$eventId])) { + Civi::$statics[__CLASS__]['permission']['delete'][$eventId] = FALSE; + if (CRM_Core_Permission::check('delete in CiviEvent')) { + Civi::$statics[__CLASS__]['permission']['delete'][$eventId] = TRUE; + } + } + return Civi::$statics[__CLASS__]['permission']['delete'][$eventId]; + } + } + + /** + * This is a helper for refactoring checkPermission + * FIXME: We should be able to get rid of these arrays, but that would require understanding how CRM_ACL_API::group actually works! + * + * @param int $eventId + * + * @return array $allEvents, $createdEvents + * @throws \CiviCRM_API3_Exception + */ + private static function checkPermissionGetInfo($eventId = NULL) { + $params = [ + 'check_permissions' => 1, + 'return' => 'id, created_id', + 'options' => ['limit' => 0], + ]; + if ($eventId) { + $params['id'] = $eventId; + } + + $allEvents = []; + $createdEvents = []; + $eventResult = civicrm_api3('Event', 'get', $params); + if ($eventResult['count'] > 0) { + $contactId = CRM_Core_Session::getLoggedInContactID(); + foreach ($eventResult['values'] as $eventId => $eventDetail) { + $allEvents[$eventId] = $eventId; + if (isset($eventDetails['created_id']) && $contactId == $eventDetail['created_id']) { + $createdEvents[$eventId] = $eventId; + } + } + } + return [$allEvents, $createdEvents]; + } + /** + * Make sure that the user has permission to access this event. + * + * @param int $type + * Type of CRM_Core_Permission + * + * @return array + * Array of events with permissions (array_keys=permissions) + * @throws \CiviCRM_API3_Exception + */ + public static function getAllPermissions($type = CRM_Core_Permission::VIEW) { + if (!isset(Civi::$statics[__CLASS__]['permissions'])) { + list($allEvents, $createdEvents) = self::checkPermissionGetInfo(); // Note: for a multisite setup, a user with edit all events, can edit all events // including those from other sites @@ -2123,10 +2199,6 @@ public static function checkPermission($eventId = NULL, $type = CRM_Core_Permiss } } - if ($eventId) { - return in_array($eventId, Civi::$statics[__CLASS__]['permissions'][$type]) ? TRUE : FALSE; - } - return Civi::$statics[__CLASS__]['permissions']; }