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