diff --git a/application/controllers/admin/participantsaction.php b/application/controllers/admin/participantsaction.php index ab4b42bbf86..84d9aba7fce 100644 --- a/application/controllers/admin/participantsaction.php +++ b/application/controllers/admin/participantsaction.php @@ -343,7 +343,7 @@ public function displayParticipants() Yii::app()->clientScript->registerPackage('bootstrap-datetimepicker'); Yii::app()->clientScript->registerPackage('bootstrap-switch'); - $aData['massiveAction'] = App()->getController()->renderPartial('/admin/participants/massive_actions/_selector', array(), true, false); + $aData['massiveAction'] = App()->getController()->renderPartial('/admin/participants/massive_actions/_selector', array('participantOwnerUid' => $participantParam['owner_uid'] ?? ''), true, false); // Set page size if ($request->getPost('pageSizeParticipantView')) { @@ -362,7 +362,8 @@ public function displayParticipants() public function deleteParticipant() { // Abort if no permission - if (!Permission::model()->hasGlobalPermission('participantpanel', 'delete')) { + $deletePermission = Permission::model()->hasGlobalPermission('participantpanel', 'delete'); + if (!$deletePermission) { ls\ajax\AjaxHelper::outputNoPermission(); } @@ -383,7 +384,7 @@ public function deleteParticipant() // Deletes from participants only $deletedParticipants = null; if ($selectoption == 'po') { - $deletedParticipants = Participant::model()->deleteParticipants($participantIds); + $deletedParticipants = Participant::model()->deleteParticipants($participantIds, !$deletePermission); } // Deletes from central and survey participants table else if ($selectoption == 'ptt') { diff --git a/application/models/Participant.php b/application/models/Participant.php index 30bf24ed9a5..587c5148f52 100755 --- a/application/models/Participant.php +++ b/application/models/Participant.php @@ -135,7 +135,8 @@ public function getButtons() // Only owner or superadmin can delete $userId = Yii::app()->user->id; $isSuperAdmin = Permission::model()->hasGlobalPermission('superadmin', 'read'); - if ($this->owner_uid == $userId || $isSuperAdmin) { + $deletePermission = Permission::model()->hasGlobalPermission('participantpanel', 'delete'); + if ($this->owner_uid == $userId || $isSuperAdmin || $deletePermission) { // Delete button $deleteData = array( 'action_participant_deleteModal', @@ -144,16 +145,6 @@ public function getButtons() 'trash text-danger' ); $buttons .= vsprintf($raw_button_template, $deleteData); - - // Share this participant - $infoData = array( - 'action_participant_shareParticipant', - '', - gT("Share this participant"), - 'share' - ); - $buttons .= vsprintf($raw_button_template, $infoData); - } else { // Invisible button $deleteData = array( @@ -163,15 +154,15 @@ public function getButtons() 'trash text-danger' ); $buttons .= vsprintf($raw_button_template, $deleteData); - $infoData = array( - 'action_participant_shareParticipant invisible', - '', - gT("Share this participant"), - 'share' - ); - $buttons .= vsprintf($raw_button_template, $infoData); } - + // Share this participant + $infoData = array( + 'action_participant_shareParticipant', + '', + gT("Share this participant"), + 'share' + ); + $buttons .= vsprintf($raw_button_template, $infoData); } else { // Three empty buttons for correct alignment // TODO: For some reason, the delete button is smaller than the others @@ -182,14 +173,30 @@ public function getButtons() 'edit' ); $buttons .= vsprintf($raw_button_template, $editData); - $buttons .= vsprintf($raw_button_template, $editData); - $deleteData = array( - 'action_participant_deleteModal invisible', - 'text-danger', - gT("Delete this participant"), - 'trash text-danger' - ); + $deletePermission = Permission::model()->hasGlobalPermission('participantpanel', 'delete'); + if ($deletePermission){ + $deleteData = array( + 'action_participant_deleteModal', + 'text-danger', + gT("Delete this participant"), + 'trash text-danger' + ); + } else { + $deleteData = array( + 'action_participant_deleteModal invisible', + 'text-danger', + gT("Delete this participant"), + 'trash text-danger' + ); + } $buttons .= vsprintf($raw_button_template, $deleteData); + $infoData = array( + 'action_participant_shareParticipant invisible', + '', + gT("Share this participant"), + 'share' + ); + $buttons .= vsprintf($raw_button_template, $infoData); } // Survey information @@ -527,11 +534,12 @@ public function search() $sort->attributes = $sortAttributes; $sort->defaultOrder = 't.lastname ASC'; - // Users can only see: 1) Participants they own; 2) participants shared with them; and 3) participants shared with everyone + // Users can only see: 1) Participants they own; 2) participants shared with them; and 3) participants shared with everyone 4) all participants if they have global permission // Superadmins can see all users. $isSuperAdmin = Permission::model()->hasGlobalPermission('superadmin', 'read'); - if (!$isSuperAdmin) { - $criteria->addCondition('t.owner_uid = '.Yii::app()->user->id.' OR '.Yii::app()->user->id.' = shares.share_uid OR shares.share_uid = -1'); + $readAllPermission = Permission::model()->hasGlobalPermission('participantpanel', 'read'); + if (!$isSuperAdmin && !$readAllPermission) { + $criteria->addCondition('t.owner_uid = '.App()->user->id.' OR '.Yii::app()->user->id.' = shares.share_uid OR shares.share_uid = -1'); } $pageSize = Yii::app()->user->getState('pageSizeParticipantView', Yii::app()->params['defaultPageSize']); @@ -996,12 +1004,12 @@ public function deleteParticipantTokenAnswer($sParticipantsIDs) ->where('participant_id = :row') ->bindParam(":row", $row, PDO::PARAM_INT) ->queryAll(); - - + + foreach ($tokens as $key => $surveyLink) { $surveyId = $surveyLink['survey_id']; $survey = Survey::model()->findByPk($surveyId); - + $tokentable = $survey->tokensTableName; if (Yii::app()->db->schema->getTable($tokentable)) { $tokenid = Yii::app()->db->createCommand() @@ -1010,7 +1018,7 @@ public function deleteParticipantTokenAnswer($sParticipantsIDs) ->where('participant_id = :pid') ->bindParam(":pid", $surveyLink['participant_id'], PDO::PARAM_INT) ->queryAll(); - + if(!isset($tokenid[0])) { continue; } @@ -1025,7 +1033,7 @@ public function deleteParticipantTokenAnswer($sParticipantsIDs) ->where('token = :token') ->bindParam(":token", $token['token'], PDO::PARAM_STR) ->queryAll(); - + if(isset($gettoken[0])) { $gettoken = $gettoken[0]; Yii::app()->db->createCommand() @@ -1041,9 +1049,9 @@ public function deleteParticipantTokenAnswer($sParticipantsIDs) } } } - + $iDeletedParticipants = $this->deleteParticipants($sParticipantsIDs, false); - + return $iDeletedParticipants; } @@ -2099,8 +2107,8 @@ public function userHasPermissionToEdit() $owner = $this->owner_uid == $userId; - if (Permission::model()->hasGlobalPermission('superadmin')) { - // Superadmins can do anything + if (Permission::model()->hasGlobalPermission('superadmin') || (Permission::model()->hasGlobalPermission('participantpanel', 'update'))) { + // Superadmins can do anything and users with global edit permission can to edit all participants return true; } else if ($shared && $shared->share_uid == -1 && $shared->can_edit) { // -1 = shared with everyone @@ -2161,7 +2169,7 @@ public function getLanguageOptions(){ return $returner; } public function getOwnerOptions(){ - + return []; } } diff --git a/application/views/admin/participants/massive_actions/_selector.php b/application/views/admin/participants/massive_actions/_selector.php index 387342d2f8e..801248048a9 100644 --- a/application/views/admin/participants/massive_actions/_selector.php +++ b/application/views/admin/participants/massive_actions/_selector.php @@ -1,103 +1,146 @@ widget('ext.admin.grid.MassiveActionsWidget.MassiveActionsWidget', array( - 'pk' => 'selectedParticipant', - 'gridid' => 'list_central_participants', - 'dropupId' => 'tokenListActions', - 'dropUpText' => gT('Selected participant(s)...'), - - 'aActions' => array( - // Delete - array( - // li element - 'type' => 'action', - 'action' => 'delete', - 'url' => App()->createUrl('/admin/participants/sa/deleteParticipant/'), - 'iconClasses' => 'text-danger fa fa-trash', - 'text' => gT('Delete'), - 'grid-reload' => 'yes', - 'on-success' => "(function(result) { LS.AjaxHelper.onSuccess(result); })", +$userId = App()->user->id; +$showActions = []; +$aActions = [ + 'delete' => [ + // li element + 'type' => 'action', + 'action' => 'delete', + 'url' => App()->createUrl('/admin/participants/sa/deleteParticipant/'), + 'iconClasses' => 'text-danger fa fa-trash', + 'text' => gT('Delete'), + 'grid-reload' => 'yes', + 'on-success' => "(function(result) { LS.AjaxHelper.onSuccess(result); })", - // Modal - 'actionType' => 'modal', - 'modalType' => 'empty', - 'keepopen' => 'no', - 'sModalTitle' => gT('Delete one or more participants...'), - 'htmlModalBody' => - '

