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