Support for larger size codes (such as SNOMED US Extension codes)
[openemr.git] / gacl / gacl_api.class.php
blob94d778ef7d850b5a9993c483bb8607cc2aa8af63
1 <?php
2 /**
3 * phpGACL - Generic Access Control List
4 * Copyright (C) 2002,2003 Mike Benoit
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * For questions, help, comments, discussion, etc., please join the
21 * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
23 * You may contact the author of phpGACL by e-mail at:
24 * ipso@snappymail.ca
26 * The latest version of phpGACL can be obtained from:
27 * http://phpgacl.sourceforge.net/
29 * @package phpGACL
35 * For examples, see example.php or the Administration interface,
36 * as it makes use of nearly every API Call.
39 /**
40 * gacl_api Extended API Class
42 * Class gacl_api should be used for applications that must interface directly with
43 * phpGACL's data structures, objects, and rules.
45 * @package phpGACL
46 * @author Mike Benoit <ipso@snappymail.ca>
50 class gacl_api extends gacl {
54 * Misc helper functions.
58 /**
59 * showarray()
61 * Dump all contents of an array in HTML (kinda)
63 * @param array
66 function showarray($array) {
67 echo "<br><pre>\n";
68 var_dump($array);
69 echo "</pre><br>\n";
72 /**
73 * count_all()
75 * Recursively counts elements in an array and sub-arrays.
77 * This is different from count($arg, COUNT_RECURSIVE)
78 * in PHP >= 4.2.0, which includes sub-arrays in the count.
80 * @return int The returned count is a count of all scalar elements found.
82 * @param array Array to count
84 function count_all($arg = NULL) {
85 switch (TRUE) {
86 case is_scalar($arg):
87 case is_object($arg):
88 // single object
89 return 1;
90 case is_array($arg):
91 // call recursively for all elements of $arg
92 $count = 0;
93 foreach ($arg as $val) {
94 $count += $this->count_all($val);
96 return $count;
98 return FALSE;
102 * get_version()
104 * Grabs phpGACL version from the database.
106 * @return string Version of phpGACL
108 function get_version() {
109 $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'version'";
110 $version = $this->db->GetOne($query);
112 return $version;
116 * get_schema_version()
118 * Grabs phpGACL schema version from the database.
120 * @return string Schema Version
122 function get_schema_version() {
123 $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'schema_version'";
124 $version = $this->db->GetOne($query);
126 return $version;
131 * ACL
136 * consolidated_edit_acl()
138 * Add's an ACL but checks to see if it can consolidate it with another one first.
140 * This ONLY works with ACO's and ARO's. Groups, and AXO are excluded.
141 * As well this function is designed for handling ACLs with return values,
142 * and consolidating on the return_value, in hopes of keeping the ACL count to a minimum.
144 * A return value of false must _always_ be handled outside this function.
145 * As this function will remove AROs from ACLs and return false, in most cases
146 * you will need to a create a completely new ACL on a false return.
148 * @return bool Special boolean return value. See note.
150 * @param string ACO Section Value
151 * @param string ACO Value
152 * @param string ARO Section Value
153 * @param string ARO Value
154 * @param string Return Value of ACL
156 function consolidated_edit_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, $return_value) {
158 $this->debug_text("consolidated_edit_acl(): ACO Section Value: $aco_section_value ACO Value: $aco_value ARO Section Value: $aro_section_value ARO Value: $aro_value Return Value: $return_value");
160 $acl_ids = array();
162 if (empty($aco_section_value) ) {
163 $this->debug_text("consolidated_edit_acl(): ACO Section Value ($aco_section_value) is empty, this is required!");
164 return false;
167 if (empty($aco_value) ) {
168 $this->debug_text("consolidated_edit_acl(): ACO Value ($aco_value) is empty, this is required!");
169 return false;
172 if (empty($aro_section_value) ) {
173 $this->debug_text("consolidated_edit_acl(): ARO Section Value ($aro_section_value) is empty, this is required!");
174 return false;
177 if (empty($aro_value) ) {
178 $this->debug_text("consolidated_edit_acl(): ARO Value ($aro_value) is empty, this is required!");
179 return false;
182 if (empty($return_value) ) {
183 $this->debug_text("consolidated_edit_acl(): Return Value ($return_value) is empty, this is required!");
184 return false;
187 //See if a current ACL exists with the current objects, excluding return value
188 $current_acl_ids = $this->search_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, FALSE, FALSE, FALSE, FALSE, FALSE);
189 //showarray($current_acl_ids);
191 if (is_array($current_acl_ids)) {
192 $this->debug_text("add_consolidated_acl(): Found current ACL_IDs, counting ACOs");
194 foreach ($current_acl_ids as $current_acl_id) {
195 //Check to make sure these ACLs only have a single ACO mapped to them.
196 $current_acl_array = &$this->get_acl($current_acl_id);
198 //showarray($current_acl_array);
199 $this->debug_text("add_consolidated_acl(): Current Count: ".$this->count_all($current_acl_array['aco'])."");
201 if ( $this->count_all($current_acl_array['aco']) == 1) {
202 $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO.");
204 //Test to see if the return values match, if they do, no need removing or appending ARO. Just return true.
205 if ($current_acl_array['return_value'] == $return_value) {
206 $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO, and the same return value. No need to modify.");
207 return true;
210 $acl_ids[] = $current_acl_id;
216 //showarray($acl_ids);
217 $acl_ids_count = count($acl_ids);
219 //If acl_id's turns up more then one ACL, lets remove the ARO from all of them in hopes to
220 //eliminate any conflicts.
221 if (is_array($acl_ids) AND $acl_ids_count > 0) {
222 $this->debug_text("add_consolidated_acl(): Removing specified ARO from existing ACL.");
224 foreach ($acl_ids as $acl_id) {
225 //Remove ARO from current ACLs, so we don't create conflicting ACLs later on.
226 if (!$this->shift_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
227 $this->debug_text("add_consolidated_acl(): Error removing specified ARO from ACL ID: $acl_id");
228 return false;
231 } else {
232 $this->debug_text("add_consolidated_acl(): Didn't find any current ACLs with a single ACO. ");
234 //unset($acl_ids);
235 $acl_ids = array();
236 unset($acl_ids_count);
238 //At this point there should be no conflicting ACLs, searching for an existing ACL with the new values.
239 $new_acl_ids = $this->search_acl($aco_section_value, $aco_value, FALSE, FALSE, NULL, NULL, NULL, NULL, $return_value);
240 $new_acl_count = count($new_acl_ids);
241 //showarray($new_acl_ids);
243 if (is_array($new_acl_ids)) {
244 $this->debug_text("add_consolidated_acl(): Found new ACL_IDs, counting ACOs");
246 foreach ($new_acl_ids as $new_acl_id) {
247 //Check to make sure these ACLs only have a single ACO mapped to them.
248 $new_acl_array = &$this->get_acl($new_acl_id);
249 //showarray($new_acl_array);
250 $this->debug_text("add_consolidated_acl(): New Count: ".$this->count_all($new_acl_array['aco'])."");
251 if ( $this->count_all($new_acl_array['aco']) == 1) {
253 $this->debug_text("add_consolidated_acl(): ACL ID: $new_acl_id has 1 ACO, append should be able to take place.");
254 $acl_ids[] = $new_acl_id;
260 //showarray($acl_ids);
261 $acl_ids_count = count($acl_ids);
263 if (is_array($acl_ids) AND $acl_ids_count == 1) {
264 $this->debug_text("add_consolidated_acl(): Appending specified ARO to existing ACL.");
266 $acl_id=$acl_ids[0];
268 if (!$this->append_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
269 $this->debug_text("add_consolidated_acl(): Error appending specified ARO to ACL ID: $acl_id");
270 return false;
273 $this->debug_text("add_consolidated_acl(): Hot damn, ACL consolidated!");
274 return true;
275 } elseif($acl_ids_count > 1) {
276 $this->debug_text("add_consolidated_acl(): Found more then one ACL with a single ACO. Possible conflicting ACLs.");
277 return false;
278 } elseif ($acl_ids_count == 0) {
279 $this->debug_text("add_consolidated_acl(): No existing ACLs found, create a new one.");
281 if (!$this->add_acl( array( $aco_section_value => array($aco_value) ),
282 array( $aro_section_value => array($aro_value) ),
283 NULL,
284 NULL,
285 NULL,
286 TRUE,
287 TRUE,
288 $return_value,
289 NULL)
291 $this->debug_text("add_consolidated_acl(): Error adding new ACL for ACO Section: $aco_section_value ACO Value: $aco_value Return Value: $return_value");
292 return false;
295 $this->debug_text("add_consolidated_acl(): ADD_ACL() successfull, returning True.");
296 return true;
299 $this->debug_text("add_consolidated_acl(): Returning false.");
300 return false;
304 * search_acl()
306 * Searches for ACL's with specified objects mapped to them.
308 * NULL values are included in the search, if you want to ignore
309 * for instance aro_groups use FALSE instead of NULL.
311 * @return array containing ACL IDs if search is successful
313 * @param string ACO Section Value
314 * @param string ACO Value
315 * @param string ARO Section Value
316 * @param string ARO Value
317 * @param string ARO Group Name
318 * @param string AXO Section Value
319 * @param string AXO Value
320 * @param string AXO Group Name
321 * @param string Return Value
323 function search_acl($aco_section_value=NULL, $aco_value=NULL, $aro_section_value=NULL, $aro_value=NULL, $aro_group_name=NULL, $axo_section_value=NULL, $axo_value=NULL, $axo_group_name=NULL, $return_value=NULL) {
324 $this->debug_text("search_acl(): aco_section_value: $aco_section_value aco_value: $aco_value, aro_section_value: $aro_section_value, aro_value: $aro_value, aro_group_name: $aro_group_name, axo_section_value: $axo_section_value, axo_value: $axo_value, axo_group_name: $axo_group_name, return_value: $return_value");
326 $query = '
327 SELECT a.id
328 FROM '. $this->_db_table_prefix .'acl a';
330 $where_query = array();
332 // ACO
333 if ($aco_section_value !== FALSE AND $aco_value !== FALSE) {
334 $query .= '
335 LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON a.id=ac.acl_id';
337 if ($aco_section_value == NULL AND $aco_value == NULL) {
338 $where_query[] = '(ac.section_value IS NULL AND ac.value IS NULL)';
339 } else {
340 $where_query[] = '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value='. $this->db->quote($aco_value) .')';
344 // ARO
345 if ($aro_section_value !== FALSE AND $aro_value !== FALSE) {
346 $query .= '
347 LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON a.id=ar.acl_id';
349 if ($aro_section_value == NULL AND $aro_value == NULL) {
350 $where_query[] = '(ar.section_value IS NULL AND ar.value IS NULL)';
351 } else {
352 $where_query[] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value='. $this->db->quote($aro_value) .')';
356 // AXO
357 if ($axo_section_value !== FALSE AND $axo_value !== FALSE) {
358 $query .= '
359 LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON a.id=ax.acl_id';
361 if ($axo_section_value == NULL AND $axo_value == NULL) {
362 $where_query[] = '(ax.section_value IS NULL AND ax.value IS NULL)';
363 } else {
364 $where_query[] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value='. $this->db->quote($axo_value) .')';
368 // ARO Group
369 if ($aro_group_name !== FALSE) {
370 $query .= '
371 LEFT JOIN '. $this->_db_table_prefix .'aro_groups_map arg ON a.id=arg.acl_id
372 LEFT JOIN '. $this->_db_table_prefix .'aro_groups rg ON arg.group_id=rg.id';
374 if ($aro_group_name == NULL) {
375 $where_query[] = '(rg.name IS NULL)';
376 } else {
377 $where_query[] = '(rg.name='. $this->db->quote($aro_group_name) .')';
381 // AXO Group
382 if ($axo_group_name !== FALSE) {
383 $query .= '
384 LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON a.id=axg.acl_id
385 LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON axg.group_id=xg.id';
387 if ($axo_group_name == NULL) {
388 $where_query[] = '(xg.name IS NULL)';
389 } else {
390 $where_query[] = '(xg.name='. $this->db->quote($axo_group_name) .')';
393 if ($return_value != FALSE) {
394 if ($return_value == NULL) {
395 $where_query[] = '(a.return_value IS NULL)';
396 } else {
397 $where_query[] = '(a.return_value='. $this->db->quote($return_value) .')';
401 if (count($where_query) > 0) {
402 $query .= '
403 WHERE '. implode (' AND ', $where_query);
406 return $this->db->GetCol($query);
410 * append_acl()
412 * Appends objects on to a specific ACL.
414 * @return bool TRUE if successful, FALSE otherwise.
416 * @param int ACL ID #
417 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
418 * @param array Array of Group IDs
419 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
420 * @param array Array of Group IDs
421 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
423 function append_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
424 $this->debug_text("append_acl(): ACL_ID: $acl_id");
426 $update = 0;
428 if (empty($acl_id)) {
429 $this->debug_text("append_acl(): No ACL_ID specified! ACL_ID: $acl_id");
430 return false;
433 //Grab ACL data.
434 $acl_array = &$this->get_acl($acl_id);
436 //Append each object type seperately.
437 if (is_array($aro_array) AND count($aro_array) > 0) {
438 $this->debug_text("append_acl(): Appending ARO's");
440 while (list($aro_section_value,$aro_value_array) = @each($aro_array)) {
441 foreach ($aro_value_array as $aro_value) {
442 if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
443 if (!in_array($aro_value, $acl_array['aro'][$aro_section_value])) {
444 $this->debug_text("append_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
445 $acl_array['aro'][$aro_section_value][] = $aro_value;
446 $update=1;
447 } else {
448 $this->debug_text("append_acl(): Duplicate ARO, ignoring... ");
450 } else { //Array is empty so add this aro value.
451 $acl_array['aro'][$aro_section_value][] = $aro_value;
452 $update = 1;
458 if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
459 $this->debug_text("append_acl(): Appending ARO_GROUP_ID's");
461 while (list(,$aro_group_id) = @each($aro_group_ids)) {
462 if (!is_array($acl_array['aro_groups']) OR !in_array($aro_group_id, $acl_array['aro_groups'])) {
463 $this->debug_text("append_acl(): ARO Group ID: $aro_group_id");
464 $acl_array['aro_groups'][] = $aro_group_id;
465 $update = 1;
466 } else {
467 $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
472 if (is_array($axo_array) AND count($axo_array) > 0) {
473 $this->debug_text("append_acl(): Appending AXO's");
475 while (list($axo_section_value,$axo_value_array) = @each($axo_array)) {
476 foreach ($axo_value_array as $axo_value) {
477 if (!in_array($axo_value, $acl_array['axo'][$axo_section_value])) {
478 $this->debug_text("append_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
479 $acl_array['axo'][$axo_section_value][] = $axo_value;
480 $update = 1;
481 } else {
482 $this->debug_text("append_acl(): Duplicate AXO, ignoring... ");
489 if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
490 $this->debug_text("append_acl(): Appending AXO_GROUP_ID's");
491 while (list(,$axo_group_id) = @each($axo_group_ids)) {
492 if (!is_array($acl_array['axo_groups']) OR !in_array($axo_group_id, $acl_array['axo_groups'])) {
493 $this->debug_text("append_acl(): AXO Group ID: $axo_group_id");
494 $acl_array['axo_groups'][] = $axo_group_id;
495 $update = 1;
496 } else {
497 $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
502 if (is_array($aco_array) AND count($aco_array) > 0) {
503 $this->debug_text("append_acl(): Appending ACO's");
505 while (list($aco_section_value,$aco_value_array) = @each($aco_array)) {
506 foreach ($aco_value_array as $aco_value) {
507 if (!in_array($aco_value, $acl_array['aco'][$aco_section_value])) {
508 $this->debug_text("append_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
509 $acl_array['aco'][$aco_section_value][] = $aco_value;
510 $update = 1;
511 } else {
512 $this->debug_text("append_acl(): Duplicate ACO, ignoring... ");
518 if ($update == 1) {
519 $this->debug_text("append_acl(): Update flag set, updating ACL.");
520 //function edit_acl($acl_id, $aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $allow=1, $enabled=1, $return_value=NULL, $note=NULL) {
521 return $this->edit_acl($acl_id, $acl_array['aco'], $acl_array['aro'], $acl_array['aro_groups'], $acl_array['axo'], $acl_array['axo_groups'], $acl_array['allow'], $acl_array['enabled'], $acl_array['return_value'], $acl_array['note']);
524 //Return true if everything is duplicate and no ACL id updated.
525 $this->debug_text("append_acl(): Update flag not set, NOT updating ACL.");
526 return true;
530 * shift_acl()
532 * Opposite of append_acl(). Removes objects from a specific ACL. (named after PHP's array_shift())
534 * @return bool TRUE if successful, FALSE otherwise.
536 * @param int ACL ID #
537 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
538 * @param array Array of Group IDs
539 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
540 * @param array Array of Group IDs
541 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
543 function shift_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
544 $this->debug_text("shift_acl(): ACL_ID: $acl_id");
546 $update = 0;
548 if (empty($acl_id)) {
549 $this->debug_text("shift_acl(): No ACL_ID specified! ACL_ID: $acl_id");
550 return false;
553 //Grab ACL data.
554 $acl_array = &$this->get_acl($acl_id);
556 //showarray($acl_array);
557 //Remove each object type seperately.
558 if (is_array($aro_array) AND count($aro_array) > 0) {
559 $this->debug_text("shift_acl(): Removing ARO's");
561 while (list($aro_section_value,$aro_value_array) = @each($aro_array)) {
562 foreach ($aro_value_array as $aro_value) {
563 $this->debug_text("shift_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
565 //Only search if aro array contains data.
566 if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
567 $aro_key = array_search($aro_value, $acl_array['aro'][$aro_section_value]);
569 if ($aro_key !== FALSE) {
570 $this->debug_text("shift_acl(): Removing ARO. ($aro_key)");
571 unset($acl_array['aro'][$aro_section_value][$aro_key]);
572 $update = 1;
573 } else {
574 $this->debug_text("shift_acl(): ARO doesn't exist, can't remove it.");
582 if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
583 $this->debug_text("shift_acl(): Removing ARO_GROUP_ID's");
585 while (list(,$aro_group_id) = @each($aro_group_ids)) {
586 $this->debug_text("shift_acl(): ARO Group ID: $aro_group_id");
587 $aro_group_key = array_search($aro_group_id, $acl_array['aro_groups']);
589 if ($aro_group_key !== FALSE) {
590 $this->debug_text("shift_acl(): Removing ARO Group. ($aro_group_key)");
591 unset($acl_array['aro_groups'][$aro_group_key]);
592 $update = 1;
593 } else {
594 $this->debug_text("shift_acl(): ARO Group doesn't exist, can't remove it.");
599 if (is_array($axo_array) AND count($axo_array) > 0) {
600 $this->debug_text("shift_acl(): Removing AXO's");
602 while (list($axo_section_value,$axo_value_array) = @each($axo_array)) {
603 foreach ($axo_value_array as $axo_value) {
604 $this->debug_text("shift_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
605 $axo_key = array_search($axo_value, $acl_array['axo'][$axo_section_value]);
607 if ($axo_key !== FALSE) {
608 $this->debug_text("shift_acl(): Removing AXO. ($axo_key)");
609 unset($acl_array['axo'][$axo_section_value][$axo_key]);
610 $update = 1;
611 } else {
612 $this->debug_text("shift_acl(): AXO doesn't exist, can't remove it.");
618 if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
619 $this->debug_text("shift_acl(): Removing AXO_GROUP_ID's");
621 while (list(,$axo_group_id) = @each($axo_group_ids)) {
622 $this->debug_text("shift_acl(): AXO Group ID: $axo_group_id");
623 $axo_group_key = array_search($axo_group_id, $acl_array['axo_groups']);
625 if ($axo_group_key !== FALSE) {
626 $this->debug_text("shift_acl(): Removing AXO Group. ($axo_group_key)");
627 unset($acl_array['axo_groups'][$axo_group_key]);
628 $update = 1;
629 } else {
630 $this->debug_text("shift_acl(): AXO Group doesn't exist, can't remove it.");
635 if (is_array($aco_array) AND count($aco_array) > 0) {
636 $this->debug_text("shift_acl(): Removing ACO's");
638 while (list($aco_section_value,$aco_value_array) = @each($aco_array)) {
639 foreach ($aco_value_array as $aco_value) {
640 $this->debug_text("shift_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
641 $aco_key = array_search($aco_value, $acl_array['aco'][$aco_section_value]);
643 if ($aco_key !== FALSE) {
644 $this->debug_text("shift_acl(): Removing ACO. ($aco_key)");
645 unset($acl_array['aco'][$aco_section_value][$aco_key]);
646 $update = 1;
647 } else {
648 $this->debug_text("shift_acl(): ACO doesn't exist, can't remove it.");
654 if ($update == 1) {
655 //We know something was changed, so lets see if no ACO's or no ARO's are left assigned to this ACL, if so, delete the ACL completely.
656 //$this->showarray($acl_array);
657 $this->debug_text("shift_acl(): ACOs: ". $this->count_all($acl_array['aco']) ." AROs: ".$this->count_all($acl_array['aro'])."");
659 if ( $this->count_all($acl_array['aco']) == 0
660 OR ( $this->count_all($acl_array['aro']) == 0
661 AND ( $this->count_all($acl_array['axo']) == 0 OR $acl_array['axo'] == FALSE)
662 AND (count($acl_array['aro_groups']) == 0 OR $acl_array['aro_groups'] == FALSE)
663 AND (count($acl_array['axo_groups']) == 0 OR $acl_array['axo_groups'] == FALSE)
664 ) ) {
665 $this->debug_text("shift_acl(): No ACOs or ( AROs AND AXOs AND ARO Groups AND AXO Groups) left assigned to this ACL (ID: $acl_id), deleting ACL.");
667 return $this->del_acl($acl_id);
670 $this->debug_text("shift_acl(): Update flag set, updating ACL.");
672 return $this->edit_acl($acl_id, $acl_array['aco'], $acl_array['aro'], $acl_array['aro_groups'], $acl_array['axo'], $acl_array['axo_groups'], $acl_array['allow'], $acl_array['enabled'], $acl_array['return_value'], $acl_array['note']);
675 //Return true if everything is duplicate and no ACL id updated.
676 $this->debug_text("shift_acl(): Update flag not set, NOT updating ACL.");
677 return true;
681 * get_acl()
683 * Grabs ACL data.
685 * @return bool FALSE if not found, or Associative Array with the following items:
687 * - 'aco' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
688 * - 'aro' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
689 * - 'axo' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
690 * - 'aro_groups' => Array of Group IDs
691 * - 'axo_groups' => Array of Group IDs
692 * - 'acl_id' => int ACL ID #
693 * - 'allow' => int Allow flag
694 * - 'enabled' => int Enabled flag
695 * - 'return_value' => string Return Value
696 * - 'note' => string Note
698 * @param int ACL ID #
700 function get_acl($acl_id) {
702 $this->debug_text("get_acl(): ACL_ID: $acl_id");
704 if (empty($acl_id)) {
705 $this->debug_text("get_acl(): No ACL_ID specified! ACL_ID: $acl_id");
706 return false;
709 //Grab ACL information
710 $query = "select id, allow, enabled, return_value, note from ".$this->_db_table_prefix."acl where id = ".$acl_id."";
711 $acl_row = $this->db->GetRow($query);
713 // return false if not found
714 if (!$acl_row) {
715 $this->debug_text("get_acl(): No ACL found for that ID! ACL_ID: $acl_id");
716 return false;
719 list($retarr['acl_id'], $retarr['allow'], $retarr['enabled'], $retarr['return_value'], $retarr['note']) = $acl_row;
721 //Grab selected ACO's
722 $query = "select distinct a.section_value, a.value, c.name, b.name from ".$this->_db_table_prefix."aco_map a, ".$this->_db_table_prefix."aco b, ".$this->_db_table_prefix."aco_sections c
723 where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
724 $rs = $this->db->Execute($query);
725 $rows = $rs->GetRows();
727 $retarr['aco'] = array();
728 while (list(,$row) = @each($rows)) {
729 list($section_value, $value, $section, $aco) = $row;
730 $this->debug_text("Section Value: $section_value Value: $value Section: $section ACO: $aco");
732 $retarr['aco'][$section_value][] = $value;
735 //showarray($aco);
737 //Grab selected ARO's
738 $query = "select distinct a.section_value, a.value, c.name, b.name from ".$this->_db_table_prefix."aro_map a, ".$this->_db_table_prefix."aro b, ".$this->_db_table_prefix."aro_sections c
739 where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
740 $rs = $this->db->Execute($query);
741 $rows = $rs->GetRows();
743 $retarr['aro'] = array();
744 while (list(,$row) = @each($rows)) {
745 list($section_value, $value, $section, $aro) = $row;
746 $this->debug_text("Section Value: $section_value Value: $value Section: $section ARO: $aro");
748 $retarr['aro'][$section_value][] = $value;
751 //showarray($options_aro);
753 //Grab selected AXO's
754 $query = "select distinct a.section_value, a.value, c.name, b.name from ".$this->_db_table_prefix."axo_map a, ".$this->_db_table_prefix."axo b, ".$this->_db_table_prefix."axo_sections c
755 where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
756 $rs = $this->db->Execute($query);
757 $rows = $rs->GetRows();
759 $retarr['axo'] = array();
760 while (list(,$row) = @each($rows)) {
761 list($section_value, $value, $section, $axo) = $row;
762 $this->debug_text("Section Value: $section_value Value: $value Section: $section AXO: $axo");
764 $retarr['axo'][$section_value][] = $value;
767 //showarray($options_aro);
769 //Grab selected ARO groups.
770 $retarr['aro_groups'] = array();
771 $query = "select distinct group_id from ".$this->_db_table_prefix."aro_groups_map where acl_id = $acl_id";
772 $retarr['aro_groups'] = $this->db->GetCol($query);
773 //showarray($selected_groups);
775 //Grab selected AXO groups.
776 $retarr['axo_groups'] = array();
777 $query = "select distinct group_id from ".$this->_db_table_prefix."axo_groups_map where acl_id = $acl_id";
778 $retarr['axo_groups'] = $this->db->GetCol($query);
779 //showarray($selected_groups);
781 return $retarr;
785 * is_conflicting_acl()
787 * Checks for conflicts when adding a specific ACL.
789 * @return bool Returns true if conflict is found.
791 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
792 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
793 * @param array Array of Group IDs
794 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
795 * @param array Array of Group IDs
796 * @param array Array of ACL IDs to ignore from the result set.
799 function is_conflicting_acl($aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $ignore_acl_ids=NULL) {
800 //Check for potential conflicts. Ignore groups, as groups will almost always have "conflicting" ACLs.
801 //Thats part of inheritance.
803 if (!is_array($aco_array)) {
804 $this->debug_text('is_conflicting_acl(): Invalid ACO Array.');
805 return FALSE;
808 if (!is_array($aro_array)) {
809 $this->debug_text('is_conflicting_acl(): Invalid ARO Array.');
810 return FALSE;
813 $query = '
814 SELECT a.id
815 FROM '. $this->_db_table_prefix .'acl a
816 LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON ac.acl_id=a.id
817 LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON ar.acl_id=a.id
818 LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON ax.acl_id=a.id
819 LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON axg.acl_id=a.id
820 LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON xg.id=axg.group_id
823 //ACO
824 foreach ($aco_array as $aco_section_value => $aco_value_array) {
825 $this->debug_text("is_conflicting_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value_array");
826 //showarray($aco_array);
828 if (!is_array($aco_value_array)) {
829 $this->debug_text('is_conflicting_acl(): Invalid Format for ACO Array item. Skipping...');
830 continue;
831 // return TRUE;
833 //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
834 //'ac1' => 'ac.acl_id=a.id',
835 $where_query = array(
836 'ac2' => '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value IN (\''. implode ('\',\'', $aco_value_array) .'\'))'
839 //ARO
840 foreach ($aro_array as $aro_section_value => $aro_value_array) {
841 $this->debug_text("is_conflicting_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value_array");
843 if (!is_array($aro_value_array))
845 $this->debug_text('is_conflicting_acl(): Invalid Format for ARO Array item. Skipping...');
846 continue;
847 // return TRUE;
850 $this->debug_text("is_conflicting_acl(): Search: ACO Section: $aco_section_value ACO Value: $aco_value_array ARO Section: $aro_section_value ARO Value: $aro_value_array");
852 //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
853 //$where_query['ar1'] = 'ar.acl_id=a.id';
854 $where_query['ar2'] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value IN (\''. implode ('\',\'', $aro_value_array) .'\'))';
856 if (is_array($axo_array) AND count($axo_array) > 0) {
857 foreach ($axo_array as $axo_section_value => $axo_value_array) {
858 $this->debug_text("is_conflicting_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value_array");
860 if (!is_array($axo_value_array)) {
861 $this->debug_text('is_conflicting_acl(): Invalid Format for AXO Array item. Skipping...');
862 continue;
863 // return TRUE;
866 $this->debug_text("is_conflicting_acl(): Search: ACO Section: $aco_section_value ACO Value: $aco_value_array ARO Section: $aro_section_value ARO Value: $aro_value_array AXO Section: $axo_section_value AXO Value: $axo_value_array");
868 //$where_query['ax1'] = 'ax.acl_id=x.id';
869 $where_query['ax1'] = 'ax.acl_id=a.id';
870 $where_query['ax2'] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value IN (\''. implode ('\',\'', $axo_value_array) .'\'))';
872 $where = 'WHERE ' . implode(' AND ', $where_query);
874 $conflict_result = $this->db->GetCol($query . $where);
876 if (is_array($conflict_result) AND !empty($conflict_result)) {
877 // showarray($conflict_result);
879 if (is_array($ignore_acl_ids)) {
880 $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
883 if (count($conflict_result) > 0) {
884 $conflicting_acls_str = implode(',', $conflict_result);
885 $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
886 return TRUE;
890 } else {
891 $where_query['ax1'] = '(ax.section_value IS NULL AND ax.value IS NULL)';
892 $where_query['ax2'] = 'xg.name IS NULL';
894 $where = 'WHERE ' . implode(' AND ', $where_query);
896 $conflict_result = $this->db->GetCol($query . $where);
898 if (is_array($conflict_result) AND !empty($conflict_result)) {
899 // showarray($conflict_result);
901 if (is_array($ignore_acl_ids)) {
902 $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
905 if (count($conflict_result) > 0) {
906 $conflicting_acls_str = implode(',', $conflict_result);
907 $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
908 return TRUE;
915 $this->debug_text('is_conflicting_acl(): No conflicting ACL found.');
916 return FALSE;
920 * add_acl()
922 * Add's an ACL. ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
924 * @return bool Return ACL ID of new ACL if successful, FALSE otherewise.
926 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
927 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
928 * @param array Array of Group IDs
929 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
930 * @param array Array of Group IDs
931 * @param int Allow flag
932 * @param int Enabled flag
933 * @param string Return Value
934 * @param string Note
935 * @param string ACL Section Value
936 * @param int ACL ID # Specific Request
939 function add_acl($aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $allow=1, $enabled=1, $return_value=NULL, $note=NULL, $section_value=NULL, $acl_id=FALSE ) {
941 $this->debug_text("add_acl():");
943 if (count($aco_array) == 0) {
944 $this->debug_text("Must select at least one Access Control Object");
945 return false;
948 if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
949 $this->debug_text("Must select at least one Access Request Object or Group");
950 return false;
953 if (empty($allow)) {
954 $allow=0;
957 if (empty($enabled)) {
958 $enabled=0;
961 if (!empty($section_value)
962 AND !$this->get_object_section_section_id(NULL, $section_value, 'ACL')) {
963 $this->debug_text("add_acl(): Section Value: $section_value DOES NOT exist in the database.");
964 return false;
967 //Unique the group arrays. Later one we unique ACO/ARO/AXO arrays.
968 if (is_array($aro_group_ids)) {
969 $aro_group_ids = array_unique($aro_group_ids);
971 if (is_array($axo_group_ids)) {
972 $axo_group_ids = array_unique($axo_group_ids);
975 //Check for conflicting ACLs.
976 if ($this->is_conflicting_acl($aco_array,$aro_array,$aro_group_ids,$axo_array,$axo_group_ids,array($acl_id))) {
977 $this->debug_text("add_acl(): Detected possible ACL conflict, not adding ACL!");
978 return false;
981 //Edit ACL if acl_id is set. This is simply if we're being called by edit_acl().
982 if ($this->get_acl($acl_id) == FALSE) {
983 if ( empty($section_value) ) {
984 $section_value='system';
985 if( !$this->get_object_section_section_id(NULL, $section_value, 'ACL') ) {
986 // Use the acl section with the lowest order value.
987 $acl_sections_table = $this->_db_table_prefix .'acl_sections';
988 $acl_section_order_value = $this->db->GetOne("SELECT min(order_value) from $acl_sections_table");
990 $query = "
991 SELECT value
992 FROM $acl_sections_table
993 WHERE order_value = $acl_section_order_value
995 $section_value = $this->db->GetOne($query);
997 if ( empty($section_value) ) {
998 $this->debug_text("add_acl(): No valid acl section found.");
999 return false;
1000 } else {
1001 $this->debug_text("add_acl(): Using default section value: $section_value.");
1006 //ACL not specified, so create acl_id
1007 if (empty($acl_id)) {
1008 //Create ACL row first, so we have the acl_id
1009 $acl_id = $this->db->GenID($this->_db_table_prefix.'acl_seq',10);
1011 //Double check the ACL ID was generated.
1012 if (empty($acl_id)) {
1013 $this->debug_text("add_acl(): ACL_ID generation failed!");
1014 return false;
1018 //Begin transaction _after_ GenID. Because on the first run, if GenID has to create the sequence,
1019 //the transaction will fail.
1020 $this->db->BeginTrans();
1022 $query = 'INSERT INTO '.$this->_db_table_prefix.'acl (id,section_value,allow,enabled,return_value,note,updated_date) VALUES('. $acl_id .','. $this->db->quote($section_value) .','. $allow .','. $enabled .','. $this->db->quote($return_value) .', '. $this->db->quote($note) .','. time() .')';
1023 $result = $this->db->Execute($query);
1024 } else {
1025 $section_sql = '';
1026 if ( !empty($section_value) ) {
1027 $section_sql = 'section_value='. $this->db->quote ($section_value) .',';
1030 $this->db->BeginTrans();
1032 //Update ACL row, and remove all mappings so they can be re-inserted.
1033 $query = '
1034 UPDATE '. $this->_db_table_prefix .'acl
1035 SET ' . $section_sql . '
1036 allow='. $allow .',
1037 enabled='. $enabled .',
1038 return_value='. $this->db->quote($return_value) .',
1039 note='. $this->db->quote($note) .',
1040 updated_date='. time() .'
1041 WHERE id='. $acl_id;
1042 $result = $this->db->Execute($query);
1044 if ($result) {
1045 $this->debug_text("Update completed without error, delete mappings...");
1046 //Delete all mappings so they can be re-inserted.
1047 foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
1048 $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. $acl_id;
1049 $rs = $this->db->Execute($query);
1051 if (!is_object($rs))
1053 $this->debug_db('add_acl');
1054 $this->db->RollBackTrans();
1055 return FALSE;
1061 if (!is_object($result)) {
1062 $this->debug_db('add_acl');
1063 $this->db->RollBackTrans();
1064 return false;
1067 $this->debug_text("Insert or Update completed without error, insert new mappings.");
1068 // Insert ACO/ARO/AXO mappings
1069 foreach (array('aco', 'aro', 'axo') as $map) {
1070 $map_array = ${$map .'_array'};
1072 if (!is_array ($map_array)) {
1073 continue;
1076 foreach ($map_array as $section_value => $value_array) {
1077 $this->debug_text ('Insert: '. strtoupper($map) .' Section Value: '. $section_value .' '. strtoupper($map) .' VALUE: '. $value_array);
1078 // $this->showarray ($aco_value_array);
1080 if (!is_array($value_array)) {
1081 $this->debug_text ('add_acl (): Invalid Format for '. strtoupper ($map) .' Array item. Skipping...');
1082 continue;
1083 // return true;
1086 $value_array = array_unique($value_array);
1088 foreach ($value_array as $value) {
1089 $object_id = &$this->get_object_id($section_value, $value, $map);
1091 if (empty($object_id))
1093 $this->debug_text('add_acl(): '. strtoupper($map) . " Object Section Value: $section_value Value: $value DOES NOT exist in the database. Skipping...");
1094 $this->db->RollBackTrans();
1095 return false;
1098 $query = 'INSERT INTO '. $this->_db_table_prefix . $map .'_map (acl_id,section_value,value) VALUES ('. $acl_id .', '. $this->db->quote($section_value) .', '. $this->db->quote($value) .')';
1099 $rs = $this->db->Execute($query);
1101 if (!is_object($rs))
1103 $this->debug_db('add_acl');
1104 $this->db->RollBackTrans();
1105 return false;
1111 // Insert ARO/AXO GROUP mappings
1112 foreach (array('aro', 'axo') as $map) {
1113 $map_group_ids = ${$map .'_group_ids'};
1115 if (!is_array($map_group_ids)) {
1116 continue;
1119 foreach ($map_group_ids as $group_id) {
1120 $this->debug_text ('Insert: '. strtoupper($map) .' GROUP ID: '. $group_id);
1122 $group_data = &$this->get_group_data($group_id, $map);
1124 if (empty($group_data)) {
1125 $this->debug_text('add_acl(): '. strtoupper($map) . " Group: $group_id DOES NOT exist in the database. Skipping...");
1126 $this->db->RollBackTrans();
1127 return false;
1130 $query = 'INSERT INTO '. $this->_db_table_prefix . $map .'_groups_map (acl_id,group_id) VALUES ('. $acl_id .', '. $group_id .')';
1131 $rs = $this->db->Execute($query);
1133 if (!is_object($rs)) {
1134 $this->debug_db('add_acl');
1135 $this->db->RollBackTrans();
1136 return false;
1141 $this->db->CommitTrans();
1143 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1144 //Expire all cache.
1145 $this->Cache_Lite->clean('default');
1148 //Return only the ID in the first row.
1149 return $acl_id;
1153 * edit_acl()
1155 * Edit's an ACL, ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
1157 * @return bool Return TRUE if successful, FALSE otherewise.
1159 * @param int ACL ID # to edit
1160 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1161 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1162 * @param array Array of Group IDs
1163 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1164 * @param array Array of Group IDs
1165 * @param int Allow flag
1166 * @param int Enabled flag
1167 * @param string Return Value
1168 * @param string Note
1169 * @param string ACL Section Value
1171 function edit_acl($acl_id, $aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $allow=1, $enabled=1, $return_value=NULL, $note=NULL, $section_value=NULL) {
1173 $this->debug_text("edit_acl():");
1175 if (empty($acl_id) ) {
1176 $this->debug_text("edit_acl(): Must specify a single ACL_ID to edit");
1177 return false;
1179 if (count($aco_array) == 0) {
1180 $this->debug_text("edit_acl(): Must select at least one Access Control Object");
1181 return false;
1184 if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
1185 $this->debug_text("edit_acl(): Must select at least one Access Request Object or Group");
1186 return false;
1189 if (empty($allow)) {
1190 $allow=0;
1193 if (empty($enabled)) {
1194 $enabled=0;
1197 //if ($this->add_acl($aco_array, $aro_array, $group_ids, $allow, $enabled, $acl_id)) {
1198 if ($this->add_acl($aco_array, $aro_array, $aro_group_ids, $axo_array, $axo_group_ids, $allow, $enabled, $return_value, $note, $section_value, $acl_id)) {
1199 return true;
1200 } else {
1201 $this->debug_text("edit_acl(): error in add_acl()");
1202 return false;
1207 * del_acl()
1209 * Deletes a given ACL
1211 * @return bool Returns TRUE if successful, FALSE otherwise.
1213 * @param int ACL ID # to delete
1215 function del_acl($acl_id) {
1217 $this->debug_text("del_acl(): ID: $acl_id");
1219 if (empty($acl_id) ) {
1220 $this->debug_text("del_acl(): ACL_ID ($acl_id) is empty, this is required");
1221 return false;
1224 $this->db->BeginTrans();
1226 // Delete all mappings to the ACL first
1227 foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
1228 $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. $acl_id;
1229 $rs = $this->db->Execute($query);
1231 if (!is_object($rs)) {
1232 $this->debug_db('del_acl');
1233 $this->db->RollBackTrans();
1234 return false;
1238 // Delete the ACL
1239 $query = 'DELETE FROM '. $this->_db_table_prefix .'acl WHERE id='. $acl_id;
1240 $this->debug_text('delete query: '. $query);
1241 $rs = $this->db->Execute($query);
1243 if (!is_object($rs)) {
1244 $this->debug_db('del_acl');
1245 $this->db->RollBackTrans();
1246 return false;
1249 $this->debug_text("del_acl(): deleted ACL ID: $acl_id");
1250 $this->db->CommitTrans();
1252 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1253 //Expire all cache.
1254 $this->Cache_Lite->clean('default');
1257 return TRUE;
1263 * Groups
1268 * sort_groups()
1270 * Grabs all the groups from the database doing preliminary grouping by parent
1272 * @return array Returns 2-Dimensional array: $array[<parent_id>][<group_id>] = <group_name>
1274 * @param string Group Type, either 'ARO' or 'AXO'
1276 function sort_groups($group_type='ARO') {
1278 switch(strtolower(trim($group_type))) {
1279 case 'axo':
1280 $table = $this->_db_table_prefix .'axo_groups';
1281 break;
1282 default:
1283 $table = $this->_db_table_prefix .'aro_groups';
1284 break;
1287 //Grab all groups from the database.
1288 $query = 'SELECT id, parent_id, name FROM '. $table .' ORDER BY parent_id, name';
1289 $rs = $this->db->Execute($query);
1291 if (!is_object($rs)) {
1292 $this->debug_db('sort_groups');
1293 return false;
1297 * Save groups in an array sorted by parent. Should be make it easier for later on.
1299 $sorted_groups = array();
1301 while ($row = $rs->FetchRow()) {
1302 $id = &$row[0];
1303 $parent_id = &$row[1];
1304 $name = &$row[2];
1306 $sorted_groups[$parent_id][$id] = $name;
1309 return $sorted_groups;
1313 * format_groups()
1315 * Takes the array returned by sort_groups() and formats for human
1316 * consumption. Recursively calls itself to produce the desired output.
1318 * @return array Array of formatted text, ordered by group id, formatted according to $type
1320 * @param array Output from gacl_api->sorted_groups($group_type)
1321 * @param array Output type desired, either 'TEXT', 'HTML', or 'ARRAY'
1322 * @param int Root of tree to produce
1323 * @param int Current level of depth
1324 * @param array Pass the current formatted groups object for appending via recursion.
1326 function format_groups($sorted_groups, $type='TEXT', $root_id=0, $level=0, $formatted_groups=NULL) {
1327 if ( !is_array ($sorted_groups) ) {
1328 return FALSE;
1331 if ( !is_array ($formatted_groups) ) {
1332 $formatted_groups = array ();
1335 //$this->showarray($formatted_groups);
1337 //while (list($id,$name) = @each($sorted_groups[$root_id])) {
1338 if (isset($sorted_groups[$root_id])) {
1339 //$last_id = end( array_keys($sorted_groups[$root_id]));
1340 //PHP5 compatibility
1341 $keys = array_keys($sorted_groups[$root_id]);
1342 $last_id = end($keys);
1343 unset($keys);
1345 foreach ($sorted_groups[$root_id] as $id => $name) {
1346 switch (strtoupper($type)) {
1347 case 'TEXT':
1349 * Formatting optimized for TEXT (combo box) output.
1352 if ( is_numeric($level) ) {
1353 $level = str_repeat('&nbsp;&nbsp; ', $level);
1356 if ( strlen($level) >= 8 ) {
1357 if ( $id == $last_id ) {
1358 $spacing = substr($level, 0, -8) .'\'- ';
1359 $level = substr($level, 0, -8) .'&nbsp;&nbsp; ';
1360 } else {
1361 $spacing = substr($level, 0, -8) .'|- ';
1363 } else {
1364 $spacing = $level;
1367 $next = $level .'|&nbsp; ';
1368 $text = $spacing.$name;
1369 break;
1370 case 'HTML':
1372 * Formatting optimized for HTML (tables) output.
1374 $width= $level * 20;
1375 $spacing = "<img src=\"s.gif\" width=\"$width\">";
1376 $next = $level + 1;
1377 $text = $spacing." ".$name;
1378 break;
1379 case 'ARRAY':
1380 $next = $level;
1381 $text = $name;
1382 break;
1383 default:
1384 return FALSE;
1387 $formatted_groups[$id] = $text;
1389 * Recurse if we can.
1392 //if (isset($sorted_groups[$id]) AND count($sorted_groups[$id]) > 0) {
1393 if (isset($sorted_groups[$id]) ) {
1394 //$this->debug_text("format_groups(): Recursing! Level: $level");
1395 $formatted_groups = $this->format_groups($sorted_groups, $type, $id, $next, $formatted_groups);
1396 } else {
1397 //$this->debug_text("format_groups(): Found last branch!");
1402 //$this->debug_text("format_groups(): Returning final array.");
1404 return $formatted_groups;
1408 * get_group_id()
1410 * Gets the group_id given the name or value.
1412 * Will only return one group id, so if there are duplicate names, it will return false.
1414 * @return int Returns Group ID if found and Group ID is unique in database, otherwise, returns FALSE
1416 * @param string Group Value
1417 * @param string Group Name
1418 * @param string Group Type, either 'ARO' or 'AXO'
1420 function get_group_id($value = NULL, $name = NULL, $group_type = 'ARO') {
1422 $this->debug_text("get_group_id(): Value: $value, Name: $name, Type: $group_type" );
1424 switch(strtolower(trim($group_type))) {
1425 case 'axo':
1426 $table = $this->_db_table_prefix .'axo_groups';
1427 break;
1428 default:
1429 $table = $this->_db_table_prefix .'aro_groups';
1430 break;
1433 $name = trim($name);
1434 $value = trim($value);
1436 if (empty($name) AND empty($value) ) {
1437 $this->debug_text("get_group_id(): name and value, at least one is required");
1438 return false;
1441 $query = 'SELECT id FROM '. $table .' WHERE ';
1442 if ( !empty($value) ) {
1443 $query .= ' value='. $this->db->quote($value);
1444 } else {
1445 $query .= ' name='. $this->db->quote($name);
1447 $rs = $this->db->Execute($query);
1449 if (!is_object($rs)) {
1450 $this->debug_db('get_group_id');
1451 return false;
1454 $row_count = $rs->RecordCount();
1456 if ($row_count > 1) {
1457 $this->debug_text("get_group_id(): Returned $row_count rows, can only return one. Please make your names unique.");
1458 return false;
1461 if ($row_count == 0) {
1462 $this->debug_text("get_group_id(): Returned $row_count rows");
1463 return false;
1466 $row = $rs->FetchRow();
1468 //Return the ID.
1469 return $row[0];
1473 * get_group_children()
1475 * Gets a groups child IDs
1477 * @return array Array of Child ID's of the referenced group
1479 * @param int Group ID #
1480 * @param int Group Type, either 'ARO' or 'AXO'
1481 * @param string Either 'RECURSE' or 'NO_RECURSE', to recurse while fetching group children.
1483 function get_group_children($group_id, $group_type = 'ARO', $recurse = 'NO_RECURSE') {
1484 $this->debug_text("get_group_children(): Group_ID: $group_id Group Type: $group_type Recurse: $recurse");
1486 switch (strtolower(trim($group_type))) {
1487 case 'axo':
1488 $group_type = 'axo';
1489 $table = $this->_db_table_prefix .'axo_groups';
1490 break;
1491 default:
1492 $group_type = 'aro';
1493 $table = $this->_db_table_prefix .'aro_groups';
1496 if (empty($group_id)) {
1497 $this->debug_text("get_group_children(): ID ($group_id) is empty, this is required");
1498 return FALSE;
1501 $query = '
1502 SELECT g1.id
1503 FROM '. $table .' g1';
1505 //FIXME-mikeb: Why is group_id in quotes?
1506 switch (strtoupper($recurse)) {
1507 case 'RECURSE':
1508 $query .= '
1509 LEFT JOIN '. $table .' g2 ON g2.lft<g1.lft AND g2.rgt>g1.rgt
1510 WHERE g2.id='. $group_id;
1511 break;
1512 default:
1513 $query .= '
1514 WHERE g1.parent_id='. $group_id;
1517 $query .= '
1518 ORDER BY g1.value';
1520 return $this->db->GetCol($query);
1524 * get_group_data()
1526 * Gets the group data given the GROUP_ID.
1528 * @return array Returns numerically indexed array with the following columns:
1529 * - array[0] = (int) Group ID #
1530 * - array[1] = (int) Parent Group ID #
1531 * - array[2] = (string) Group Value
1532 * - array[3] = (string) Group Name
1533 * - array[4] = (int) lft MPTT Value
1534 * - array[5] = (int) rgt MPTT Value
1536 * @param int Group ID #
1537 * @param string Group Type, either 'ARO' or 'AXO'
1539 function get_group_data($group_id, $group_type = 'ARO') {
1541 $this->debug_text("get_group_data(): Group_ID: $group_id Group Type: $group_type");
1543 switch(strtolower(trim($group_type))) {
1544 case 'axo':
1545 $group_type = 'axo';
1546 $table = $this->_db_table_prefix .'axo_groups';
1547 break;
1548 default:
1549 $group_type = 'aro';
1550 $table = $this->_db_table_prefix .'aro_groups';
1551 break;
1554 if (empty($group_id) ) {
1555 $this->debug_text("get_group_data(): ID ($group_id) is empty, this is required");
1556 return false;
1559 $query = 'SELECT id, parent_id, value, name, lft, rgt FROM '. $table .' WHERE id='. $group_id;
1560 //$rs = $this->db->Execute($query);
1561 $row = $this->db->GetRow($query);
1563 if ($row) {
1564 return $row;
1567 $this->debug_text("get_object_data(): Group does not exist.");
1568 return false;
1572 * get_group_parent_id()
1574 * Grabs the parent_id of a given group
1576 * @return int Parent ID of the Group
1578 * @param int Group ID #
1579 * @param string Group Type, either 'ARO' or 'AXO'
1581 function get_group_parent_id($id, $group_type='ARO') {
1583 $this->debug_text("get_group_parent_id(): ID: $id Group Type: $group_type");
1585 switch(strtolower(trim($group_type))) {
1586 case 'axo':
1587 $table = $this->_db_table_prefix .'axo_groups';
1588 break;
1589 default:
1590 $table = $this->_db_table_prefix .'aro_groups';
1591 break;
1594 if (empty($id) ) {
1595 $this->debug_text("get_group_parent_id(): ID ($id) is empty, this is required");
1596 return false;
1599 $query = 'SELECT parent_id FROM '. $table .' WHERE id='. $id;
1600 $rs = $this->db->Execute($query);
1602 if (!is_object($rs)) {
1603 $this->debug_db('get_group_parent_id');
1604 return false;
1607 $row_count = $rs->RecordCount();
1609 if ($row_count > 1) {
1610 $this->debug_text("get_group_parent_id(): Returned $row_count rows, can only return one. Please make your names unique.");
1611 return false;
1614 if ($row_count == 0) {
1615 $this->debug_text("get_group_parent_id(): Returned $row_count rows");
1616 return false;
1619 $row = $rs->FetchRow();
1621 //Return the ID.
1622 return $row[0];
1627 * get_root_group_id ()
1629 * Grabs the id of the root group for the specified tree
1631 * @return int Root Group ID #
1633 * @param string Group Type, either 'ARO' or 'AXO'
1635 function get_root_group_id($group_type='ARO') {
1637 $this->debug_text('get_root_group_id(): Group Type: '. $group_type);
1639 switch (strtolower($group_type)) {
1640 case 'axo':
1641 $table = $this->_db_table_prefix .'axo_groups';
1642 break;
1643 case 'aro':
1644 $table = $this->_db_table_prefix .'aro_groups';
1645 break;
1646 default:
1647 $this->debug_text('get_root_group_id(): Invalid Group Type: '. $group_type);
1648 return FALSE;
1651 $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
1652 $rs = $this->db->Execute($query);
1654 if (!is_object($rs)) {
1655 $this->debug_db('get_root_group_id');
1656 return FALSE;
1659 $row_count = $rs->RecordCount();
1661 switch ($row_count) {
1662 case 1:
1663 $row = $rs->FetchRow();
1664 // Return the ID.
1665 return $row[0];
1666 case 0:
1667 $this->debug_text('get_root_group_id(): Returned 0 rows, you do not have a root group defined yet.');
1668 return FALSE;
1671 $this->debug_text('get_root_group_id(): Returned '. $row_count .' rows, can only return one. Your tree is very broken.');
1672 return FALSE;
1675 /*======================================================================*\
1676 Function: map_path_to_root()
1677 Purpose: Maps a unique path to root to a specific group. Each group can only have
1678 one path to root.
1679 \*======================================================================*/
1680 /** REMOVED **/
1681 /*======================================================================*\
1682 Function: put_path_to_root()
1683 Purpose: Writes the unique path to root to the database. There should really only be
1684 one path to root for each level "deep" the groups go. If the groups are branched
1685 10 levels deep, there should only be 10 unique path to roots. These of course
1686 overlap each other more and more the closer to the root/trunk they get.
1687 \*======================================================================*/
1688 /** REMOVED **/
1689 /*======================================================================*\
1690 Function: clean_path_to_root()
1691 Purpose: Cleans up any paths that are not being used.
1692 \*======================================================================*/
1693 /** REMOVED **/
1694 /*======================================================================*\
1695 Function: get_path_to_root()
1696 Purpose: Generates the path to root for a given group.
1697 \*======================================================================*/
1698 /** REMOVED **/
1701 * add_group()
1703 * Inserts a group, defaults to be on the "root" branch.
1705 * Since v3.3.x you can only create one group with Parent_ID=0
1706 * So, its a good idea to create a "Virtual Root" group with Parent_ID=0
1707 * Then assign other groups to that.
1709 * @return int New Group ID # if successful, FALSE if otherwise.
1711 * @param string Group Value
1712 * @param string Group Name
1713 * @param int Parent Group ID #
1714 * @param string Group Type, either 'ARO' or 'AXO'
1716 function add_group($value, $name, $parent_id=0, $group_type='ARO') {
1718 switch(strtolower(trim($group_type))) {
1719 case 'axo':
1720 $group_type = 'axo';
1721 $table = $this->_db_table_prefix .'axo_groups';
1722 break;
1723 default:
1724 $group_type = 'aro';
1725 $table = $this->_db_table_prefix .'aro_groups';
1726 break;
1729 $this->debug_text("add_group(): Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
1731 $name = trim($name);
1732 $value = trim($value);
1734 if ( $name == '' ) {
1735 $this->debug_text("add_group(): name ($name) OR parent id ($parent_id) is empty, this is required");
1736 return false;
1739 //This has to be outside the transaction, because the first time it is run, it will say the sequence
1740 //doesn't exist. Then try to create it, but the transaction will already by aborted by then.
1741 $insert_id = $this->db->GenID($this->_db_table_prefix.$group_type.'_groups_id_seq',10);
1742 if ( $value === '' ) {
1743 $value = $insert_id;
1746 $this->db->BeginTrans();
1748 // special case for root group
1749 if ($parent_id == 0) {
1750 // check a root group is not already defined
1751 $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
1752 $rs = $this->db->Execute($query);
1754 if (!is_object($rs)) {
1755 $this->debug_db('add_group');
1756 $this->db->RollBackTrans();
1757 return FALSE;
1760 if ($rs->RowCount() > 0) {
1761 $this->debug_text('add_group (): A root group already exists.');
1762 $this->db->RollBackTrans();
1763 return FALSE;
1766 $parent_lft = 0;
1767 $parent_rgt = 1;
1768 } else {
1769 if (empty($parent_id)) {
1770 $this->debug_text("add_group (): parent id ($parent_id) is empty, this is required");
1771 $this->db->RollbackTrans();
1772 return FALSE;
1775 // grab parent details from database
1776 $query = 'SELECT id, lft, rgt FROM '. $table .' WHERE id='. $parent_id;
1777 $row = $this->db->GetRow($query);
1779 if (!is_array($row)) {
1780 $this->debug_db('add_group');
1781 $this->db->RollBackTrans();
1782 return FALSE;
1785 if (empty($row)) {
1786 $this->debug_text('add_group (): Parent ID: '. $parent_id .' not found.');
1787 $this->db->RollBackTrans();
1788 return FALSE;
1791 $parent_lft = &$row[1];
1792 $parent_rgt = &$row[2];
1794 // make room for the new group
1795 $query = 'UPDATE '. $table .' SET rgt=rgt+2 WHERE rgt>='. $parent_rgt;
1796 $rs = $this->db->Execute($query);
1798 if (!is_object($rs)) {
1799 $this->debug_db('add_group');
1800 $this->db->RollBackTrans();
1801 return FALSE;
1804 $query = 'UPDATE '. $table .' SET lft=lft+2 WHERE lft>'. $parent_rgt;
1805 $rs = $this->db->Execute($query);
1807 if (!is_object($rs)) {
1808 $this->debug_db('add_group');
1809 $this->db->RollBackTrans();
1810 return FALSE;
1814 $query = 'INSERT INTO '. $table .' (id,parent_id,name,value,lft,rgt) VALUES ('. $insert_id .','. $parent_id .','. $this->db->quote($name) .','. $this->db->quote($value) .','. $parent_rgt .','. ($parent_rgt + 1) .')';
1815 $rs = $this->db->Execute($query);
1817 if (!is_object($rs)) {
1818 $this->debug_db('add_group');
1819 $this->db->RollBackTrans();
1820 return FALSE;
1823 $this->db->CommitTrans();
1825 $this->debug_text('add_group (): Added group as ID: '. $insert_id);
1826 return $insert_id;
1830 * get_group_objects()
1832 * Gets all objects assigned to a group.
1834 * If $option == 'RECURSE' it will get all objects in child groups as well.
1835 * defaults to omit child groups.
1837 * @return array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1840 * @param int Group ID #
1841 * @param string Group Type, either 'ARO' or 'AXO'
1842 * @param string Option, either 'RECURSE' or 'NO_RECURSE'
1844 function get_group_objects($group_id, $group_type='ARO', $option='NO_RECURSE') {
1846 switch(strtolower(trim($group_type))) {
1847 case 'axo':
1848 $group_type = 'axo';
1849 $object_table = $this->_db_table_prefix .'axo';
1850 $group_table = $this->_db_table_prefix .'axo_groups';
1851 $map_table = $this->_db_table_prefix .'groups_axo_map';
1852 break;
1853 default:
1854 $group_type = 'aro';
1855 $object_table = $this->_db_table_prefix .'aro';
1856 $group_table = $this->_db_table_prefix .'aro_groups';
1857 $map_table = $this->_db_table_prefix .'groups_aro_map';
1858 break;
1861 $this->debug_text("get_group_objects(): Group ID: $group_id");
1863 if (empty($group_id)) {
1864 $this->debug_text("get_group_objects(): Group ID: ($group_id) is empty, this is required");
1865 return false;
1868 $query = '
1869 SELECT o.section_value,o.value';
1871 if ($option == 'RECURSE') {
1872 $query .= '
1873 FROM '. $group_table .' g2
1874 JOIN '. $group_table .' g1 ON g1.lft>=g2.lft AND g1.rgt<=g2.rgt
1875 JOIN '. $map_table .' gm ON gm.group_id=g1.id
1876 JOIN '. $object_table .' o ON o.id=gm.'. $group_type .'_id
1877 WHERE g2.id='. $group_id;
1878 } else {
1879 $query .= '
1880 FROM '. $map_table .' gm
1881 JOIN '. $object_table .' o ON o.id=gm.'. $group_type .'_id
1882 WHERE gm.group_id='. $group_id;
1885 $rs = $this->db->Execute($query);
1887 if (!is_object($rs)) {
1888 $this->debug_db('get_group_objects');
1889 return false;
1892 $this->debug_text("get_group_objects(): Got group objects, formatting array.");
1894 $retarr = array();
1896 //format return array.
1897 while ($row = $rs->FetchRow()) {
1898 $section = &$row[0];
1899 $value = &$row[1];
1901 $retarr[$section][] = $value;
1904 return $retarr;
1908 * add_group_object()
1910 * Assigns an Object to a group
1912 * @return bool Returns TRUE if successful, FALSE otherwise.
1914 * @param int Group ID #
1915 * @param string Object Section Value
1916 * @param string Object Value
1917 * @param string Group Type, either 'ARO' or 'AXO'
1919 function add_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
1921 switch(strtolower(trim($group_type))) {
1922 case 'axo':
1923 $group_type = 'axo';
1924 $table = $this->_db_table_prefix .'groups_axo_map';
1925 $object_table = $this->_db_table_prefix .'axo';
1926 $group_table = $this->_db_table_prefix .'axo_groups';
1927 break;
1928 default:
1929 $group_type = 'aro';
1930 $table = $this->_db_table_prefix .'groups_aro_map';
1931 $object_table = $this->_db_table_prefix .'aro';
1932 $group_table = $this->_db_table_prefix .'aro_groups';
1933 break;
1936 $this->debug_text("add_group_object(): Group ID: $group_id Section Value: $object_section_value Value: $object_value Group Type: $group_type");
1938 $object_section_value = trim($object_section_value);
1939 $object_value = trim($object_value);
1941 if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
1942 $this->debug_text("add_group_object(): Group ID: ($group_id) OR Value ($object_value) OR Section value ($object_section_value) is empty, this is required");
1943 return false;
1946 // test to see if object & group exist and if object is already a member
1947 $query = '
1948 SELECT o.id AS id,g.id AS group_id,gm.group_id AS member
1949 FROM '. $object_table .' o
1950 LEFT JOIN '. $group_table .' g ON g.id='. $group_id .'
1951 LEFT JOIN '. $table .' gm ON (gm.'. $group_type .'_id=o.id AND gm.group_id=g.id)
1952 WHERE (o.section_value='. $this->db->quote($object_section_value) .' AND o.value='. $this->db->quote($object_value) .')';
1953 $rs = $this->db->Execute($query);
1955 if (!is_object($rs)) {
1956 $this->debug_db('add_group_object');
1957 return FALSE;
1960 if ($rs->RecordCount() != 1) {
1961 $this->debug_text('add_group_object(): Value ('. $object_value .') OR Section value ('. $object_section_value .') is invalid. Does this object exist?');
1962 return FALSE;
1965 $row = $rs->FetchRow();
1967 if ($row[1] != $group_id) {
1968 $this->debug_text('add_group_object(): Group ID ('. $group_id .') is invalid. Does this group exist?');
1969 return FALSE;
1972 //Group_ID == Member
1973 if ($row[1] == $row[2]) {
1974 $this->debug_text('add_group_object(): Object: ('. $object_section_value .' -> '. $object_value .') is already a member of Group: ('. $group_id .')');
1975 //Object is already assigned to group. Return true.
1976 return TRUE;
1979 $object_id = $row[0];
1981 $query = 'INSERT INTO '. $table .' (group_id,'. $group_type .'_id) VALUES ('. $group_id .','. $object_id .')';
1982 $rs = $this->db->Execute($query);
1984 if (!is_object($rs)) {
1985 $this->debug_db('add_group_object');
1986 return FALSE;
1989 $this->debug_text('add_group_object(): Added Object: '. $object_id .' to Group ID: '. $group_id);
1991 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1992 //Expire all cache.
1993 $this->Cache_Lite->clean('default');
1996 return TRUE;
2000 * del_group_object()
2002 * Removes an Object from a group.
2004 * @return bool Returns TRUE if successful, FALSE otherwise
2006 * @param int Group ID #
2007 * @param string Object Section Value
2008 * @param string Object Value
2009 * @param string Group Type, either 'ARO' or 'AXO'
2011 function del_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
2013 switch(strtolower(trim($group_type))) {
2014 case 'axo':
2015 $group_type = 'axo';
2016 $table = $this->_db_table_prefix .'groups_axo_map';
2017 break;
2018 default:
2019 $group_type = 'aro';
2020 $table = $this->_db_table_prefix .'groups_aro_map';
2021 break;
2024 $this->debug_text("del_group_object(): Group ID: $group_id Section value: $object_section_value Value: $object_value");
2026 $object_section_value = trim($object_section_value);
2027 $object_value = trim($object_value);
2029 if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
2030 $this->debug_text("del_group_object(): Group ID: ($group_id) OR Section value: $object_section_value OR Value ($object_value) is empty, this is required");
2031 return false;
2034 if (!$object_id = $this->get_object_id($object_section_value, $object_value, $group_type)) {
2035 $this->debug_text ("del_group_object (): Group ID ($group_id) OR Value ($object_value) OR Section value ($object_section_value) is invalid. Does this object exist?");
2036 return FALSE;
2039 $query = 'DELETE FROM '. $table .' WHERE group_id='. $group_id .' AND '. $group_type .'_id='. $object_id;
2040 $rs = $this->db->Execute($query);
2042 if (!is_object($rs)) {
2043 $this->debug_db('del_group_object');
2044 return false;
2047 $this->debug_text("del_group_object(): Deleted Value: $object_value to Group ID: $group_id assignment");
2049 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2050 //Expire all cache.
2051 $this->Cache_Lite->clean('default');
2054 return true;
2058 * edit_group()
2060 * Edits a group
2062 * @returns bool Returns TRUE if successful, FALSE otherwise
2064 * @param int Group ID #
2065 * @param string Group Value
2066 * @param string Group Name
2067 * @param int Parent ID #
2068 * @param string Group Type, either 'ARO' or 'AXO'
2070 function edit_group($group_id, $value=NULL, $name=NULL, $parent_id=NULL, $group_type='ARO') {
2071 $this->debug_text("edit_group(): ID: $group_id Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
2073 switch(strtolower(trim($group_type))) {
2074 case 'axo':
2075 $group_type = 'axo';
2076 $table = $this->_db_table_prefix .'axo_groups';
2077 break;
2078 default:
2079 $group_type = 'aro';
2080 $table = $this->_db_table_prefix .'aro_groups';
2081 break;
2084 if (empty($group_id) ) {
2085 $this->debug_text('edit_group(): Group ID ('. $group_id .') is empty, this is required');
2086 return FALSE;
2089 if ( !is_array($curr = $this->get_group_data($group_id, $group_type)) ) {
2090 $this->debug_text('edit_group(): Invalid Group ID: '. $group_id);
2091 return FALSE;
2094 $name = trim($name);
2096 // don't set name if it is unchanged
2097 if ($name == $curr[3]) {
2098 unset($name);
2101 // don't set parent_id if it is unchanged
2102 if ($parent_id == $curr[1]) {
2103 unset($parent_id);
2106 if (!empty($parent_id)) {
2107 if ($group_id == $parent_id) {
2108 $this->debug_text('edit_group(): Groups can\'t be a parent to themselves. Incest is bad. ;)');
2109 return FALSE;
2112 //Make sure we don't re-parent to our own children.
2113 //Grab all children of this group_id.
2114 $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
2115 if (is_array($children_ids)) {
2116 if (@in_array($parent_id, $children_ids) ) {
2117 $this->debug_text('edit_group(): Groups can\'t be re-parented to their own children, this would be incestuous!');
2118 return FALSE;
2121 unset($children_ids);
2123 // make sure parent exists
2124 if (!$this->get_group_data($parent_id, $group_type)) {
2125 $this->debug_text('edit_group(): Parent Group ('. $parent_id .') doesn\'t exist');
2126 return FALSE;
2130 $set = array();
2132 // update name if it is specified.
2133 if (!empty($name)) {
2134 $set[] = 'name='. $this->db->quote($name);
2137 // update parent_id if it is specified.
2138 if (!empty($parent_id)) {
2139 $set[] = 'parent_id='. $parent_id;
2142 // update value if it is specified.
2143 if (!empty($value)) {
2144 $set[] = 'value='. $this->db->quote($value);
2147 if (empty($set)) {
2148 $this->debug_text('edit_group(): Nothing to update.');
2149 return FALSE;
2152 $this->db->BeginTrans();
2154 $query = 'UPDATE '. $table .' SET '. implode(',', $set) .' WHERE id='. $group_id;
2155 $rs = $this->db->Execute($query);
2157 if (!is_object($rs)) {
2158 $this->debug_db('edit_group');
2159 $this->db->RollbackTrans();
2160 return FALSE;
2163 $this->debug_text('edit_group(): Modified group ID: '. $group_id);
2165 // rebuild group tree if parent_id has changed
2166 if (!empty($parent_id)) {
2167 if (!$this->_rebuild_tree($table, $this->get_root_group_id($group_type))) {
2168 $this->db->RollbackTrans();
2169 return FALSE;
2173 $this->db->CommitTrans();
2175 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2176 // Expire all cache.
2177 $this->Cache_Lite->clean('default');
2180 return TRUE;
2184 * rebuild_tree ()
2186 * rebuilds the group tree for the given type
2188 * @return bool Returns TRUE if successful, FALSE otherwise
2190 * @param string Group Type, either 'ARO' or 'AXO'
2191 * @param int Group ID #
2192 * @param int Left value of Group
2194 function rebuild_tree($group_type = 'ARO', $group_id = NULL, $left = 1) {
2195 $this->debug_text("rebuild_tree(): Group Type: $group_type Group ID: $group_id Left: $left");
2197 switch (strtolower(trim($group_type))) {
2198 case 'axo':
2199 $group_type = 'axo';
2200 $table = $this->_db_table_prefix .'axo_groups';
2201 break;
2202 default:
2203 $group_type = 'aro';
2204 $table = $this->_db_table_prefix .'aro_groups';
2205 break;
2208 if (!isset($group_id)) {
2209 if ($group_id = $this->get_root_group_id($group_type)) {
2210 $left = 1;
2211 $this->debug_text('rebuild_tree(): No Group ID Specified, using Root Group ID: '. $group_id);
2212 } else {
2213 $this->debug_text('rebuild_tree(): A Root group could not be found, are there any groups defined?');
2214 return FALSE;
2218 $this->db->BeginTrans();
2219 $rebuilt = $this->_rebuild_tree($table, $group_id, $left);
2221 if ($rebuilt === FALSE) {
2222 $this->debug_text('rebuild_tree(): Error rebuilding tree!');
2223 $this->db->RollBackTrans();
2224 return FALSE;
2227 $this->db->CommitTrans();
2228 $this->debug_text('rebuild_tree(): Tree rebuilt.');
2229 return TRUE;
2232 * _rebuild_tree ()
2234 * Utility recursive function called by rebuild_tree()
2236 * @return int Returns right value of this node + 1
2238 * @param string Table name of group type
2239 * @param int Group ID #
2240 * @param int Left value of Group
2242 function _rebuild_tree($table, $group_id, $left = 1) {
2243 $this->debug_text("_rebuild_tree(): Table: $table Group ID: $group_id Left: $left");
2245 // get all children of this node
2246 $query = 'SELECT id FROM '. $table .' WHERE parent_id='. $group_id;
2247 $rs = $this->db->Execute($query);
2249 if (!is_object($rs)) {
2250 $this->debug_db('_rebuild_tree');
2251 return FALSE;
2254 // the right value of this node is the left value + 1
2255 $right = $left + 1;
2257 while ($row = $rs->FetchRow()) {
2258 // recursive execution of this function for each
2259 // child of this node
2260 // $right is the current right value, which is
2261 // incremented by the rebuild_tree function
2262 $right = $this->_rebuild_tree($table, $row[0], $right);
2264 if ($right === FALSE) {
2265 return FALSE;
2269 // we've got the left value, and now that we've processed
2270 // the children of this node we also know the right value
2271 $query = 'UPDATE '. $table .' SET lft='. $left .', rgt='. $right .' WHERE id='. $group_id;
2272 $rs = $this->db->Execute($query);
2274 if (!is_object($rs)) {
2275 $this->debug_db('_rebuild_tree');
2276 return FALSE;
2279 // return the right value of this node + 1
2280 return $right + 1;
2284 * del_group()
2286 * deletes a given group
2288 * @return bool Returns TRUE if successful, FALSE otherwise.
2290 * @param int Group ID #
2291 * @param bool If TRUE, child groups of this group will be reparented to the current group's parent.
2292 * @param string Group Type, either 'ARO' or 'AXO'
2294 function del_group($group_id, $reparent_children=TRUE, $group_type='ARO') {
2296 switch(strtolower(trim($group_type))) {
2297 case 'axo':
2298 $group_type = 'axo';
2299 $table = $this->_db_table_prefix .'axo_groups';
2300 $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
2301 $groups_object_map_table = $this->_db_table_prefix .'groups_axo_map';
2302 break;
2303 default:
2304 $group_type = 'aro';
2305 $table = $this->_db_table_prefix .'aro_groups';
2306 $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
2307 $groups_object_map_table = $this->_db_table_prefix .'groups_aro_map';
2308 break;
2311 $this->debug_text("del_group(): ID: $group_id Reparent Children: $reparent_children Group Type: $group_type");
2313 if (empty($group_id) ) {
2314 $this->debug_text("del_group(): Group ID ($group_id) is empty, this is required");
2315 return false;
2318 // Get details of this group
2319 $query = 'SELECT id, parent_id, name, lft, rgt FROM '. $table .' WHERE id='. $group_id;
2320 $group_details = $this->db->GetRow($query);
2322 if (!is_array($group_details)) {
2323 $this->debug_db('del_group');
2324 return false;
2327 $parent_id = $group_details[1];
2329 $left = $group_details[3];
2330 $right = $group_details[4];
2332 $this->db->BeginTrans();
2334 // grab list of all children
2335 $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
2337 // prevent deletion of root group & reparent of children if it has more than one immediate child
2338 if ($parent_id == 0) {
2339 $query = 'SELECT count(*) FROM '. $table .' WHERE parent_id='. $group_id;
2340 $child_count = $this->db->GetOne($query);
2342 if (($child_count > 1) AND $reparent_children) {
2343 $this->debug_text ('del_group (): You cannot delete the root group and reparent children, this would create multiple root groups.');
2344 $this->db->RollbackTrans();
2345 return FALSE;
2349 $success = FALSE;
2352 * Handle children here.
2354 switch (TRUE) {
2355 // there are no child groups, just delete group
2356 case !is_array($children_ids):
2357 case count($children_ids) == 0:
2358 // remove acl maps
2359 $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $group_id;
2360 $rs = $this->db->Execute($query);
2362 if (!is_object($rs)) {
2363 break;
2366 // remove group object maps
2367 $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $group_id;
2368 $rs = $this->db->Execute($query);
2370 if (!is_object($rs)) {
2371 break;
2374 // remove group
2375 $query = 'DELETE FROM '. $table .' WHERE id='. $group_id;
2376 $rs = $this->db->Execute($query);
2378 if (!is_object($rs)) {
2379 break;
2382 // move all groups right of deleted group left by width of deleted group
2383 $query = 'UPDATE '. $table .' SET lft=lft-'. ($right-$left+1) .' WHERE lft>'. $right;
2384 $rs = $this->db->Execute($query);
2386 if (!is_object($rs)) {
2387 break;
2390 $query = 'UPDATE '. $table .' SET rgt=rgt-'. ($right-$left+1) .' WHERE rgt>'. $right;
2391 $rs = $this->db->Execute($query);
2393 if (!is_object($rs)) {
2394 break;
2397 $success = TRUE;
2398 break;
2399 case $reparent_children == TRUE:
2400 // remove acl maps
2401 $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $group_id;
2402 $rs = $this->db->Execute($query);
2404 if (!is_object($rs)) {
2405 break;
2408 // remove group object maps
2409 $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $group_id;
2410 $rs = $this->db->Execute($query);
2412 if (!is_object($rs)) {
2413 break;
2416 // remove group
2417 $query = 'DELETE FROM '. $table .' WHERE id='. $group_id;
2418 $rs = $this->db->Execute($query);
2420 if (!is_object($rs)) {
2421 break;
2424 // set parent of immediate children to parent group
2425 $query = 'UPDATE '. $table .' SET parent_id='. $parent_id .' WHERE parent_id='. $group_id;
2426 $rs = $this->db->Execute($query);
2428 if (!is_object($rs)) {
2429 break;
2432 // move all children left by 1
2433 $query = 'UPDATE '. $table .' SET lft=lft-1, rgt=rgt-1 WHERE lft>'. $left .' AND rgt<'. $right;
2434 $rs = $this->db->Execute($query);
2436 if (!is_object($rs)) {
2437 break;
2440 // move all groups right of deleted group left by 2
2441 $query = 'UPDATE '. $table .' SET lft=lft-2 WHERE lft>'. $right;
2442 $rs = $this->db->Execute($query);
2444 if (!is_object($rs)) {
2445 break;
2448 $query = 'UPDATE '. $table .' SET rgt=rgt-2 WHERE rgt>'. $right;
2449 $rs = $this->db->Execute($query);
2451 if (!is_object($rs)) {
2452 break;
2455 $success = TRUE;
2456 break;
2457 default:
2458 // make list of group and all children
2459 $group_ids = $children_ids;
2460 $group_ids[] = $group_id;
2462 // remove acl maps
2463 $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
2464 $rs = $this->db->Execute($query);
2466 if (!is_object($rs)) {
2467 break;
2470 // remove group object maps
2471 $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
2472 $rs = $this->db->Execute($query);
2474 if (!is_object($rs)) {
2475 break;
2478 // remove groups
2479 $query = 'DELETE FROM '. $table .' WHERE id IN ('. implode (',', $group_ids) .')';
2480 $rs = $this->db->Execute($query);
2482 if (!is_object($rs)) {
2483 break;
2486 // move all groups right of deleted group left by width of deleted group
2487 $query = 'UPDATE '. $table .' SET lft=lft-'. ($right - $left + 1) .' WHERE lft>'. $right;
2488 $rs = $this->db->Execute($query);
2490 if (!is_object($rs)) {
2491 break;
2494 $query = 'UPDATE '. $table .' SET rgt=rgt-'. ($right - $left + 1) .' WHERE rgt>'. $right;
2495 $rs = $this->db->Execute($query);
2497 if (!is_object($rs)) {
2498 break;
2501 $success = TRUE;
2504 // if the delete failed, rollback the trans and return false
2505 if (!$success) {
2507 $this->debug_db('del_group');
2508 $this->db->RollBackTrans();
2509 return false;
2512 $this->debug_text("del_group(): deleted group ID: $group_id");
2513 $this->db->CommitTrans();
2515 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2516 //Expire all cache.
2517 $this->Cache_Lite->clean('default');
2520 return true;
2527 * Objects (ACO/ARO/AXO)
2532 * get_object()
2534 * Grabs all Objects's in the database, or specific to a section_value
2536 * @return ADORecordSet Returns recordset directly, with object ID only selected:
2538 * @param string Filter to this section value
2539 * @param int Returns hidden objects if 1, leaves them out otherwise.
2540 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
2542 function get_object($section_value = null, $return_hidden=1, $object_type=NULL) {
2544 switch(strtolower(trim($object_type))) {
2545 case 'aco':
2546 $object_type = 'aco';
2547 $table = $this->_db_table_prefix .'aco';
2548 break;
2549 case 'aro':
2550 $object_type = 'aro';
2551 $table = $this->_db_table_prefix .'aro';
2552 break;
2553 case 'axo':
2554 $object_type = 'axo';
2555 $table = $this->_db_table_prefix .'axo';
2556 break;
2557 case 'acl':
2558 $object_type = 'acl';
2559 $table = $this->_db_table_prefix .'acl';
2560 break;
2561 default:
2562 $this->debug_text('get_object(): Invalid Object Type: '. $object_type);
2563 return FALSE;
2566 $this->debug_text("get_object(): Section Value: $section_value Object Type: $object_type");
2568 $query = 'SELECT id FROM '. $table;
2570 $where = array();
2572 if (!empty($section_value)) {
2573 $where[] = 'section_value='. $this->db->quote($section_value);
2576 if ($return_hidden==0 AND $object_type != 'acl') {
2577 $where[] = 'hidden=0';
2580 if (!empty($where)) {
2581 $query .= ' WHERE '. implode(' AND ', $where);
2584 $rs = $this->db->GetCol($query);
2586 if (!is_array($rs)) {
2587 $this->debug_db('get_object');
2588 return false;
2591 // Return Object IDs
2592 return $rs;
2595 * get_ungrouped_objects()
2597 * Grabs ID's of all Objects (ARO's and AXO's only) in the database not assigned to a Group.
2599 * This function is useful for applications that synchronize user databases with an outside source.
2600 * If syncrhonization doesn't automatically place users in an appropriate group, this function can
2601 * quickly identify them so that they can be assigned to the correct group.
2603 * @return array Returns an array of object ID's
2605 * @param int Returns hidden objects if 1, does not if 0.
2606 * @param string Object Type, either 'ARO' or 'AXO' (groupable types)
2609 function get_ungrouped_objects($return_hidden=1, $object_type=NULL) {
2611 switch(strtolower(trim($object_type))) {
2612 case 'aro':
2613 $object_type = 'aro';
2614 $table = $this->_db_table_prefix .'aro';
2615 break;
2616 case 'axo':
2617 $object_type = 'axo';
2618 $table = $this->_db_table_prefix .'axo';
2619 break;
2620 default:
2621 $this->debug_text('get_ungrouped_objects(): Invalid Object Type: '. $object_type);
2622 return FALSE;
2625 $this->debug_text("get_ungrouped_objects(): Object Type: $object_type");
2627 $query = 'SELECT id FROM '. $table. ' a
2628 LEFT JOIN ' . $this->_db_table_prefix. 'groups_'.$object_type.'_map b ON a.id = b.'. $object_type .'_id';
2630 $where = array();
2631 $where[] = 'b.group_id IS NULL';
2633 if ($return_hidden==0) {
2634 $where[] = 'a.hidden=0';
2637 if (!empty($where)) {
2638 $query .= ' WHERE '. implode(' AND ', $where);
2641 $rs = $this->db->Execute($query);
2643 if (!is_object($rs)) {
2644 $this->debug_db('get_ungrouped_objects');
2645 return false;
2648 while(!$rs->EOF) {
2649 $retarr[] = $rs->fields[0];
2650 $rs->MoveNext();
2653 // Return Array of object IDS
2654 return $retarr;
2659 * get_objects ()
2661 * Grabs all Objects in the database, or specific to a section_value
2663 * @return array Returns objects in format suitable for add_acl and is_conflicting_acl
2664 * - i.e. Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
2666 * @param string Filter for section value
2667 * @param int Returns hidden objects if 1, does not if 0
2668 * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2670 function get_objects($section_value = NULL, $return_hidden = 1, $object_type = NULL) {
2671 switch (strtolower(trim($object_type))) {
2672 case 'aco':
2673 $object_type = 'aco';
2674 $table = $this->_db_table_prefix .'aco';
2675 break;
2676 case 'aro':
2677 $object_type = 'aro';
2678 $table = $this->_db_table_prefix .'aro';
2679 break;
2680 case 'axo':
2681 $object_type = 'axo';
2682 $table = $this->_db_table_prefix .'axo';
2683 break;
2684 default:
2685 $this->debug_text('get_objects(): Invalid Object Type: '. $object_type);
2686 return FALSE;
2689 $this->debug_text("get_objects(): Section Value: $section_value Object Type: $object_type");
2691 $query = 'SELECT section_value,value FROM '. $table;
2693 $where = array();
2695 if (!empty($section_value)) {
2696 $where[] = 'section_value='. $this->db->quote($section_value);
2699 if ($return_hidden==0) {
2700 $where[] = 'hidden=0';
2703 if (!empty($where)) {
2704 $query .= ' WHERE '. implode(' AND ', $where);
2707 $rs = $this->db->Execute($query);
2709 if (!is_object($rs)) {
2710 $this->debug_db('get_objects');
2711 return FALSE;
2714 $retarr = array();
2716 while ($row = $rs->FetchRow()) {
2717 $retarr[$row[0]][] = $row[1];
2720 // Return objects
2721 return $retarr;
2725 * get_object_data()
2727 * Gets all data pertaining to a specific Object.
2729 * @return array Returns 2-Dimensional array of rows with columns = ( section_value, value, order_value, name, hidden )
2731 * @param int Object ID #
2732 * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2734 function get_object_data($object_id, $object_type=NULL) {
2736 switch(strtolower(trim($object_type))) {
2737 case 'aco':
2738 $object_type = 'aco';
2739 $table = $this->_db_table_prefix .'aco';
2740 break;
2741 case 'aro':
2742 $object_type = 'aro';
2743 $table = $this->_db_table_prefix .'aro';
2744 break;
2745 case 'axo':
2746 $object_type = 'axo';
2747 $table = $this->_db_table_prefix .'axo';
2748 break;
2749 default:
2750 $this->debug_text('get_object_data(): Invalid Object Type: '. $object_type);
2751 return FALSE;
2754 $this->debug_text("get_object_data(): Object ID: $object_id Object Type: $object_type");
2756 if (empty($object_id) ) {
2757 $this->debug_text("get_object_data(): Object ID ($object_id) is empty, this is required");
2758 return false;
2761 if (empty($object_type) ) {
2762 $this->debug_text("get_object_data(): Object Type ($object_type) is empty, this is required");
2763 return false;
2766 $query = 'SELECT section_value,value,order_value,name,hidden FROM '. $table .' WHERE id='. $object_id;
2767 $rs = $this->db->Execute($query);
2769 if (!is_object($rs)) {
2770 $this->debug_db('get_object_data');
2771 return false;
2774 if ($rs->RecordCount() < 1) {
2775 $this->debug_text('get_object_data(): Returned '. $row_count .' rows');
2776 return FALSE;
2779 // Return all objects
2780 return $rs->GetRows();
2784 * get_object_id()
2786 * Gets the object_id given the section_value AND value of the object.
2788 * @return int Object ID #
2790 * @param string Object Section Value
2791 * @param string Object Value
2792 * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2794 function get_object_id($section_value, $value, $object_type=NULL) {
2796 switch(strtolower(trim($object_type))) {
2797 case 'aco':
2798 $object_type = 'aco';
2799 $table = $this->_db_table_prefix .'aco';
2800 break;
2801 case 'aro':
2802 $object_type = 'aro';
2803 $table = $this->_db_table_prefix .'aro';
2804 break;
2805 case 'axo':
2806 $object_type = 'axo';
2807 $table = $this->_db_table_prefix .'axo';
2808 break;
2809 default:
2810 $this->debug_text('get_object_id(): Invalid Object Type: '. $object_type);
2811 return FALSE;
2814 $this->debug_text("get_object_id(): Section Value: $section_value Value: $value Object Type: $object_type");
2816 $section_value = trim($section_value);
2817 $value = trim($value);
2819 if (empty($section_value) AND empty($value) ) {
2820 $this->debug_text("get_object_id(): Section Value ($value) AND value ($value) is empty, this is required");
2821 return false;
2824 if (empty($object_type) ) {
2825 $this->debug_text("get_object_id(): Object Type ($object_type) is empty, this is required");
2826 return false;
2829 $query = 'SELECT id FROM '. $table .' WHERE section_value='. $this->db->quote($section_value) .' AND value='. $this->db->quote($value);
2830 $rs = $this->db->Execute($query);
2832 if (!is_object($rs)) {
2833 $this->debug_db('get_object_id');
2834 return false;
2837 $row_count = $rs->RecordCount();
2839 if ($row_count > 1) {
2840 $this->debug_text("get_object_id(): Returned $row_count rows, can only return one. This should never happen, the database may be missing a unique key.");
2841 return false;
2844 if ($row_count == 0) {
2845 $this->debug_text("get_object_id(): Returned $row_count rows");
2846 return false;
2849 $row = $rs->FetchRow();
2851 //Return the ID.
2852 return $row[0];
2856 * get_object_section_value()
2858 * Gets the object_section_value given object id
2860 * @return string Object Section Value
2862 * @param int Object ID #
2863 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
2865 function get_object_section_value($object_id, $object_type=NULL) {
2867 switch(strtolower(trim($object_type))) {
2868 case 'aco':
2869 $object_type = 'aco';
2870 $table = $this->_db_table_prefix .'aco';
2871 break;
2872 case 'aro':
2873 $object_type = 'aro';
2874 $table = $this->_db_table_prefix .'aro';
2875 break;
2876 case 'axo':
2877 $object_type = 'axo';
2878 $table = $this->_db_table_prefix .'axo';
2879 break;
2880 default:
2881 $this->debug_text('get_object_section_value(): Invalid Object Type: '. $object_type);
2882 return FALSE;
2885 $this->debug_text("get_object_section_value(): Object ID: $object_id Object Type: $object_type");
2887 if (empty($object_id) ) {
2888 $this->debug_text("get_object_section_value(): Object ID ($object_id) is empty, this is required");
2889 return false;
2892 if (empty($object_type) ) {
2893 $this->debug_text("get_object_section_value(): Object Type ($object_type) is empty, this is required");
2894 return false;
2897 $query = 'SELECT section_value FROM '. $table .' WHERE id='. $object_id;
2898 $rs = $this->db->Execute($query);
2900 if (!is_object($rs)) {
2901 $this->debug_db('get_object_section_value');
2902 return false;
2905 $row_count = $rs->RecordCount();
2907 if ($row_count > 1) {
2908 $this->debug_text("get_object_section_value(): Returned $row_count rows, can only return one.");
2909 return false;
2912 if ($row_count == 0) {
2913 $this->debug_text("get_object_section_value(): Returned $row_count rows");
2914 return false;
2917 $row = $rs->FetchRow();
2919 //Return the ID.
2920 return $row[0];
2924 * get_object_groups()
2926 * Gets all groups an object is a member of.
2928 * If $option == 'RECURSE' it will get all ancestor groups.
2929 * defaults to only get direct parents.
2931 * @return array Array of Group ID #'s, or FALSE if Failed
2933 * @param int Object ID #
2934 * @param string Object Type, either 'ARO' or 'AXO'
2935 * @param string Option, either 'RECURSE', or 'NO_RECURSE'
2937 function get_object_groups($object_id, $object_type = 'ARO', $option = 'NO_RECURSE') {
2938 $this->debug_text('get_object_groups(): Object ID: '. $object_id .' Object Type: '. $object_type .' Option: '. $option);
2940 switch(strtolower(trim($object_type))) {
2941 case 'axo':
2942 $object_type = 'axo';
2943 $group_table = $this->_db_table_prefix .'axo_groups';
2944 $map_table = $this->_db_table_prefix .'groups_axo_map';
2945 break;
2946 case 'aro':
2947 $object_type = 'aro';
2948 $group_table = $this->_db_table_prefix .'aro_groups';
2949 $map_table = $this->_db_table_prefix .'groups_aro_map';
2950 break;
2951 default:
2952 $this->debug_text('get_object_groups(): Invalid Object Type: '. $object_type);
2953 return FALSE;
2956 if (empty($object_id)) {
2957 $this->debug_text('get_object_groups(): Object ID: ('. $object_id .') is empty, this is required');
2958 return FALSE;
2961 if (strtoupper($option) == 'RECURSE') {
2962 $query = '
2963 SELECT DISTINCT g.id AS group_id
2964 FROM '. $map_table .' gm
2965 LEFT JOIN '. $group_table .' g1 ON g1.id=gm.group_id
2966 LEFT JOIN '. $group_table .' g ON g.lft<=g1.lft AND g.rgt>=g1.rgt';
2967 } else {
2968 $query = '
2969 SELECT gm.group_id
2970 FROM '. $map_table .' gm';
2973 $query .= '
2974 WHERE gm.'. $object_type .'_id='. $object_id;
2975 $rs = $this->db->Execute($query);
2977 if (!is_object($rs)) {
2978 $this->debug_db('get_object_groups');
2979 return FALSE;
2982 $retarr = array();
2984 while ($row = $rs->FetchRow()) {
2985 $retarr[] = $row[0];
2988 return $retarr;
2992 * add_object()
2994 * Inserts a new object
2996 * @return int Returns the ID # of the new object if successful, FALSE otherwise
2998 * @param string Object Section Value
2999 * @param string Object Name
3000 * @param string Object Value
3001 * @param int Display Order
3002 * @param int Hidden Flag, either 1 to hide, or 0 to show.
3003 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3005 function add_object($section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3007 switch(strtolower(trim($object_type))) {
3008 case 'aco':
3009 $object_type = 'aco';
3010 $table = $this->_db_table_prefix .'aco';
3011 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3012 break;
3013 case 'aro':
3014 $object_type = 'aro';
3015 $table = $this->_db_table_prefix .'aro';
3016 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3017 break;
3018 case 'axo':
3019 $object_type = 'axo';
3020 $table = $this->_db_table_prefix .'axo';
3021 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3022 break;
3023 default:
3024 $this->debug_text('add_object(): Invalid Object Type: '. $object_type);
3025 return FALSE;
3028 $this->debug_text("add_object(): Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
3030 $section_value = trim($section_value);
3031 $name = trim($name);
3032 $value = trim($value);
3033 $order = trim($order);
3034 $hidden = intval($hidden);
3036 if ($order == NULL OR $order == '') {
3037 $order = 0;
3040 if (empty($name) OR empty($section_value) ) {
3041 $this->debug_text("add_object(): name ($name) OR section value ($section_value) is empty, this is required");
3042 return false;
3045 if (strlen($name) >= 255 OR strlen($value) >= 230 ) {
3046 $this->debug_text("add_object(): name ($name) OR value ($value) is too long.");
3047 return false;
3050 if (empty($object_type) ) {
3051 $this->debug_text("add_object(): Object Type ($object_type) is empty, this is required");
3052 return false;
3055 // Test to see if the section is invalid or object already exists.
3056 $query = '
3057 SELECT CASE WHEN o.id IS NULL THEN 0 ELSE 1 END AS object_exists
3058 FROM '. $object_sections_table .' s
3059 LEFT JOIN '. $table .' o ON (s.value=o.section_value AND o.value='. $this->db->quote($value) .')
3060 WHERE s.value='. $this->db->quote($section_value);
3061 $rs = $this->db->Execute($query);
3063 if (!is_object($rs)) {
3064 $this->debug_db('add_object');
3065 return FALSE;
3068 if ($rs->RecordCount() != 1) {
3069 // Section is invalid
3070 $this->debug_text("add_object(): Section Value: $section_value Object Type ($object_type) does not exist, this is required");
3071 return false;
3074 $row = $rs->FetchRow();
3076 if ($row[0] == 1) {
3077 //Object is already created.
3078 return true;
3081 $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_seq',10);
3082 $query = 'INSERT INTO '. $table .' (id,section_value,value,order_value,name,hidden) VALUES('. $insert_id .','. $this->db->quote($section_value) .','. $this->db->quote($value) .','. $order .','. $this->db->quote($name) .','. $hidden .')';
3083 $rs = $this->db->Execute($query);
3085 if (!is_object($rs)) {
3086 $this->debug_db('add_object');
3087 return false;
3090 $this->debug_text("add_object(): Added object as ID: $insert_id");
3091 return $insert_id;
3095 * edit_object()
3097 * Edits a given Object
3099 * @return bool Returns TRUE if successful, FALSE otherwise
3101 * @param int Object ID #
3102 * @param string Object Section Value
3103 * @param string Object Name
3104 * @param string Object Value
3105 * @param int Display Order
3106 * @param int Hidden Flag, either 1 to hide, or 0 to show
3107 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3109 function edit_object($object_id, $section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3111 switch(strtolower(trim($object_type))) {
3112 case 'aco':
3113 $object_type = 'aco';
3114 $table = $this->_db_table_prefix .'aco';
3115 $object_map_table = $this->_db_table_prefix .'aco_map';
3116 break;
3117 case 'aro':
3118 $object_type = 'aro';
3119 $table = $this->_db_table_prefix .'aro';
3120 $object_map_table = $this->_db_table_prefix .'aro_map';
3121 break;
3122 case 'axo':
3123 $object_type = 'axo';
3124 $table = $this->_db_table_prefix .'axo';
3125 $object_map_table = $this->_db_table_prefix .'axo_map';
3126 break;
3129 $this->debug_text("edit_object(): ID: $object_id Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
3131 $section_value = trim($section_value);
3132 $name = trim($name);
3133 $value = trim($value);
3134 $order = trim($order);
3135 $hidden = intval($hidden);
3137 if (empty($object_id) OR empty($section_value) ) {
3138 $this->debug_text("edit_object(): Object ID ($object_id) OR Section Value ($section_value) is empty, this is required");
3139 return false;
3142 if (empty($name) ) {
3143 $this->debug_text("edit_object(): name ($name) is empty, this is required");
3144 return false;
3147 if (empty($object_type) ) {
3148 $this->debug_text("edit_object(): Object Type ($object_type) is empty, this is required");
3149 return false;
3152 $this->db->BeginTrans();
3154 //Get old value incase it changed, before we do the update.
3155 $query = 'SELECT value, section_value FROM '. $table .' WHERE id='. $object_id;
3156 $old = $this->db->GetRow($query);
3158 $query = '
3159 UPDATE '. $table .'
3160 SET section_value='. $this->db->quote($section_value) .',
3161 value='. $this->db->quote($value) .',
3162 order_value='. $this->db->quote($order) .',
3163 name='. $this->db->quote($name) .',
3164 hidden='. $hidden .'
3165 WHERE id='. $object_id;
3166 $rs = $this->db->Execute($query);
3168 if (!is_object($rs)) {
3169 $this->debug_db('edit_object');
3170 $this->db->RollbackTrans();
3171 return false;
3174 $this->debug_text('edit_object(): Modified '. strtoupper($object_type) .' ID: '. $object_id);
3176 if ($old[0] != $value OR $old[1] != $section_value) {
3177 $this->debug_text("edit_object(): Value OR Section Value Changed, update other tables.");
3179 $query = '
3180 UPDATE '. $object_map_table .'
3181 SET value='. $this->db->quote($value) .',
3182 section_value='. $this->db->quote($section_value) .'
3183 WHERE section_value='. $this->db->quote($old[1]) .'
3184 AND value='. $this->db->quote($old[0]);
3185 $rs = $this->db->Execute($query);
3187 if (!is_object($rs)) {
3188 $this->debug_db('edit_object');
3189 $this->db->RollbackTrans();
3190 return FALSE;
3193 $this->debug_text ('edit_object(): Modified Map Value: '. $value .' Section Value: '. $section_value);
3196 $this->db->CommitTrans();
3198 return TRUE;
3202 * del_object()
3204 * Deletes a given Object and, if instructed to do so, erase all referencing objects
3206 * ERASE feature by: Martino Piccinato
3208 * @return bool Returns TRUE if successful, FALSE otherwise.
3210 * @param int Object ID #
3211 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3212 * @param bool Erases all referencing objects if TRUE, leaves them alone otherwise.
3214 function del_object($object_id, $object_type=NULL, $erase=FALSE) {
3216 switch(strtolower(trim($object_type))) {
3217 case 'aco':
3218 $object_type = 'aco';
3219 $table = $this->_db_table_prefix .'aco';
3220 $object_map_table = $this->_db_table_prefix .'aco_map';
3221 break;
3222 case 'aro':
3223 $object_type = 'aro';
3224 $table = $this->_db_table_prefix .'aro';
3225 $object_map_table = $this->_db_table_prefix .'aro_map';
3226 $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
3227 $object_group_table = $this->_db_table_prefix .'groups_aro_map';
3228 break;
3229 case 'axo':
3230 $object_type = 'axo';
3231 $table = $this->_db_table_prefix .'axo';
3232 $object_map_table = $this->_db_table_prefix .'axo_map';
3233 $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
3234 $object_group_table = $this->_db_table_prefix .'groups_axo_map';
3235 break;
3236 default:
3237 $this->debug_text('del_object(): Invalid Object Type: '. $object_type);
3238 return FALSE;
3241 $this->debug_text("del_object(): ID: $object_id Object Type: $object_type, Erase all referencing objects: $erase");
3243 if (empty($object_id) ) {
3244 $this->debug_text("del_object(): Object ID ($object_id) is empty, this is required");
3245 return false;
3248 if (empty($object_type) ) {
3249 $this->debug_text("del_object(): Object Type ($object_type) is empty, this is required");
3250 return false;
3253 $this->db->BeginTrans();
3255 // Get Object section_value/value (needed to look for referencing objects)
3256 $query = 'SELECT section_value,value FROM '. $table .' WHERE id='. $object_id;
3257 $object = $this->db->GetRow($query);
3259 if (empty($object)) {
3260 $this->debug_text('del_object(): The specified object ('. strtoupper($object_type) .' ID: '. $object_id .') could not be found.');
3261 $this->db->RollbackTrans();
3262 return FALSE;
3265 $section_value = $object[0];
3266 $value = $object[1];
3268 // Get ids of acl referencing the Object (if any)
3269 $query = "SELECT acl_id FROM $object_map_table WHERE value='$value' AND section_value='$section_value'";
3270 $acl_ids = $this->db->GetCol($query);
3272 if ($erase) {
3273 // We were asked to erase all acl referencing it
3275 $this->debug_text("del_object(): Erase was set to TRUE, delete all referencing objects");
3277 if ($object_type == "aro" OR $object_type == "axo") {
3278 // The object can be referenced in groups_X_map tables
3279 // in the future this branching may become useless because
3280 // ACO might me "groupable" too
3282 // Get rid of groups_map referencing the Object
3283 $query = 'DELETE FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id;
3284 $rs = $this->db->Execute($query);
3286 if (!is_object($rs)) {
3287 $this->debug_db('edit_object');
3288 $this->db->RollBackTrans();
3289 return false;
3293 if (!empty($acl_ids)) {
3294 //There are acls actually referencing the object
3296 if ($object_type == 'aco') {
3297 // I know it's extremely dangerous but
3298 // if asked to really erase an ACO
3299 // we should delete all acl referencing it
3300 // (and relative maps)
3302 // Do this below this branching
3303 // where it uses $orphan_acl_ids as
3304 // the array of the "orphaned" acl
3305 // in this case all referenced acl are
3306 // orhpaned acl
3308 $orphan_acl_ids = $acl_ids;
3309 } else {
3310 // The object is not an ACO and might be referenced
3311 // in still valid acls regarding also other object.
3312 // In these cases the acl MUST NOT be deleted
3314 // Get rid of $object_id map referencing erased objects
3315 $query = "DELETE FROM $object_map_table WHERE section_value='$section_value' AND value='$value'";
3316 $this->db->Execute($query);
3318 if (!is_object($rs)) {
3319 $this->debug_db('edit_object');
3320 $this->db->RollBackTrans();
3321 return false;
3324 // Find the "orphaned" acl. I mean acl referencing the erased Object (map)
3325 // not referenced anymore by other objects
3327 $sql_acl_ids = implode(",", $acl_ids);
3329 $query = '
3330 SELECT a.id
3331 FROM '. $this->_db_table_prefix .'acl a
3332 LEFT JOIN '. $object_map_table .' b ON a.id=b.acl_id
3333 LEFT JOIN '. $groups_map_table .' c ON a.id=c.acl_id
3334 WHERE b.value IS NULL
3335 AND b.section_value IS NULL
3336 AND c.group_id IS NULL
3337 AND a.id in ('. $sql_acl_ids .')';
3338 $orphan_acl_ids = $this->db->GetCol($query);
3340 } // End of else section of "if ($object_type == "aco")"
3342 if ($orphan_acl_ids) {
3343 // If there are orphaned acls get rid of them
3345 foreach ($orphan_acl_ids as $acl) {
3346 $this->del_acl($acl);
3350 } // End of if ($acl_ids)
3352 // Finally delete the Object itself
3353 $query = "DELETE FROM $table WHERE id='$object_id'";
3354 $rs = $this->db->Execute($query);
3356 if (!is_object($rs)) {
3357 $this->debug_db('edit_object');
3358 $this->db->RollBackTrans();
3359 return false;
3362 $this->db->CommitTrans();
3363 return true;
3365 } // End of "if ($erase)"
3367 $groups_ids = FALSE;
3369 if ($object_type == 'axo' OR $object_type == 'aro') {
3370 // If the object is "groupable" (may become unnecessary,
3371 // see above
3373 // Get id of groups where the object is assigned:
3374 // you must explicitly remove the object from its groups before
3375 // deleting it (don't know if this is really needed, anyway it's safer ;-)
3377 $query = 'SELECT group_id FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id;
3378 $groups_ids = $this->db->GetCol($query);
3381 if ( ( isset($acl_ids) AND !empty($acl_ids) ) OR ( isset($groups_ids) AND !empty($groups_ids) ) ) {
3382 // The Object is referenced somewhere (group or acl), can't delete it
3384 $this->debug_text("del_object(): Can't delete the object as it is being referenced by GROUPs (".@implode($groups_ids).") or ACLs (".@implode($acl_ids,",").")");
3385 $this->db->RollBackTrans();
3386 return false;
3387 } else {
3388 // The Object is NOT referenced anywhere, delete it
3390 $query = "DELETE FROM $table WHERE id='$object_id'";
3391 $rs = $this->db->Execute($query);
3393 if ( !is_object($rs) ) {
3394 $this->debug_db('edit_object');
3395 $this->db->RollBackTrans();
3396 return false;
3399 $this->db->CommitTrans();
3400 return true;
3403 $this->db->RollbackTrans();
3404 return false;
3409 * Object Sections
3414 * get_object_section_section_id()
3416 * Gets the object_section_id given the name AND/OR value of the section.
3418 * Will only return one section id, so if there are duplicate names it will return false.
3420 * @return int Object Section ID if the object section is found AND is unique, or FALSE otherwise.
3422 * @param string Object Name
3423 * @param string Object Value
3424 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3427 function get_object_section_section_id($name = NULL, $value = NULL, $object_type = NULL) {
3428 $this->debug_text("get_object_section_section_id(): Value: $value Name: $name Object Type: $object_type");
3430 switch(strtolower(trim($object_type))) {
3431 case 'aco':
3432 case 'aro':
3433 case 'axo':
3434 case 'acl':
3435 $object_type = strtolower(trim($object_type));
3436 $table = $this->_db_table_prefix . $object_type;
3437 $object_sections_table = $this->_db_table_prefix . $object_type .'_sections';
3438 break;
3439 default:
3440 $this->debug_text('get_object_section_section_id(): Invalid Object Type ('. $object_type . ')');
3441 return FALSE;
3444 $name = trim($name);
3445 $value = trim($value);
3447 if (empty($name) AND empty($value) ) {
3448 $this->debug_text('get_object_section_section_id(): Both Name ('. $name .') and Value ('. $value .') are empty, you must specify at least one.');
3449 return FALSE;
3452 $query = 'SELECT id FROM '. $object_sections_table;
3453 $where = ' WHERE ';
3455 // limit by value if specified
3456 if (!empty($value)) {
3457 $query .= $where .'value='. $this->db->quote($value);
3458 $where = ' AND ';
3461 // only use name if asked, this is SLOW
3462 if (!empty($name)) {
3463 $query .= $where .'name='. $this->db->quote($name);
3466 $rs = $this->db->Execute($query);
3468 if (!is_object($rs)) {
3469 $this->debug_db('get_object_section_section_id');
3470 return FALSE;
3473 $row_count = $rs->RecordCount();
3475 // If only one row is returned
3476 if ($row_count == 1) {
3477 // Return only the ID in the first row.
3478 $row = $rs->FetchRow();
3479 return $row[0];
3482 // If more than one row is returned
3483 // should only ever occur when using name as values are unique.
3484 if ($row_count > 1) {
3485 $this->debug_text('get_object_section_section_id(): Returned '. $row_count .' rows, can only return one. Please search by value not name, or make your names unique.');
3486 return FALSE;
3489 // No rows returned, no matching section found
3490 $this->debug_text('get_object_section_section_id(): Returned '. $row_count .' rows, no matching section found.');
3491 return FALSE;
3495 * add_object_section()
3497 * Inserts an object Section
3499 * @return int Object Section ID of new section
3501 * @param string Object Name
3502 * @param string Object Value
3503 * @param int Display Order
3504 * @param int Hidden flag, hides section if 1, shows section if 0
3505 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3507 function add_object_section($name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3509 switch(strtolower(trim($object_type))) {
3510 case 'aco':
3511 $object_type = 'aco';
3512 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3513 break;
3514 case 'aro':
3515 $object_type = 'aro';
3516 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3517 break;
3518 case 'axo':
3519 $object_type = 'axo';
3520 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3521 break;
3522 case 'acl':
3523 $object_type = 'acl';
3524 $object_sections_table = $this->_db_table_prefix .'acl_sections';
3525 break;
3528 $this->debug_text("add_object_section(): Value: $value Order: $order Name: $name Object Type: $object_type");
3530 $name = trim($name);
3531 $value = trim($value);
3532 $order = trim($order);
3533 $hidden = intval($hidden);
3535 if ($order == NULL OR $order == '') {
3536 $order = 0;
3539 if (empty($name) ) {
3540 $this->debug_text("add_object_section(): name ($name) is empty, this is required");
3541 return false;
3544 if (empty($object_type) ) {
3545 $this->debug_text("add_object_section(): Object Type ($object_type) is empty, this is required");
3546 return false;
3549 $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_sections_seq',10);
3550 $query = 'insert into '. $object_sections_table .' (id,value,order_value,name,hidden) VALUES( '. $insert_id .', '. $this->db->quote($value) .', '. $order .', '. $this->db->quote($name) .', '. $hidden .')';
3551 $rs = $this->db->Execute($query);
3553 if (!is_object($rs)) {
3554 $this->debug_db('add_object_section');
3555 return false;
3556 } else {
3557 $this->debug_text("add_object_section(): Added object_section as ID: $insert_id");
3558 return $insert_id;
3563 * edit_object_section()
3565 * Edits a given Object Section
3567 * @return bool Returns TRUE if successful, FALSE otherwise
3569 * @param int Object Section ID #
3570 * @param string Object Section Name
3571 * @param string Object Section Value
3572 * @param int Display Order
3573 * @param int Hidden Flag, hide object section if 1, show if 0
3574 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3576 function edit_object_section($object_section_id, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3578 switch(strtolower(trim($object_type))) {
3579 case 'aco':
3580 $object_type = 'aco';
3581 $table = $this->_db_table_prefix .'aco';
3582 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3583 $object_map_table = $this->_db_table_prefix .'aco_map';
3584 break;
3585 case 'aro':
3586 $object_type = 'aro';
3587 $table = $this->_db_table_prefix .'aro';
3588 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3589 $object_map_table = $this->_db_table_prefix .'aro_map';
3590 break;
3591 case 'axo':
3592 $object_type = 'axo';
3593 $table = $this->_db_table_prefix .'axo';
3594 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3595 $object_map_table = $this->_db_table_prefix .'axo_map';
3596 break;
3597 case 'acl':
3598 $object_type = 'acl';
3599 $table = $this->_db_table_prefix .'acl';
3600 $object_sections_table = $this->_db_table_prefix .'acl_sections';
3601 break;
3602 default:
3603 $this->debug_text('edit_object_section(): Invalid Object Type: '. $object_type);
3604 return FALSE;
3607 $this->debug_text("edit_object_section(): ID: $object_section_id Value: $value Order: $order Name: $name Object Type: $object_type");
3609 $name = trim($name);
3610 $value = trim($value);
3611 $order = trim($order);
3612 $hidden = intval($hidden);
3614 if (empty($object_section_id) ) {
3615 $this->debug_text("edit_object_section(): Section ID ($object_section_id) is empty, this is required");
3616 return false;
3619 if (empty($name) ) {
3620 $this->debug_text("edit_object_section(): name ($name) is empty, this is required");
3621 return false;
3624 if (empty($object_type) ) {
3625 $this->debug_text("edit_object_section(): Object Type ($object_type) is empty, this is required");
3626 return false;
3629 $this->db->BeginTrans();
3631 //Get old value incase it changed, before we do the update.
3632 $query = "select value from $object_sections_table where id=$object_section_id";
3633 $old_value = $this->db->GetOne($query);
3635 $query = "update $object_sections_table set
3636 value='$value',
3637 order_value='$order',
3638 name='$name',
3639 hidden=$hidden
3640 where id=$object_section_id";
3641 $rs = $this->db->Execute($query);
3643 if (!is_object($rs)) {
3644 $this->debug_db('edit_object_section');
3646 $this->db->RollbackTrans();
3648 return false;
3649 } else {
3650 $this->debug_text("edit_object_section(): Modified aco_section ID: $object_section_id");
3652 if ($old_value != $value) {
3653 $this->debug_text("edit_object_section(): Value Changed, update other tables.");
3655 $query = "update $table set
3656 section_value='$value'
3657 where section_value = '$old_value'";
3658 $rs = $this->db->Execute($query);
3660 if (!is_object($rs)) {
3661 $this->debug_db('edit_object_section');
3663 $this->db->RollbackTrans();
3665 return false;
3666 } else {
3667 if (!empty($object_map_table)) {
3668 $query = "update $object_map_table set
3669 section_value='$value'
3670 where section_value = '$old_value'";
3671 $rs = $this->db->Execute($query);
3673 if ( !is_object($rs) ) {
3674 $this->debug_db('edit_object_section');
3676 $this->db->RollbackTrans();
3678 return false;
3679 } else {
3680 $this->debug_text("edit_object_section(): Modified ojbect_map value: $value");
3682 $this->db->CommitTrans();
3683 return true;
3685 } else {
3686 //ACL sections, have no mapping table. Return true.
3688 $this->db->CommitTrans();
3690 return true;
3695 $this->db->CommitTrans();
3696 return true;
3701 * del_object_section()
3703 * Deletes a given Object Section and, if explicitly asked, all the section objects
3705 * ERASE feature by: Martino Piccinato
3707 * @return bool Returns TRUE if successful, FALSE otherwise
3709 * @param int Object Section ID # to delete
3710 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3711 * @param bool Erases all section objects assigned to the section
3713 function del_object_section($object_section_id, $object_type=NULL, $erase=FALSE) {
3715 switch(strtolower(trim($object_type))) {
3716 case 'aco':
3717 $object_type = 'aco';
3718 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3719 break;
3720 case 'aro':
3721 $object_type = 'aro';
3722 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3723 break;
3724 case 'axo':
3725 $object_type = 'axo';
3726 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3727 break;
3728 case 'acl':
3729 $object_type = 'acl';
3730 $object_sections_table = $this->_db_table_prefix .'acl_sections';
3731 break;
3734 $this->debug_text("del_object_section(): ID: $object_section_id Object Type: $object_type, Erase all: $erase");
3736 if (empty($object_section_id) ) {
3737 $this->debug_text("del_object_section(): Section ID ($object_section_id) is empty, this is required");
3738 return false;
3741 if (empty($object_type) ) {
3742 $this->debug_text("del_object_section(): Object Type ($object_type) is empty, this is required");
3743 return false;
3746 // Get the value of the section
3747 $query="SELECT value FROM $object_sections_table WHERE id='$object_section_id'";
3748 $section_value = $this->db->GetOne($query);
3750 // Get all objects ids in the section
3751 $object_ids = $this->get_object($section_value, 1, $object_type);
3753 if($erase) {
3754 // Delete all objects in the section and for
3755 // each object delete the referencing object
3756 // (see del_object method)
3757 if (is_array($object_ids)) {
3758 foreach ($object_ids as $id) {
3759 if ( $object_type === 'acl' ) {
3760 $this->del_acl($id);
3761 } else {
3762 $this->del_object($id, $object_type, TRUE);
3768 if($object_ids AND !$erase) {
3769 // There are objects in the section and we
3770 // were not asked to erase them: don't delete it
3772 $this->debug_text("del_object_section(): Could not delete the section ($section_value) as it is not empty.");
3774 return false;
3776 } else {
3777 // The section is empty (or emptied by this method)
3779 $query = "DELETE FROM $object_sections_table where id='$object_section_id'";
3780 $rs = $this->db->Execute($query);
3782 if (!is_object($rs)) {
3783 $this->debug_db('del_object_section');
3784 return false;
3785 } else {
3786 $this->debug_text("del_object_section(): deleted section ID: $object_section_id Value: $section_value");
3787 return true;
3792 return false;
3796 * get_section_data()
3798 * Gets the section data given the Section Value
3800 * @return array Returns numerically indexed array with the following columns:
3801 * - array[0] = (int) Section ID #
3802 * - array[1] = (string) Section Value
3803 * - array[2] = (int) Section Order
3804 * - array[3] = (string) Section Name
3805 * - array[4] = (int) Section Hidden?
3806 * @param string Section Value
3807 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3809 function get_section_data($section_value, $object_type=NULL) {
3811 switch(strtolower(trim($object_type))) {
3812 case 'aco':
3813 $object_type = 'aco';
3814 $table = $this->_db_table_prefix .'aco_sections';
3815 break;
3816 case 'aro':
3817 $object_type = 'aro';
3818 $table = $this->_db_table_prefix .'aro_sections';
3819 break;
3820 case 'axo':
3821 $object_type = 'axo';
3822 $table = $this->_db_table_prefix .'axo_sections';
3823 break;
3824 default:
3825 $this->debug_text('get_section_data(): Invalid Object Type: '. $object_type);
3826 return FALSE;
3829 $this->debug_text("get_section_data(): Section Value: $section_value Object Type: $object_type");
3831 if (empty($section_value) ) {
3832 $this->debug_text("get_section_data(): Section Value ($section_value) is empty, this is required");
3833 return false;
3836 if (empty($object_type) ) {
3837 $this->debug_text("get_section_data(): Object Type ($object_type) is empty, this is required");
3838 return false;
3841 $query = "SELECT id, value, order_value, name, hidden FROM $table WHERE value='$section_value'";
3842 $row = $this->db->GetRow($query);
3844 if ($row) {
3845 return $row;
3848 $this->debug_text("get_section_data(): Section does not exist.");
3849 return false;
3853 * clear_database()
3855 * Deletes all data from the phpGACL tables. USE WITH CAUTION.
3857 * @return bool Returns TRUE if successful, FALSE otherwise
3860 function clear_database(){
3862 $tablesToClear = array(
3863 $this->_db_table_prefix.'acl',
3864 $this->_db_table_prefix.'aco',
3865 $this->_db_table_prefix.'aco_map',
3866 $this->_db_table_prefix.'aco_sections',
3867 $this->_db_table_prefix.'aro',
3868 $this->_db_table_prefix.'aro_groups',
3869 $this->_db_table_prefix.'aro_groups_map',
3870 $this->_db_table_prefix.'aro_map',
3871 $this->_db_table_prefix.'aro_sections',
3872 $this->_db_table_prefix.'axo',
3873 $this->_db_table_prefix.'axo_groups',
3874 $this->_db_table_prefix.'axo_groups_map',
3875 $this->_db_table_prefix.'axo_map',
3876 $this->_db_table_prefix.'axo_sections',
3877 $this->_db_table_prefix.'groups_aro_map',
3878 $this->_db_table_prefix.'groups_axo_map'
3881 // Get all the table names and loop
3882 $tableNames = $this->db->MetaTables('TABLES');
3883 $query = array();
3884 foreach ($tableNames as $key => $value){
3885 if (in_array($value, $tablesToClear) ) {
3886 $query[] = 'TRUNCATE TABLE '.$value.';';
3890 // Loop the queries and return.
3891 foreach ($query as $key => $value){
3892 $result = $this->db->Execute($value);
3895 return TRUE;