3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * Class contains Contact dashboard related functions.
21 class CRM_Core_BAO_Dashboard
extends CRM_Core_DAO_Dashboard
{
26 * @param array $params
32 public static function create($params) {
33 $hook = empty($params['id']) ?
'create' : 'edit';
34 CRM_Utils_Hook
::pre($hook, 'Dashboard', CRM_Utils_Array
::value('id', $params), $params);
35 $dao = self
::addDashlet($params);
36 CRM_Utils_Hook
::post($hook, 'Dashboard', $dao->id
, $dao);
41 * Get the list of dashlets enabled by admin.
45 * @param bool $checkPermission
46 * All or only authorized for the current user.
51 public static function getDashlets($all = TRUE, $checkPermission = TRUE) {
53 $dao = new CRM_Core_DAO_Dashboard();
59 $dao->domain_id
= CRM_Core_Config
::domainID();
62 while ($dao->fetch()) {
63 if ($checkPermission && !self
::checkPermission($dao->permission
, $dao->permission_operator
)) {
68 CRM_Core_DAO
::storeValues($dao, $values);
69 $dashlets[$dao->id
] = $values;
76 * Get the list of dashlets for the current user or the specified user.
78 * Additionlly, initializes the dashboard with defaults if this is the
79 * user's first visit to their dashboard.
81 * @param int $contactID
82 * Defaults to the current user.
87 public static function getContactDashlets($contactID = NULL) {
88 $contactID = $contactID ?
$contactID : CRM_Core_Session
::getLoggedInContactID();
91 // Get contact dashboard dashlets.
92 $results = civicrm_api3('DashboardContact', 'get', [
93 'contact_id' => $contactID,
95 'dashboard_id.is_active' => 1,
96 'dashboard_id.domain_id' => CRM_Core_Config
::domainID(),
97 'options' => ['sort' => 'weight', 'limit' => 0],
104 'dashboard_id.label',
106 'dashboard_id.fullscreen_url',
107 'dashboard_id.cache_minutes',
108 'dashboard_id.permission',
109 'dashboard_id.permission_operator',
113 foreach ($results['values'] as $item) {
114 if (self
::checkPermission(CRM_Utils_Array
::value('dashboard_id.permission', $item), CRM_Utils_Array
::value('dashboard_id.permission_operator', $item))) {
115 $dashlets[$item['id']] = [
116 'dashboard_id' => $item['dashboard_id'],
117 'weight' => $item['weight'],
118 'column_no' => $item['column_no'],
119 'name' => $item['dashboard_id.name'],
120 'label' => $item['dashboard_id.label'],
121 'url' => $item['dashboard_id.url'],
122 'cache_minutes' => $item['dashboard_id.cache_minutes'],
123 'fullscreen_url' => $item['dashboard_id.fullscreen_url'] ??
NULL,
128 // If empty, then initialize default dashlets for this user.
129 if (!$results['count']) {
130 // They may just have disabled all their dashlets. Check if any records exist for this contact.
131 if (!civicrm_api3('DashboardContact', 'getcount', ['contact_id' => $contactID, 'dashboard_id.domain_id' => CRM_Core_Config
::domainID()])) {
132 $dashlets = self
::initializeDashlets();
142 public static function getContactDashletsForJS() {
144 foreach (self
::getContactDashlets() as $item) {
145 $data[$item['column_no']][] = [
146 'id' => (int) $item['dashboard_id'],
147 'name' => $item['name'],
148 'title' => $item['label'],
149 'url' => self
::parseUrl($item['url']),
150 'cacheMinutes' => $item['cache_minutes'],
151 'fullscreenUrl' => self
::parseUrl($item['fullscreen_url']),
158 * Setup default dashlets for new users.
160 * When a user accesses their dashboard for the first time, set up
161 * the default dashlets.
164 * Array of dashboard_id's
165 * @throws \CiviCRM_API3_Exception
167 public static function initializeDashlets() {
169 $getDashlets = civicrm_api3("Dashboard", "get", [
170 'domain_id' => CRM_Core_Config
::domainID(),
173 $contactID = CRM_Core_Session
::getLoggedInContactID();
174 $allDashlets = CRM_Utils_Array
::index(['name'], $getDashlets['values']);
175 $defaultDashlets = [];
176 $defaults = ['blog' => 1, 'getting-started' => '0'];
177 foreach ($defaults as $name => $column) {
178 if (!empty($allDashlets[$name]) && !empty($allDashlets[$name]['id'])) {
179 $defaultDashlets[$name] = [
180 'dashboard_id' => $allDashlets[$name]['id'],
182 'column_no' => $column,
183 'contact_id' => $contactID,
187 CRM_Utils_Hook
::dashboard_defaults($allDashlets, $defaultDashlets);
188 if (is_array($defaultDashlets) && !empty($defaultDashlets)) {
189 foreach ($defaultDashlets as $id => $defaultDashlet) {
190 $dashboard_id = $defaultDashlet['dashboard_id'];
191 $dashlet = $getDashlets['values'][$dashboard_id];
192 if (!self
::checkPermission(CRM_Utils_Array
::value('permission', $dashlet), CRM_Utils_Array
::value('permission_operator', $dashlet))) {
196 $assignDashlets = civicrm_api3("dashboard_contact", "create", $defaultDashlet);
197 $values = $assignDashlets['values'][$assignDashlets['id']];
198 $dashlets[$assignDashlets['id']] = [
199 'dashboard_id' => $values['dashboard_id'],
200 'weight' => $values['weight'],
201 'column_no' => $values['column_no'],
202 'name' => $dashlet['name'],
203 'label' => $dashlet['label'],
204 'cache_minutes' => $dashlet['cache_minutes'],
205 'url' => $dashlet['url'],
206 'fullscreen_url' => $dashlet['fullscreen_url'] ??
NULL,
218 public static function parseUrl($url) {
219 // Check if it is already a fully-formed url
220 if ($url && substr($url, 0, 4) != 'http' && $url[0] != '/') {
221 $urlParam = explode('?', $url);
222 $url = CRM_Utils_System
::url($urlParam[0], CRM_Utils_Array
::value(1, $urlParam), FALSE, NULL, FALSE);
228 * Check dashlet permission for current user.
230 * @param string $permission
231 * Comma separated list.
232 * @param string $operator
235 * true if use has permission else false
237 public static function checkPermission($permission, $operator) {
239 $permissions = explode(',', $permission);
240 $config = CRM_Core_Config
::singleton();
242 static $allComponents;
243 if (!$allComponents) {
244 $allComponents = CRM_Core_Component
::getNames();
247 $hasPermission = FALSE;
248 foreach ($permissions as $key) {
251 $componentName = NULL;
252 if (strpos($key, 'access') === 0) {
253 $componentName = trim(substr($key, 6));
254 if (!in_array($componentName, $allComponents)) {
255 $componentName = NULL;
259 // hack to handle case permissions
261 && in_array($key, ['access my cases and activities', 'access all cases and activities'])
263 $componentName = 'CiviCase';
266 //hack to determine if it's a component related permission
267 if ($componentName) {
268 if (!in_array($componentName, $config->enableComponents
) ||
269 !CRM_Core_Permission
::check($key)
271 $showDashlet = FALSE;
272 if ($operator == 'AND') {
277 $hasPermission = TRUE;
280 elseif (!CRM_Core_Permission
::check($key)) {
281 $showDashlet = FALSE;
282 if ($operator == 'AND') {
287 $hasPermission = TRUE;
291 if (!$showDashlet && !$hasPermission) {
299 // if permission is not set consider everyone has permission to access it.
305 * Save changes made by user to the Dashlet.
307 * @param array $columns
309 * @param int $contactID
311 * @throws RuntimeException
313 public static function saveDashletChanges($columns, $contactID = NULL) {
315 $contactID = CRM_Core_Session
::getLoggedInContactID();
318 if (empty($contactID)) {
319 throw new RuntimeException("Failed to determine contact ID");
323 if (is_array($columns)) {
324 foreach ($columns as $colNo => $dashlets) {
325 if (!is_int($colNo)) {
329 foreach ($dashlets as $dashletID => $isMinimized) {
330 $dashletID = (int) $dashletID;
331 $query = "INSERT INTO civicrm_dashboard_contact
332 (weight, column_no, is_active, dashboard_id, contact_id)
333 VALUES({$weight}, {$colNo}, 1, {$dashletID}, {$contactID})
334 ON DUPLICATE KEY UPDATE weight = {$weight}, column_no = {$colNo}, is_active = 1";
335 // fire update query for each column
336 CRM_Core_DAO
::executeQuery($query);
338 $dashletIDs[] = $dashletID;
344 // Find dashlets in this domain.
345 $domainDashlets = civicrm_api3('Dashboard', 'get', [
346 'return' => array('id'),
347 'domain_id' => CRM_Core_Config
::domainID(),
348 'options' => ['limit' => 0],
351 // Get the array of IDs.
352 $domainDashletIDs = [];
353 if ($domainDashlets['is_error'] == 0) {
354 $domainDashletIDs = CRM_Utils_Array
::collect('id', $domainDashlets['values']);
357 // Restrict query to Dashlets in this domain.
358 $domainDashletClause = !empty($domainDashletIDs) ?
"dashboard_id IN (" . implode(',', $domainDashletIDs) . ")" : '(1)';
360 // Target only those Dashlets which are inactive.
361 $dashletClause = $dashletIDs ?
"dashboard_id NOT IN (" . implode(',', $dashletIDs) . ")" : '(1)';
365 1 => [$contactID, 'Integer'],
369 $updateQuery = "UPDATE civicrm_dashboard_contact
371 WHERE $domainDashletClause
373 AND contact_id = %1";
375 // Disable inactive widgets.
376 CRM_Core_DAO
::executeQuery($updateQuery, $params);
382 * @param array $params
385 * $dashlet returns dashlet object
387 public static function addDashlet(&$params) {
389 // special case to handle duplicate entries for report instances
390 $dashboardID = CRM_Utils_Array
::value('id', $params);
392 if (!empty($params['instanceURL'])) {
394 FROM `civicrm_dashboard`
395 WHERE url LIKE '" . CRM_Utils_Array
::value('instanceURL', $params) . "&%'";
396 $dashboardID = CRM_Core_DAO
::singleValueQuery($query);
399 $dashlet = new CRM_Core_DAO_Dashboard();
403 // Assign domain before search to allow identical dashlets in different domains.
404 if (empty($params['domain_id'])) {
405 $dashlet->domain_id
= CRM_Core_Config
::domainID();
408 $dashlet->domain_id
= CRM_Utils_Array
::value('domain_id', $params);
411 // Try and find an existing dashlet - it will be updated if found.
412 if (!empty($params['name'])) {
413 $dashlet->name
= CRM_Utils_Array
::value('name', $params);
414 $dashlet->find(TRUE);
417 $dashlet->url
= CRM_Utils_Array
::value('url', $params);
418 $dashlet->find(TRUE);
423 $dashlet->id
= $dashboardID;
426 if (is_array(CRM_Utils_Array
::value('permission', $params))) {
427 $params['permission'] = implode(',', $params['permission']);
429 $dashlet->copyValues($params);
432 // now we need to make dashlet entries for each contact
433 self
::addContactDashlet($dashlet);
439 * Update contact dashboard with new dashlet.
441 * @param object $dashlet
443 public static function addContactDashlet($dashlet) {
444 $admin = CRM_Core_Permission
::check('administer CiviCRM');
446 // if dashlet is created by admin then you need to add it all contacts.
447 // else just add to contact who is creating this dashlet
450 $query = "SELECT distinct( contact_id )
451 FROM civicrm_dashboard_contact";
452 $dao = CRM_Core_DAO
::executeQuery($query);
453 while ($dao->fetch()) {
454 $contactIDs[$dao->contact_id
] = NULL;
458 //Get the id of Logged in User
459 $contactID = CRM_Core_Session
::getLoggedInContactID();
460 if (!empty($contactID)) {
461 $contactIDs[$contactID] = NULL;
465 // Remove contact ids that already have this dashlet to avoid DB
466 // constraint violation.
467 $query = "SELECT distinct( contact_id )
468 FROM civicrm_dashboard_contact WHERE dashboard_id = {$dashlet->id}";
469 $dao = CRM_Core_DAO
::executeQuery($query);
470 while ($dao->fetch()) {
471 if (array_key_exists($dao->contact_id
, $contactIDs)) {
472 unset($contactIDs[$dao->contact_id
]);
475 if (!empty($contactIDs)) {
476 foreach ($contactIDs as $contactID => $value) {
477 $valuesArray[] = " ( {$dashlet->id}, {$contactID} )";
479 $valuesString = implode(',', $valuesArray);
481 INSERT INTO civicrm_dashboard_contact ( dashboard_id, contact_id )
482 VALUES {$valuesString}";
484 CRM_Core_DAO
::executeQuery($query);
489 * @param array $params
490 * Each item is a spec for a dashlet on the contact's dashboard.
493 public static function addContactDashletToDashboard(&$params) {
494 $valuesString = NULL;
496 foreach ($params as $dashboardIDs) {
497 $contactID = CRM_Utils_Array
::value('contact_id', $dashboardIDs);
498 $dashboardID = CRM_Utils_Array
::value('dashboard_id', $dashboardIDs);
499 $column = $dashboardIDs['column_no'] ??
0;
500 $columns[$column][$dashboardID] = 0;
502 self
::saveDashletChanges($columns, $contactID);
509 * @param int $dashletID
513 public static function deleteDashlet($dashletID) {
514 $dashlet = new CRM_Core_DAO_Dashboard();
515 $dashlet->id
= $dashletID;
516 if (!$dashlet->find(TRUE)) {