CRM-17310 Add my reports functionality
authoreileenmcnaugton <eileen@fuzion.co.nz>
Wed, 30 Sep 2015 07:11:19 +0000 (20:11 +1300)
committereileen <emcnaughton@wikimedia.org>
Tue, 7 Jun 2016 17:17:35 +0000 (11:17 -0600)
This includes a new my reports menu & the ability to save reports as 'my report' to show on there

CRM/Core/BAO/Navigation.php
CRM/Report/BAO/ReportInstance.php
CRM/Report/Form.php
CRM/Report/Form/Instance.php
CRM/Report/Info.php
CRM/Report/Page/InstanceList.php
templates/CRM/Report/Form/Tabs/Instance.tpl
templates/CRM/Report/Form/Tabs/Settings.hlp
templates/CRM/Report/Page/InstanceList.tpl

index 08c345ef2529f3a15c03e24923ce137a9c07b0f3..ed189576a24d5ce3d8b9c8195609971e9da424e6 100644 (file)
@@ -604,6 +604,13 @@ ORDER BY parent_id, weight";
             return $showItem;
           }
         }
+        // CRM-17310 my reports allow people with access own reports to see the report if it is theirs.
+        elseif ($key == 'access own private reports') {
+          // Special permission processing for private reports.
+          $report_url = parse_url(ltrim($url, '/'));
+          $instance_id = CRM_Report_Utils_Report::getInstanceID($report_url['path']);
+          $hasPermission = $showItem = CRM_Report_BAO_ReportInstance::contactIsOwner($instance_id);
+        }
         else {
           $hasPermission = TRUE;
         }
index 2971b7bff07d26107593f968a479520b4bda8e80..9fe13ebaf6cbd2dfca4ba4f58dd01774b702578a 100644 (file)
@@ -264,4 +264,56 @@ class CRM_Report_BAO_ReportInstance extends CRM_Report_DAO_ReportInstance {
     return NULL;
   }
 
+  /**
+   * Check if report is private.
+   *
+   * @param int $instance_id
+   *
+   * @return bool
+   */
+  public static function reportIsPrivate($instance_id) {
+    $owner_id = CRM_Core_DAO::getFieldValue('CRM_Report_DAO_ReportInstance', $instance_id, 'owner_id', 'id');
+    if ($owner_id) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Check if the logged in user is the owner.
+   *
+   * @param int $instance_id
+   *
+   * @return TRUE if contact owns the report, FALSE if not
+   */
+  public static function contactIsOwner($instance_id) {
+    $session = CRM_Core_Session::singleton();
+    $contact_id = $session->get('userID');
+    $owner_id = CRM_Core_DAO::getFieldValue('CRM_Report_DAO_ReportInstance', $instance_id, 'owner_id', 'id');
+    if ($contact_id === $owner_id) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Check if the logged in contact can administer the report.
+   *
+   * @param int $instance_id
+   *
+   * @return bool
+   *   True if contact can edit the private report, FALSE if not.
+   */
+  public static function contactCanAdministerReport($instance_id) {
+    if (self::reportIsPrivate($instance_id)) {
+      if (self::contactIsOwner($instance_id) || CRM_Core_Permission::check('access all private reports')) {
+        return TRUE;
+      }
+    }
+    elseif (CRM_Core_Permission::check('administer Reports')) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
 }
index d1ba8f6bd30282ac60c60668bec659a24ccfe967..aeb5720d2df77267ffd7d3f2d15b2c331220057c 100644 (file)
@@ -1331,7 +1331,10 @@ class CRM_Report_Form extends CRM_Core_Form {
         }
       }
     }
