Merge pull request #19087 from civicrm/5.32
[civicrm-core.git] / CRM / Core / BAO / Dashboard.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * Class contains Contact dashboard related functions.
20 */
21 class CRM_Core_BAO_Dashboard extends CRM_Core_DAO_Dashboard {
22
23 /**
24 * Create or update Dashboard.
25 *
26 * @param array $params
27 *
28 * @return CRM_Core_DAO_Dashboard
29 */
30 public static function create($params) {
31 $hook = empty($params['id']) ? 'create' : 'edit';
32 CRM_Utils_Hook::pre($hook, 'Dashboard', CRM_Utils_Array::value('id', $params), $params);
33 $dao = self::addDashlet($params);
34 CRM_Utils_Hook::post($hook, 'Dashboard', $dao->id, $dao);
35 return $dao;
36 }
37
38 /**
39 * Get all available contact dashlets
40 *
41 * @return array
42 * array of dashlets
43 */
44 public static function getContactDashlets() {
45 if (!isset(Civi::$statics[__CLASS__][__FUNCTION__])) {
46 Civi::$statics[__CLASS__][__FUNCTION__] = [];
47 $params = [
48 'select' => ['*', 'dashboard_contact.*'],
49 'join' => [
50 ['DashboardContact AS dashboard_contact', FALSE, ['dashboard_contact.contact_id', '=', CRM_Core_Session::getLoggedInContactID()]],
51 ],
52 'where' => [
53 ['domain_id', '=', 'current_domain'],
54 ],
55 'orderBy' => ['dashboard_contact.weight' => 'ASC'],
56 ];
57
58 // Get Dashboard + any joined DashboardContact records.
59 $results = civicrm_api4('Dashboard', 'get', $params);
60
61 // If empty, then initialize default dashlets for this user.
62 if (!array_filter($results->column('dashboard_contact.id'))) {
63 self::initializeDashlets();
64 }
65 $results = civicrm_api4('Dashboard', 'get', $params);
66
67 foreach ($results as $item) {
68 if ($item['is_active'] && self::checkPermission($item['permission'], $item['permission_operator'])) {
69 Civi::$statics[__CLASS__][__FUNCTION__][] = $item;
70 }
71 }
72 }
73 return Civi::$statics[__CLASS__][__FUNCTION__];
74 }
75
76 /**
77 * Set default dashlets for new users.
78 *
79 * Called when a user accesses their dashboard for the first time.
80 */
81 public static function initializeDashlets() {
82 $allDashlets = (array) civicrm_api4('Dashboard', 'get', [
83 'where' => [['domain_id', '=', 'current_domain']],
84 ], 'name');
85 $defaultDashlets = [];
86 $defaults = ['blog' => 1, 'getting-started' => '0'];
87 foreach ($defaults as $name => $column) {
88 if (!empty($allDashlets[$name]) && !empty($allDashlets[$name]['id'])) {
89 $defaultDashlets[$name] = [
90 'dashboard_id' => $allDashlets[$name]['id'],
91 'is_active' => 1,
92 'column_no' => $column,
93 ];
94 }
95 }
96 CRM_Utils_Hook::dashboard_defaults($allDashlets, $defaultDashlets);
97 if (is_array($defaultDashlets) && !empty($defaultDashlets)) {
98 \Civi\Api4\DashboardContact::save(FALSE)
99 ->setRecords($defaultDashlets)
100 ->setDefaults(['contact_id' => CRM_Core_Session::getLoggedInContactID()])
101 ->execute();
102 }
103 }
104
105 /**
106 * Check dashlet permission for current user.
107 *
108 * @param array $permissions
109 * @param string $operator
110 *
111 * @return bool
112 * true if user has permission to view dashlet
113 */
114 public static function checkPermission($permissions, $operator) {
115 if ($permissions) {
116 $config = CRM_Core_Config::singleton();
117
118 static $allComponents;
119 if (!$allComponents) {
120 $allComponents = CRM_Core_Component::getNames();
121 }
122
123 $hasPermission = FALSE;
124 foreach ($permissions as $key) {
125 $showDashlet = TRUE;
126
127 $componentName = NULL;
128 if (strpos($key, 'access') === 0) {
129 $componentName = trim(substr($key, 6));
130 if (!in_array($componentName, $allComponents)) {
131 $componentName = NULL;
132 }
133 }
134
135 // hack to handle case permissions
136 if (!$componentName
137 && in_array($key, ['access my cases and activities', 'access all cases and activities'])
138 ) {
139 $componentName = 'CiviCase';
140 }
141
142 //hack to determine if it's a component related permission
143 if ($componentName) {
144 if (!in_array($componentName, $config->enableComponents) ||
145 !CRM_Core_Permission::check($key)
146 ) {
147 $showDashlet = FALSE;
148 if ($operator == 'AND') {
149 return $showDashlet;
150 }
151 }
152 else {
153 $hasPermission = TRUE;
154 }
155 }
156 elseif (!CRM_Core_Permission::check($key)) {
157 $showDashlet = FALSE;
158 if ($operator == 'AND') {
159 return $showDashlet;
160 }
161 }
162 else {
163 $hasPermission = TRUE;
164 }
165 }
166
167 if (!$showDashlet && !$hasPermission) {
168 return FALSE;
169 }
170 else {
171 return TRUE;
172 }
173 }
174 else {
175 // if permission is not set consider everyone has permission to access it.
176 return TRUE;
177 }
178 }
179
180 /**
181 * Add dashlets.
182 *
183 * @param array $params
184 *
185 * @return object
186 * $dashlet returns dashlet object
187 */
188 public static function addDashlet(&$params) {
189
190 // special case to handle duplicate entries for report instances
191 $dashboardID = $params['id'] ?? NULL;
192
193 if (!empty($params['instanceURL'])) {
194 $query = "SELECT id
195 FROM `civicrm_dashboard`
196 WHERE url LIKE '" . CRM_Utils_Array::value('instanceURL', $params) . "&%'";
197 $dashboardID = CRM_Core_DAO::singleValueQuery($query);
198 }
199
200 $dashlet = new CRM_Core_DAO_Dashboard();
201
202 if (!$dashboardID) {
203 // Assign domain before search to allow identical dashlets in different domains.
204 $dashlet->domain_id = $params['domain_id'] ?? CRM_Core_Config::domainID();
205
206 // Try and find an existing dashlet - it will be updated if found.
207 if (!empty($params['name']) || !empty($params['url'])) {
208 $dashlet->name = $params['name'] ?? NULL;
209 $dashlet->url = $params['url'] ?? NULL;
210 $dashlet->find(TRUE);
211 }
212 }
213 else {
214 $dashlet->id = $dashboardID;
215 }
216
217 $dashlet->copyValues($params);
218 $dashlet->save();
219
220 // now we need to make dashlet entries for each contact
221 self::addContactDashlet($dashlet);
222
223 return $dashlet;
224 }
225
226 /**
227 * Update contact dashboard with new dashlet.
228 *
229 * @param object $dashlet
230 */
231 public static function addContactDashlet($dashlet) {
232 $admin = CRM_Core_Permission::check('administer CiviCRM');
233
234 // if dashlet is created by admin then you need to add it all contacts.
235 // else just add to contact who is creating this dashlet
236 $contactIDs = [];
237 if ($admin) {
238 $query = "SELECT distinct( contact_id )
239 FROM civicrm_dashboard_contact";
240 $dao = CRM_Core_DAO::executeQuery($query);
241 while ($dao->fetch()) {
242 $contactIDs[$dao->contact_id] = NULL;
243 }
244 }
245 else {
246 //Get the id of Logged in User
247 $contactID = CRM_Core_Session::getLoggedInContactID();
248 if (!empty($contactID)) {
249 $contactIDs[$contactID] = NULL;
250 }
251 }
252
253 // Remove contact ids that already have this dashlet to avoid DB
254 // constraint violation.
255 $query = "SELECT distinct( contact_id )
256 FROM civicrm_dashboard_contact WHERE dashboard_id = {$dashlet->id}";
257 $dao = CRM_Core_DAO::executeQuery($query);
258 while ($dao->fetch()) {
259 if (array_key_exists($dao->contact_id, $contactIDs)) {
260 unset($contactIDs[$dao->contact_id]);
261 }
262 }
263 if (!empty($contactIDs)) {
264 foreach ($contactIDs as $contactID => $value) {
265 $valuesArray[] = " ( {$dashlet->id}, {$contactID} )";
266 }
267 $valuesString = implode(',', $valuesArray);
268 $query = "
269 INSERT INTO civicrm_dashboard_contact ( dashboard_id, contact_id )
270 VALUES {$valuesString}";
271
272 CRM_Core_DAO::executeQuery($query);
273 }
274 }
275
276 }