CRM-17663 - Implement localStorage cache
[civicrm-core.git] / CRM / Core / BAO / Dashboard.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
fa938177 6 | Copyright CiviCRM LLC (c) 2004-2016 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
fa938177 31 * @copyright CiviCRM LLC (c) 2004-2016
6a488035
TO
32 */
33
34/**
192d36c5 35 * Class contains Contact dashboard related functions.
6a488035
TO
36 */
37class CRM_Core_BAO_Dashboard extends CRM_Core_DAO_Dashboard {
3cfa8e5e 38 /**
fe482240 39 * Add Dashboard.
3cfa8e5e 40 *
6a0b768e
TO
41 * @param array $params
42 * Values.
3cfa8e5e 43 *
3cfa8e5e
EM
44 *
45 * @return object
46 */
00be9182 47 public static function create($params) {
3cfa8e5e
EM
48 $hook = empty($params['id']) ? 'create' : 'edit';
49 CRM_Utils_Hook::pre($hook, 'Dashboard', CRM_Utils_Array::value('id', $params), $params);
50 $dao = self::addDashlet($params);
51 CRM_Utils_Hook::post($hook, 'Dashboard', $dao->id, $dao);
52 return $dao;
53 }
6a488035
TO
54
55 /**
fe482240 56 * Get the list of dashlets enabled by admin.
6a488035 57 *
6a0b768e
TO
58 * @param bool $all
59 * All or only active.
60 * @param bool $checkPermission
61 * All or only authorized for the current user.
6a488035 62 *
a6c01b45
CW
63 * @return array
64 * array of dashlets
6a488035 65 */
00be9182 66 public static function getDashlets($all = TRUE, $checkPermission = TRUE) {
6a488035
TO
67 $dashlets = array();
68 $dao = new CRM_Core_DAO_Dashboard();
69
70 if (!$all) {
71 $dao->is_active = 1;
72 }
73
74 $dao->domain_id = CRM_Core_Config::domainID();
75
76 $dao->find();
77 while ($dao->fetch()) {
ee117e9c 78 if ($checkPermission && !self::checkPermission($dao->permission, $dao->permission_operator)) {
6a488035
TO
79 continue;
80 }
81
82 $values = array();
83 CRM_Core_DAO::storeValues($dao, $values);
84 $dashlets[$dao->id] = $values;
85 }
86
87 return $dashlets;
88 }
89
90 /**
08727453 91 * Get the list of dashlets for the current user or the specified user.
6a488035 92 *
5aa910d4
JM
93 * Additionlly, initializes the dashboard with defaults if this is the
94 * user's first visit to their dashboard.
6a488035 95 *
6a0b768e 96 * @param int $contactID
94864a5f 97 * Defaults to the current user.
77b97be7 98 *
a6c01b45
CW
99 * @return array
100 * array of dashlets
6a488035 101 */
94864a5f
CW
102 public static function getContactDashlets($contactID = NULL) {
103 $contactID = $contactID ? $contactID : CRM_Core_Session::singleton()->getLoggedInContactID();
6a488035
TO
104 $dashlets = array();
105
5aa910d4 106 // Get contact dashboard dashlets.
dd3770bc 107 $results = civicrm_api3('DashboardContact', 'get', array(
94864a5f 108 'contact_id' => $contactID,
dd3770bc
CW
109 'is_active' => 1,
110 'dashboard_id.is_active' => 1,
111 'options' => array('sort' => 'weight'),
112 'return' => array(
113 'id',
114 'weight',
115 'column_no',
116 'is_minimized',
117 'dashboard_id',
118 'dashboard_id.name',
119 'dashboard_id.label',
120 'dashboard_id.url',
121 'dashboard_id.fullscreen_url',
122 'dashboard_id.permission',
123 'dashboard_id.permission_operator',
124 ),
94864a5f 125 ));
5f3f6ec3 126
94864a5f 127 foreach ($results['values'] as $item) {
dd3770bc
CW
128 if (self::checkPermission(CRM_Utils_Array::value('dashboard_id.permission', $item), CRM_Utils_Array::value('dashboard_id.permission_operator', $item))) {
129 $dashlets[$item['id']] = array(
130 'dashboard_id' => $item['dashboard_id'],
131 'weight' => $item['weight'],
132 'column_no' => $item['column_no'],
133 'is_minimized' => $item['is_minimized'],
134 'name' => $item['dashboard_id.name'],
135 'label' => $item['dashboard_id.label'],
136 'url' => $item['dashboard_id.url'],
137 'fullscreen_url' => $item['dashboard_id.fullscreen_url'],
138 );
6a488035
TO
139 }
140 }
141
dd3770bc 142 // If empty, then initialize default dashlets for this user.
94864a5f 143 if (!$results['count']) {
dd3770bc
CW
144 // They may just have disabled all their dashlets. Check if any records exist for this contact.
145 if (!civicrm_api3('DashboardContact', 'getcount', array('contact_id' => $contactID))) {
146 $dashlets = self::initializeDashlets();
147 }
5aa910d4 148 }
94864a5f 149
5aa910d4 150 return $dashlets;
15d9b3ae
N
151 }
152
dd3770bc
CW
153 public static function getContactDashletsForJS() {
154 $data = array(array(), array());
155 foreach (self::getContactDashlets() as $item) {
156 $data[$item['column_no']][] = array(
157 'id' => (int) $item['dashboard_id'],
dd3770bc
CW
158 'name' => $item['name'],
159 'title' => $item['label'],
160 'url' => self::parseUrl($item['url']),
161 'fullscreenUrl' => self::parseUrl($item['fullscreen_url']),
162 );
163 }
164 return $data;
165 }
166
b5c2afd0 167 /**
fe482240 168 * Setup default dashlets for new users.
b5c2afd0 169 *
5aa910d4
JM
170 * When a user accesses their dashboard for the first time, set up
171 * the default dashlets.
172 *
a6c01b45 173 * @return array
ad37ac8e 174 * Array of dashboard_id's
175 * @throws \CiviCRM_API3_Exception
b5c2afd0 176 */
94864a5f 177 public static function initializeDashlets() {
5aa910d4 178 $dashlets = array();
353ffa53
TO
179 $getDashlets = civicrm_api3("Dashboard", "get", array(
180 'domain_id' => CRM_Core_Config::domainID(),
408b79bf 181 'option.limit' => 0,
353ffa53 182 ));
5f3f6ec3 183 $contactID = CRM_Core_Session::singleton()->getLoggedInContactID();
15d9b3ae
N
184 $allDashlets = CRM_Utils_Array::index(array('name'), $getDashlets['values']);
185 $defaultDashlets = array();
c202dd9e 186 $defaults = array('blog' => 1, 'getting-started' => '0');
187 foreach ($defaults as $name => $column) {
fbd19c80 188 if (!empty($allDashlets[$name]) && !empty($allDashlets[$name]['id'])) {
40c0dd53 189 $defaultDashlets[$name] = array(
190 'dashboard_id' => $allDashlets[$name]['id'],
191 'is_active' => 1,
192 'column_no' => $column,
193 'contact_id' => $contactID,
194 );
195 }
15d9b3ae
N
196 }
197 CRM_Utils_Hook::dashboard_defaults($allDashlets, $defaultDashlets);
198 if (is_array($defaultDashlets) && !empty($defaultDashlets)) {
5aa910d4
JM
199 foreach ($defaultDashlets as $id => $defaultDashlet) {
200 $dashboard_id = $defaultDashlet['dashboard_id'];
dd3770bc
CW
201 $dashlet = $getDashlets['values'][$dashboard_id];
202 if (!self::checkPermission(CRM_Utils_Array::value('permission', $dashlet), CRM_Utils_Array::value('permission_operator', $dashlet))) {
15d9b3ae
N
203 continue;
204 }
205 else {
206 $assignDashlets = civicrm_api3("dashboard_contact", "create", $defaultDashlet);
94864a5f 207 $values = $assignDashlets['values'][$assignDashlets['id']];
dd3770bc
CW
208 $dashlets[$assignDashlets['id']] = array(
209 'dashboard_id' => $values['dashboard_id'],
210 'weight' => $values['weight'],
211 'column_no' => $values['column_no'],
212 'is_minimized' => $values['is_minimized'],
213 'name' => $dashlet['name'],
214 'label' => $dashlet['label'],
215 'url' => $dashlet['url'],
216 'fullscreen_url' => $dashlet['fullscreen_url'],
217 );
6a488035 218 }
6a488035
TO
219 }
220 }
5aa910d4 221 return $dashlets;
6a488035 222 }
08727453 223
dd3770bc
CW
224 /**
225 * @param $url
226 * @return string
227 */
228 public static function parseUrl($url) {
229 if (substr($url, 0, 4) != 'http') {
230 $urlParam = explode('?', $url);
231 $url = CRM_Utils_System::url($urlParam[0], $urlParam[1], FALSE, NULL, FALSE);
232 }
233 return $url;
234 }
6a488035
TO
235
236 /**
fe482240 237 * Check dashlet permission for current user.
6a488035 238 *
6a0b768e
TO
239 * @param string $permission
240 * Comma separated list.
c490a46a 241 * @param string $operator
6a488035 242 *
408b79bf 243 * @return bool
a6c01b45 244 * true if use has permission else false
6a488035 245 */
00be9182 246 public static function checkPermission($permission, $operator) {
6a488035
TO
247 if ($permission) {
248 $permissions = explode(',', $permission);
249 $config = CRM_Core_Config::singleton();
250
251 static $allComponents;
252 if (!$allComponents) {
253 $allComponents = CRM_Core_Component::getNames();
254 }
255
256 $hasPermission = FALSE;
257 foreach ($permissions as $key) {
258 $showDashlet = TRUE;
259
260 $componentName = NULL;
261 if (strpos($key, 'access') === 0) {
262 $componentName = trim(substr($key, 6));
263 if (!in_array($componentName, $allComponents)) {
264 $componentName = NULL;
265 }
266 }
267
268 // hack to handle case permissions
269 if (!$componentName && in_array($key, array(
353ffa53 270 'access my cases and activities',
408b79bf 271 'access all cases and activities',
353ffa53
TO
272 ))
273 ) {
6a488035
TO
274 $componentName = 'CiviCase';
275 }
276
277 //hack to determine if it's a component related permission
278 if ($componentName) {
279 if (!in_array($componentName, $config->enableComponents) ||
280 !CRM_Core_Permission::check($key)
281 ) {
282 $showDashlet = FALSE;
283 if ($operator == 'AND') {
284 return $showDashlet;
285 }
286 }
287 else {
288 $hasPermission = TRUE;
289 }
290 }
291 elseif (!CRM_Core_Permission::check($key)) {
292 $showDashlet = FALSE;
293 if ($operator == 'AND') {
294 return $showDashlet;
295 }
296 }
297 else {
298 $hasPermission = TRUE;
299 }
300 }
301
302 if (!$showDashlet && !$hasPermission) {
303 return FALSE;
304 }
305 else {
306 return TRUE;
307 }
308 }
309 else {
310 // if permission is not set consider everyone has permission to access it.
311 return TRUE;
312 }
313 }
314
315 /**
fe482240 316 * Get details of each dashlets.
6a488035 317 *
6a0b768e
TO
318 * @param int $dashletID
319 * Widget ID.
6a488035 320 *
a6c01b45
CW
321 * @return array
322 * associted array title and content
6a488035 323 */
00be9182 324 public static function getDashletInfo($dashletID) {
6a488035
TO
325 $dashletInfo = array();
326
327 $params = array(1 => array($dashletID, 'Integer'));
15d9b3ae 328 $query = "SELECT name, label, url, fullscreen_url, is_fullscreen FROM civicrm_dashboard WHERE id = %1";
6a488035
TO
329 $dashboadDAO = CRM_Core_DAO::executeQuery($query, $params);
330 $dashboadDAO->fetch();
331
332 // build the content
333 $dao = new CRM_Contact_DAO_DashboardContact();
334
353ffa53
TO
335 $session = CRM_Core_Session::singleton();
336 $dao->contact_id = $session->get('userID');
6a488035
TO
337 $dao->dashboard_id = $dashletID;
338 $dao->find(TRUE);
339
340 //reset content based on the cache time set in config
341 $createdDate = strtotime($dao->created_date);
342 $dateDiff = round(abs(time() - $createdDate) / 60);
343
344 $config = CRM_Core_Config::singleton();
345 if ($config->dashboardCacheTimeout <= $dateDiff) {
346 $dao->content = NULL;
347 }
348
349 // if content is empty and url is set, retrieve it from url
350 if (!$dao->content && $dashboadDAO->url) {
351 $url = $dashboadDAO->url;
352
353 // CRM-7087
354 // -lets use relative url for internal use.
355 // -make sure relative url should not be htmlize.
356 if (substr($dashboadDAO->url, 0, 4) != 'http') {
36ffcc5f 357 $urlParam = explode('?', $dashboadDAO->url);
6a488035
TO
358 $url = CRM_Utils_System::url($urlParam[0], $urlParam[1], TRUE, NULL, FALSE);
359 }
360
361 //get content from url
362 $dao->content = CRM_Utils_System::getServerResponse($url);
363 $dao->created_date = date("YmdHis");
364 $dao->save();
365 }
366
367 $dashletInfo = array(
368 'title' => $dashboadDAO->label,
15d9b3ae 369 'name' => $dashboadDAO->name,
6a488035
TO
370 'content' => $dao->content,
371 );
372
373 if ($dashboadDAO->is_fullscreen) {
374 $fullscreenUrl = $dashboadDAO->fullscreen_url;
375 if (substr($fullscreenUrl, 0, 4) != 'http') {
36ffcc5f 376 $urlParam = explode('?', $dashboadDAO->fullscreen_url);
6a488035
TO
377 $fullscreenUrl = CRM_Utils_System::url($urlParam[0], $urlParam[1], TRUE, NULL, FALSE);
378 }
379 $dashletInfo['fullscreenUrl'] = $fullscreenUrl;
380 }
381 return $dashletInfo;
382 }
383
384 /**
fe482240 385 * Save changes made by use to the Dashlet.
6a488035 386 *
6a0b768e 387 * @param array $columns
6a488035 388 *
100fef9d 389 * @param int $contactID
77b97be7
EM
390 *
391 * @throws RuntimeException
6a488035 392 */
2aa397bc 393 public static function saveDashletChanges($columns, $contactID = NULL) {
15d9b3ae 394 if (!$contactID) {
ce2cc43e 395 $contactID = CRM_Core_Session::getLoggedInContactID();
15d9b3ae
N
396 }
397
f583d89b
TO
398 if (empty($contactID)) {
399 throw new RuntimeException("Failed to determine contact ID");
400 }
6a488035 401
6a488035
TO
402 $dashletIDs = array();
403 if (is_array($columns)) {
404 foreach ($columns as $colNo => $dashlets) {
408b79bf 405 if (!is_int($colNo)) {
6a488035
TO
406 continue;
407 }
408 $weight = 1;
409 foreach ($dashlets as $dashletID => $isMinimized) {
410 $isMinimized = (int) $isMinimized;
00c27b41
CW
411 $dashletID = (int) $dashletID;
412 $query = "INSERT INTO civicrm_dashboard_contact
413 (weight, is_minimized, column_no, is_active, dashboard_id, contact_id)
414 VALUES({$weight}, {$isMinimized}, {$colNo}, 1, {$dashletID}, {$contactID})
415 ON DUPLICATE KEY UPDATE weight = {$weight}, is_minimized = {$isMinimized}, column_no = {$colNo}, is_active = 1";
6a488035 416 // fire update query for each column
00c27b41 417 CRM_Core_DAO::executeQuery($query);
6a488035
TO
418
419 $dashletIDs[] = $dashletID;
420 $weight++;
421 }
422 }
423 }
424
00c27b41
CW
425 // Disable inactive widgets
426 $dashletClause = $dashletIDs ? "dashboard_id NOT IN (" . implode(',', $dashletIDs) . ")" : '(1)';
427 $updateQuery = "UPDATE civicrm_dashboard_contact
428 SET is_active = 0
429 WHERE $dashletClause AND contact_id = {$contactID}";
6a488035
TO
430
431 CRM_Core_DAO::executeQuery($updateQuery);
432 }
433
434 /**
fe482240 435 * Add dashlets.
6a488035 436 *
6a0b768e 437 * @param array $params
6a488035 438 *
a6c01b45
CW
439 * @return object
440 * $dashlet returns dashlet object
6a488035 441 */
00be9182 442 public static function addDashlet(&$params) {
6a488035 443
32c93376 444 // special case to handle duplicate entries for report instances
15d9b3ae
N
445 $dashboardID = CRM_Utils_Array::value('id', $params);
446
a7488080 447 if (!empty($params['instanceURL'])) {
6a488035
TO
448 $query = "SELECT id
449 FROM `civicrm_dashboard`
450 WHERE url LIKE '" . CRM_Utils_Array::value('instanceURL', $params) . "&%'";
451 $dashboardID = CRM_Core_DAO::singleValueQuery($query);
452 }
453
454 $dashlet = new CRM_Core_DAO_Dashboard();
455
456 if (!$dashboardID) {
457 // check url is same as exiting entries, if yes just update existing
a7488080 458 if (!empty($params['name'])) {
15d9b3ae
N
459 $dashlet->name = CRM_Utils_Array::value('name', $params);
460 $dashlet->find(TRUE);
461 }
462 else {
463 $dashlet->url = CRM_Utils_Array::value('url', $params);
464 $dashlet->find(TRUE);
465 }
3cfa8e5e
EM
466 if (empty($params['domain_id'])) {
467 $dashlet->domain_id = CRM_Core_Config::domainID();
468 }
6a488035
TO
469 }
470 else {
471 $dashlet->id = $dashboardID;
472 }
473
474 if (is_array(CRM_Utils_Array::value('permission', $params))) {
475 $params['permission'] = implode(',', $params['permission']);
476 }
477 $dashlet->copyValues($params);
6a488035
TO
478 $dashlet->save();
479
480 // now we need to make dashlet entries for each contact
481 self::addContactDashlet($dashlet);
482
483 return $dashlet;
484 }
485
b5c2afd0
EM
486 /**
487 * @param $url
488 *
489 * @return string
490 */
00be9182 491 public static function getDashletName($url) {
fa4916a4 492 $urlElements = explode('/', $url);
493 if ($urlElements[1] == 'dashlet') {
494 return $urlElements[2];
495 }
496 elseif ($urlElements[1] == 'report') {
497 return 'report/' . $urlElements[3];
498 }
499 return $url;
500 }
353ffa53 501
6a488035 502 /**
fe482240 503 * Update contact dashboard with new dashlet.
6a488035 504 *
192d36c5 505 * @param object $dashlet
6a488035 506 */
00be9182 507 public static function addContactDashlet($dashlet) {
6a488035
TO
508 $admin = CRM_Core_Permission::check('administer CiviCRM');
509
510 // if dashlet is created by admin then you need to add it all contacts.
511 // else just add to contact who is creating this dashlet
512 $contactIDs = array();
513 if ($admin) {
514 $query = "SELECT distinct( contact_id )
515 FROM civicrm_dashboard_contact
516 WHERE contact_id NOT IN (
517 SELECT distinct( contact_id )
518 FROM civicrm_dashboard_contact WHERE dashboard_id = {$dashlet->id}
519 )";
520
521 $dao = CRM_Core_DAO::executeQuery($query);
522 while ($dao->fetch()) {
523 $contactIDs[] = $dao->contact_id;
524 }
525 }
526 else {
527 //Get the id of Logged in User
528 $session = CRM_Core_Session::singleton();
155a0ed0 529 $contactID = $session->get('userID');
22e263ad 530 if (!empty($contactID)) {
155a0ed0
JM
531 $contactIDs[] = $session->get('userID');
532 }
6a488035
TO
533 }
534
535 if (!empty($contactIDs)) {
536 foreach ($contactIDs as $contactID) {
537 $valuesArray[] = " ( {$dashlet->id}, {$contactID} )";
538 }
539
540 $valuesString = implode(',', $valuesArray);
541 $query = "
542 INSERT INTO civicrm_dashboard_contact ( dashboard_id, contact_id )
543 VALUES {$valuesString}";
544
545 CRM_Core_DAO::executeQuery($query);
546 }
547 }
548
dcf56200 549 /**
6a0b768e
TO
550 * @param array $params
551 * Each item is a spec for a dashlet on the contact's dashboard.
dcf56200
TO
552 * @return bool
553 */
00be9182 554 public static function addContactDashletToDashboard(&$params) {
15d9b3ae
N
555 $valuesString = NULL;
556 $columns = array();
557 foreach ($params as $dashboardIDs) {
558 $contactID = CRM_Utils_Array::value('contact_id', $dashboardIDs);
559 $dashboardID = CRM_Utils_Array::value('dashboard_id', $dashboardIDs);
560 $column = CRM_Utils_Array::value('column_no', $dashboardIDs, 0);
561 $columns[$column][$dashboardID] = 0;
562 }
563 self::saveDashletChanges($columns, $contactID);
564 return TRUE;
565 }
566
6a488035 567 /**
fe482240 568 * Reset dashlet cache.
6a488035 569 *
6a0b768e
TO
570 * @param int $contactID
571 * Reset cache only for specific contact.
6a488035 572 */
2aa397bc
TO
573 public static function resetDashletCache($contactID = NULL) {
574 $whereClause = NULL;
6a488035
TO
575 $params = array();
576 if ($contactID) {
577 $whereClause = "WHERE contact_id = %1";
578 $params[1] = array($contactID, 'Integer');
579 }
580 $query = "UPDATE civicrm_dashboard_contact SET content = NULL $whereClause";
581 $dao = CRM_Core_DAO::executeQuery($query, $params);
582 }
583
584 /**
fe482240 585 * Delete Dashlet.
6a488035 586 *
100fef9d 587 * @param int $dashletID
2a6da8d7 588 *
192d36c5 589 * @return bool
6a488035 590 */
00be9182 591 public static function deleteDashlet($dashletID) {
6a488035
TO
592 $dashlet = new CRM_Core_DAO_Dashboard();
593 $dashlet->id = $dashletID;
594 $dashlet->delete();
15d9b3ae 595 return TRUE;
6a488035 596 }
96025800 597
6a488035 598}