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