Convert case activity links to 'actionLinks'
authorMatthew Wire (MJW Consulting) <mjw@mjwconsult.co.uk>
Mon, 15 Jul 2019 23:32:13 +0000 (00:32 +0100)
committerMatthew Wire (MJW Consulting) <mjw@mjwconsult.co.uk>
Fri, 1 Nov 2019 11:43:38 +0000 (11:43 +0000)
CRM/Case/BAO/Case.php
CRM/Case/Form/ActivityView.php
CRM/Case/Selector/Search.php
templates/CRM/Case/Form/ActivityView.tpl
templates/CRM/common/formButtons.tpl

index 680a7949ede1a64151bab0eb72eaaf08a504f522..d9f0667e6a6f60330ff9d05cf3e4c55704343a3a 100644 (file)
@@ -1094,7 +1094,8 @@ SELECT civicrm_case.id, case_status.label AS case_status, status_id, civicrm_cas
         $caseActivity['no_attachments'] = count($attachmentIDs);
       }
 
-      $caseActivities[$caseActivityId]['links'] = CRM_Case_Selector_Search::addCaseActivityLinks($caseID, $contactID, $userID, $context, $dao);
+      $caseActivities[$caseActivityId]['links']
+        = CRM_Case_Selector_Search::addCaseActivityLinks($caseID, $contactID, $userID, $context, $dao);
     }
 
     $caseActivitiesDT = [];
index b18be74fdc365abe2ff6415579b4413c9864ab2a..af9c5c4b70854be37036b9a60846af08424f85fc 100644 (file)
@@ -204,6 +204,17 @@ class CRM_Case_Form_ActivityView extends CRM_Core_Form {
       ],
     ];
     CRM_Utils_System::appendBreadCrumb($breadcrumb);
+
+    $this->addButtons([
+      [
+        'type' => 'cancel',
+        'name' => ts('Done'),
+      ],
+    ]);
+    // Add additional action links
+    $activityDeleted = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $activityID, 'is_deleted');
+    $actionLinks = CRM_Case_Selector_Search::permissionedActionLinks($caseID, $contactID, CRM_Core_Session::getLoggedInContactID(), NULL, $activityTypeID, $activityDeleted, $activityID, FALSE);
+    $this->assign('actionLinks', $actionLinks);
   }
 
 }
