Code comment cleanup
[civicrm-core.git] / CRM / ACL / BAO / ACL.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
232624b1 4 | CiviCRM version 4.4 |
6a488035
TO
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36/**
37 * Access Control List
38 */
39class CRM_ACL_BAO_ACL extends CRM_ACL_DAO_ACL {
40 static $_entityTable = NULL;
41 static $_objectTable = NULL;
42 static $_operation = NULL;
43
44 static $_fieldKeys = NULL;
45
46 static function entityTable() {
47 if (!self::$_entityTable) {
48 self::$_entityTable = array(
49 'civicrm_contact' => ts('Contact'),
50 'civicrm_acl_role' => ts('ACL Role'),
51 );
52 }
53 return self::$_entityTable;
54 }
55
56 static function objectTable() {
57 if (!self::$_objectTable) {
58 self::$_objectTable = array(
59 'civicrm_contact' => ts('Contact'),
60 'civicrm_group' => ts('Group'),
61 'civicrm_saved_search' => ts('Contact Group'),
62 'civicrm_admin' => ts('Administer'),
63 'civicrm_admin' => ts('Import'),
64 );
65 }
66 return self::$_objectTable;
67 }
68
69 static function operation() {
70 if (!self::$_operation) {
71 self::$_operation = array(
72 'View' => ts('View'),
73 'Edit' => ts('Edit'),
74 'Create' => ts('Create'),
75 'Delete' => ts('Delete'),
76 'Search' => ts('Search'),
77 'All' => ts('All'),
78 );
79 }
80 return self::$_operation;
81 }
82
83 /**
84 * Construct a WHERE clause to handle permissions to $object_*
85 *
86 * @param array ref $tables - Any tables that may be needed in the FROM
87 * @param string $operation - The operation being attempted
88 * @param string $object_table - The table of the object in question
89 * @param int $object_id - The ID of the object in question
90 * @param int $acl_id - If it's a grant/revoke operation, the ACL ID
91 * @param boolean $acl_role - For grant operations, this flag determines if we're granting a single acl (false) or an entire group.
92 *
93 * @return string - The WHERE clause, or 0 on failure
94 * @access public
95 * @static
96 */
97 public static function permissionClause(&$tables, $operation,
98 $object_table = NULL, $object_id = NULL,
99 $acl_id = NULL, $acl_role = FALSE
100 ) {
101 $dao = new CRM_ACL_DAO_ACL;
102
103 $t = array(
104 'ACL' => self::getTableName(),
105 'ACLRole' => 'civicrm_acl_role',
106 'ACLEntityRole' => CRM_ACL_DAO_EntityRole::getTableName(),
107 'Contact' => CRM_Contact_DAO_Contact::getTableName(),
108 'Group' => CRM_Contact_DAO_Group::getTableName(),
109 'GroupContact' => CRM_Contact_DAO_GroupContact::getTableName(),
110 );
111
112 $session = CRM_Core_Session::singleton();
113 $contact_id = $session->get('userID');
114
115 $where = " {$t['ACL']}.operation = '" . CRM_Utils_Type::escape($operation, 'String') . "'";
116
117 /* Include clause if we're looking for a specific table/id permission */
118
119
120 if (!empty($object_table)) {
121 $where .= " AND ( {$t['ACL']}.object_table IS null
122 OR ({$t['ACL']}.object_table = '" . CRM_Utils_Type::escape($object_table, 'String') . "'";
123 if (!empty($object_id)) {
124 $where .= " AND ({$t['ACL']}.object_id IS null
125 OR {$t['ACL']}.object_id = " . CRM_Utils_Type::escape($object_id, 'Integer') . ')';
126 }
127 $where .= '))';
128 }
129
130 /* Include clause if we're granting an ACL or ACL Role */
131
132
133 if (!empty($acl_id)) {
134 $where .= " AND ({$t['ACL']}.acl_id IS null
135 OR {$t['ACL']}.acl_id = " . CRM_Utils_Type::escape($acl_id, 'Integer') . ')';
136 if ($acl_role) {
137 $where .= " AND {$t['ACL']}.acl_table = '{$t['ACLRole']}'";
138 }
139 else {
140 $where .= " AND {$t['ACL']}.acl_table = '{$t['ACL']}'";
141 }
142 }
143
144 $query = array();
145
146 /* Query for permissions granted to all contacts in the domain */
147
148
149 $query[] = "SELECT {$t['ACL']}.*, 0 as override
150 FROM {$t['ACL']}
151
152 WHERE {$t['ACL']}.entity_table = '{$t['Domain']}'
153 AND ($where)";
154
155 /* Query for permissions granted to all contacts through an ACL group */
156
157
158 $query[] = "SELECT {$t['ACL']}.*, 0 as override
159 FROM {$t['ACL']}
160
161 INNER JOIN {$t['ACLEntityRole']}
162 ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
163 AND {$t['ACL']}.entity_id =
164 {$t['ACLEntityRole']}.acl_role_id)
165
166 INNER JOIN {$t['ACLRole']}
167 ON {$t['ACL']}.entity_id =
168 {$t['ACLRole']}.id
169
170 WHERE {$t['ACLEntityRole']}.entity_table =
171 '{$t['Domain']}'
172 AND {$t['ACLRole']}.is_active = 1
173 AND ($where)";
174
175 /* Query for permissions granted directly to the contact */
176
177
178 $query[] = "SELECT {$t['ACL']}.*, 1 as override
179 FROM {$t['ACL']}
180
181 INNER JOIN {$t['Contact']}
182 ON ({$t['ACL']}.entity_table = '{$t['Contact']}'
183 AND {$t['ACL']}.entity_id = {$t['Contact']}.id)
184
185 WHERE {$t['Contact']}.id = $contact_id
186 AND ($where)";
187
188 /* Query for permissions granted to the contact through an ACL group */
189
190
191 $query[] = "SELECT {$t['ACL']}.*, 1 as override
192 FROM {$t['ACL']}
193
194 INNER JOIN {$t['ACLEntityRole']}
195 ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
196 AND {$t['ACL']}.entity_id =
197 {$t['ACLEntityRole']}.acl_role_id)
198
199 INNER JOIN {$t['ACLRole']}
200 ON {$t['ACL']}.entity_id = {$t['ACLRole']}.id
201
202 WHERE {$t['ACLEntityRole']}.entity_table =
203 '{$t['Contact']}'
204 AND {$t['ACLRole']}.is_active = 1
205 AND {$t['ACLEntityRole']}.entity_id = $contact_id
206 AND ($where)";
207
208 /* Query for permissions granted to the contact through a group */
209
210
211 $query[] = "SELECT {$t['ACL']}.*, 0 as override
212 FROM {$t['ACL']}
213
214 INNER JOIN {$t['GroupContact']}
215 ON ({$t['ACL']}.entity_table = '{$t['Group']}'
216 AND {$t['ACL']}.entity_id =
217 {$t['GroupContact']}.group_id)
218
219 WHERE ($where)
220 AND {$t['GroupContact']}.contact_id = $contact_id
221 AND {$t['GroupContact']}.status = 'Added')";
222
223
224 /* Query for permissions granted through an ACL group to a Contact
225 * group */
226
227
228 $query[] = "SELECT {$t['ACL']}.*, 0 as override
229 FROM {$t['ACL']}
230
231 INNER JOIN {$t['ACLEntityRole']}
232 ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
233 AND {$t['ACL']}.entity_id =
234 {$t['ACLEntityRole']}.acl_role_id)
235
236 INNER JOIN {$t['ACLRole']}
237 ON {$t['ACL']}.entity_id = {$t['ACLRole']}.id
238
239 INNER JOIN {$t['GroupContact']}
240 ON ({$t['ACLEntityRole']}.entity_table =
241 '{$t['Group']}'
242 AND {$t['ACLEntityRole']}.entity_id =
243 {$t['GroupContact']}.group_id)
244
245 WHERE ($where)
246 AND {$t['ACLRole']}.is_active = 1
247 AND {$t['GroupContact']}.contact_id = $contact_id
248 AND {$t['GroupContact']}.status = 'Added'";
249
250 $union = '(' . implode(') UNION DISTINCT (', $query) . ')';
251
252 $dao->query($union);
253
254 $allow = array(0);
255 $deny = array(0);
256 $override = array();
257
258 while ($dao->fetch()) {
259 /* Instant bypass for the following cases:
260 * 1) the rule governs all tables
261 * 2) the rule governs all objects in the table in question
262 * 3) the rule governs the specific object we want
263 */
264
265
266 if (empty($dao->object_table) ||
267 ($dao->object_table == $object_table
268 && (empty($dao->object_id)
269 || $dao->object_id == $object_id
270 )
271 )
272 ) {
273 $clause = 1;
274 }
275 else {
276 /* Otherwise try to generate a clause for this rule */
277
278
279 $clause = self::getClause(
280 $dao->object_table, $dao->object_id, $tables
281 );
282
283 /* If the clause returned is null, then the rule is a blanket
284 * (id is null) on a table other than the one we're interested
285 * in. So skip it. */
286
287
288 if (empty($clause)) {
289 continue;
290 }
291 }
292
293 /* Now we figure out if this is an allow or deny rule, and possibly
294 * a contact-level override */
295
296
297 if ($dao->deny) {
298 $deny[] = $clause;
299 }
300 else {
301 $allow[] = $clause;
302
303 if ($dao->override) {
304 $override[] = $clause;
305 }
306 }
307 }
308
309 $allows = '(' . implode(' OR ', $allow) . ')';
310 $denies = '(' . implode(' OR ', $deny) . ')';
311 if (!empty($override)) {
312 $denies = '(NOT (' . implode(' OR ', $override) . ") AND $denies)";
313 }
314
315 return "($allows AND NOT $denies)";
316 }
317
318 /**
319 * Given a table and id pair, return the filter clause
320 *
321 * @param string $table - The table owning the object
322 * @param int $id - The ID of the object
323 * @param array ref $tables - Tables that will be needed in the FROM
324 *
325 * @return string|null - WHERE-style clause to filter results,
326 or null if $table or $id is null
327 * @access public
328 * @static
329 */
330 public static function getClause($table, $id, &$tables) {
331 $table = CRM_Utils_Type::escape($table, 'String');
332 $id = CRM_Utils_Type::escape($id, 'Integer');
333 $whereTables = array();
334
335 $ssTable = CRM_Contact_BAO_SavedSearch::getTableName();
336
337 if (empty($table)) {
338 return NULL;
339 }
340 elseif ($table == $ssTable) {
341 return CRM_Contact_BAO_SavedSearch::whereClause($id, $tables, $whereTables);
342 }
343 elseif (!empty($id)) {
344 $tables[$table] = TRUE;
345 return "$table.id = $id";
346 }
347 return NULL;
348 }
349
350 /**
351 * Construct an associative array of an ACL rule's properties
352 *
353 * @param string sprintf format for array
354 * @param bool empty only return elemnts that have a value set.
355 *
356 * @return array - Assoc. array of the ACL rule's properties
357 * @access public
358 */
359 function toArray($format = '%s', $hideEmpty = false) {
360 $result = array();
361
362 if (!self::$_fieldKeys) {
363 $fields = CRM_ACL_DAO_ACL::fields();
364 self::$_fieldKeys = array_keys($fields);
365 }
366
367 foreach (self::$_fieldKeys as $field) {
368 $result[$field] = $this->$field;
369 }
370 return $result;
371 }
372
373 /**
374 * Retrieve ACLs for a contact or group. Note that including a contact id
375 * without a group id will return those ACL rules which are granted
376 * directly to the contact, but not those granted to the contact through
377 * any/all of his group memberships.
378 *
379 * @param int $contact_id - ID of a contact to search for
380 * @param int $group_id - ID of a group to search for
381 * @param boolean $aclRoles - Should we include ACL Roles
382 *
383 * @return array - Array of assoc. arrays of ACL rules
384 * @access public
385 * @static
386 */
387 public static function &getACLs($contact_id = NULL, $group_id = NULL, $aclRoles = FALSE) {
388 $results = array();
389
390 if (empty($contact_id)) {
391 return $results;
392 }
393
394 $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer');
395 if ($group_id) {
396 $group_id = CRM_Utils_Type::escape($group_id, 'Integer');
397 }
398
399 $rule = new CRM_ACL_BAO_ACL();
400
401
402 $acl = self::getTableName();
403 $contact = CRM_Contact_BAO_Contact::getTableName();
404 $c2g = CRM_Contact_BAO_GroupContact::getTableName();
405 $group = CRM_Contact_BAO_Group::getTableName();
406
407 $query = " SELECT $acl.*
408 FROM $acl ";
409
410 if (!empty($group_id)) {
411 $query .= " INNER JOIN $c2g
412 ON $acl.entity_id = $c2g.group_id
413 WHERE $acl.entity_table = '$group'
414 AND $acl.is_active = 1
415 AND $c2g.group_id = $group_id";
416
417 if (!empty($contact_id)) {
418 $query .= " AND $c2g.contact_id = $contact_id
419 AND $c2g.status = 'Added'";
420 }
421 }
422 else {
423 if (!empty($contact_id)) {
424 $query .= " WHERE $acl.entity_table = '$contact'
425 AND $acl.entity_id = $contact_id";
426 }
427 }
428
429 $rule->query($query);
430
431 while ($rule->fetch()) {
432 $results[$rule->id] = $rule->toArray();
433 }
434
435 if ($aclRoles) {
436 $results += self::getACLRoles($contact_id, $group_id);
437 }
438
439 return $results;
440 }
441
442 /**
443 * Get all of the ACLs through ACL groups
444 *
445 * @param int $contact_id - ID of a contact to search for
446 * @param int $group_id - ID of a group to search for
447 *
448 * @return array - Array of assoc. arrays of ACL rules
449 * @access public
450 * @static
451 */
452 public static function &getACLRoles($contact_id = NULL, $group_id = NULL) {
453 $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer');
454 if ($group_id) {
455 $group_id = CRM_Utils_Type::escape($group_id, 'Integer');
456 }
457
458 $rule = new CRM_ACL_BAO_ACL();
459
460 $acl = self::getTableName();
461 $aclRole = 'civicrm_acl_role';
462 $aclRoleJoin = CRM_ACL_DAO_EntityRole::getTableName();
463 $contact = CRM_Contact_BAO_Contact::getTableName();
464 $c2g = CRM_Contact_BAO_GroupContact::getTableName();
465 $group = CRM_Contact_BAO_Group::getTableName();
466
467 $query = " SELECT $acl.*
468 FROM $acl
469 INNER JOIN civicrm_option_group og
470 ON og.name = 'acl_role'
471 INNER JOIN civicrm_option_value ov
472 ON $acl.entity_table = '$aclRole'
473 AND ov.option_group_id = og.id
474 AND $acl.entity_id = ov.value";
475
476 if (!empty($group_id)) {
477 $query .= " INNER JOIN $c2g
478 ON $acl.entity_id = $c2g.group_id
479 WHERE $acl.entity_table = '$group'
480 AND $acl.is_active = 1
481 AND $c2g.group_id = $group_id";
482
483 if (!empty($contact_id)) {
484 $query .= " AND $c2g.contact_id = $contact_id
485 AND $c2g.status = 'Added'";
486 }
487 }
488 else {
489 if (!empty($contact_id)) {
490 $query .= " WHERE $acl.entity_table = '$contact'
491 AND $acl.is_active = 1
492 AND $acl.entity_id = $contact_id";
493 }
494 }
495
496 $results = array();
497
498 $rule->query($query);
499
500 while ($rule->fetch()) {
a5611c8e 501 $results[$rule->id] = $rule->toArray();
6a488035
TO
502 }
503
504 return $results;
505 }
506
507 /**
508 * Get all ACLs granted to a contact through all group memberships
509 *
510 * @param int $contact_id - The contact's ID
511 * @param boolean $aclRoles - Include ACL Roles?
512 *
513 * @return array - Assoc array of ACL rules
514 * @access public
515 * @static
516 */
517 public static function &getGroupACLs($contact_id, $aclRoles = FALSE) {
518 $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer');
519
520 $rule = new CRM_ACL_BAO_ACL();
521
522
523 $acl = self::getTableName();
524 $c2g = CRM_Contact_BAO_GroupContact::getTableName();
525 $group = CRM_Contact_BAO_Group::getTableName();
526 $results = array();
527
528 if ($contact_id) {
529 $query = "
530SELECT $acl.*
531 FROM $acl
532 INNER JOIN $c2g
533 ON $acl.entity_id = $c2g.group_id
534 WHERE $acl.entity_table = '$group'
535 AND $c2g.contact_id = $contact_id
536 AND $c2g.status = 'Added'";
537
538 $rule->query($query);
539
540 while ($rule->fetch()) {
541 $results[$rule->id] = &$rule->toArray();
542 }
543 }
544
545 if ($aclRoles) {
546 $results += self::getGroupACLRoles($contact_id);
547 }
548
549 return $results;
550 }
551
552 /**
553 * Get all of the ACLs for a contact through ACL groups owned by Contact
554 * groups.
555 *
556 * @param int $contact_id - ID of a contact to search for
557 *
558 * @return array - Array of assoc. arrays of ACL rules
559 * @access public
560 * @static
561 */
562 public static function &getGroupACLRoles($contact_id) {
563 $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer');
564
565 $rule = new CRM_ACL_BAO_ACL();
566
567 $acl = self::getTableName();
568 $aclRole = 'civicrm_acl_role';
569
570
571 $aclER = CRM_ACL_DAO_EntityRole::getTableName();
572 $c2g = CRM_Contact_BAO_GroupContact::getTableName();
573 $group = CRM_Contact_BAO_Group::getTableName();
574
575 $query = " SELECT $acl.*
576 FROM $acl
577 INNER JOIN civicrm_option_group og
578 ON og.name = 'acl_role'
579 INNER JOIN civicrm_option_value ov
580 ON $acl.entity_table = '$aclRole'
581 AND ov.option_group_id = og.id
582 AND $acl.entity_id = ov.value
583 AND ov.is_active = 1
584 INNER JOIN $aclER
585 ON $aclER.acl_role_id = $acl.entity_id
586 AND $aclER.is_active = 1
587 INNER JOIN $c2g
588 ON $aclER.entity_id = $c2g.group_id
589 AND $aclER.entity_table = 'civicrm_group'
590 WHERE $acl.entity_table = '$aclRole'
591 AND $acl.is_active = 1
592 AND $c2g.contact_id = $contact_id
593 AND $c2g.status = 'Added'";
594
595 $results = array();
596
597 $rule->query($query);
598
599 while ($rule->fetch()) {
39eb89f4 600 $results[$rule->id] = $rule->toArray();
6a488035
TO
601 }
602
603 // also get all acls for "Any Role" case
604 // and authenticated User Role if present
605 $roles = "0";
606 $session = CRM_Core_Session::singleton();
607 if ($session->get('ufID') > 0) {
608 $roles .= ",2";
609 }
610
611 $query = "
612SELECT $acl.*
613 FROM $acl
614 WHERE $acl.entity_id IN ( $roles )
615 AND $acl.entity_table = 'civicrm_acl_role'
616";
617
618 $rule->query($query);
619 while ($rule->fetch()) {
620 $results[$rule->id] = $rule->toArray();
621 }
622
623 return $results;
624 }
625
626 /**
627 * Get all ACLs owned by a given contact, including domain and group-level.
628 *
629 * @param int $contact_id - The contact ID
630 *
631 * @return array - Assoc array of ACL rules
632 * @access public
633 * @static
634 */
635 public static function &getAllByContact($contact_id) {
636 $result = array();
637
638 /* First, the contact-specific ACLs, including ACL Roles */
639 $result += self::getACLs($contact_id, NULL, TRUE);
640
641 /* Then, all ACLs granted through group membership */
642 $result += self::getGroupACLs($contact_id, TRUE);
643
644 return $result;
645 }
646
647 static function create(&$params) {
648 $dao = new CRM_ACL_DAO_ACL();
649 $dao->copyValues($params);
650 $dao->save();
651 }
652
653 static function retrieve(&$params, &$defaults) {
654 CRM_Core_DAO::commonRetrieve('CRM_ACL_DAO_ACL', $params, $defaults);
655 }
656
657 /**
658 * update the is_active flag in the db
659 *
660 * @param int $id id of the database record
661 * @param boolean $is_active value we want to set the is_active field
662 *
663 * @return Object DAO object on sucess, null otherwise
664 * @static
665 */
666 static function setIsActive($id, $is_active) {
667 // note this also resets any ACL cache
668 CRM_Core_BAO_Cache::deleteGroup('contact fields');
669
670 return CRM_Core_DAO::setFieldValue('CRM_ACL_DAO_ACL', $id, 'is_active', $is_active);
671 }
672
673 static function check($str, $contactID) {
674
675 $acls = CRM_ACL_BAO_Cache::build($contactID);
676
677 $aclKeys = array_keys($acls);
678 $aclKeys = implode(',', $aclKeys);
679
680 if (empty($aclKeys)) {
681 return FALSE;
682 }
683
684
685 $query = "
686SELECT count( a.id )
687 FROM civicrm_acl_cache c, civicrm_acl a
688 WHERE c.acl_id = a.id
689 AND a.is_active = 1
690 AND a.object_table = %1
691 AND a.id IN ( $aclKeys )
692";
693 $params = array(1 => array($str, 'String'));
694
695 $count = CRM_Core_DAO::singleValueQuery($query, $params);
696 return ($count) ? TRUE : FALSE;
697 }
698
699 public static function whereClause($type, &$tables, &$whereTables, $contactID = NULL) {
6a488035
TO
700 $acls = CRM_ACL_BAO_Cache::build($contactID);
701 //CRM_Core_Error::debug( "a: $contactID", $acls );
702
703 $whereClause = NULL;
704 $clauses = array();
705
706 if (!empty($acls)) {
707 $aclKeys = array_keys($acls);
708 $aclKeys = implode(',', $aclKeys);
709
710 $query = "
711SELECT a.operation, a.object_id
712 FROM civicrm_acl_cache c, civicrm_acl a
713 WHERE c.acl_id = a.id
714 AND a.is_active = 1
715 AND a.object_table = 'civicrm_saved_search'
716 AND a.id IN ( $aclKeys )
717ORDER BY a.object_id
718";
719
720 $dao = CRM_Core_DAO::executeQuery($query);
721
722 // do an or of all the where clauses u see
723 $ids = array();
724 while ($dao->fetch()) {
725 // make sure operation matches the type TODO
726 if (self::matchType($type, $dao->operation)) {
727 if (!$dao->object_id) {
728 $ids = array();
729 $whereClause = ' ( 1 ) ';
730 break;
731 }
732 $ids[] = $dao->object_id;
733 }
734 }
735
736 if (!empty($ids)) {
737 $ids = implode(',', $ids);
738 $query = "
739SELECT g.*
740 FROM civicrm_group g
741 WHERE g.id IN ( $ids )
742 AND g.is_active = 1
743";
744 $dao = CRM_Core_DAO::executeQuery($query);
745 $staticGroupIDs = array();
746 $cachedGroupIDs = array();
747 while ($dao->fetch()) {
748 // currently operation is restrcited to VIEW/EDIT
749 if ($dao->where_clause) {
750 if ($dao->select_tables) {
751 $tmpTables = array();
752 foreach (unserialize($dao->select_tables) as $tmpName => $tmpInfo) {
753 if ($tmpName == '`civicrm_group_contact-' . $dao->id . '`') {
754 $tmpName = '`civicrm_group_contact-ACL`';
755 $tmpInfo = str_replace('civicrm_group_contact-' . $dao->id, 'civicrm_group_contact-ACL', $tmpInfo);
756 }
757 elseif ($tmpName == '`civicrm_group_contact_cache_' . $dao->id . '`') {
758 $tmpName = '`civicrm_group_contact_cache-ACL`';
759 $tmpInfo = str_replace('civicrm_group_contact_cache_' . $dao->id, 'civicrm_group_contact_cache-ACL', $tmpInfo);
760 }
761 $tmpTables[$tmpName] = $tmpInfo;
762 }
763 $tables = array_merge($tables,
764 $tmpTables
765 );
766 }
767 if ($dao->where_tables) {
768 $tmpTables = array();
769 foreach (unserialize($dao->where_tables) as $tmpName => $tmpInfo) {
770 if ($tmpName == '`civicrm_group_contact-' . $dao->id . '`') {
771 $tmpName = '`civicrm_group_contact-ACL`';
772 $tmpInfo = str_replace('civicrm_group_contact-' . $dao->id, 'civicrm_group_contact-ACL', $tmpInfo);
773 $staticGroupIDs[] = $dao->id;
774 }
775 elseif ($tmpName == '`civicrm_group_contact_cache_' . $dao->id . '`') {
776 $tmpName = '`civicrm_group_contact_cache-ACL`';
777 $tmpInfo = str_replace('civicrm_group_contact_cache_' . $dao->id, 'civicrm_group_contact_cache-ACL', $tmpInfo);
778 $cachedGroupIDs[] = $dao->id;
779 }
780 $tmpTables[$tmpName] = $tmpInfo;
781 }
782 $whereTables = array_merge($whereTables, $tmpTables);
783 }
784 }
785
786 if (($dao->saved_search_id || $dao->children || $dao->parents) &&
787 $dao->cache_date == NULL) {
788 CRM_Contact_BAO_GroupContactCache::load($dao);
789 }
790 }
791
792 if ($staticGroupIDs) {
793 $clauses[] = '( `civicrm_group_contact-ACL`.group_id IN (' . join(', ', $staticGroupIDs) . ') AND `civicrm_group_contact-ACL`.status IN ("Added") )';
794 }
795
796 if ($cachedGroupIDs) {
797 $clauses[] = '`civicrm_group_contact_cache-ACL`.group_id IN (' . join(', ', $cachedGroupIDs) . ')';
798 }
799 }
800 }
801
802 if (!empty($clauses)) {
803 $whereClause = ' ( ' . implode(' OR ', $clauses) . ' ) ';
804 }
805
806 // call the hook to get additional whereClauses
807 CRM_Utils_Hook::aclWhereClause($type, $tables, $whereTables, $contactID, $whereClause);
808
809 if (empty($whereClause)) {
810 $whereClause = ' ( 0 ) ';
811 }
812
813 return $whereClause;
814 }
815
816 public static function group($type,
817 $contactID = NULL,
818 $tableName = 'civicrm_saved_search',
819 $allGroups = NULL,
820 $includedGroups = NULL
821 ) {
822
823 $acls = CRM_ACL_BAO_Cache::build($contactID);
824
b1f4e637 825 $ids = array();
6a488035
TO
826 if (!empty($acls)) {
827 $aclKeys = array_keys($acls);
828 $aclKeys = implode(',', $aclKeys);
829
557f8c17
ARW
830 $cacheKey = "$tableName-$aclKeys";
831 $cache = CRM_Utils_Cache::singleton();
832 $ids = $cache->get($cacheKey);
833 if (!$ids) {
834 $query = "
6a488035
TO
835SELECT a.operation, a.object_id
836 FROM civicrm_acl_cache c, civicrm_acl a
837 WHERE c.acl_id = a.id
838 AND a.is_active = 1
839 AND a.object_table = %1
840 AND a.id IN ( $aclKeys )
841GROUP BY a.operation,a.object_id
842ORDER BY a.object_id
843";
557f8c17
ARW
844 $params = array(1 => array($tableName, 'String'));
845 $dao = CRM_Core_DAO::executeQuery($query, $params);
846 while ($dao->fetch()) {
847 if ($dao->object_id) {
848 if (self::matchType($type, $dao->operation)) {
849 $ids[] = $dao->object_id;
850 }
6a488035 851 }
557f8c17
ARW
852 else {
853 // this user has got the permission for all objects of this type
854 // check if the type matches
855 if (self::matchType($type, $dao->operation)) {
856 foreach ($allGroups as $id => $dontCare) {
857 $ids[] = $id;
858 }
6a488035 859 }
557f8c17 860 break;
6a488035 861 }
6a488035 862 }
557f8c17 863 $cache->set($cacheKey, $ids);
6a488035
TO
864 }
865 }
866
b1f4e637
RN
867 if (empty($ids) && !empty($includedGroups) &&
868 is_array($includedGroups)
869 ) {
870 $ids = $includedGroups;
871 }
872
6a488035
TO
873 CRM_Utils_Hook::aclGroup($type, $contactID, $tableName, $allGroups, $ids);
874
875 return $ids;
876 }
877
878 static function matchType($type, $operation) {
879 $typeCheck = FALSE;
880 switch ($operation) {
881 case 'All':
882 $typeCheck = TRUE;
883 break;
884
885 case 'View':
886 if ($type == CRM_ACL_API::VIEW) {
887 $typeCheck = TRUE;
888 }
889 break;
890
891 case 'Edit':
892 if ($type == CRM_ACL_API::VIEW || $type == CRM_ACL_API::EDIT) {
893 $typeCheck = TRUE;
894 }
895 break;
896
897 case 'Create':
898 if ($type == CRM_ACL_API::CREATE) {
899 $typeCheck = TRUE;
900 }
901 break;
902
903 case 'Delete':
904 if ($type == CRM_ACL_API::DELETE) {
905 $typeCheck = TRUE;
906 }
907 break;
908
909 case 'Search':
910 if ($type == CRM_ACL_API::SEARCH) {
911 $typeCheck = TRUE;
912 }
913 break;
914 }
915 return $typeCheck;
916 }
917
918 /**
919 * Function to delete ACL records
920 *
921 * @param int $aclId ID of the ACL record to be deleted.
922 *
923 * @access public
924 * @static
925 */
926 static function del($aclId) {
927 // delete all entries from the acl cache
928 CRM_ACL_BAO_Cache::resetCache();
929
930 $acl = new CRM_ACL_DAO_ACL();
931 $acl->id = $aclId;
932 $acl->delete();
933 }
934}
935