-    if (!empty($this->_options)) {
+    if (!empty($this->_options) &&
+        (!$this->_id
+          || ($this->_id && CRM_Report_BAO_ReportInstance::contactCanAdministerReport($this->_id)))
+    ) {
       $this->tabs['ReportOptions'] = array(
         'title' => ts('Display Options'),
         'tpl' => 'ReportOptions',
index 814511450bc078c9323f8d9e161ea0b00a1c4981..2c14372e9539db4c44dcf48e057b1a28d2300ee0 100644 (file)
@@ -114,6 +114,8 @@ class CRM_Report_Form_Instance {
 
     $form->addElement('checkbox', 'addToDashboard', ts('Available for Dashboard?'), NULL,
       array('onclick' => "return showHideByValue('addToDashboard','','limit_result','table-row','radio',false);"));
+    $form->addElement('checkbox', 'add_to_my_reports', ts('Add to My Reports?'), NULL);
+
     $form->addElement('checkbox', 'is_reserved', ts('Reserved Report?'));
     if (!CRM_Core_Permission::check('administer reserved reports')) {
       $form->freeze('is_reserved');
@@ -271,6 +273,12 @@ class CRM_Report_Form_Instance {
         $defaults['report_footer'] = $defaults['footer'];
       }
 
+      // CRM-17310 private reports option.
+      $defaults['add_to_my_reports'] = 0;
+      if (CRM_Utils_Array::value('owner_id', $defaults) != NULL) {
+        $defaults['add_to_my_reports'] = 1;
+      }
+
       if (!empty($defaults['navigation_id'])) {
         // Get the default navigation parent id.
         $params = array('id' => $defaults['navigation_id']);
@@ -355,6 +363,19 @@ class CRM_Report_Form_Instance {
       unset($formValues[$field]);
     }
     $view_mode = $formValues['view_mode'];
+
+    // CRM-17310 my reports functionality - we should set owner if the checkbox is 1,
+    // it seems to be not set at all if unchecked.
+    if (!empty($formValues['add_to_my_reports'])) {
+      $params['owner_id'] = CRM_Core_Session::singleton()->getLoggedInContactID();
+      $params['permission'] = 'access own private reports';
+      $params['grouprole'] = array();
+    }
+    else {
+      $params['owner_id'] = 'null';
+    }
+    unset($formValues['add_to_my_reports']);
+
     // pass form_values as string
     $params['form_values'] = serialize($formValues);
 
index adb81363d6b9f25b10c7f630616c2a736131fb0e..6f4ee789c476ca17ad3096725657b2027b3fbba4 100644 (file)
@@ -30,7 +30,6 @@
  * information about it. It needs to extend CRM_Core_Component_Info
  * abstract class.
  *
- * @package CRM
  * @copyright CiviCRM LLC (c) 2004-2016
  * $Id$
  *
@@ -51,9 +50,6 @@ class CRM_Report_Info extends CRM_Core_Component_Info {
    * @return array
    *   collection of required component settings
    */
-  /**
-   * @return array
-   */
   public function getInfo() {
     return array(
       'name' => 'CiviReport',
@@ -91,6 +87,14 @@ class CRM_Report_Info extends CRM_Core_Component_Info {
         ts('access Report Criteria'),
         ts('Change report search criteria'),
       ),
+      'access own private reports' => array(
+        ts('access own private reports'),
+        ts('Access reports owned by the contact'),
+      ),
+      'access all private reports' => array(
+        ts('access all private reports'),
+        ts('Access all private reports'),
+      ),
       'administer reserved reports' => array(
         ts('administer reserved reports'),
         ts('Edit all reports that have been marked as reserved'),
@@ -124,9 +128,6 @@ class CRM_Report_Info extends CRM_Core_Component_Info {
    *   collection of required dashboard settings,
    *                    null if no element offered
    */
-  /**
-   * @return array|null
-   */
   public function getUserDashboardElement() {
     // no dashboard element for this component
     return NULL;
index 3051a4b1561054a75c6e8fb8f4a43a3a22c6187c..143c48ef772e11f5a164240bb586ae08b018ef9e 100644 (file)
@@ -108,9 +108,12 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
     elseif ($this->grouping) {
       $report .= " AND v.grouping = '{$this->grouping}' ";
     }
+    elseif ($this->myReports) {
+      $report .= " AND inst.owner_id = " . CRM_Core_Session::getLoggedInContactID();
+    }
 
     $sql = "
-        SELECT inst.id, inst.title, inst.report_id, inst.description, v.label, v.grouping, v.name as class_name,
+        SELECT inst.id, inst.title, inst.report_id, inst.description,  inst.owner_id, v.label, v.grouping, v.name as class_name,
         CASE
           WHEN comp.name IS NOT NULL THEN SUBSTRING(comp.name, 5)
           WHEN v.grouping IS NOT NULL THEN v.grouping
@@ -136,6 +139,7 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
     $config = CRM_Core_Config::singleton();
     $rows = array();
     $url = 'civicrm/report/instance';
+    $my_reports_grouping = 'My';
     while ($dao->fetch()) {
       if (in_array($dao->report_id, self::$_exceptions)) {
         continue;
@@ -145,6 +149,12 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
       if ($dao->compName == 'Contact' || $dao->compName == $dao->grouping) {
         $enabled = TRUE;
       }
+
+      // filter report listings for private reports
+      if (!empty($dao->owner_id) && CRM_Core_Session::getLoggedInContactID() != $dao->owner_id) {
+        continue;
+      }
+
       //filter report listings by permissions
       if (!($enabled && CRM_Report_Utils_Report::isInstancePermissioned($dao->id))) {
         continue;
@@ -158,14 +168,25 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
         if ($this->ovID) {
           $this->title = ts("Report(s) created from the template: %1", array(1 => $dao->label));
         }
-        $rows[$dao->compName][$dao->id]['title'] = $dao->title;
-        $rows[$dao->compName][$dao->id]['label'] = $dao->label;
-        $rows[$dao->compName][$dao->id]['description'] = $dao->description;
-        $rows[$dao->compName][$dao->id]['url'] = CRM_Utils_System::url("{$url}/{$dao->id}", "reset=1&output=criteria");
-        $rows[$dao->compName][$dao->id]['viewUrl'] = CRM_Utils_System::url("{$url}/{$dao->id}", 'force=1&reset=1');
-        $rows[$dao->compName][$dao->id]['actions'] = $this->getActionLinks($dao->id, $dao->class_name);
+
+        $report_grouping = $dao->compName;
+        if ($dao->owner_id != NULL) {
+          $report_grouping = $my_reports_grouping;
+        }
+        $rows[$report_grouping][$dao->id]['title'] = $dao->title;
+        $rows[$report_grouping][$dao->id]['label'] = $dao->label;
+        $rows[$report_grouping][$dao->id]['description'] = $dao->description;
+        $rows[$report_grouping][$dao->id]['url'] = CRM_Utils_System::url("{$url}/{$dao->id}", "reset=1&output=criteria");
+        $rows[$report_grouping][$dao->id]['viewUrl'] = CRM_Utils_System::url("{$url}/{$dao->id}", 'force=1&reset=1');
+        $rows[$report_grouping][$dao->id]['actions'] = $this->getActionLinks($dao->id, $dao->class_name);
       }
     }
+    // Move My Reports to the beginning of the reports list
+    if (isset($rows[$my_reports_grouping])) {
+      $my_reports = $rows[$my_reports_grouping];
+      unset($rows[$my_reports_grouping]);
+      $rows = array($my_reports_grouping => $my_reports) + $rows;
+    }
     return $rows;
   }
 
@@ -175,6 +196,7 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
   public function run() {
     //Filters by source report template or by component
     $this->ovID = CRM_Utils_Request::retrieve('ovid', 'Positive', $this);
+    $this->myReports = CRM_Utils_Request::retrieve('myreports', 'String', $this);
     $this->compID = CRM_Utils_Request::retrieve('compid', 'Positive', $this);
     $this->grouping = CRM_Utils_Request::retrieve('grp', 'String', $this);
 
@@ -205,6 +227,7 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
       $this->assign('newButton', $newButton);
       $this->assign('templateUrl', $templateUrl);
       $this->assign('compName', $this->_compName);
+      $this->assign('myReports', $this->myReports);
     }
     return parent::run();
   }
index eda7ed50f3cf27c365a08331aa515e3cde2cacdd..17e5eec343a33268ac179ebc4692cfb64d20a99f 100644 (file)
         <td>{$form.grouprole.html|crmAddClass:huge}</td>
       </tr>
     {/if}
+    <tr class="crm-report-instanceForm-form-block-add-to-my-reports">
+      <td class="report-label">{$form.add_to_my_reports.label} {help id="id-add_to_my_reports" file="CRM/Report/Form/Tabs/Settings.hlp"}</td>
+      <td>{$form.add_to_my_reports.html}
+        <span class="description">{ts}If set to Yes, this report will appear in the My Reports section of the reports listing page and will only be visible by you.{/ts}</span>
+      </td>
+    </tr>
     <tr class="crm-report-instanceForm-form-block-isReserved">
       <td class="report-label">{$form.is_reserved.label} {help id="id-is_reserved" file="CRM/Report/Form/Tabs/Settings.hlp"}</td>
       <td>{$form.is_reserved.html}
index 2a0d8da6e01848b17b49dd66a1658aaa6bbb9f0f..6c85a44ff4812300542f24ef2f0898f3fecd682d 100644 (file)
@@ -55,7 +55,7 @@
 {/htxt}
 {htxt id="id-report_perms"}
 {ts}You can control access to this report by selecting a 'Permission' from the list, or selecting one or more Roles. For example, you might select <em>access CiviContribute</em> for contribution reports (e.g. the same people who can see contribution data would also have access to the report). You can also prevent users from modifying the default report criteria and filters for reports by NOT giving them <em>access Report Criteria</em> permission. Those users will be able to run the report - but only with the criteria and filters that you've established for them.{/ts}
-{/htxt} 
+{/htxt}
 
 {htxt id="id-dash_avail-title"}
   {ts}Dashboard{/ts}
 {ts}Users with 'administer reserved reports' permission can mark a report instance as reserved, which prevents other users from accessing or modifying Report Criteria and Report Settings. This is particularly useful for report instances whose criteria affect the data available on non-report screens. For example, the display columns configured for the  Contact Logging Summary affect the columns shown under each contact's Change Log tab.{/ts}
 {/htxt}
 
+{htxt id="id-add_to_my_reports-title"}
+{ts}Add to My Reports{/ts}
+{/htxt}
+{htxt id="id-add_to_my_reports"}
+{ts}Selecting Yes will set the report to be visible only to the user
+  that clicked this option and saved the report settings form. If this is
+  enabled, the permissions configuration for this report will be disabled.{/ts}
+{/htxt}
index f9341c2a9821e297c86e378458e87f02badd3919..bf64c4c0af5345b7000486e5f815335ce88aa373 100644 (file)
@@ -38,7 +38,7 @@
       {foreach from=$list item=rows key=report}
         <div class="crm-accordion-wrapper crm-accordion_{$report}-accordion ">
           <div class="crm-accordion-header">
-            {if $title}{$title}{elseif $report EQ 'Contribute'}{ts}Contribution Reports{/ts}{else}{$report} {ts}Reports{/ts}{/if}</a>
+            {if $title}{$title}{elseif $report EQ 'Contribute'}{ts}Contribution Reports{/ts}{else}{ts}{$report} Reports{/ts}{/if}</a>
           </div><!-- /.crm-accordion-header -->
           <div class="crm-accordion-body">
             <div id="{$report}" class="boxBlock">
     <div class="crm-content-block">
       <div class="messages status no-popup">
         <div class="icon inform-icon"></div>&nbsp;
-        {ts 1=$compName}No %1 reports have been created.{/ts} &nbsp;
-        {if $templateUrl}
-          {ts 1=$templateUrl}You can create reports by selecting from the <a href="%1">list of report templates here.</a>{/ts}
+        {if $myReports}
+          {ts}You do not have any private reports. To add a report to this section, edit the Report Settings for a report and set 'Add to My Reports' to Yes.{/ts} &nbsp;
         {else}
-          {ts}Contact your site administrator for help creating reports.{/ts}
+          {ts 1=$compName}No %1 reports have been created.{/ts} &nbsp;
+          {if $templateUrl}
+            {ts 1=$templateUrl}You can create reports by selecting from the <a href="%1">list of report templates here.</a>{/ts}
+          {else}
+            {ts}Contact your site administrator for help creating reports.{/ts}
+          {/if}
         {/if}
       </div>
     </div>