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