Merge pull request #869 from totten/cms-perms
[civicrm-core.git] / CRM / Report / Utils / Report.php
CommitLineData
6a488035 1<?php
6a488035
TO
2
3/*
4 +--------------------------------------------------------------------+
5 | CiviCRM version 4.3 |
6 +--------------------------------------------------------------------+
7 | Copyright CiviCRM LLC (c) 2004-2013 |
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
10 | |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public |
21 | License and the CiviCRM Licensing Exception along |
22 | with this program; if not, contact CiviCRM LLC |
23 | at info[AT]civicrm[DOT]org. If you have questions about the |
24 | GNU Affero General Public License or the licensing of CiviCRM, |
25 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
26 +--------------------------------------------------------------------+
27*/
28
29/**
30 *
31 * @package CRM
32 * @copyright CiviCRM LLC (c) 2004-2013
33 * $Id$
34 *
35 */
36class CRM_Report_Utils_Report {
37
38 static function getValueFromUrl($instanceID = NULL) {
39 if ($instanceID) {
40 $optionVal = CRM_Core_DAO::getFieldValue('CRM_Report_DAO_Instance',
41 $instanceID,
42 'report_id'
43 );
44 }
45 else {
46 $config = CRM_Core_Config::singleton();
47 $args = explode('/', $_GET[$config->userFrameworkURLVar]);
48
49 // remove 'civicrm/report' from args
50 array_shift($args);
51 array_shift($args);
52
53 // put rest of arguement back in the form of url, which is how value
54 // is stored in option value table
55 $optionVal = implode('/', $args);
56 }
57 return $optionVal;
58 }
59
60 static function getValueIDFromUrl($instanceID = NULL) {
61 $optionVal = self::getValueFromUrl($instanceID);
62
63 if ($optionVal) {
64 $templateInfo = CRM_Core_OptionGroup::getRowValues('report_template', "{$optionVal}", 'value');
877022f7 65 return array(CRM_Utils_Array::value('id', $templateInfo), $optionVal);
6a488035
TO
66 }
67
68 return FALSE;
69 }
70
71 static function getInstanceIDForValue($optionVal) {
72 static $valId = array();
73
74 if (!array_key_exists($optionVal, $valId)) {
75 $sql = "
76SELECT MIN(id) FROM civicrm_report_instance
77WHERE report_id = %1";
78
79 $params = array(1 => array($optionVal, 'String'));
80 $valId[$optionVal] = CRM_Core_DAO::singleValueQuery($sql, $params);
81 }
82 return $valId[$optionVal];
83 }
84
85 static function getInstanceIDForPath($path = NULL) {
86 static $valId = array();
87
88 // if $path is null, try to get it from url
89 $path = self::getInstancePath();
90
91 if ($path && !array_key_exists($path, $valId)) {
92 $sql = "
93SELECT MIN(id) FROM civicrm_report_instance
94WHERE TRIM(BOTH '/' FROM CONCAT(report_id, '/', name)) = %1";
95
96 $params = array(1 => array($path, 'String'));
97 $valId[$path] = CRM_Core_DAO::singleValueQuery($sql, $params);
98 }
99 return CRM_Utils_Array::value($path, $valId);
100 }
101
102 static function getNextUrl($urlValue, $query = 'reset=1', $absolute = FALSE, $instanceID = NULL, $drilldownReport = array()) {
103 if ($instanceID) {
104 $drilldownInstanceID = false;
6001af1f 105 if (array_key_exists($urlValue, $drilldownReport))
6a488035
TO
106 $drilldownInstanceID = CRM_Core_DAO::getFieldValue('CRM_Report_DAO_Instance', $instanceID, 'drilldown_id', 'id');
107
6001af1f 108 if (!$drilldownInstanceID)
6a488035
TO
109 $drilldownInstanceID = self::getInstanceIDForValue($urlValue);
110
111 if ($drilldownInstanceID) {
112 return CRM_Utils_System::url("civicrm/report/instance/{$drilldownInstanceID}",
113 "{$query}", $absolute
114 );
115 }
116 else {
117 return FALSE;
118 }
119 }
120 else {
121 return CRM_Utils_System::url("civicrm/report/" . trim($urlValue, '/'),
122 $query, $absolute
123 );
124 }
125 }
126
127 // get instance count for a template
128 static function getInstanceCount($optionVal) {
129 $sql = "
130SELECT count(inst.id)
131FROM civicrm_report_instance inst
132WHERE inst.report_id = %1";
133
134 $params = array(1 => array($optionVal, 'String'));
135 $count = CRM_Core_DAO::singleValueQuery($sql, $params);
136 return $count;
137 }
138
139 static function mailReport($fileContent, $instanceID = NULL, $outputMode = 'html', $attachments = array(
140 )) {
141 if (!$instanceID) {
142 return FALSE;
143 }
144
145 list($domainEmailName,
146 $domainEmailAddress
147 ) = CRM_Core_BAO_Domain::getNameAndEmail();
148
149 $params = array('id' => $instanceID);
150 $instanceInfo = array();
151 CRM_Core_DAO::commonRetrieve('CRM_Report_DAO_Instance',
152 $params,
153 $instanceInfo
154 );
155
156 $params = array();
157 $params['groupName'] = 'Report Email Sender';
158 $params['from'] = '"' . $domainEmailName . '" <' . $domainEmailAddress . '>';
159 //$domainEmailName;
160 $params['toName'] = "";
161 $params['toEmail'] = CRM_Utils_Array::value('email_to', $instanceInfo);
162 $params['cc'] = CRM_Utils_Array::value('email_cc', $instanceInfo);
163 $params['subject'] = CRM_Utils_Array::value('email_subject', $instanceInfo);
164 if (!CRM_Utils_Array::value('attachments', $instanceInfo)) {
165 $instanceInfo['attachments'] = array();
166 }
167 $params['attachments'] = array_merge(CRM_Utils_Array::value('attachments', $instanceInfo), $attachments);
168 $params['text'] = '';
169 $params['html'] = $fileContent;
170
171 return CRM_Utils_Mail::send($params);
172 }
173
174 static function export2csv(&$form, &$rows) {
175 //Mark as a CSV file.
176 header('Content-Type: text/csv');
177
178 //Force a download and name the file using the current timestamp.
179 $datetime = date('Ymd-Gi', $_SERVER['REQUEST_TIME']);
180 header('Content-Disposition: attachment; filename=Report_' . $datetime . '.csv');
181 echo self::makeCsv($form, $rows);
182 CRM_Utils_System::civiExit();
183 }
184
185 /**
186 * Utility function for export2csv and CRM_Report_Form::endPostProcess
187 * - make CSV file content and return as string.
188 */
189 static function makeCsv(&$form, &$rows) {
190 $config = CRM_Core_Config::singleton();
191 $csv = '';
192
193 // Add headers if this is the first row.
194 $columnHeaders = array_keys($form->_columnHeaders);
195
196 // Replace internal header names with friendly ones, where available.
197 foreach ($columnHeaders as $header) {
198 if (isset($form->_columnHeaders[$header])) {
199 $headers[] = '"' . html_entity_decode(strip_tags($form->_columnHeaders[$header]['title'])) . '"';
200 }
201 }
202 // Add the headers.
203 $csv .= implode($config->fieldSeparator,
204 $headers
205 ) . "\r\n";
206
207 $displayRows = array();
208 $value = NULL;
209 foreach ($rows as $row) {
210 foreach ($columnHeaders as $k => $v) {
211 $value = CRM_Utils_Array::value($v, $row);
212 if (isset($value)) {
213 // Remove HTML, unencode entities, and escape quotation marks.
214 $value = str_replace('"', '""', html_entity_decode(strip_tags($value)));
215
216 if (CRM_Utils_Array::value('type', $form->_columnHeaders[$v]) & 4) {
217 if (CRM_Utils_Array::value('group_by', $form->_columnHeaders[$v]) == 'MONTH' ||
218 CRM_Utils_Array::value('group_by', $form->_columnHeaders[$v]) == 'QUARTER'
219 ) {
220 $value = CRM_Utils_Date::customFormat($value, $config->dateformatPartial);
221 }
222 elseif (CRM_Utils_Array::value('group_by', $form->_columnHeaders[$v]) == 'YEAR') {
223 $value = CRM_Utils_Date::customFormat($value, $config->dateformatYear);
224 }
225 else {
226 $value = CRM_Utils_Date::customFormat($value, '%Y-%m-%d');
227 }
228 }
229 elseif (CRM_Utils_Array::value('type', $form->_columnHeaders[$v]) == 1024) {
230 $value = CRM_Utils_Money::format($value);
231 }
232 $displayRows[$v] = '"' . $value . '"';
233 }
234 else {
235 $displayRows[$v] = " ";
236 }
237 }
238 // Add the data row.
239 $csv .= implode($config->fieldSeparator,
240 $displayRows
241 ) . "\r\n";
242 }
243
244 return $csv;
245 }
246
247 static function getInstanceID() {
248
249 $config = CRM_Core_Config::singleton();
250 $arg = explode('/', $_GET[$config->userFrameworkURLVar]);
251
252 if ($arg[1] == 'report' &&
253 CRM_Utils_Array::value(2, $arg) == 'instance'
254 ) {
255 if (CRM_Utils_Rule::positiveInteger($arg[3])) {
256 return $arg[3];
257 }
258 }
259 }
260
261 static function getInstancePath() {
262 $config = CRM_Core_Config::singleton();
263 $arg = explode('/', $_GET[$config->userFrameworkURLVar]);
264
265 if ($arg[1] == 'report' &&
266 CRM_Utils_Array::value(2, $arg) == 'instance'
267 ) {
268 unset($arg[0], $arg[1], $arg[2]);
269 $path = trim(CRM_Utils_Type::escape(implode('/', $arg), 'String'), '/');
270 return $path;
271 }
272 }
273
274 static function isInstancePermissioned($instanceId) {
275 if (!$instanceId) {
276 return TRUE;
277 }
278
279 $instanceValues = array();
280 $params = array('id' => $instanceId);
281 CRM_Core_DAO::commonRetrieve('CRM_Report_DAO_Instance',
282 $params,
283 $instanceValues
284 );
285
286 if (!empty($instanceValues['permission']) &&
287 (!(CRM_Core_Permission::check($instanceValues['permission']) ||
288 CRM_Core_Permission::check('administer Reports')
289 ))
290 ) {
291 return FALSE;
292 }
293
294 return TRUE;
295 }
296
297 /**
298 * Check if the user can view a report instance based on their role(s)
299 *
300 * @instanceId string $str the report instance to check
301 *
302 * @return boolean true if yes, else false
303 * @static
304 * @access public
305 */
306 static function isInstanceGroupRoleAllowed($instanceId) {
307 if (!$instanceId) {
308 return TRUE;
309 }
310
311 $instanceValues = array();
312 $params = array('id' => $instanceId);
313 CRM_Core_DAO::commonRetrieve('CRM_Report_DAO_Instance',
314 $params,
315 $instanceValues
316 );
317 //transform grouprole to array
318 if (!empty($instanceValues['grouprole'])) {
319 $grouprole_array = explode(CRM_Core_DAO::VALUE_SEPARATOR,
320 $instanceValues['grouprole']
321 );
322 if (!CRM_Core_Permission::checkGroupRole($grouprole_array) &&
323 !CRM_Core_Permission::check('administer Reports')
324 ) {
325 return FALSE;
326 }
327 }
328 return TRUE;
329 }
330
331 static function processReport($params) {
6a488035
TO
332 $instanceId = CRM_Utils_Array::value('instanceId', $params);
333
334 // hack for now, CRM-8358
335 $_REQUEST['instanceId'] = $instanceId;
336 $_REQUEST['sendmail'] = CRM_Utils_Array::value('sendmail', $params, 1);
884605ca 337
6a488035
TO
338 // if cron is run from terminal --output is reserved, and therefore we would provide another name 'format'
339 $_REQUEST['output'] = CRM_Utils_Array::value('format', $params, CRM_Utils_Array::value('output', $params, 'pdf'));
340 $_REQUEST['reset'] = CRM_Utils_Array::value('reset', $params, 1);
341
342 $optionVal = self::getValueFromUrl($instanceId);
343 $messages = array("Report Mail Triggered...");
344
345 $templateInfo = CRM_Core_OptionGroup::getRowValues('report_template', $optionVal, 'value');
346 $obj = new CRM_Report_Page_Instance();
347 $is_error = 0;
348 if (strstr(CRM_Utils_Array::value('name', $templateInfo), '_Form')) {
349 $instanceInfo = array();
350 CRM_Report_BAO_Instance::retrieve(array('id' => $instanceId), $instanceInfo);
351
352 if (!empty($instanceInfo['title'])) {
353 $obj->assign('reportTitle', $instanceInfo['title']);
354 }
355 else {
356 $obj->assign('reportTitle', $templateInfo['label']);
357 }
358
359 $wrapper = new CRM_Utils_Wrapper();
884605ca
DL
360 $arguments = array(
361 'urlToSession' => array(
362 array(
363 'urlVar' => 'instanceId',
364 'type' => 'Positive',
365 'sessionVar' => 'instanceId',
366 'default' => 'null',
367 ),
6001af1f 368 ),
884605ca 369 'ignoreKey' => TRUE
6001af1f 370 );
6a488035
TO
371 $messages[] = $wrapper->run($templateInfo['name'], NULL, $arguments);
372 }
373 else {
374 $is_error = 1;
375 if (!$instanceId) {
376 $messages[] = 'Required parameter missing: instanceId';
377 }
378 else {
379 $messages[] = 'Did not find valid instance to execute';
380 }
381 }
382
383 $result = array(
384 'is_error' => $is_error,
385 'messages' => implode("\n", $messages),
386 );
387 return $result;
388 }
389
390 /**
391 * Build a URL query string containing all report filter criteria that are
392 * stipulated in $_GET or in a report Preview, but which haven't yet been
393 * saved in the report instance.
394 *
395 * @param array $defaults The report criteria that aren't coming in as submitted form values, as in CRM_Report_Form::_defaults
396 * @param array $params All effective report criteria, as in CRM_Report_Form::_params
397 *
398 * @return string URL query string
399 */
400 static function getPreviewCriteriaQueryParams($defaults = array(
401 ), $params = array()) {
402 static $query_string;
403 if (!isset($query_string)) {
404 if (!empty($params)) {
405 $url_params = $op_values = $string_values = $process_params = array();
406
407 // We'll only use $params that are different from what's in $default.
408 foreach ($params as $field_name => $field_value) {
409 if (!array_key_exists($field_name, $defaults) || $defaults[$field_name] != $field_value) {
410 $process_params[$field_name] = $field_value;
411 }
412 }
413 // Criteria stipulated in $_GET will be in $defaults even if they're not
414 // saved, so we can't easily tell if they're saved or not. So just include them.
415 $process_params += $_GET;
416
417 // All $process_params should be passed on if they have an effective value
418 // (in other words, there's no point in propagating blank filters).
419 foreach ($process_params as $field_name => $field_value) {
420 $suffix_position = strrpos($field_name, '_');
421 $suffix = substr($field_name, $suffix_position);
422 $basename = substr($field_name, 0, $suffix_position);
423 if ($suffix == '_min' || $suffix == '_max' ||
424 $suffix == '_from' || $suffix == '_to' ||
425 $suffix == '_relative'
426 ) {
427 // For these types, we only keep them if they have a value.
428 if (!empty($field_value)) {
429 $url_params[$field_name] = $field_value;
430 }
431 }
432 elseif ($suffix == '_value') {
433 // These filters can have an effect even without a value
434 // (e.g., values for 'nll' and 'nnll' ops are blank),
435 // so store them temporarily and examine below.
436 $string_values[$basename] = $field_value;
437 $op_values[$basename] = CRM_Utils_Array::value("{$basename}_op", $params);
438 }
439 elseif ($suffix == '_op') {
440 // These filters can have an effect even without a value
441 // (e.g., values for 'nll' and 'nnll' ops are blank),
442 // so store them temporarily and examine below.
443 $op_values[$basename] = $field_value;
444 $string_values[$basename] = $params["{$basename}_value"];
445 }
446 }
447
448 // Check the *_value and *_op criteria and include them if
449 // they'll have an effective value.
450 foreach ($op_values as $basename => $field_value) {
451 if ($field_value == 'nll' || $field_value == 'nnll') {
452 // 'nll' and 'nnll' filters should be included even with empty values.
453 $url_params["{$basename}_op"] = $field_value;
454 }
455 elseif ($string_values[$basename]) {
456 // Other filters are only included if they have a value.
457 $url_params["{$basename}_op"] = $field_value;
458 $url_params["{$basename}_value"] = (is_array($string_values[$basename]) ? implode(',', $string_values[$basename]) : $string_values[$basename]);
459 }
460 }
461 $query_string = http_build_query($url_params);
462 }
463 else {
464 $query_string = '';
465 }
466 }
467 return $query_string;
468 }
469
470 static function getInstanceList($reportUrl) {
471 static $instanceDetails = array();
6001af1f 472
6a488035
TO
473 if (!array_key_exists($reportUrl, $instanceDetails )) {
474 $instanceDetails[$reportUrl] = array();
475
476 $sql = "
477SELECT id, title FROM civicrm_report_instance
478WHERE report_id = %1";
479 $params = array(1 => array($reportUrl, 'String'));
480 $result = CRM_Core_DAO::executeQuery($sql, $params);
481 while( $result->fetch()) {
482 $instanceDetails[$reportUrl][$result->id] = $result->title . " (ID: {$result->id})";
483 }
484 }
485 return $instanceDetails[$reportUrl];
486 }
487}