Merge pull request #13241 from seamuslee001/561_schedule_reminders
[civicrm-core.git] / CRM / Core / BAO / Dashboard.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
6b83d5bd 31 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
32 */
33
34/**
192d36c5 35 * Class contains Contact dashboard related functions.
6a488035
TO
36 */
37class CRM_Core_BAO_Dashboard extends CRM_Core_DAO_Dashboard {
3cfa8e5e 38 /**
fe482240 39 * Add Dashboard.
3cfa8e5e 40 *
6a0b768e
TO
41 * @param array $params
42 * Values.
3cfa8e5e 43 *
3cfa8e5e
EM
44 *
45 * @return object
46 */
00be9182 47 public static function create($params) {
3cfa8e5e
EM
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 }
6a488035
TO
54
55 /**
fe482240 56 * Get the list of dashlets enabled by admin.
6a488035 57 *
6a0b768e
TO
58 * @param bool $all
59 * All or only active.
60 * @param bool $checkPermission
61 * All or only authorized for the current user.
6a488035 62 *
a6c01b45
CW
63 * @return array
64 * array of dashlets
6a488035 65 */
00be9182 66 public static function getDashlets($all = TRUE, $checkPermission = TRUE) {
6a488035
TO
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()) {
ee117e9c 78 if ($checkPermission && !self::checkPermission($dao->permission, $dao->permission_operator)) {
6a488035
TO
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 /**
08727453 91 * Get the list of dashlets for the current user or the specified user.
6a488035 92 *
5aa910d4
JM
93 * Additionlly, initializes the dashboard with defaults if this is the
94 * user's first visit to their dashboard.
6a488035 95 *
6a0b768e 96 * @param int $contactID
94864a5f 97 * Defaults to the current user.
77b97be7 98 *
a6c01b45
CW
99 * @return array
100 * array of dashlets
6a488035 101 */
94864a5f 102 public static function getContactDashlets($contactID = NULL) {
3bdcd4ec 103 $contactID = $contactID ? $contactID : CRM_Core_Session::getLoggedInContactID();
6a488035
TO
104 $dashlets = array();
105
5aa910d4 106 // Get contact dashboard dashlets.
dd3770bc 107 $results = civicrm_api3('DashboardContact', 'get', array(
94864a5f 108 'contact_id' => $contactID,
dd3770bc
CW
109 'is_active' => 1,
110 'dashboard_id.is_active' => 1,
c07d0653 111 'options' => array('sort' => 'weight', 'limit' => 0),
dd3770bc
CW
112 'return' => array(
113 'id',
114 'weight',
115 'column_no',
dd3770bc
CW
116 'dashboard_id',
117 'dashboard_id.name',
118 'dashboard_id.label',
119 'dashboard_id.url',
120 'dashboard_id.fullscreen_url',
a8f56d71 121 'dashboard_id.cache_minutes',
dd3770bc
CW
122 'dashboard_id.permission',
123 'dashboard_id.permission_operator',
124 ),
94864a5f 125 ));
5f3f6ec3 126
94864a5f 127 foreach ($results['values'] as $item) {
dd3770bc
CW
128 if (self::checkPermission(CRM_Utils_Array::value('dashboard_id.permission', $item), CRM_Utils_Array::value('dashboard_id.permission_operator', $item))) {
129 $dashlets[$item['id']] = array(
130 'dashboard_id' => $item['dashboard_id'],
131 'weight' => $item['weight'],
132 'column_no' => $item['column_no'],
dd3770bc
CW
133 'name' => $item['dashboard_id.name'],
134 'label' => $item['dashboard_id.label'],
135 'url' => $item['dashboard_id.url'],
a8f56d71 136 'cache_minutes' => $item['dashboard_id.cache_minutes'],
7ec4b96d 137 'fullscreen_url' => CRM_Utils_Array::value('dashboard_id.fullscreen_url', $item),
dd3770bc 138 );
6a488035
TO
139 }
140 }
141
dd3770bc 142 // If empty, then initialize default dashlets for this user.
94864a5f 143 if (!$results['count']) {
dd3770bc
CW
144 // They may just have disabled all their dashlets. Check if any records exist for this contact.
145 if (!civicrm_api3('DashboardContact', 'getcount', array('contact_id' => $contactID))) {
146 $dashlets = self::initializeDashlets();
147 }
5aa910d4 148 }
94864a5f 149
5aa910d4 150 return $dashlets;
15d9b3ae
N
151 }
152
242055d3
CW
153 /**
154 * @return array
155 */
dd3770bc
CW
156 public static function getContactDashletsForJS() {
157 $data = array(array(), array());
158 foreach (self::getContactDashlets() as $item) {
159 $data[$item['column_no']][] = array(
160 'id' => (int) $item['dashboard_id'],
dd3770bc
CW
161 'name' => $item['name'],
162 'title' => $item['label'],
163 'url' => self::parseUrl($item['url']),
a8f56d71 164 'cacheMinutes' => $item['cache_minutes'],
dd3770bc
CW
165 'fullscreenUrl' => self::parseUrl($item['fullscreen_url']),
166 );
167 }
168 return $data;
169 }
170
b5c2afd0 171 /**
fe482240 172 * Setup default dashlets for new users.
b5c2afd0 173 *
5aa910d4
JM
174 * When a user accesses their dashboard for the first time, set up
175 * the default dashlets.
176 *
a6c01b45 177 * @return array
ad37ac8e 178 * Array of dashboard_id's
179 * @throws \CiviCRM_API3_Exception
b5c2afd0 180 */
94864a5f 181 public static function initializeDashlets() {
5aa910d4 182 $dashlets = array();
353ffa53
TO
183 $getDashlets = civicrm_api3("Dashboard", "get", array(
184 'domain_id' => CRM_Core_Config::domainID(),
408b79bf 185 'option.limit' => 0,
353ffa53 186 ));
3bdcd4ec 187 $contactID = CRM_Core_Session::getLoggedInContactID();
15d9b3ae
N
188 $allDashlets = CRM_Utils_Array::index(array('name'), $getDashlets['values']);
189 $defaultDashlets = array();
c202dd9e 190 $defaults = array('blog' => 1, 'getting-started' => '0');
191 foreach ($defaults as $name => $column) {
fbd19c80 192 if (!empty($allDashlets[$name]) && !empty($allDashlets[$name]['id'])) {
40c0dd53 193 $defaultDashlets[$name] = array(
194 'dashboard_id' => $allDashlets[$name]['id'],
195 'is_active' => 1,
196 'column_no' => $column,
197 'contact_id' => $contactID,
198 );
199 }
15d9b3ae
N
200 }
201 CRM_Utils_Hook::dashboard_defaults($allDashlets, $defaultDashlets);
202 if (is_array($defaultDashlets) && !empty($defaultDashlets)) {
5aa910d4
JM
203 foreach ($defaultDashlets as $id => $defaultDashlet) {
204 $dashboard_id = $defaultDashlet['dashboard_id'];
dd3770bc
CW
205 $dashlet = $getDashlets['values'][$dashboard_id];
206 if (!self::checkPermission(CRM_Utils_Array::value('permission', $dashlet), CRM_Utils_Array::value('permission_operator', $dashlet))) {
15d9b3ae
N
207 continue;
208 }
209 else {
210 $assignDashlets = civicrm_api3("dashboard_contact", "create", $defaultDashlet);
94864a5f 211 $values = $assignDashlets['values'][$assignDashlets['id']];
dd3770bc
CW
212 $dashlets[$assignDashlets['id']] = array(
213 'dashboard_id' => $values['dashboard_id'],
214 'weight' => $values['weight'],
215 'column_no' => $values['column_no'],
dd3770bc
CW
216 'name' => $dashlet['name'],
217 'label' => $dashlet['label'],
a8f56d71 218 'cache_minutes' => $dashlet['cache_minutes'],
dd3770bc 219 'url' => $dashlet['url'],
7ec4b96d 220 'fullscreen_url' => CRM_Utils_Array::value('fullscreen_url', $dashlet),
dd3770bc 221 );
6a488035 222 }
6a488035
TO
223 }
224 }
5aa910d4 225 return $dashlets;
6a488035 226 }
08727453 227
dd3770bc
CW
228 /**
229 * @param $url
230 * @return string
231 */
232 public static function parseUrl($url) {
8f6fefed 233 // Check if it is already a fully-formed url
7ec4b96d 234 if ($url && substr($url, 0, 4) != 'http' && $url[0] != '/') {
dd3770bc 235 $urlParam = explode('?', $url);
8f6fefed 236 $url = CRM_Utils_System::url($urlParam[0], CRM_Utils_Array::value(1, $urlParam), FALSE, NULL, FALSE);
dd3770bc
CW
237 }
238 return $url;
239 }
6a488035
TO
240
241 /**
fe482240 242 * Check dashlet permission for current user.
6a488035 243 *
6a0b768e
TO
244 * @param string $permission
245 * Comma separated list.
c490a46a 246 * @param string $operator
6a488035 247 *
408b79bf 248 * @return bool
a6c01b45 249 * true if use has permission else false
6a488035 250 */
00be9182 251 public static function checkPermission($permission, $operator) {
6a488035
TO
252 if ($permission) {
253 $permissions = explode(',', $permission);
254 $config = CRM_Core_Config::singleton();
255
256 static $allComponents;
257 if (!$allComponents) {
258 $allComponents = CRM_Core_Component::getNames();
259 }
260
261 $hasPermission = FALSE;
262 foreach ($permissions as $key) {
263 $showDashlet = TRUE;
264
265 $componentName = NULL;
266 if (strpos($key, 'access') === 0) {
267 $componentName = trim(substr($key, 6));
268 if (!in_array($componentName, $allComponents)) {
269 $componentName = NULL;
270 }
271 }
272
273 // hack to handle case permissions
274 if (!$componentName && in_array($key, array(
353ffa53 275 'access my cases and activities',
408b79bf 276 'access all cases and activities',
353ffa53
TO
277 ))
278 ) {
6a488035
TO
279 $componentName = 'CiviCase';
280 }
281
282 //hack to determine if it's a component related permission
283 if ($componentName) {
284 if (!in_array($componentName, $config->enableComponents) ||
285 !CRM_Core_Permission::check($key)
286 ) {
287 $showDashlet = FALSE;
288 if ($operator == 'AND') {
289 return $showDashlet;
290 }
291 }
292 else {
293 $hasPermission = TRUE;
294 }
295 }
296 elseif (!CRM_Core_Permission::check($key)) {
297 $showDashlet = FALSE;
298 if ($operator == 'AND') {
299 return $showDashlet;
300 }
301 }
302 else {
303 $hasPermission = TRUE;
304 }
305 }
306
307 if (!$showDashlet && !$hasPermission) {
308 return FALSE;
309 }
310 else {
311 return TRUE;
312 }
313 }
314 else {
315 // if permission is not set consider everyone has permission to access it.
316 return TRUE;
317 }
318 }
319
320 /**
242055d3 321 * Save changes made by user to the Dashlet.
6a488035 322 *
6a0b768e 323 * @param array $columns
6a488035 324 *
100fef9d 325 * @param int $contactID
77b97be7
EM
326 *
327 * @throws RuntimeException
6a488035 328 */
2aa397bc 329 public static function saveDashletChanges($columns, $contactID = NULL) {
15d9b3ae 330 if (!$contactID) {
ce2cc43e 331 $contactID = CRM_Core_Session::getLoggedInContactID();
15d9b3ae
N
332 }
333
f583d89b
TO
334 if (empty($contactID)) {
335 throw new RuntimeException("Failed to determine contact ID");
336 }
6a488035 337
6a488035
TO
338 $dashletIDs = array();
339 if (is_array($columns)) {
340 foreach ($columns as $colNo => $dashlets) {
408b79bf 341 if (!is_int($colNo)) {
6a488035
TO
342 continue;
343 }
344 $weight = 1;
345 foreach ($dashlets as $dashletID => $isMinimized) {
00c27b41
CW
346 $dashletID = (int) $dashletID;
347 $query = "INSERT INTO civicrm_dashboard_contact
242055d3
CW
348 (weight, column_no, is_active, dashboard_id, contact_id)
349 VALUES({$weight}, {$colNo}, 1, {$dashletID}, {$contactID})
350 ON DUPLICATE KEY UPDATE weight = {$weight}, column_no = {$colNo}, is_active = 1";
6a488035 351 // fire update query for each column
00c27b41 352 CRM_Core_DAO::executeQuery($query);
6a488035
TO
353
354 $dashletIDs[] = $dashletID;
355 $weight++;
356 }
357 }
358 }
359
00c27b41
CW
360 // Disable inactive widgets
361 $dashletClause = $dashletIDs ? "dashboard_id NOT IN (" . implode(',', $dashletIDs) . ")" : '(1)';
362 $updateQuery = "UPDATE civicrm_dashboard_contact
363 SET is_active = 0
364 WHERE $dashletClause AND contact_id = {$contactID}";
6a488035
TO
365
366 CRM_Core_DAO::executeQuery($updateQuery);
367 }
368
369 /**
fe482240 370 * Add dashlets.
6a488035 371 *
6a0b768e 372 * @param array $params
6a488035 373 *
a6c01b45
CW
374 * @return object
375 * $dashlet returns dashlet object
6a488035 376 */
00be9182 377 public static function addDashlet(&$params) {
6a488035 378
32c93376 379 // special case to handle duplicate entries for report instances
15d9b3ae
N
380 $dashboardID = CRM_Utils_Array::value('id', $params);
381
a7488080 382 if (!empty($params['instanceURL'])) {
6a488035
TO
383 $query = "SELECT id
384 FROM `civicrm_dashboard`
385 WHERE url LIKE '" . CRM_Utils_Array::value('instanceURL', $params) . "&%'";
386 $dashboardID = CRM_Core_DAO::singleValueQuery($query);
387 }
388
389 $dashlet = new CRM_Core_DAO_Dashboard();
390
391 if (!$dashboardID) {
392 // check url is same as exiting entries, if yes just update existing
a7488080 393 if (!empty($params['name'])) {
15d9b3ae
N
394 $dashlet->name = CRM_Utils_Array::value('name', $params);
395 $dashlet->find(TRUE);
396 }
397 else {
398 $dashlet->url = CRM_Utils_Array::value('url', $params);
399 $dashlet->find(TRUE);
400 }
3cfa8e5e
EM
401 if (empty($params['domain_id'])) {
402 $dashlet->domain_id = CRM_Core_Config::domainID();
403 }
6a488035
TO
404 }
405 else {
406 $dashlet->id = $dashboardID;
407 }
408
409 if (is_array(CRM_Utils_Array::value('permission', $params))) {
410 $params['permission'] = implode(',', $params['permission']);
411 }
412 $dashlet->copyValues($params);
6a488035
TO
413 $dashlet->save();
414
415 // now we need to make dashlet entries for each contact
416 self::addContactDashlet($dashlet);
417
418 return $dashlet;
419 }
420
421 /**
fe482240 422 * Update contact dashboard with new dashlet.
6a488035 423 *
192d36c5 424 * @param object $dashlet
6a488035 425 */
00be9182 426 public static function addContactDashlet($dashlet) {
6a488035
TO
427 $admin = CRM_Core_Permission::check('administer CiviCRM');
428
429 // if dashlet is created by admin then you need to add it all contacts.
430 // else just add to contact who is creating this dashlet
431 $contactIDs = array();
432 if ($admin) {
433 $query = "SELECT distinct( contact_id )
a3138c9e 434 FROM civicrm_dashboard_contact";
6a488035
TO
435 $dao = CRM_Core_DAO::executeQuery($query);
436 while ($dao->fetch()) {
a3138c9e 437 $contactIDs[$dao->contact_id] = NULL;
6a488035
TO
438 }
439 }
440 else {
441 //Get the id of Logged in User
df099613 442 $contactID = CRM_Core_Session::getLoggedInContactID();
22e263ad 443 if (!empty($contactID)) {
a3138c9e 444 $contactIDs[$contactID] = NULL;
155a0ed0 445 }
6a488035
TO
446 }
447
a3138c9e
JM
448 // Remove contact ids that already have this dashlet to avoid DB
449 // constraint violation.
450 $query = "SELECT distinct( contact_id )
451 FROM civicrm_dashboard_contact WHERE dashboard_id = {$dashlet->id}";
452 $dao = CRM_Core_DAO::executeQuery($query);
a3138c9e 453 while ($dao->fetch()) {
cc4988ae 454 if (array_key_exists($dao->contact_id, $contactIDs)) {
a3138c9e
JM
455 unset($contactIDs[$dao->contact_id]);
456 }
457 }
6a488035 458 if (!empty($contactIDs)) {
a3138c9e 459 foreach ($contactIDs as $contactID => $value) {
6a488035
TO
460 $valuesArray[] = " ( {$dashlet->id}, {$contactID} )";
461 }
6a488035
TO
462 $valuesString = implode(',', $valuesArray);
463 $query = "
464 INSERT INTO civicrm_dashboard_contact ( dashboard_id, contact_id )
465 VALUES {$valuesString}";
466
467 CRM_Core_DAO::executeQuery($query);
468 }
469 }
470
dcf56200 471 /**
6a0b768e
TO
472 * @param array $params
473 * Each item is a spec for a dashlet on the contact's dashboard.
dcf56200
TO
474 * @return bool
475 */
00be9182 476 public static function addContactDashletToDashboard(&$params) {
15d9b3ae
N
477 $valuesString = NULL;
478 $columns = array();
479 foreach ($params as $dashboardIDs) {
480 $contactID = CRM_Utils_Array::value('contact_id', $dashboardIDs);
481 $dashboardID = CRM_Utils_Array::value('dashboard_id', $dashboardIDs);
482 $column = CRM_Utils_Array::value('column_no', $dashboardIDs, 0);
483 $columns[$column][$dashboardID] = 0;
484 }
485 self::saveDashletChanges($columns, $contactID);
486 return TRUE;
487 }
488
6a488035 489 /**
fe482240 490 * Delete Dashlet.
6a488035 491 *
100fef9d 492 * @param int $dashletID
2a6da8d7 493 *
192d36c5 494 * @return bool
6a488035 495 */
00be9182 496 public static function deleteDashlet($dashletID) {
6a488035
TO
497 $dashlet = new CRM_Core_DAO_Dashboard();
498 $dashlet->id = $dashletID;
a60c0bc8
SL
499 if (!$dashlet->find(TRUE)) {
500 return FALSE;
501 }
6a488035 502 $dashlet->delete();
15d9b3ae 503 return TRUE;
6a488035 504 }
96025800 505
6a488035 506}