Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 TO |
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 | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
3106b838 | 18 | use Civi\Api4\DashboardContact; |
19 | ||
6a488035 | 20 | /** |
192d36c5 | 21 | * Class contains Contact dashboard related functions. |
6a488035 TO |
22 | */ |
23 | class CRM_Core_BAO_Dashboard extends CRM_Core_DAO_Dashboard { | |
518fa0ee | 24 | |
3cfa8e5e | 25 | /** |
f263929f | 26 | * Create or update Dashboard. |
3cfa8e5e | 27 | * |
6a0b768e | 28 | * @param array $params |
3cfa8e5e | 29 | * |
f263929f | 30 | * @return CRM_Core_DAO_Dashboard |
3cfa8e5e | 31 | */ |
00be9182 | 32 | public static function create($params) { |
3cfa8e5e EM |
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); | |
37 | return $dao; | |
38 | } | |
6a488035 TO |
39 | |
40 | /** | |
f263929f | 41 | * Get all available contact dashlets |
77b97be7 | 42 | * |
a6c01b45 CW |
43 | * @return array |
44 | * array of dashlets | |
3106b838 | 45 | * @throws \API_Exception |
6a488035 | 46 | */ |
3106b838 | 47 | public static function getContactDashlets(): array { |
0070596d CW |
48 | $cid = CRM_Core_Session::getLoggedInContactID(); |
49 | if ($cid && !isset(Civi::$statics[__CLASS__][__FUNCTION__][$cid])) { | |
50 | Civi::$statics[__CLASS__][__FUNCTION__][$cid] = []; | |
3106b838 | 51 | // If empty, then initialize default dashlets for this user. |
52 | if (0 === DashboardContact::get(FALSE)->selectRowCount()->addWhere('contact_id', '=', $cid)->execute()->count()) { | |
53 | self::initializeDashlets(); | |
54 | } | |
55 | $contactDashboards = (array) DashboardContact::get(FALSE) | |
56 | ->addSelect('column_no', 'is_active', 'dashboard_id', 'weight', 'contact_id') | |
57 | ->addWhere('contact_id', '=', $cid) | |
58 | ->addOrderBy('weight') | |
59 | ->execute()->indexBy('dashboard_id'); | |
60 | ||
f263929f CW |
61 | $params = [ |
62 | 'select' => ['*', 'dashboard_contact.*'], | |
f263929f CW |
63 | 'where' => [ |
64 | ['domain_id', '=', 'current_domain'], | |
65 | ], | |
f263929f | 66 | ]; |
6a488035 | 67 | |
f263929f | 68 | // Get Dashboard + any joined DashboardContact records. |
3106b838 | 69 | $results = (array) civicrm_api4('Dashboard', 'get', $params); |
f263929f | 70 | foreach ($results as $item) { |
3106b838 | 71 | $item['dashboard_contact.id'] = $contactDashboards[$item['id']]['id'] ?? NULL; |
72 | $item['dashboard_contact.contact_id'] = $contactDashboards[$item['id']]['contact_id'] ?? NULL; | |
73 | $item['dashboard_contact.weight'] = $contactDashboards[$item['id']]['weight'] ?? NULL; | |
74 | $item['dashboard_contact.column_no'] = $contactDashboards[$item['id']]['column_no'] ?? NULL; | |
75 | $item['dashboard_contact.is_active'] = $contactDashboards[$item['id']]['is_active'] ?? NULL; | |
f263929f | 76 | if ($item['is_active'] && self::checkPermission($item['permission'], $item['permission_operator'])) { |
0070596d | 77 | Civi::$statics[__CLASS__][__FUNCTION__][$cid][] = $item; |
f263929f | 78 | } |
dd3770bc | 79 | } |
3106b838 | 80 | usort(Civi::$statics[__CLASS__][__FUNCTION__][$cid], static function ($a, $b) { |
81 | // Sort by dashboard contact weight, preferring not null to null. | |
82 | // I had hoped to do this in mysql either by | |
83 | // 1) making the dashboard contact part of the query NOT permissioned while | |
84 | // the parent query IS or | |
85 | // 2) using FIELD like | |
86 | // $params['orderBy'] = ['FIELD(id,' . implode(',', array_keys($contactDashboards)) . ')' => 'ASC']; | |
87 | // 3) or making the dashboard contact acl more inclusive such that 'view own contact' | |
88 | // is not required to view own contact's acl | |
89 | // but I couldn't see a way to make any of the above work. Perhaps improve in master? | |
90 | if (!isset($b['dashboard_contact.weight']) && !isset($a[$b['dashboard_contact.weight']])) { | |
91 | return 0; | |
92 | } | |
93 | if (!isset($b['dashboard_contact.weight'])) { | |
94 | return -1; | |
95 | } | |
96 | if (!isset($a['dashboard_contact.weight'])) { | |
97 | return 1; | |
98 | } | |
11d593ed | 99 | return $a['dashboard_contact.weight'] <=> $b['dashboard_contact.weight']; |
3106b838 | 100 | }); |
5aa910d4 | 101 | } |
0070596d | 102 | return Civi::$statics[__CLASS__][__FUNCTION__][$cid] ?? []; |
15d9b3ae N |
103 | } |
104 | ||
242055d3 | 105 | /** |
f263929f | 106 | * Set default dashlets for new users. |
5aa910d4 | 107 | * |
f263929f | 108 | * Called when a user accesses their dashboard for the first time. |
b5c2afd0 | 109 | */ |
94864a5f | 110 | public static function initializeDashlets() { |
f263929f CW |
111 | $allDashlets = (array) civicrm_api4('Dashboard', 'get', [ |
112 | 'where' => [['domain_id', '=', 'current_domain']], | |
113 | ], 'name'); | |
be2fb01f CW |
114 | $defaultDashlets = []; |
115 | $defaults = ['blog' => 1, 'getting-started' => '0']; | |
c202dd9e | 116 | foreach ($defaults as $name => $column) { |
fbd19c80 | 117 | if (!empty($allDashlets[$name]) && !empty($allDashlets[$name]['id'])) { |
be2fb01f | 118 | $defaultDashlets[$name] = [ |
40c0dd53 | 119 | 'dashboard_id' => $allDashlets[$name]['id'], |
120 | 'is_active' => 1, | |
121 | 'column_no' => $column, | |
be2fb01f | 122 | ]; |
40c0dd53 | 123 | } |
15d9b3ae N |
124 | } |
125 | CRM_Utils_Hook::dashboard_defaults($allDashlets, $defaultDashlets); | |
126 | if (is_array($defaultDashlets) && !empty($defaultDashlets)) { | |
3106b838 | 127 | DashboardContact::save(FALSE) |
f263929f CW |
128 | ->setRecords($defaultDashlets) |
129 | ->setDefaults(['contact_id' => CRM_Core_Session::getLoggedInContactID()]) | |
130 | ->execute(); | |
6a488035 | 131 | } |
dd3770bc | 132 | } |
6a488035 TO |
133 | |
134 | /** | |
fe482240 | 135 | * Check dashlet permission for current user. |
6a488035 | 136 | * |
f263929f | 137 | * @param array $permissions |
c490a46a | 138 | * @param string $operator |
6a488035 | 139 | * |
408b79bf | 140 | * @return bool |
f263929f | 141 | * true if user has permission to view dashlet |
6a488035 | 142 | */ |
f263929f CW |
143 | public static function checkPermission($permissions, $operator) { |
144 | if ($permissions) { | |
6a488035 TO |
145 | $config = CRM_Core_Config::singleton(); |
146 | ||
147 | static $allComponents; | |
148 | if (!$allComponents) { | |
149 | $allComponents = CRM_Core_Component::getNames(); | |
150 | } | |
151 | ||
152 | $hasPermission = FALSE; | |
153 | foreach ($permissions as $key) { | |
154 | $showDashlet = TRUE; | |
155 | ||
156 | $componentName = NULL; | |
157 | if (strpos($key, 'access') === 0) { | |
158 | $componentName = trim(substr($key, 6)); | |
159 | if (!in_array($componentName, $allComponents)) { | |
160 | $componentName = NULL; | |
161 | } | |
162 | } | |
163 | ||
164 | // hack to handle case permissions | |
cf9ccf98 TO |
165 | if (!$componentName |
166 | && in_array($key, ['access my cases and activities', 'access all cases and activities']) | |
353ffa53 | 167 | ) { |
6a488035 TO |
168 | $componentName = 'CiviCase'; |
169 | } | |
170 | ||
171 | //hack to determine if it's a component related permission | |
172 | if ($componentName) { | |
173 | if (!in_array($componentName, $config->enableComponents) || | |
174 | !CRM_Core_Permission::check($key) | |
175 | ) { | |
176 | $showDashlet = FALSE; | |
177 | if ($operator == 'AND') { | |
178 | return $showDashlet; | |
179 | } | |
180 | } | |
181 | else { | |
182 | $hasPermission = TRUE; | |
183 | } | |
184 | } | |
185 | elseif (!CRM_Core_Permission::check($key)) { | |
186 | $showDashlet = FALSE; | |
187 | if ($operator == 'AND') { | |
188 | return $showDashlet; | |
189 | } | |
190 | } | |
191 | else { | |
192 | $hasPermission = TRUE; | |
193 | } | |
194 | } | |
195 | ||
196 | if (!$showDashlet && !$hasPermission) { | |
197 | return FALSE; | |
198 | } | |
199 | else { | |
200 | return TRUE; | |
201 | } | |
202 | } | |
203 | else { | |
204 | // if permission is not set consider everyone has permission to access it. | |
205 | return TRUE; | |
206 | } | |
207 | } | |
208 | ||
6a488035 | 209 | /** |
fe482240 | 210 | * Add dashlets. |
6a488035 | 211 | * |
6a0b768e | 212 | * @param array $params |
6a488035 | 213 | * |
a6c01b45 CW |
214 | * @return object |
215 | * $dashlet returns dashlet object | |
6a488035 | 216 | */ |
00be9182 | 217 | public static function addDashlet(&$params) { |
6a488035 | 218 | |
32c93376 | 219 | // special case to handle duplicate entries for report instances |
9c1bc317 | 220 | $dashboardID = $params['id'] ?? NULL; |
15d9b3ae | 221 | |
a7488080 | 222 | if (!empty($params['instanceURL'])) { |
6a488035 TO |
223 | $query = "SELECT id |
224 | FROM `civicrm_dashboard` | |
225 | WHERE url LIKE '" . CRM_Utils_Array::value('instanceURL', $params) . "&%'"; | |
226 | $dashboardID = CRM_Core_DAO::singleValueQuery($query); | |
227 | } | |
228 | ||
229 | $dashlet = new CRM_Core_DAO_Dashboard(); | |
230 | ||
231 | if (!$dashboardID) { | |
1a23f3fd | 232 | // Assign domain before search to allow identical dashlets in different domains. |
a279e546 | 233 | $dashlet->domain_id = $params['domain_id'] ?? CRM_Core_Config::domainID(); |
1a23f3fd CW |
234 | |
235 | // Try and find an existing dashlet - it will be updated if found. | |
8f7fd744 | 236 | if (!empty($params['name'])) { |
9c1bc317 | 237 | $dashlet->name = $params['name'] ?? NULL; |
15d9b3ae N |
238 | $dashlet->find(TRUE); |
239 | } | |
6a488035 TO |
240 | } |
241 | else { | |
242 | $dashlet->id = $dashboardID; | |
243 | } | |
244 | ||
6a488035 | 245 | $dashlet->copyValues($params); |
6a488035 TO |
246 | $dashlet->save(); |
247 | ||
248 | // now we need to make dashlet entries for each contact | |
249 | self::addContactDashlet($dashlet); | |
250 | ||
251 | return $dashlet; | |
252 | } | |
253 | ||
254 | /** | |
fe482240 | 255 | * Update contact dashboard with new dashlet. |
6a488035 | 256 | * |
192d36c5 | 257 | * @param object $dashlet |
6a488035 | 258 | */ |
00be9182 | 259 | public static function addContactDashlet($dashlet) { |
6a488035 TO |
260 | $admin = CRM_Core_Permission::check('administer CiviCRM'); |
261 | ||
262 | // if dashlet is created by admin then you need to add it all contacts. | |
263 | // else just add to contact who is creating this dashlet | |
be2fb01f | 264 | $contactIDs = []; |
6a488035 TO |
265 | if ($admin) { |
266 | $query = "SELECT distinct( contact_id ) | |
a3138c9e | 267 | FROM civicrm_dashboard_contact"; |
6a488035 TO |
268 | $dao = CRM_Core_DAO::executeQuery($query); |
269 | while ($dao->fetch()) { | |
a3138c9e | 270 | $contactIDs[$dao->contact_id] = NULL; |
6a488035 TO |
271 | } |
272 | } | |
273 | else { | |
274 | //Get the id of Logged in User | |
df099613 | 275 | $contactID = CRM_Core_Session::getLoggedInContactID(); |
22e263ad | 276 | if (!empty($contactID)) { |
a3138c9e | 277 | $contactIDs[$contactID] = NULL; |
155a0ed0 | 278 | } |
6a488035 TO |
279 | } |
280 | ||
a3138c9e JM |
281 | // Remove contact ids that already have this dashlet to avoid DB |
282 | // constraint violation. | |
283 | $query = "SELECT distinct( contact_id ) | |
284 | FROM civicrm_dashboard_contact WHERE dashboard_id = {$dashlet->id}"; | |
285 | $dao = CRM_Core_DAO::executeQuery($query); | |
a3138c9e | 286 | while ($dao->fetch()) { |
cc4988ae | 287 | if (array_key_exists($dao->contact_id, $contactIDs)) { |
a3138c9e JM |
288 | unset($contactIDs[$dao->contact_id]); |
289 | } | |
290 | } | |
6a488035 | 291 | if (!empty($contactIDs)) { |
a3138c9e | 292 | foreach ($contactIDs as $contactID => $value) { |
6a488035 TO |
293 | $valuesArray[] = " ( {$dashlet->id}, {$contactID} )"; |
294 | } | |
6a488035 TO |
295 | $valuesString = implode(',', $valuesArray); |
296 | $query = " | |
297 | INSERT INTO civicrm_dashboard_contact ( dashboard_id, contact_id ) | |
298 | VALUES {$valuesString}"; | |
299 | ||
300 | CRM_Core_DAO::executeQuery($query); | |
301 | } | |
302 | } | |
303 | ||
6a488035 | 304 | } |