index e34a3cc5fed03cac382c869965f4d5539fffad4b..37dc38ce7cc15afbbd9d795f27f3ccf4d46a8ccc 100644 (file)
@@ -493,70 +493,192 @@ class CRM_Case_Selector_Search extends CRM_Core_Selector_Base {
    * @param int $contactID
    * @param int $userID
    * @param string $context
-   * @param \CRM_Core_DAO $dao
+   * @param \CRM_Activity_BAO_Activity $dao
+   * @param bool $allowView
    *
-   * @return string
-   *   HTML formatted Link
+   * @return string $linksMarkup
    */
-  public static function addCaseActivityLinks($caseID, $contactID, $userID, $context, $dao) {
-    // FIXME: Why are we not using CRM_Core_Action for these links? This is too much manual work and likely to get out-of-sync with core markup.
-    $caseActivityId = $dao->id;
-    $allowView = CRM_Case_BAO_Case::checkPermission($caseActivityId, 'view', $dao->activity_type_id, $userID);
-    $allowEdit = CRM_Case_BAO_Case::checkPermission($caseActivityId, 'edit', $dao->activity_type_id, $userID);
-    $allowDelete = CRM_Case_BAO_Case::checkPermission($caseActivityId, 'delete', $dao->activity_type_id, $userID);
-    $emailActivityTypeIDs = [
-      'Email' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Email'),
-      'Inbound Email' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Inbound Email'),
-    ];
-    $url = CRM_Utils_System::url("civicrm/case/activity",
-      "reset=1&cid={$contactID}&caseid={$caseID}", FALSE, NULL, FALSE
-    );
-    $contextUrl = '';
-    if ($context == 'fulltext') {
-      $contextUrl = "&context={$context}";
-    }
-    $editUrl = "{$url}&action=update{$contextUrl}";
-    $deleteUrl = "{$url}&action=delete{$contextUrl}";
-    $restoreUrl = "{$url}&action=renew{$contextUrl}";
-    $viewTitle = ts('View activity');
+  public static function addCaseActivityLinks($caseID, $contactID, $userID, $context, $dao, $allowView = TRUE) {
     $caseDeleted = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_Case', $caseID, 'is_deleted');
-
-    $url = "";
-    $css = 'class="action-item crm-hover-button"';
-    if ($allowView) {
-      $viewUrl = CRM_Utils_System::url('civicrm/case/activity/view', array('cid' => $contactID, 'aid' => $caseActivityId));
-      $url = '<a ' . str_replace('action-item', 'action-item medium-pop-up', $css) . 'href="' . $viewUrl . '" title="' . $viewTitle . '">' . ts('View') . '</a>';
+    $actionLinks = self::actionLinks();
+    // Check logged in user for permission.
+    if (CRM_Case_BAO_Case::checkPermission($dao->id, 'view', $dao->activity_type_id, $userID)) {
+      $permissions[] = CRM_Core_Permission::VIEW;
+    }
+    if (!$allowView) {
+      unset($actionLinks[CRM_Core_Action::VIEW]);
     }
-    $additionalUrl = "&id={$caseActivityId}";
     if (!$dao->deleted) {
-      //hide edit link of activity type email.CRM-4530.
-      if (!in_array($dao->type, $emailActivityTypeIDs)) {
-        //hide Edit link if activity type is NOT editable (special case activities).CRM-5871
-        if ($allowEdit) {
-          $url .= '<a ' . $css . ' href="' . $editUrl . $additionalUrl . '">' . ts('Edit') . '</a> ';
-        }
+      // Activity is not deleted, allow user to edit/delete if they have permission
+      // hide Edit link if:
+      // 1. User does not have edit permission.
+      // 2. Activity type is NOT editable (special case activities).CRM-5871
+      if (CRM_Case_BAO_Case::checkPermission($dao->id, 'edit', $dao->activity_type_id, $userID)) {
+        $permissions[] = CRM_Core_Permission::EDIT;
       }
-      if ($allowDelete) {
-        $url .= ' <a ' . str_replace('action-item', 'action-item small-popup', $css) . ' href="' . $deleteUrl . $additionalUrl . '">' . ts('Delete') . '</a>';
+      if (in_array($dao->activity_type_id, CRM_Activity_BAO_Activity::getViewOnlyActivityTypeIDs())) {
+        unset($actionLinks[CRM_Core_Action::UPDATE]);
       }
+      if (CRM_Case_BAO_Case::checkPermission($dao->id, 'delete', $dao->activity_type_id, $userID)) {
+        $permissions[] = CRM_Core_Permission::DELETE;
+      }
+      unset($actionLinks[CRM_Core_Action::RENEW]);
     }
-    elseif (!$caseDeleted) {
-      $url = ' <a ' . $css . ' href="' . $restoreUrl . $additionalUrl . '">' . ts('Restore') . '</a>';
+    $extraMask = 0;
+    if ($dao->deleted && !$caseDeleted
+      && (CRM_Case_BAO_Case::checkPermission($dao->id, 'delete', $dao->activity_type_id, $userID))) {
+      // Case is not deleted but activity is.
+      // Allow user to restore activity if they have delete permissions
+      unset($actionLinks[CRM_Core_Action::DELETE]);
+      $extraMask = CRM_Core_Action::RENEW;
     }
-
-    //check for operations.
-    if (CRM_Case_BAO_Case::checkPermission($caseActivityId, 'Move To Case', $dao->activity_type_id)) {
-      $url .= ' <a ' . $css . ' href="#" onClick="Javascript:fileOnCase( \'move\',' . $caseActivityId . ', ' . $caseID . ', this ); return false;">' . ts('Move To Case') . '</a> ';
+    if (!CRM_Case_BAO_Case::checkPermission($dao->id, 'Move To Case', $dao->activity_type_id)) {
+      unset($actionLinks[CRM_Core_Action::DETACH]);
     }
-    if (CRM_Case_BAO_Case::checkPermission($caseActivityId, 'Copy To Case', $dao->activity_type_id)) {
-      $url .= ' <a ' . $css . ' href="#" onClick="Javascript:fileOnCase( \'copy\',' . $caseActivityId . ',' . $caseID . ', this ); return false;">' . ts('Copy To Case') . '</a> ';
+    if (!CRM_Case_BAO_Case::checkPermission($dao->id, 'Copy To Case', $dao->activity_type_id)) {
+      unset($actionLinks[CRM_Core_Action::COPY]);
     }
+    $actionMask = CRM_Core_Action::mask($permissions) | $extraMask;
+    $values = [
+      'aid' => $dao->id,
+      'cid' => $contactID,
+      'cxt' => empty($context) ? '' : "&context={$context}",
+      'caseid' => $caseID,
+    ];
+    $linksMarkup = CRM_Core_Action::formLink($actionLinks,
+      $actionMask,
+      $values,
+      ts('more'),
+      FALSE,
+      'case.tab.row',
+      'Activity',
+      $dao->id
+    );
     // if there are file attachments we will return how many and, if only one, add a link to it
     if (!empty($dao->attachment_ids)) {
-      $url .= implode(' ', CRM_Core_BAO_File::paperIconAttachment('civicrm_activity', $caseActivityId));
+      $linksMarkup .= implode(' ', CRM_Core_BAO_File::paperIconAttachment('civicrm_activity', $dao->id));
     }
+    return $linksMarkup;
+  }
 
-    return $url;
+  /**
+   * @param int $caseID
+   * @param int $contactID
+   * @param int $userID
+   * @param string $context
+   * @param int $activityTypeID
+   * @param int $activityDeleted
+   * @param int $activityID
+   * @param bool $allowView
+   *
+   * @return array|null
+   */
+  public static function permissionedActionLinks($caseID, $contactID, $userID, $context, $activityTypeID, $activityDeleted, $activityID, $allowView = TRUE) {
+    $caseDeleted = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_Case', $caseID, 'is_deleted');
+    $values = [
+      'aid' => $activityID,
+      'cid' => $contactID,
+      'cxt' => empty($context) ? '' : "&context={$context}",
+      'caseid' => $caseID,
+    ];
+    $actionLinks = self::actionLinks();
+
+    // Check logged in user for permission.
+    if (CRM_Case_BAO_Case::checkPermission($activityID, 'view', $activityTypeID, $userID)) {
+      $permissions[] = CRM_Core_Permission::VIEW;
+    }
+    if (!$allowView) {
+      unset($actionLinks[CRM_Core_Action::VIEW]);
+    }
+    if (!$activityDeleted) {
+      // Activity is not deleted, allow user to edit/delete if they have permission
+
+      // hide Edit link if:
+      // 1. User does not have edit permission.
+      // 2. Activity type is NOT editable (special case activities).CRM-5871
+      if (CRM_Case_BAO_Case::checkPermission($activityID, 'edit', $activityTypeID, $userID)) {
+        $permissions[] = CRM_Core_Permission::EDIT;
+      }
+      if (in_array($activityTypeID, CRM_Activity_BAO_Activity::getViewOnlyActivityTypeIDs())) {
+        unset($actionLinks[CRM_Core_Action::UPDATE]);
+      }
+      if (CRM_Case_BAO_Case::checkPermission($activityID, 'delete', $activityTypeID, $userID)) {
+        $permissions[] = CRM_Core_Permission::DELETE;
+      }
+      unset($actionLinks[CRM_Core_Action::RENEW]);
+    }
+    $extraMask = 0;
+    if ($activityDeleted && !$caseDeleted
+      && (CRM_Case_BAO_Case::checkPermission($activityID, 'delete', $activityTypeID, $userID))) {
+      // Case is not deleted but activity is.
+      // Allow user to restore activity if they have delete permissions
+      unset($actionLinks[CRM_Core_Action::DELETE]);
+      $extraMask = CRM_Core_Action::RENEW;
+    }
+    if (!CRM_Case_BAO_Case::checkPermission($activityID, 'Move To Case', $activityTypeID)) {
+      unset($actionLinks[CRM_Core_Action::DETACH]);
+    }
+    if (!CRM_Case_BAO_Case::checkPermission($activityID, 'Copy To Case', $activityTypeID)) {
+      unset($actionLinks[CRM_Core_Action::COPY]);
+    }
+
+    $actionMask = CRM_Core_Action::mask($permissions) | $extraMask;
+    return CRM_Core_Action::filterLinks($actionLinks, $actionMask, $values, 'case.activity', 'Activity', $activityID);
+  }
+
+  /**
+   * Get the action links for this page.
+   *
+   * @return array
+   */
+  public static function actionLinks() {
+    // check if variable _actionsLinks is populated
+    if (!isset(self::$_actionLinks)) {
+      self::$_actionLinks = [
+        CRM_Core_Action::VIEW => [
+          'name' => ts('View'),
+          'url' => 'civicrm/case/activity/view',
+          'qs' => 'reset=1&cid=%%cid%%&caseid=%%caseid%%&aid=%%aid%%',
+          'title' => ts('View'),
+        ],
+        CRM_Core_Action::UPDATE => [
+          'name' => ts('Edit'),
+          'url' => 'civicrm/case/activity',
+          'qs' => 'reset=1&cid=%%cid%%&caseid=%%caseid%%&id=%%aid%%&action=update%%cxt%%',
+          'title' => ts('Edit'),
+          'icon' => 'fa-pencil',
+        ],
+        CRM_Core_Action::DELETE => [
+          'name' => ts('Delete'),
+          'url' => 'civicrm/case/activity',
+          'qs' => 'reset=1&cid=%%cid%%&caseid=%%caseid%%&id=%%aid%%&action=delete%%cxt%%',
+          'title' => ts('Delete'),
+          'icon' => 'fa-trash',
+        ],
+        CRM_Core_Action::RENEW => [
+          'name' => ts('Restore'),
+          'url' => 'civicrm/case/activity',
+          'qs' => 'reset=1&cid=%%cid%%&caseid=%%caseid%%&id=%%aid%%&action=renew%%cxt%%',
+          'title' => ts('Restore'),
+          'icon' => 'fa-undo',
+        ],
+        CRM_Core_Action::DETACH => [
+          'name' => ts('Move To Case'),
+          'ref' => 'move_to_case_action',
+          'title' => ts('Move To Case'),
+          'extra' => 'onclick = "Javascript:fileOnCase( \'move\', %%aid%%, %%caseid%%, this ); return false;"',
+          'icon' => 'fa-clipboard',
+        ],
+        CRM_Core_Action::COPY => [
+          'name' => ts('Copy To Case'),
+          'ref' => 'copy_to_case_action',
+          'title' => ts('Copy To Case'),
+          'extra' => 'onclick = "Javascript:fileOnCase( \'copy\', %%aid%%, %%caseid%%, this ); return false;"',
+          'icon' => 'fa-files-o',
+        ],
+      ];
+    }
+    return self::$_actionLinks;
   }
 
 }
index b1ac29b9113efe37472d1e74d7c41413af3702d8..cf4c0e92907d79b3aff8700d0a164ab2098452f7 100644 (file)
@@ -25,6 +25,7 @@
 *}
 {* View Case Activities *}
 <div class="crm-block crm-content-block crm-case-activity-view-block">
+  <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top" linkButtons=$actionLinks}</div>
   {if $revs}
     {strip}
       <table class="crm-info-panel">
@@ -77,7 +78,7 @@
       </table>
     {/if}
   {/if}
-  <div class="crm-submit-buttons">
-    {crmButton p='civicrm/case' q="reset=1" class='cancel' icon='times'}{ts}Done{/ts}{/crmButton}
-  </div>
+  <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom" linkButtons=$actionLinks}</div>
 </div>
+
+{include file="CRM/Case/Form/ActivityToCase.tpl"}
index a264de1eae563d75a53aa8780836d7f900d40083..4f6a7978cd5e3a66d62272ee3871991d678a0311 100644 (file)
  +--------------------------------------------------------------------+
 *}
 
-{* Loops through $form.buttons.html array and assigns separate spans with classes to allow theming
-   by button and name. crmBtnType grabs type keyword from button name (e.g. 'upload', 'next', 'back', 'cancel') so
-   types of buttons can be styled differently via css. *}
 {crmRegion name='form-buttons'}
+{* Loops through $linkButtons and assigns html "a" (link) buttons to the template. Used for additional entity functions such as "Move to Case" or "Renew Membership" *}
+{if $linkButtons}
+  {foreach from=$linkButtons item=linkButton}
+    {if $linkButton.accesskey}
+      {capture assign=accessKey}accesskey="{$linkButton.accessKey}"{/capture}
+    {else}{assign var="accessKey" value=""}
+    {/if}
+    {if $linkButton.icon}
+      {capture assign=icon}<i class="crm-i {$linkButton.icon}"></i> {/capture}
+    {else}{assign var="icon" value=""}
+    {/if}
+    {if $linkButton.ref}
+      {capture assign=linkname}name="{$linkButton.ref}"{/capture}
+    {else}{capture assign=linkname}name="{$linkButton.name}"{/capture}
+    {/if}
+    <a class="button" {$linkname} href="{crmURL p=$linkButton.url q=$linkButton.qs}" {$accessKey} {$linkButton.extra}><span>{$icon}{$linkButton.title}</span></a>
+  {/foreach}
+{/if}
+
+{* Loops through $form.buttons.html array and assigns separate spans with classes to allow theming by button and name.
+ * crmBtnType grabs type keyword from button name (e.g. 'upload', 'next', 'back', 'cancel') so types of buttons can be styled differently via css.
+ *}
 {foreach from=$form.buttons item=button key=key name=btns}
   {if $key|substring:0:4 EQ '_qf_'}
     {if $location}