CRM-17155 improve links & options from all reports page
authoreileen <emcnaughton@wikimedia.org>
Fri, 6 Nov 2015 23:27:33 +0000 (15:27 -0800)
committereileen <emcnaughton@wikimedia.org>
Tue, 24 Nov 2015 03:50:58 +0000 (16:50 +1300)
This allows people to view the report in various formats, delete or update it from the all reports page

CRM/Report/BAO/ReportInstance.php
CRM/Report/Form.php
CRM/Report/Page/Instance.php
CRM/Report/Page/InstanceList.php
CRM/Report/Utils/Report.php
api/v3/ReportTemplate.php
templates/CRM/Report/Form/Actions.tpl
templates/CRM/Report/Page/InstanceList.tpl

index adb089d2ae70f1ab012e7fe046e9560fcef153c7..c692aeeb67c930882e05f379041f690df63baf6a 100644 (file)
@@ -119,6 +119,7 @@ class CRM_Report_BAO_ReportInstance extends CRM_Report_DAO_ReportInstance {
 
   /**
    * Create instance.
+   *
    * takes an associative array and creates a instance object and does any related work like permissioning, adding to dashboard etc.
    *
    * This function is invoked from within the web form layer and also from the api layer
index e1532b3037c58303df5f15205c23f6cbbf121515..cf5ab6c8ff886bc61086e24cb484fe013a961cfe 100644 (file)
@@ -176,6 +176,13 @@ class CRM_Report_Form extends CRM_Core_Form {
    */
   protected $tabs = array();
 
+  /**
+   * Should we add paging.
+   *
+   * @var bool
+   */
+  protected $addPaging = TRUE;
+
   /**
    * An attribute for checkbox/radio form field layout
    *
@@ -237,7 +244,8 @@ class CRM_Report_Form extends CRM_Core_Form {
    * This can be set to specify a limit to the number of rows
    * Since it is currently envisaged as part of the api usage it is only being applied
    * when $_output mode is not 'html' or 'group' so as not to have to interpret / mess with that part
-   * of the code (see limit() fn
+   * of the code (see limit() fn.
+   *
    * @var integer
    */
   protected $_limitValue = NULL;
@@ -295,11 +303,21 @@ class CRM_Report_Form extends CRM_Core_Form {
   protected $_selectedTables;
 
   /**
-   * Output mode e.g 'print', 'csv', 'pdf'
+   * Output mode e.g 'print', 'csv', 'pdf'.
+   *
    * @var string
    */
   protected $_outputMode;
 
+  /**
+   * Format of any chart in use.
+   *
+   * (it's unclear if this could be merged with outputMode at this stage)
+   *
+   * @var
+   */
+  protected $_format;
+
   public $_having = NULL;
   public $_select = NULL;
   public $_selectClauses = array();
@@ -512,11 +530,22 @@ class CRM_Report_Form extends CRM_Core_Form {
         $this->_formValues = NULL;
       }
 
+      $this->setOutputMode();
+
+      if ($this->_outputMode == 'copy') {
+        $this->_createNew = ($this->_outputMode == 'copy');
+        $this->_params = $this->_formValues;
+        $this->_params['view_mode'] = 'criteria';
+        $this->_params['title'] = ts('(copy)') . $this->getTitle();
+        // Do not pass go. Do not collect another chance to re-run the same query.
+        CRM_Report_Form_Instance::postProcess($this);
+      }
+
       // lets always do a force if reset is found in the url.
       // Hey why not? see CRM-17225 for more about this. The use of reset to be force is historical for reasons stated
       // in the comment line above these 2.
-      if (!empty($_REQUEST['reset']) && CRM_Utils_Request::retrieve('output', 'String') != 'criteria'
-          && CRM_Utils_Request::retrieve('output', 'String') != 'save') {
+      if (!empty($_REQUEST['reset'])
+          && !in_array(CRM_Utils_Request::retrieve('output', 'String'), array('save', 'criteria'))) {
         $this->_force = 1;
       }
 
@@ -981,6 +1010,15 @@ class CRM_Report_Form extends CRM_Core_Form {
     $this->_offsetValue = $_offsetValue;
   }
 
+  /**
+   * Setter for $addPaging.
+   *
+   * @param bool $value
+   */
+  public function setAddPaging($value) {
+    $this->addPaging = $value;
+  }
+
   /**
    * Getter for $_defaultValues.
    *
@@ -2599,13 +2637,7 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
    * Set output mode.
    */
   public function processReportMode() {
-    $buttonName = $this->controller->getButtonName();
-
-    $output = CRM_Utils_Request::retrieve(
-      'output',
-      'String',
-      CRM_Core_DAO::$_nullObject
-    );
+    $this->setOutputMode();
 
     $this->_sendmail
       = CRM_Utils_Request::retrieve(
@@ -2618,44 +2650,40 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
     $printOnly = FALSE;
     $this->assign('printOnly', FALSE);
 
-    if ($this->_printButtonName == $buttonName || $output == 'print' ||
-      ($this->_sendmail && !$output)
+    if ($this->_outputMode == 'print' ||
+      ($this->_sendmail && !$this->_outputMode)
     ) {
       $this->assign('printOnly', TRUE);
       $printOnly = TRUE;
+      $this->addPaging = FALSE;
       $this->assign('outputMode', 'print');
       $this->_outputMode = 'print';
       if ($this->_sendmail) {
         $this->_absoluteUrl = TRUE;
       }
     }
-    elseif ($this->_pdfButtonName == $buttonName || $output == 'pdf') {
-      $this->assign('printOnly', TRUE);
+    elseif ($this->_outputMode == 'pdf') {
       $printOnly = TRUE;
-      $this->assign('outputMode', 'pdf');
-      $this->_outputMode = 'pdf';
+      $this->addPaging = FALSE;
       $this->_absoluteUrl = TRUE;
     }
-    elseif ($this->_csvButtonName == $buttonName || $output == 'csv') {
-      $this->assign('printOnly', TRUE);
+    elseif ($this->_outputMode == 'csv') {
       $printOnly = TRUE;
-      $this->assign('outputMode', 'csv');
-      $this->_outputMode = 'csv';
       $this->_absoluteUrl = TRUE;
+      $this->addPaging = FALSE;
     }
-    elseif ($this->_groupButtonName == $buttonName || $output == 'group') {
+    elseif ($this->_outputMode == 'group') {
       $this->assign('outputMode', 'group');
-      $this->_outputMode = 'group';
     }
-    elseif ($output == 'create_report' && $this->_criteriaForm) {
+    elseif ($this->_outputMode == 'create_report' && $this->_criteriaForm) {
       $this->assign('outputMode', 'create_report');
-      $this->_outputMode = 'create_report';
     }
-    else {
-      $this->assign('outputMode', 'html');
-      $this->_outputMode = 'html';
+    elseif ($this->_outputMode == 'copy' && $this->_criteriaForm) {
+      $this->_createNew = TRUE;
     }
 
+    $this->assign('outputMode', $this->_outputMode);
+    $this->assign('printOnly', $printOnly);
     // Get today's date to include in printed reports
     if ($printOnly) {
       $reportDate = CRM_Utils_Date::customFormat(date('Y-m-d H:i'));
@@ -2667,10 +2695,10 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
    * Post Processing function for Form.
    *
    * postProcessCommon should be used to set other variables from input as the api accesses that function.
+   * This function is not accessed when the api calls the report.
    */
   public function beginPostProcess() {
     $this->setParams($this->controller->exportValues($this->_name));
-
     if (empty($this->_params) &&
       $this->_force
     ) {
@@ -2695,7 +2723,16 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
     ) {
       $this->assign('updateReportButton', TRUE);
     }
+
     $this->processReportMode();
+
+    if ($this->_outputMode == 'save' || $this->_outputMode == 'copy') {
+      $this->_createNew = ($this->_outputMode == 'copy');
+      // Do not pass go. Do not collect another chance to re-run the same query.
+      // This will be called from the button - there is an earlier response to the url
+      // perhaps they can still be consolidated more.
+      CRM_Report_Form_Instance::postProcess($this);
+    }
     $this->beginPostProcessCommon();
   }
 
@@ -3270,15 +3307,6 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
       $group = $this->_params['groups'];
       $this->add2group($group);
     }
-    elseif ($this->_instanceButtonName == $this->controller->getButtonName()) {
-      CRM_Report_Form_Instance::postProcess($this);
-    }
-    elseif ($this->_createNewButtonName == $this->controller->getButtonName() ||
-      $this->_outputMode == 'create_report'
-    ) {
-      $this->_createNew = TRUE;
-      CRM_Report_Form_Instance::postProcess($this);
-    }
   }
 
   /**
@@ -3368,7 +3396,7 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
     if ($this->_dashBoardRowCount) {
       $rowCount = $this->_dashBoardRowCount;
     }
-    if ($this->_outputMode == 'html' || $this->_outputMode == 'group') {
+    if ($this->addPaging) {
       $this->_select = str_ireplace('SELECT ', 'SELECT SQL_CALC_FOUND_ROWS ', $this->_select);
 
       $pageId = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
@@ -4604,4 +4632,60 @@ LEFT JOIN civicrm_contact {$field['alias']} ON {$field['alias']}.id = {$this->_a
     $query->_from .= $from;
   }
 
+  /**
+   * Get label for show results buttons.
+   *
+   * @return string
+   */
+  public function getResultsLabel() {
+    $showResultsLabel = $this->resultsDisplayed() ? ts('Refresh results') : ts('View results');
+    return $showResultsLabel;
+  }
+
+  /**
+   * Determine the output mode from the url or input.
+   *
+   * Output could be
+   *   - pdf : Render as pdf
+   *   - csv : Render as csv
+   *   - print : Render in print format
+   *   - save : save the report and display the new report
+   *   - copy : save the report as a new instance and display that.
+   *   - group : go to the add to group screen.
+   *
+   *  Potentially chart variations could also be included but the complexity
+   *   is that we might print a bar chart as a pdf.
+   */
+  protected function setOutputMode() {
+    $buttonName = $this->controller->getButtonName();
+    $this->_outputMode = CRM_Utils_Request::retrieve(
+      'output',
+      'String',
+      CRM_Core_DAO::$_nullObject,
+      FALSE,
+      CRM_Utils_Array::value('task', $this->_params)
+    );
+
+    if ($buttonName) {
+      if ($buttonName == $this->_instanceButtonName) {
+        $this->_outputMode = 'save';
+      }
+      if ($buttonName == $this->_printButtonName) {
+        $this->_outputMode = 'print';
+      }
+      if ($buttonName == $this->_pdfButtonName) {
+        $this->_outputMode = 'pdf';
+      }
+      if ($this->_csvButtonName == $buttonName) {
+        $this->_outputMode = 'csv';
+      }
+      if ($this->_groupButtonName == $buttonName) {
+        $this->_outputMode = 'group';
+      }
+      if ($buttonName == $this->_createNewButtonName) {
+        $this->_outputMode = 'copy';
+      }
+    }
+  }
+
 }
index 3b727dc95577325a0031bc6b632971dd6b8dd4cd..1409a435a8a65cdcc584cb82d2a4118940aaa4e0 100644 (file)
@@ -43,6 +43,10 @@ class CRM_Report_Page_Instance extends CRM_Core_Page {
     if (!$instanceId) {
       $instanceId = CRM_Report_Utils_Report::getInstanceIDForPath();
     }
+    if (is_numeric($instanceId)) {
+      $instanceURL = CRM_Utils_System::url("civicrm/report/instance/{$instanceId}", 'reset=1');
+      CRM_Core_Session::singleton()->replaceUserContext($instanceURL);
+    }
     $action = CRM_Utils_Request::retrieve('action', 'String', $this);
     $optionVal = CRM_Report_Utils_Report::getValueFromUrl($instanceId);
     $reportUrl = CRM_Utils_System::url('civicrm/report/list', "reset=1");
index e3b6455fdec5b280504fd864a81913856612c323..508eb67a106cc43842029e41df0c2360a70af99f 100644 (file)
@@ -82,7 +82,7 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
    *
    * @return array
    */
-  public function &info() {
+  public function info() {
 
     $report = '';
     if ($this->ovID) {
@@ -110,7 +110,7 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
     }
 
     $sql = "
-        SELECT inst.id, inst.title, inst.report_id, inst.description, v.label, v.grouping,
+        SELECT inst.id, inst.title, inst.report_id, inst.description, 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
@@ -161,10 +161,9 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
         $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");
-        if (CRM_Core_Permission::check('administer Reports')) {
-          $rows[$dao->compName][$dao->id]['deleteUrl'] = CRM_Utils_System::url("{$url}/{$dao->id}", 'action=delete&reset=1');
-        }
+        $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);
       }
     }
     return $rows;
@@ -210,4 +209,53 @@ class CRM_Report_Page_InstanceList extends CRM_Core_Page {
     return parent::run();
   }
 
+  /**
+   * Get action links.
+   *
+   * @param int $instanceID
+   * @param string $className
+   *
+   * @return array
+   */
+  protected function getActionLinks($instanceID, $className) {
+    $urlCommon = 'civicrm/report/instance/' . $instanceID;
+    $actions = array(
+      'copy' => array(
+        'url' => CRM_Utils_System::url($urlCommon, 'reset=1&output=copy'),
+        'label' => ts('Save a Copy'),
+      ),
+      'pdf' => array(
+        'url' => CRM_Utils_System::url($urlCommon, 'reset=1&force=1&output=pdf'),
+        'label' => ts('View as pdf'),
+      ),
+      'print' => array(
+        'url' => CRM_Utils_System::url($urlCommon, 'reset=1&force=1&output=print'),
+        'label' => ts('Print report'),
+      ),
+    );
+    // Hackery, Hackera, Hacker ahahahahahaha a super nasty hack.
+    // Almost all report classes support csv & loading each class to call the method seems too
+    // expensive. We also have on our later list 'do they support charts' which is instance specific
+    // e.g use of group by might affect it. So, lets just skip for the few that don't for now.
+    $csvBlackList = array(
+      'CRM_Report_Form_Contact_Detail',
+      'CRM_Report_Form_Event_Income',
+    );
+    if (!in_array($className, $csvBlackList)) {
+      $actions['csv'] = array(
+        'url' => CRM_Utils_System::url($urlCommon, 'reset=1&force=1&output=csv'),
+        'label' => ts('Export to csv'),
+      );
+    }
+    if (CRM_Core_Permission::check('administer Reports')) {
+      $actions['delete'] = array(
+        'url' => CRM_Utils_System::url($urlCommon, 'reset=1&action=delete'),
+        'label' => ts('Delete report'),
+        'confirm_message' => ts('Are you sure you want delete this report? This action cannot be undone.'),
+      );
+    }
+
+    return $actions;
+  }
+
 }
index 2337edb9599ede3cf14db39b21c1963ca3fb1c42..8aa59cd6a53651b4d63e19323f2ba301423f9d68 100644 (file)
@@ -285,7 +285,9 @@ WHERE  inst.report_id = %1";
               $value = CRM_Utils_Date::customFormat($value, '%Y-%m-%d');
             }
           }
-          elseif (CRM_Utils_Array::value('type', $form->_columnHeaders[$v]) == 1024) {
+          // Note the reference to a specific field does not belong in this generic class & does not work on all reports.
+          // @todo - fix this properly rather than just supressing the en-otice. Repeat transaction report is a good example.
+          elseif (CRM_Utils_Array::value('type', $form->_columnHeaders[$v]) == 1024 && !empty($row['civicrm_contribution_currency'])) {
             $value = CRM_Utils_Money::format($value, $row['civicrm_contribution_currency']);
           }
           $displayRows[$v] = '"' . $value . '"';
index 29024d526f9cddab40091015d99440ea15b64d14..0a71b12128e727ddd8415c785940b4fdcbaccdca 100644 (file)
@@ -148,6 +148,7 @@ function _civicrm_api3_report_template_getrows($params) {
   $reportInstance->setParams(array_merge($reportInstance->getDefaultValues(), $params));
   $options = _civicrm_api3_get_options_from_params($params, TRUE, 'ReportTemplate', 'get');
   $reportInstance->setLimitValue($options['limit']);
+  $reportInstance->setAddPaging(FALSE);
   $reportInstance->setOffsetValue($options['offset']);
   $reportInstance->beginPostProcessCommon();
   $sql = $reportInstance->buildQuery();
index a7b4da30e270c76ee7c0e85f30a25490ee340a7d..01ff1224cae9d76ab959c56e820c4743ee9c8152 100644 (file)
@@ -26,7 +26,6 @@
 {if !$printOnly} {* NO print section starts *}
 
   {* build the print pdf buttons *}
-  {if $rows}
     <div class="crm-tasks">
       {assign var=print value="_qf_"|cat:$form.formName|cat:"_submit_print"}
       {assign var=pdf   value="_qf_"|cat:$form.formName|cat:"_submit_pdf"}
@@ -86,7 +85,6 @@
         </tr>
       </table>
     </div>
-  {/if}
 
 {literal}
   <script type="text/javascript">
index 1913d95201a8e5688659cd6f9389db044c9c44dc..742af460b60b2a2f3663c6564b1c58c2dcf9c057 100644 (file)
                   <tr id="row_{counter}" class="crm-report-instanceList">
                     <td class="crm-report-instanceList-title" style="width:35%"><a href="{$row.url}" title="{ts}Run this report{/ts}">&raquo; <strong>{$row.title}</strong></a></td>
                     <td class="crm-report-instanceList-description">{$row.description}</td>
-                    {if $row.deleteUrl}
-                      <td class="crm-report-instanceList-deleteUrl" style = "width:5%"><a href="{$row.deleteUrl}" onclick="return window.confirm('{ts}Are you sure you want delete this report?{/ts} {ts}This action cannot be undone.{/ts}');">{ts}Delete{/ts}</a></td>
-                    {/if}
+                    <td>
+                    <a href="{$row.viewUrl}" class="action-item crm-hover-button">{ts}View Results{/ts}</a>
+                    <span class="btn-slide crm-hover-button">more
+                      <ul class="panel">
+                        {foreach from=$row.actions item=action key=action_name}
+                          <li><a href="{$action.url}" class="{$action_name} action-item crm-hover-button small-popup"
+                          {if $action.confirm_message}onclick="return window.confirm({$action.confirm_message|json_encode|htmlspecialchars})"{/if}
+                          title="{$action.label}">{$action.label}</a></li>
+                        {/foreach}
+                      </ul>
+                    </span>
+                    </td>
                   </tr>
                 {/foreach}
               </table>