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