' . gT('Please choose one option.') . '

' . - // The class 'post-value' will make widget post input/select to controller url - ' + + + ', - 'htmlFooterButtons' => array( - // The class 'btn-ok' binds to URL above - ' ' . gT('Delete') . '', - '' . gT('Cancel') . '' - ), - 'aCustomDatas' => array( - ), + 'htmlFooterButtons' => array( + // The class 'btn-ok' binds to URL above + ' ' . gT('Delete') . '', + '' . gT('Cancel') . '' ), + 'aCustomDatas' => array(), + ], + 'update' => [ + 'type' => 'action', + 'action' => 'batchEdit', + 'url' => App()->createUrl('/admin/participants/sa/batchEdit/'), + 'iconClasses' => 'fa fa-pencil', + 'text' => gT('Batch edit'), + 'grid-reload' => 'yes', + //modal + 'actionType' => 'modal', + 'modalType' => 'yes-no', + 'keepopen' => 'yes', + 'yes' => gT('Apply'), + 'no' => gT('Cancel'), + 'sModalTitle' => gT('Batch edit the participants'), + 'htmlModalBody' => $this->renderPartial('./participants/massive_actions/_update', [], true) + ], + 'export' => [ + 'type' => 'action', + 'action' => 'export', + 'url' => '', // Not relevant + 'iconClasses' => 'icon-exportcsv', + 'text' => gT('Export'), + 'grid-reload' => 'no', - // Separator - array('type' => 'separator'), + 'actionType' => 'custom', + 'custom-js' => '(function() { LS.CPDB.onClickExport(); })' + ], + 'share' => [ + 'type' => 'action', + 'action' => 'share', + 'url' => '', // Not relevant + 'iconClasses' => 'fa fa-share', + 'text' => gT('Share'), + 'grid-reload' => 'no', - // Mass Edit - array( - 'type' => 'action', - 'action' => 'batchEdit', - 'url' => App()->createUrl('/admin/participants/sa/batchEdit/'), - 'iconClasses' => 'fa fa-pencil', - 'text' => gT('Batch edit'), - 'grid-reload' => 'yes', - //modal - 'actionType' => 'modal', - 'modalType' => 'yes-no', - 'keepopen' => 'yes', - 'yes' => gT('Apply'), - 'no' => gT('Cancel'), - 'sModalTitle' => gT('Batch edit the participants'), - 'htmlModalBody' => $this->renderPartial('./participants/massive_actions/_update', [], true) - ), - // Export - array( - 'type' => 'action', - 'action' => 'export', - 'url' => '', // Not relevant - 'iconClasses' => 'icon-exportcsv', - 'text' => gT('Export'), - 'grid-reload' => 'no', + 'actionType' => 'custom', + 'custom-js' => '(function(itemIds) { LS.CPDB.shareMassiveAction(itemIds); })' + ], + 'addToSurvey' => [ + 'type' => 'action', + 'action' => 'add-to-survey', + 'url' => '', // Not relevant + 'iconClasses' => 'fa fa-user-plus', + 'text' => gT('Add participants to survey'), + 'grid-reload' => 'no', - 'actionType' => 'custom', - 'custom-js' => '(function() { LS.CPDB.onClickExport(); })' - ), - // Share - array( - 'type' => 'action', - 'action' => 'share', - 'url' => '', // Not relevant - 'iconClasses' => 'fa fa-share', - 'text' => gT('Share'), - 'grid-reload' => 'no', + 'actionType' => 'custom', + 'custom-js' => '(function(itemIds) { LS.CPDB.addParticipantToSurvey(itemIds); })' + ], + 'seperator' => [ + 'type' => 'separator' + ] - 'actionType' => 'custom', - 'custom-js' => '(function(itemIds) { LS.CPDB.shareMassiveAction(itemIds); })' - ), - // Add to survey - array( - 'type' => 'action', - 'action' => 'add-to-survey', - 'url' => '', // Not relevant - 'iconClasses' => 'fa fa-user-plus', - 'text' => gT('Add participants to survey'), - 'grid-reload' => 'no', +]; + +$showActions = array_merge($showActions, checkPermission('delete', $userId, $aActions, $participantOwnerUid, true)); +$showActions = array_merge($showActions, checkPermission('update', $userId, $aActions, $participantOwnerUid, false)); +$showActions = array_merge($showActions, checkPermission('export', $userId, $aActions, $participantOwnerUid, false)); +$showActions = array_merge($showActions, checkPermission('update', $userId, $aActions, $participantOwnerUid, false, 'share')); +$showActions = array_merge($showActions, [$aActions['addToSurvey']]); - 'actionType' => 'custom', - 'custom-js' => '(function(itemIds) { LS.CPDB.addParticipantToSurvey(itemIds); })' - ) - ) +$this->widget('ext.admin.grid.MassiveActionsWidget.MassiveActionsWidget', array( + 'pk' => 'selectedParticipant', + 'gridid' => 'list_central_participants', + 'dropupId' => 'tokenListActions', + 'dropUpText' => gT('Selected participant(s)...'), + + 'aActions' => $showActions )); +/** + * @param string $permission + * @param string $userId + * @param array $aActions + * @param string $participantOwnerUid + * @param bool $seperator * + * @param string $overrideDisplayedButton + * + * @return array + */ +function checkPermission($permission, $userId, $aActions, $participantOwnerUid, $seperator = false, $overrideDisplayedButton = '') +{ + $isSuperAdmin = Permission::model()->hasGlobalPermission('superadmin', 'read'); + $hasPermission = Permission::model()->hasGlobalPermission('participantpanel', $permission); + $sharedParticipantExists = ParticipantShare::model()->exists('share_uid = ' . $userId); + + $displayedButton = $permission; + if ($overrideDisplayedButton) { + $displayedButton = $overrideDisplayedButton; + } + + // form an Array with Buttons to be displayed + if (!$sharedParticipantExists || $participantOwnerUid === $userId) { + $aAction[] = $aActions[$displayedButton]; + if ($seperator) { + array_push($aAction, $aActions['seperator']); + } + return $aAction; + } elseif ($isSuperAdmin || $hasPermission) { + $aAction[] = $aActions[$displayedButton]; + if ($seperator) { + array_push($aAction, $aActions['seperator']); + } + return $aAction; + } else { + return []; + } +} + ?>