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