3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2019
35 * Class contains Contact dashboard related functions.
37 class CRM_Core_BAO_Dashboard
extends CRM_Core_DAO_Dashboard
{
42 * @param array $params
48 public static function create($params) {
49 $hook = empty($params['id']) ?
'create' : 'edit';
50 CRM_Utils_Hook
::pre($hook, 'Dashboard', CRM_Utils_Array
::value('id', $params), $params);
51 $dao = self
::addDashlet($params);
52 CRM_Utils_Hook
::post($hook, 'Dashboard', $dao->id
, $dao);
57 * Get the list of dashlets enabled by admin.
61 * @param bool $checkPermission
62 * All or only authorized for the current user.
67 public static function getDashlets($all = TRUE, $checkPermission = TRUE) {
69 $dao = new CRM_Core_DAO_Dashboard();
75 $dao->domain_id
= CRM_Core_Config
::domainID();
78 while ($dao->fetch()) {
79 if ($checkPermission && !self
::checkPermission($dao->permission
, $dao->permission_operator
)) {
84 CRM_Core_DAO
::storeValues($dao, $values);
85 $dashlets[$dao->id
] = $values;
92 * Get the list of dashlets for the current user or the specified user.
94 * Additionlly, initializes the dashboard with defaults if this is the
95 * user's first visit to their dashboard.
97 * @param int $contactID
98 * Defaults to the current user.
103 public static function getContactDashlets($contactID = NULL) {
104 $contactID = $contactID ?
$contactID : CRM_Core_Session
::getLoggedInContactID();
107 // Get contact dashboard dashlets.
108 $results = civicrm_api3('DashboardContact', 'get', [
109 'contact_id' => $contactID,
111 'dashboard_id.is_active' => 1,
112 'dashboard_id.domain_id' => CRM_Core_Config
::domainID(),
113 'options' => ['sort' => 'weight', 'limit' => 0],
120 'dashboard_id.label',
122 'dashboard_id.fullscreen_url',
123 'dashboard_id.cache_minutes',
124 'dashboard_id.permission',
125 'dashboard_id.permission_operator',
129 foreach ($results['values'] as $item) {
130 if (self
::checkPermission(CRM_Utils_Array
::value('dashboard_id.permission', $item), CRM_Utils_Array
::value('dashboard_id.permission_operator', $item))) {
131 $dashlets[$item['id']] = [
132 'dashboard_id' => $item['dashboard_id'],
133 'weight' => $item['weight'],
134 'column_no' => $item['column_no'],
135 'name' => $item['dashboard_id.name'],
136 'label' => $item['dashboard_id.label'],
137 'url' => $item['dashboard_id.url'],
138 'cache_minutes' => $item['dashboard_id.cache_minutes'],
139 'fullscreen_url' => CRM_Utils_Array
::value('dashboard_id.fullscreen_url', $item),
144 // If empty, then initialize default dashlets for this user.
145 if (!$results['count']) {
146 // They may just have disabled all their dashlets. Check if any records exist for this contact.
147 if (!civicrm_api3('DashboardContact', 'getcount', ['contact_id' => $contactID, 'dashboard_id.domain_id' => CRM_Core_Config
::domainID()])) {
148 $dashlets = self
::initializeDashlets();
158 public static function getContactDashletsForJS() {
160 foreach (self
::getContactDashlets() as $item) {
161 $data[$item['column_no']][] = [
162 'id' => (int) $item['dashboard_id'],
163 'name' => $item['name'],
164 'title' => $item['label'],
165 'url' => self
::parseUrl($item['url']),
166 'cacheMinutes' => $item['cache_minutes'],
167 'fullscreenUrl' => self
::parseUrl($item['fullscreen_url']),
174 * Setup default dashlets for new users.
176 * When a user accesses their dashboard for the first time, set up
177 * the default dashlets.
180 * Array of dashboard_id's
181 * @throws \CiviCRM_API3_Exception
183 public static function initializeDashlets() {
185 $getDashlets = civicrm_api3("Dashboard", "get", [
186 'domain_id' => CRM_Core_Config
::domainID(),
189 $contactID = CRM_Core_Session
::getLoggedInContactID();
190 $allDashlets = CRM_Utils_Array
::index(['name'], $getDashlets['values']);
191 $defaultDashlets = [];
192 $defaults = ['blog' => 1, 'getting-started' => '0'];
193 foreach ($defaults as $name => $column) {
194 if (!empty($allDashlets[$name]) && !empty($allDashlets[$name]['id'])) {
195 $defaultDashlets[$name] = [
196 'dashboard_id' => $allDashlets[$name]['id'],
198 'column_no' => $column,
199 'contact_id' => $contactID,
203 CRM_Utils_Hook
::dashboard_defaults($allDashlets, $defaultDashlets);
204 if (is_array($defaultDashlets) && !empty($defaultDashlets)) {
205 foreach ($defaultDashlets as $id => $defaultDashlet) {
206 $dashboard_id = $defaultDashlet['dashboard_id'];
207 $dashlet = $getDashlets['values'][$dashboard_id];
208 if (!self
::checkPermission(CRM_Utils_Array
::value('permission', $dashlet), CRM_Utils_Array
::value('permission_operator', $dashlet))) {
212 $assignDashlets = civicrm_api3("dashboard_contact", "create", $defaultDashlet);
213 $values = $assignDashlets['values'][$assignDashlets['id']];
214 $dashlets[$assignDashlets['id']] = [
215 'dashboard_id' => $values['dashboard_id'],
216 'weight' => $values['weight'],
217 'column_no' => $values['column_no'],
218 'name' => $dashlet['name'],
219 'label' => $dashlet['label'],
220 'cache_minutes' => $dashlet['cache_minutes'],
221 'url' => $dashlet['url'],
222 'fullscreen_url' => CRM_Utils_Array
::value('fullscreen_url', $dashlet),
234 public static function parseUrl($url) {
235 // Check if it is already a fully-formed url
236 if ($url && substr($url, 0, 4) != 'http' && $url[0] != '/') {
237 $urlParam = explode('?', $url);
238 $url = CRM_Utils_System
::url($urlParam[0], CRM_Utils_Array
::value(1, $urlParam), FALSE, NULL, FALSE);
244 * Check dashlet permission for current user.
246 * @param string $permission
247 * Comma separated list.
248 * @param string $operator
251 * true if use has permission else false
253 public static function checkPermission($permission, $operator) {
255 $permissions = explode(',', $permission);
256 $config = CRM_Core_Config
::singleton();
258 static $allComponents;
259 if (!$allComponents) {
260 $allComponents = CRM_Core_Component
::getNames();
263 $hasPermission = FALSE;
264 foreach ($permissions as $key) {
267 $componentName = NULL;
268 if (strpos($key, 'access') === 0) {
269 $componentName = trim(substr($key, 6));
270 if (!in_array($componentName, $allComponents)) {
271 $componentName = NULL;
275 // hack to handle case permissions
277 && in_array($key, ['access my cases and activities', 'access all cases and activities'])
279 $componentName = 'CiviCase';
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)
287 $showDashlet = FALSE;
288 if ($operator == 'AND') {
293 $hasPermission = TRUE;
296 elseif (!CRM_Core_Permission
::check($key)) {
297 $showDashlet = FALSE;
298 if ($operator == 'AND') {
303 $hasPermission = TRUE;
307 if (!$showDashlet && !$hasPermission) {
315 // if permission is not set consider everyone has permission to access it.
321 * Save changes made by user to the Dashlet.
323 * @param array $columns
325 * @param int $contactID
327 * @throws RuntimeException
329 public static function saveDashletChanges($columns, $contactID = NULL) {
331 $contactID = CRM_Core_Session
::getLoggedInContactID();
334 if (empty($contactID)) {
335 throw new RuntimeException("Failed to determine contact ID");
339 if (is_array($columns)) {
340 foreach ($columns as $colNo => $dashlets) {
341 if (!is_int($colNo)) {
345 foreach ($dashlets as $dashletID => $isMinimized) {
346 $dashletID = (int) $dashletID;
347 $query = "INSERT INTO civicrm_dashboard_contact
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";
351 // fire update query for each column
352 CRM_Core_DAO
::executeQuery($query);
354 $dashletIDs[] = $dashletID;
360 // Find dashlets in this domain.
361 $domainDashlets = civicrm_api3('Dashboard', 'get', [
362 'return' => array('id'),
363 'domain_id' => CRM_Core_Config
::domainID(),
364 'options' => ['limit' => 0],
367 // Get the array of IDs.
368 $domainDashletIDs = [];
369 if ($domainDashlets['is_error'] == 0) {
370 $domainDashletIDs = CRM_Utils_Array
::collect('id', $domainDashlets['values']);
373 // Restrict query to Dashlets in this domain.
374 $domainDashletClause = !empty($domainDashletIDs) ?
"dashboard_id IN (" . implode(',', $domainDashletIDs) . ")" : '(1)';
376 // Target only those Dashlets which are inactive.
377 $dashletClause = $dashletIDs ?
"dashboard_id NOT IN (" . implode(',', $dashletIDs) . ")" : '(1)';
381 1 => [$contactID, 'Integer'],
385 $updateQuery = "UPDATE civicrm_dashboard_contact
387 WHERE $domainDashletClause
389 AND contact_id = %1";
391 // Disable inactive widgets.
392 CRM_Core_DAO
::executeQuery($updateQuery, $params);
398 * @param array $params
401 * $dashlet returns dashlet object
403 public static function addDashlet(&$params) {
405 // special case to handle duplicate entries for report instances
406 $dashboardID = CRM_Utils_Array
::value('id', $params);
408 if (!empty($params['instanceURL'])) {
410 FROM `civicrm_dashboard`
411 WHERE url LIKE '" . CRM_Utils_Array
::value('instanceURL', $params) . "&%'";
412 $dashboardID = CRM_Core_DAO
::singleValueQuery($query);
415 $dashlet = new CRM_Core_DAO_Dashboard();
419 // Assign domain before search to allow identical dashlets in different domains.
420 if (empty($params['domain_id'])) {
421 $dashlet->domain_id
= CRM_Core_Config
::domainID();
424 $dashlet->domain_id
= CRM_Utils_Array
::value('domain_id', $params);
427 // Try and find an existing dashlet - it will be updated if found.
428 if (!empty($params['name'])) {
429 $dashlet->name
= CRM_Utils_Array
::value('name', $params);
430 $dashlet->find(TRUE);
433 $dashlet->url
= CRM_Utils_Array
::value('url', $params);
434 $dashlet->find(TRUE);
439 $dashlet->id
= $dashboardID;
442 if (is_array(CRM_Utils_Array
::value('permission', $params))) {
443 $params['permission'] = implode(',', $params['permission']);
445 $dashlet->copyValues($params);
448 // now we need to make dashlet entries for each contact
449 self
::addContactDashlet($dashlet);
455 * Update contact dashboard with new dashlet.
457 * @param object $dashlet
459 public static function addContactDashlet($dashlet) {
460 $admin = CRM_Core_Permission
::check('administer CiviCRM');
462 // if dashlet is created by admin then you need to add it all contacts.
463 // else just add to contact who is creating this dashlet
466 $query = "SELECT distinct( contact_id )
467 FROM civicrm_dashboard_contact";
468 $dao = CRM_Core_DAO
::executeQuery($query);
469 while ($dao->fetch()) {
470 $contactIDs[$dao->contact_id
] = NULL;
474 //Get the id of Logged in User
475 $contactID = CRM_Core_Session
::getLoggedInContactID();
476 if (!empty($contactID)) {
477 $contactIDs[$contactID] = NULL;
481 // Remove contact ids that already have this dashlet to avoid DB
482 // constraint violation.
483 $query = "SELECT distinct( contact_id )
484 FROM civicrm_dashboard_contact WHERE dashboard_id = {$dashlet->id}";
485 $dao = CRM_Core_DAO
::executeQuery($query);
486 while ($dao->fetch()) {
487 if (array_key_exists($dao->contact_id
, $contactIDs)) {
488 unset($contactIDs[$dao->contact_id
]);
491 if (!empty($contactIDs)) {
492 foreach ($contactIDs as $contactID => $value) {
493 $valuesArray[] = " ( {$dashlet->id}, {$contactID} )";
495 $valuesString = implode(',', $valuesArray);
497 INSERT INTO civicrm_dashboard_contact ( dashboard_id, contact_id )
498 VALUES {$valuesString}";
500 CRM_Core_DAO
::executeQuery($query);
505 * @param array $params
506 * Each item is a spec for a dashlet on the contact's dashboard.
509 public static function addContactDashletToDashboard(&$params) {
510 $valuesString = NULL;
512 foreach ($params as $dashboardIDs) {
513 $contactID = CRM_Utils_Array
::value('contact_id', $dashboardIDs);
514 $dashboardID = CRM_Utils_Array
::value('dashboard_id', $dashboardIDs);
515 $column = CRM_Utils_Array
::value('column_no', $dashboardIDs, 0);
516 $columns[$column][$dashboardID] = 0;
518 self
::saveDashletChanges($columns, $contactID);
525 * @param int $dashletID
529 public static function deleteDashlet($dashletID) {
530 $dashlet = new CRM_Core_DAO_Dashboard();
531 $dashlet->id
= $dashletID;
532 if (!$dashlet->find(TRUE)) {