feat: More encounter UI improvements (#6794)
[openemr.git] / src / Gacl / GaclApi.php
bloba41ddb295b56b5262c55046c8ecc0d89c350ec3f
1 <?php
2 /**
3 * GaclApi class - phpGACL extended API Class
5 * Original code from phpGACL - Generic Access Control List
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * @package OpenEMR
13 * @link https://www.open-emr.org
14 * @author Mike Benoit <ipso@snappymail.ca>
15 * @author Brady Miller <brady.g.miller@gmail.com>
16 * @copyright Copyright (c) 2002-2003 Mike Benoit <ipso@snappymail.ca>
17 * @copyright Copyright (c) 2020 Brady Miller <brady.g.miller@gmail.com>
18 * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License 2.1
22 namespace OpenEMR\Gacl;
24 class GaclApi extends Gacl {
28 * Misc helper functions.
32 /**
33 * showarray()
35 * Dump all contents of an array in HTML (kinda)
37 * @param array
40 function showarray($array) {
41 echo "<br /><pre>\n";
42 var_dump($array);
43 echo "</pre><br />\n";
46 /**
47 * count_all()
49 * Recursively counts elements in an array and sub-arrays.
51 * This is different from count($arg, COUNT_RECURSIVE)
52 * in PHP >= 4.2.0, which includes sub-arrays in the count.
54 * @return int The returned count is a count of all scalar elements found.
56 * @param array Array to count
58 function count_all($arg = NULL) {
59 switch (TRUE) {
60 case is_scalar($arg):
61 case is_object($arg):
62 // single object
63 return 1;
64 case is_array($arg):
65 // call recursively for all elements of $arg
66 $count = 0;
67 foreach ($arg as $val) {
68 $count += $this->count_all($val);
70 return $count;
72 return FALSE;
75 /**
76 * get_version()
78 * Grabs phpGACL version from the database.
80 * @return string Version of phpGACL
82 function get_version() {
83 $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'version'";
84 $version = $this->db->GetOne($query);
86 return $version;
89 /**
90 * get_schema_version()
92 * Grabs phpGACL schema version from the database.
94 * @return string Schema Version
96 function get_schema_version() {
97 $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'schema_version'";
98 $version = $this->db->GetOne($query);
100 return $version;
105 * ACL
110 * consolidated_edit_acl()
112 * Add's an ACL but checks to see if it can consolidate it with another one first.
114 * This ONLY works with ACO's and ARO's. Groups, and AXO are excluded.
115 * As well this function is designed for handling ACLs with return values,
116 * and consolidating on the return_value, in hopes of keeping the ACL count to a minimum.
118 * A return value of false must _always_ be handled outside this function.
119 * As this function will remove AROs from ACLs and return false, in most cases
120 * you will need to a create a completely new ACL on a false return.
122 * @return bool Special boolean return value. See note.
124 * @param string ACO Section Value
125 * @param string ACO Value
126 * @param string ARO Section Value
127 * @param string ARO Value
128 * @param string Return Value of ACL
130 function consolidated_edit_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, $return_value) {
132 $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");
134 $acl_ids = array();
136 if (empty($aco_section_value) ) {
137 $this->debug_text("consolidated_edit_acl(): ACO Section Value ($aco_section_value) is empty, this is required!");
138 return false;
141 if (empty($aco_value) ) {
142 $this->debug_text("consolidated_edit_acl(): ACO Value ($aco_value) is empty, this is required!");
143 return false;
146 if (empty($aro_section_value) ) {
147 $this->debug_text("consolidated_edit_acl(): ARO Section Value ($aro_section_value) is empty, this is required!");
148 return false;
151 if (empty($aro_value) ) {
152 $this->debug_text("consolidated_edit_acl(): ARO Value ($aro_value) is empty, this is required!");
153 return false;
156 if (empty($return_value) ) {
157 $this->debug_text("consolidated_edit_acl(): Return Value ($return_value) is empty, this is required!");
158 return false;
161 //See if a current ACL exists with the current objects, excluding return value
162 $current_acl_ids = $this->search_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, FALSE, FALSE, FALSE, FALSE, FALSE);
163 //showarray($current_acl_ids);
165 if (is_array($current_acl_ids)) {
166 $this->debug_text("add_consolidated_acl(): Found current ACL_IDs, counting ACOs");
168 foreach ($current_acl_ids as $current_acl_id) {
169 //Check to make sure these ACLs only have a single ACO mapped to them.
170 $current_acl_array = &$this->get_acl($current_acl_id);
172 //showarray($current_acl_array);
173 $this->debug_text("add_consolidated_acl(): Current Count: ".$this->count_all($current_acl_array['aco'])."");
175 if ( $this->count_all($current_acl_array['aco']) == 1) {
176 $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO.");
178 //Test to see if the return values match, if they do, no need removing or appending ARO. Just return true.
179 if ($current_acl_array['return_value'] == $return_value) {
180 $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO, and the same return value. No need to modify.");
181 return true;
184 $acl_ids[] = $current_acl_id;
190 //showarray($acl_ids);
191 $acl_ids_count = count($acl_ids);
193 //If acl_id's turns up more then one ACL, lets remove the ARO from all of them in hopes to
194 //eliminate any conflicts.
195 if (is_array($acl_ids) AND $acl_ids_count > 0) {
196 $this->debug_text("add_consolidated_acl(): Removing specified ARO from existing ACL.");
198 foreach ($acl_ids as $acl_id) {
199 //Remove ARO from current ACLs, so we don't create conflicting ACLs later on.
200 if (!$this->shift_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
201 $this->debug_text("add_consolidated_acl(): Error removing specified ARO from ACL ID: $acl_id");
202 return false;
205 } else {
206 $this->debug_text("add_consolidated_acl(): Didn't find any current ACLs with a single ACO. ");
208 //unset($acl_ids);
209 $acl_ids = array();
210 unset($acl_ids_count);
212 //At this point there should be no conflicting ACLs, searching for an existing ACL with the new values.
213 $new_acl_ids = $this->search_acl($aco_section_value, $aco_value, FALSE, FALSE, NULL, NULL, NULL, NULL, $return_value);
214 $new_acl_count = count($new_acl_ids);
215 //showarray($new_acl_ids);
217 if (is_array($new_acl_ids)) {
218 $this->debug_text("add_consolidated_acl(): Found new ACL_IDs, counting ACOs");
220 foreach ($new_acl_ids as $new_acl_id) {
221 //Check to make sure these ACLs only have a single ACO mapped to them.
222 $new_acl_array = &$this->get_acl($new_acl_id);
223 //showarray($new_acl_array);
224 $this->debug_text("add_consolidated_acl(): New Count: ".$this->count_all($new_acl_array['aco'])."");
225 if ( $this->count_all($new_acl_array['aco']) == 1) {
227 $this->debug_text("add_consolidated_acl(): ACL ID: $new_acl_id has 1 ACO, append should be able to take place.");
228 $acl_ids[] = $new_acl_id;
234 //showarray($acl_ids);
235 $acl_ids_count = count($acl_ids);
237 if (is_array($acl_ids) AND $acl_ids_count == 1) {
238 $this->debug_text("add_consolidated_acl(): Appending specified ARO to existing ACL.");
240 $acl_id=$acl_ids[0];
242 if (!$this->append_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
243 $this->debug_text("add_consolidated_acl(): Error appending specified ARO to ACL ID: $acl_id");
244 return false;
247 $this->debug_text("add_consolidated_acl(): Hot damn, ACL consolidated!");
248 return true;
249 } elseif($acl_ids_count > 1) {
250 $this->debug_text("add_consolidated_acl(): Found more then one ACL with a single ACO. Possible conflicting ACLs.");
251 return false;
252 } elseif ($acl_ids_count == 0) {
253 $this->debug_text("add_consolidated_acl(): No existing ACLs found, create a new one.");
255 if (!$this->add_acl( array( $aco_section_value => array($aco_value) ),
256 array( $aro_section_value => array($aro_value) ),
257 NULL,
258 NULL,
259 NULL,
260 TRUE,
261 TRUE,
262 $return_value,
263 NULL)
265 $this->debug_text("add_consolidated_acl(): Error adding new ACL for ACO Section: $aco_section_value ACO Value: $aco_value Return Value: $return_value");
266 return false;
269 $this->debug_text("add_consolidated_acl(): ADD_ACL() successfull, returning True.");
270 return true;
273 $this->debug_text("add_consolidated_acl(): Returning false.");
274 return false;
278 * search_acl()
280 * Searches for ACL's with specified objects mapped to them.
282 * NULL values are included in the search, if you want to ignore
283 * for instance aro_groups use FALSE instead of NULL.
285 * @return array containing ACL IDs if search is successful
287 * @param string ACO Section Value
288 * @param string ACO Value
289 * @param string ARO Section Value
290 * @param string ARO Value
291 * @param string ARO Group Name
292 * @param string AXO Section Value
293 * @param string AXO Value
294 * @param string AXO Group Name
295 * @param string Return Value
297 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) {
298 $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");
300 $query = '
301 SELECT a.id
302 FROM '. $this->_db_table_prefix .'acl a';
304 $where_query = array();
306 // ACO
307 if ($aco_section_value !== FALSE AND $aco_value !== FALSE) {
308 $query .= '
309 LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON a.id=ac.acl_id';
311 if ($aco_section_value == NULL AND $aco_value == NULL) {
312 $where_query[] = '(ac.section_value IS NULL AND ac.value IS NULL)';
313 } else {
314 $where_query[] = '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value='. $this->db->quote($aco_value) .')';
318 // ARO
319 if ($aro_section_value !== FALSE AND $aro_value !== FALSE) {
320 $query .= '
321 LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON a.id=ar.acl_id';
323 if ($aro_section_value == NULL AND $aro_value == NULL) {
324 $where_query[] = '(ar.section_value IS NULL AND ar.value IS NULL)';
325 } else {
326 $where_query[] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value='. $this->db->quote($aro_value) .')';
330 // AXO
331 if ($axo_section_value !== FALSE AND $axo_value !== FALSE) {
332 $query .= '
333 LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON a.id=ax.acl_id';
335 if ($axo_section_value == NULL AND $axo_value == NULL) {
336 $where_query[] = '(ax.section_value IS NULL AND ax.value IS NULL)';
337 } else {
338 $where_query[] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value='. $this->db->quote($axo_value) .')';
342 // ARO Group
343 if ($aro_group_name !== FALSE) {
344 $query .= '
345 LEFT JOIN '. $this->_db_table_prefix .'aro_groups_map arg ON a.id=arg.acl_id
346 LEFT JOIN '. $this->_db_table_prefix .'aro_groups rg ON arg.group_id=rg.id';
348 if ($aro_group_name == NULL) {
349 $where_query[] = '(rg.name IS NULL)';
350 } else {
351 $where_query[] = '(rg.name='. $this->db->quote($aro_group_name) .')';
355 // AXO Group
356 if ($axo_group_name !== FALSE) {
357 $query .= '
358 LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON a.id=axg.acl_id
359 LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON axg.group_id=xg.id';
361 if ($axo_group_name == NULL) {
362 $where_query[] = '(xg.name IS NULL)';
363 } else {
364 $where_query[] = '(xg.name='. $this->db->quote($axo_group_name) .')';
367 if ($return_value != FALSE) {
368 if ($return_value == NULL) {
369 $where_query[] = '(a.return_value IS NULL)';
370 } else {
371 $where_query[] = '(a.return_value='. $this->db->quote($return_value) .')';
375 if (count($where_query) > 0) {
376 $query .= '
377 WHERE '. implode (' AND ', $where_query);
380 return $this->db->GetCol($query);
384 * append_acl()
386 * Appends objects on to a specific ACL.
388 * @return bool TRUE if successful, FALSE otherwise.
390 * @param int ACL ID #
391 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
392 * @param array Array of Group IDs
393 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
394 * @param array Array of Group IDs
395 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
397 function append_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
398 $this->debug_text("append_acl(): ACL_ID: $acl_id");
400 $update = 0;
402 if (empty($acl_id)) {
403 $this->debug_text("append_acl(): No ACL_ID specified! ACL_ID: $acl_id");
404 return false;
407 //Grab ACL data.
408 $get_acl = $this->get_acl($acl_id);
409 $acl_array = &$get_acl;
411 //Append each object type seperately.
412 if (is_array($aro_array) AND count($aro_array) > 0) {
413 $this->debug_text("append_acl(): Appending ARO's");
415 foreach ($aro_array as $aro_section_value => $aro_value_array) {
416 foreach ($aro_value_array as $aro_value) {
417 if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
418 if (!in_array($aro_value, $acl_array['aro'][$aro_section_value])) {
419 $this->debug_text("append_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
420 $acl_array['aro'][$aro_section_value][] = $aro_value;
421 $update=1;
422 } else {
423 $this->debug_text("append_acl(): Duplicate ARO, ignoring... ");
425 } else { //Array is empty so add this aro value.
426 $acl_array['aro'][$aro_section_value][] = $aro_value;
427 $update = 1;
433 if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
434 $this->debug_text("append_acl(): Appending ARO_GROUP_ID's");
436 foreach ($aro_group_ids as $aro_group_id) {
437 if (!is_array($acl_array['aro_groups']) OR !in_array($aro_group_id, $acl_array['aro_groups'])) {
438 $this->debug_text("append_acl(): ARO Group ID: $aro_group_id");
439 $acl_array['aro_groups'][] = $aro_group_id;
440 $update = 1;
441 } else {
442 $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
447 if (is_array($axo_array) AND count($axo_array) > 0) {
448 $this->debug_text("append_acl(): Appending AXO's");
450 foreach($axo_array as $axo_section_value => $axo_value_array) {
451 foreach ($axo_value_array as $axo_value) {
452 if (!in_array($axo_value, $acl_array['axo'][$axo_section_value])) {
453 $this->debug_text("append_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
454 $acl_array['axo'][$axo_section_value][] = $axo_value;
455 $update = 1;
456 } else {
457 $this->debug_text("append_acl(): Duplicate AXO, ignoring... ");
464 if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
465 $this->debug_text("append_acl(): Appending AXO_GROUP_ID's");
466 foreach ($axo_group_ids as $axo_group_id) {
467 if (!is_array($acl_array['axo_groups']) OR !in_array($axo_group_id, $acl_array['axo_groups'])) {
468 $this->debug_text("append_acl(): AXO Group ID: $axo_group_id");
469 $acl_array['axo_groups'][] = $axo_group_id;
470 $update = 1;
471 } else {
472 $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
477 if (is_array($aco_array) AND count($aco_array) > 0) {
478 $this->debug_text("append_acl(): Appending ACO's");
480 foreach ($aco_array as $aco_section_value => $aco_value_array) {
481 foreach ($aco_value_array as $aco_value) {
482 if (empty($acl_array['aco'][$aco_section_value]) || !is_array($acl_array['aco'][$aco_section_value]) || !in_array($aco_value, $acl_array['aco'][$aco_section_value])) {
483 $this->debug_text("append_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
484 $acl_array['aco'][$aco_section_value][] = $aco_value;
485 $update = 1;
486 } else {
487 $this->debug_text("append_acl(): Duplicate ACO, ignoring... ");
493 if ($update == 1) {
494 $this->debug_text("append_acl(): Update flag set, updating ACL.");
495 //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) {
496 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']);
499 //Return true if everything is duplicate and no ACL id updated.
500 $this->debug_text("append_acl(): Update flag not set, NOT updating ACL.");
501 return true;
505 * shift_acl()
507 * Opposite of append_acl(). Removes objects from a specific ACL. (named after PHP's array_shift())
509 * @return bool TRUE if successful, FALSE otherwise.
511 * @param int ACL ID #
512 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
513 * @param array Array of Group IDs
514 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
515 * @param array Array of Group IDs
516 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
518 function shift_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
519 $this->debug_text("shift_acl(): ACL_ID: $acl_id");
521 $update = 0;
523 if (empty($acl_id)) {
524 $this->debug_text("shift_acl(): No ACL_ID specified! ACL_ID: $acl_id");
525 return false;
528 //Grab ACL data.
529 $get_acl = $this->get_acl($acl_id);
530 $acl_array = &$get_acl;
532 //showarray($acl_array);
533 //Remove each object type seperately.
534 if (is_array($aro_array) AND count($aro_array) > 0) {
535 $this->debug_text("shift_acl(): Removing ARO's");
537 foreach($aro_array as $aro_section_value => $aro_value_array) {
538 foreach ($aro_value_array as $aro_value) {
539 $this->debug_text("shift_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
541 //Only search if aro array contains data.
542 if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
543 $aro_key = array_search($aro_value, $acl_array['aro'][$aro_section_value]);
545 if ($aro_key !== FALSE) {
546 $this->debug_text("shift_acl(): Removing ARO. ($aro_key)");
547 unset($acl_array['aro'][$aro_section_value][$aro_key]);
548 $update = 1;
549 } else {
550 $this->debug_text("shift_acl(): ARO doesn't exist, can't remove it.");
558 if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
559 $this->debug_text("shift_acl(): Removing ARO_GROUP_ID's");
561 foreach ($aro_group_ids as $aro_group_id) {
562 $this->debug_text("shift_acl(): ARO Group ID: $aro_group_id");
563 $aro_group_key = array_search($aro_group_id, $acl_array['aro_groups']);
565 if ($aro_group_key !== FALSE) {
566 $this->debug_text("shift_acl(): Removing ARO Group. ($aro_group_key)");
567 unset($acl_array['aro_groups'][$aro_group_key]);
568 $update = 1;
569 } else {
570 $this->debug_text("shift_acl(): ARO Group doesn't exist, can't remove it.");
575 if (is_array($axo_array) AND count($axo_array) > 0) {
576 $this->debug_text("shift_acl(): Removing AXO's");
578 foreach($axo_array as $axo_section_value => $axo_value_array) {
579 foreach ($axo_value_array as $axo_value) {
580 $this->debug_text("shift_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
581 $axo_key = array_search($axo_value, $acl_array['axo'][$axo_section_value]);
583 if ($axo_key !== FALSE) {
584 $this->debug_text("shift_acl(): Removing AXO. ($axo_key)");
585 unset($acl_array['axo'][$axo_section_value][$axo_key]);
586 $update = 1;
587 } else {
588 $this->debug_text("shift_acl(): AXO doesn't exist, can't remove it.");
594 if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
595 $this->debug_text("shift_acl(): Removing AXO_GROUP_ID's");
597 foreach ($axo_group_ids as $axo_group_id) {
598 $this->debug_text("shift_acl(): AXO Group ID: $axo_group_id");
599 $axo_group_key = array_search($axo_group_id, $acl_array['axo_groups']);
601 if ($axo_group_key !== FALSE) {
602 $this->debug_text("shift_acl(): Removing AXO Group. ($axo_group_key)");
603 unset($acl_array['axo_groups'][$axo_group_key]);
604 $update = 1;
605 } else {
606 $this->debug_text("shift_acl(): AXO Group doesn't exist, can't remove it.");
611 if (is_array($aco_array) AND count($aco_array) > 0) {
612 $this->debug_text("shift_acl(): Removing ACO's");
614 foreach ($aco_array as $aco_section_value => $aco_value_array) {
615 foreach ($aco_value_array as $aco_value) {
616 $this->debug_text("shift_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
617 $aco_key = array_search($aco_value, ($acl_array['aco'][$aco_section_value] ?? []));
619 if ($aco_key !== FALSE) {
620 $this->debug_text("shift_acl(): Removing ACO. ($aco_key)");
621 unset($acl_array['aco'][$aco_section_value][$aco_key]);
622 $update = 1;
623 } else {
624 $this->debug_text("shift_acl(): ACO doesn't exist, can't remove it.");
630 if ($update == 1) {
631 //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.
632 //$this->showarray($acl_array);
633 $this->debug_text("shift_acl(): ACOs: ". $this->count_all($acl_array['aco']) ." AROs: ".$this->count_all($acl_array['aro'])."");
635 if ( $this->count_all($acl_array['aco']) == 0
636 OR ( $this->count_all($acl_array['aro']) == 0
637 AND ( $this->count_all($acl_array['axo']) == 0 OR $acl_array['axo'] == FALSE)
638 AND (count($acl_array['aro_groups']) == 0 OR $acl_array['aro_groups'] == FALSE)
639 AND (count($acl_array['axo_groups']) == 0 OR $acl_array['axo_groups'] == FALSE)
640 ) ) {
641 $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.");
643 return $this->del_acl($acl_id);
646 $this->debug_text("shift_acl(): Update flag set, updating ACL.");
648 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']);
651 //Return true if everything is duplicate and no ACL id updated.
652 $this->debug_text("shift_acl(): Update flag not set, NOT updating ACL.");
653 return true;
657 * get_acl()
659 * Grabs ACL data.
661 * @return bool FALSE if not found, or Associative Array with the following items:
663 * - 'aco' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
664 * - 'aro' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
665 * - 'axo' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
666 * - 'aro_groups' => Array of Group IDs
667 * - 'axo_groups' => Array of Group IDs
668 * - 'acl_id' => int ACL ID #
669 * - 'allow' => int Allow flag
670 * - 'enabled' => int Enabled flag
671 * - 'return_value' => string Return Value
672 * - 'note' => string Note
674 * @param int ACL ID #
676 function get_acl($acl_id) {
678 $this->debug_text("get_acl(): ACL_ID: $acl_id");
680 if (empty($acl_id)) {
681 $this->debug_text("get_acl(): No ACL_ID specified! ACL_ID: $acl_id");
682 return false;
685 //Grab ACL information
686 $query = "select id, allow, enabled, return_value, note from ".$this->_db_table_prefix."acl where id = " . $this->db->quote($acl_id);
687 $acl_row = $this->db->GetRow($query);
689 // return false if not found
690 if (!$acl_row) {
691 $this->debug_text("get_acl(): No ACL found for that ID! ACL_ID: $acl_id");
692 return false;
695 list($retarr['acl_id'], $retarr['allow'], $retarr['enabled'], $retarr['return_value'], $retarr['note']) = $acl_row;
697 //Grab selected ACO's
698 $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
699 where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = " . $this->db->quote($acl_id);
700 $rs = $this->db->Execute($query);
701 $rows = $rs->GetRows();
703 $retarr['aco'] = array();
704 foreach ($rows as $row) {
705 list($section_value, $value, $section, $aco) = $row;
706 $this->debug_text("Section Value: $section_value Value: $value Section: $section ACO: $aco");
708 $retarr['aco'][$section_value][] = $value;
711 //showarray($aco);
713 //Grab selected ARO's
714 $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
715 where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = " . $this->db->quote($acl_id);
716 $rs = $this->db->Execute($query);
717 $rows = $rs->GetRows();
719 $retarr['aro'] = array();
720 foreach ($rows as $row) {
721 list($section_value, $value, $section, $aro) = $row;
722 $this->debug_text("Section Value: $section_value Value: $value Section: $section ARO: $aro");
724 $retarr['aro'][$section_value][] = $value;
727 //showarray($options_aro);
729 //Grab selected AXO's
730 $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
731 where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = " . $this->db->quote($acl_id);
732 $rs = $this->db->Execute($query);
733 $rows = $rs->GetRows();
735 $retarr['axo'] = array();
736 foreach ($rows as $row) {
737 list($section_value, $value, $section, $axo) = $row;
738 $this->debug_text("Section Value: $section_value Value: $value Section: $section AXO: $axo");
740 $retarr['axo'][$section_value][] = $value;
743 //showarray($options_aro);
745 //Grab selected ARO groups.
746 $retarr['aro_groups'] = array();
747 $query = "select distinct group_id from ".$this->_db_table_prefix."aro_groups_map where acl_id = " . $this->db->quote($acl_id);
748 $retarr['aro_groups'] = $this->db->GetCol($query);
749 //showarray($selected_groups);
751 //Grab selected AXO groups.
752 $retarr['axo_groups'] = array();
753 $query = "select distinct group_id from ".$this->_db_table_prefix."axo_groups_map where acl_id = " . $this->db->quote($acl_id);
754 $retarr['axo_groups'] = $this->db->GetCol($query);
755 //showarray($selected_groups);
757 return $retarr;
761 * is_conflicting_acl()
763 * Checks for conflicts when adding a specific ACL.
765 * @return bool Returns true if conflict is found.
767 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
768 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
769 * @param array Array of Group IDs
770 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
771 * @param array Array of Group IDs
772 * @param array Array of ACL IDs to ignore from the result set.
775 function is_conflicting_acl($aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $ignore_acl_ids=NULL) {
776 //Check for potential conflicts. Ignore groups, as groups will almost always have "conflicting" ACLs.
777 //Thats part of inheritance.
779 if (!is_array($aco_array)) {
780 $this->debug_text('is_conflicting_acl(): Invalid ACO Array.');
781 return FALSE;
784 if (!is_array($aro_array)) {
785 $this->debug_text('is_conflicting_acl(): Invalid ARO Array.');
786 return FALSE;
789 $query = '
790 SELECT a.id
791 FROM '. $this->_db_table_prefix .'acl a
792 LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON ac.acl_id=a.id
793 LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON ar.acl_id=a.id
794 LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON ax.acl_id=a.id
795 LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON axg.acl_id=a.id
796 LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON xg.id=axg.group_id
799 //ACO
800 foreach ($aco_array as $aco_section_value => $aco_value_array) {
801 $this->debug_text("is_conflicting_acl(): ACO Section Value: $aco_section_value ACO VALUE: " . implode(',', $aco_value_array));
802 //showarray($aco_array);
804 if (!is_array($aco_value_array)) {
805 $this->debug_text('is_conflicting_acl(): Invalid Format for ACO Array item. Skipping...');
806 continue;
807 // return TRUE;
809 //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
810 //'ac1' => 'ac.acl_id=a.id',
811 $where_query = array(
812 'ac2' => '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value IN (\''. implode ('\',\'', $aco_value_array) .'\'))'
815 //ARO
816 foreach ($aro_array as $aro_section_value => $aro_value_array) {
817 $this->debug_text("is_conflicting_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value_array");
819 if (!is_array($aro_value_array))
821 $this->debug_text('is_conflicting_acl(): Invalid Format for ARO Array item. Skipping...');
822 continue;
823 // return TRUE;
826 $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");
828 //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
829 //$where_query['ar1'] = 'ar.acl_id=a.id';
830 $where_query['ar2'] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value IN (\''. implode ('\',\'', $aro_value_array) .'\'))';
832 if (is_array($axo_array) AND count($axo_array) > 0) {
833 foreach ($axo_array as $axo_section_value => $axo_value_array) {
834 $this->debug_text("is_conflicting_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value_array");
836 if (!is_array($axo_value_array)) {
837 $this->debug_text('is_conflicting_acl(): Invalid Format for AXO Array item. Skipping...');
838 continue;
839 // return TRUE;
842 $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");
844 //$where_query['ax1'] = 'ax.acl_id=x.id';
845 $where_query['ax1'] = 'ax.acl_id=a.id';
846 $where_query['ax2'] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value IN (\''. implode ('\',\'', $axo_value_array) .'\'))';
848 $where = 'WHERE ' . implode(' AND ', $where_query);
850 $conflict_result = $this->db->GetCol($query . $where);
852 if (is_array($conflict_result) AND !empty($conflict_result)) {
853 // showarray($conflict_result);
855 if (is_array($ignore_acl_ids)) {
856 $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
859 if (count($conflict_result) > 0) {
860 $conflicting_acls_str = implode(',', $conflict_result);
861 $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
862 return TRUE;
866 } else {
867 $where_query['ax1'] = '(ax.section_value IS NULL AND ax.value IS NULL)';
868 $where_query['ax2'] = 'xg.name IS NULL';
870 $where = 'WHERE ' . implode(' AND ', $where_query);
872 $conflict_result = $this->db->GetCol($query . $where);
874 if (is_array($conflict_result) AND !empty($conflict_result)) {
875 // showarray($conflict_result);
877 if (is_array($ignore_acl_ids)) {
878 $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
881 if (count($conflict_result) > 0) {
882 $conflicting_acls_str = implode(',', $conflict_result);
883 $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
884 return TRUE;
891 $this->debug_text('is_conflicting_acl(): No conflicting ACL found.');
892 return FALSE;
896 * add_acl()
898 * Add's an ACL. ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
900 * @return bool Return ACL ID of new ACL if successful, FALSE otherewise.
902 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
903 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
904 * @param array Array of Group IDs
905 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
906 * @param array Array of Group IDs
907 * @param int Allow flag
908 * @param int Enabled flag
909 * @param string Return Value
910 * @param string Note
911 * @param string ACL Section Value
912 * @param int ACL ID # Specific Request
915 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 ) {
917 $this->debug_text("add_acl():");
919 if (empty($aco_array) || count($aco_array) == 0) {
920 $this->debug_text("Must select at least one Access Control Object");
921 return false;
924 if ((empty($aro_array) || count($aro_array) == 0) AND (empty($aro_group_ids) || count($aro_group_ids) == 0)) {
925 $this->debug_text("Must select at least one Access Request Object or Group");
926 return false;
929 if (empty($allow)) {
930 $allow=0;
933 if (empty($enabled)) {
934 $enabled=0;
937 if (!empty($section_value)
938 AND !$this->get_object_section_section_id(NULL, $section_value, 'ACL')) {
939 $this->debug_text("add_acl(): Section Value: $section_value DOES NOT exist in the database.");
940 return false;
943 //Unique the group arrays. Later one we unique ACO/ARO/AXO arrays.
944 if (is_array($aro_group_ids)) {
945 $aro_group_ids = array_unique($aro_group_ids);
947 if (is_array($axo_group_ids)) {
948 $axo_group_ids = array_unique($axo_group_ids);
951 //Check for conflicting ACLs.
952 if ($this->is_conflicting_acl($aco_array,$aro_array,$aro_group_ids,$axo_array,$axo_group_ids,array($acl_id))) {
953 $this->debug_text("add_acl(): Detected possible ACL conflict, not adding ACL!");
954 return false;
957 //Edit ACL if acl_id is set. This is simply if we're being called by edit_acl().
958 if ($this->get_acl($acl_id) == FALSE) {
959 if ( empty($section_value) ) {
960 $section_value='system';
961 if( !$this->get_object_section_section_id(NULL, $section_value, 'ACL') ) {
962 // Use the acl section with the lowest order value.
963 $acl_sections_table = $this->_db_table_prefix .'acl_sections';
964 $acl_section_order_value = $this->db->GetOne("SELECT min(order_value) from $acl_sections_table");
966 $query = "
967 SELECT value
968 FROM $acl_sections_table
969 WHERE order_value = " . $this->db->quote($acl_section_order_value);
970 $section_value = $this->db->GetOne($query);
972 if ( empty($section_value) ) {
973 $this->debug_text("add_acl(): No valid acl section found.");
974 return false;
975 } else {
976 $this->debug_text("add_acl(): Using default section value: $section_value.");
981 //ACL not specified, so create acl_id
982 if (empty($acl_id)) {
983 //Create ACL row first, so we have the acl_id
984 $acl_id = $this->db->GenID($this->_db_table_prefix.'acl_seq',10);
986 //Double check the ACL ID was generated.
987 if (empty($acl_id)) {
988 $this->debug_text("add_acl(): ACL_ID generation failed!");
989 return false;
993 //Begin transaction _after_ GenID. Because on the first run, if GenID has to create the sequence,
994 //the transaction will fail.
995 $this->db->BeginTrans();
997 $query = 'INSERT INTO '.$this->_db_table_prefix.'acl (id,section_value,allow,enabled,return_value,note,updated_date) VALUES('. $this->db->quote($acl_id) .','. $this->db->quote($section_value) .','. $this->db->quote($allow) .','. $this->db->quote($enabled) .','. $this->db->quote($return_value) .', '. $this->db->quote($note) .','. time() .')';
998 $result = $this->db->Execute($query);
999 } else {
1000 $section_sql = '';
1001 if ( !empty($section_value) ) {
1002 $section_sql = 'section_value='. $this->db->quote ($section_value) .',';
1005 $this->db->BeginTrans();
1007 //Update ACL row, and remove all mappings so they can be re-inserted.
1008 $query = '
1009 UPDATE '. $this->_db_table_prefix .'acl
1010 SET ' . $section_sql . '
1011 allow='. $this->db->quote($allow) .',
1012 enabled='. $this->db->quote($enabled) .',
1013 return_value='. $this->db->quote($return_value) .',
1014 note='. $this->db->quote($note) .',
1015 updated_date='. time() .'
1016 WHERE id='. $this->db->quote($acl_id);
1017 $result = $this->db->Execute($query);
1019 if ($result) {
1020 $this->debug_text("Update completed without error, delete mappings...");
1021 //Delete all mappings so they can be re-inserted.
1022 foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
1023 $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. $this->db->quote($acl_id);
1024 $rs = $this->db->Execute($query);
1026 if (!is_object($rs))
1028 $this->debug_db('add_acl');
1029 $this->db->RollBackTrans();
1030 return FALSE;
1036 if (!is_object($result)) {
1037 $this->debug_db('add_acl');
1038 $this->db->RollBackTrans();
1039 return false;
1042 $this->debug_text("Insert or Update completed without error, insert new mappings.");
1043 // Insert ACO/ARO/AXO mappings
1044 foreach (array('aco', 'aro', 'axo') as $map) {
1045 $map_array = ${$map .'_array'};
1047 if (!is_array ($map_array)) {
1048 continue;
1051 foreach ($map_array as $section_value => $value_array) {
1052 $this->debug_text ('Insert: '. strtoupper($map) . ' Section Value: $section_value' . strtoupper($map) . ' VALUE: $value_array');
1053 // $this->showarray ($aco_value_array);
1055 if (!is_array($value_array)) {
1056 $this->debug_text ('add_acl (): Invalid Format for '. strtoupper ($map) .' Array item. Skipping...');
1057 continue;
1058 // return true;
1061 $value_array = array_unique($value_array);
1063 foreach ($value_array as $value) {
1064 $get_object_id = $this->get_object_id($section_value, $value, $map);
1065 $object_id = &$get_object_id;
1067 if (empty($object_id))
1069 $this->debug_text('add_acl(): '. strtoupper($map) . " Object Section Value: $section_value Value: $value DOES NOT exist in the database. Skipping...");
1070 $this->db->RollBackTrans();
1071 return false;
1074 $query = 'INSERT INTO '. $this->_db_table_prefix . $map .'_map (acl_id,section_value,value) VALUES ('. $this->db->quote($acl_id) .', '. $this->db->quote($section_value) .', '. $this->db->quote($value) .')';
1075 $rs = $this->db->Execute($query);
1077 if (!is_object($rs))
1079 $this->debug_db('add_acl');
1080 $this->db->RollBackTrans();
1081 return false;
1087 // Insert ARO/AXO GROUP mappings
1088 foreach (array('aro', 'axo') as $map) {
1089 $map_group_ids = ${$map .'_group_ids'};
1091 if (!is_array($map_group_ids)) {
1092 continue;
1095 foreach ($map_group_ids as $group_id) {
1096 $this->debug_text ('Insert: '. strtoupper($map) .' GROUP ID: '. $group_id);
1097 $get_group_data = $this->get_group_data($group_id, $map);
1098 $group_data = &$get_group_data;
1100 if (empty($group_data)) {
1101 $this->debug_text('add_acl(): '. strtoupper($map) . " Group: $group_id DOES NOT exist in the database. Skipping...");
1102 $this->db->RollBackTrans();
1103 return false;
1106 $query = 'INSERT INTO '. $this->_db_table_prefix . $map .'_groups_map (acl_id,group_id) VALUES ('. $this->db->quote($acl_id) .', '. $this->db->quote($group_id) .')';
1107 $rs = $this->db->Execute($query);
1109 if (!is_object($rs)) {
1110 $this->debug_db('add_acl');
1111 $this->db->RollBackTrans();
1112 return false;
1117 $this->db->CommitTrans();
1119 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1120 //Expire all cache.
1121 $this->Cache_Lite->clean('default');
1124 //Return only the ID in the first row.
1125 return $acl_id;
1129 * edit_acl()
1131 * Edit's an ACL, ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
1133 * @return bool Return TRUE if successful, FALSE otherewise.
1135 * @param int ACL ID # to edit
1136 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1137 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1138 * @param array Array of Group IDs
1139 * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1140 * @param array Array of Group IDs
1141 * @param int Allow flag
1142 * @param int Enabled flag
1143 * @param string Return Value
1144 * @param string Note
1145 * @param string ACL Section Value
1147 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) {
1149 $this->debug_text("edit_acl():");
1151 if (empty($acl_id) ) {
1152 $this->debug_text("edit_acl(): Must specify a single ACL_ID to edit");
1153 return false;
1155 if (count($aco_array) == 0) {
1156 $this->debug_text("edit_acl(): Must select at least one Access Control Object");
1157 return false;
1160 if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
1161 $this->debug_text("edit_acl(): Must select at least one Access Request Object or Group");
1162 return false;
1165 if (empty($allow)) {
1166 $allow=0;
1169 if (empty($enabled)) {
1170 $enabled=0;
1173 //if ($this->add_acl($aco_array, $aro_array, $group_ids, $allow, $enabled, $acl_id)) {
1174 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)) {
1175 return true;
1176 } else {
1177 $this->debug_text("edit_acl(): error in add_acl()");
1178 return false;
1183 * del_acl()
1185 * Deletes a given ACL
1187 * @return bool Returns TRUE if successful, FALSE otherwise.
1189 * @param int ACL ID # to delete
1191 function del_acl($acl_id) {
1193 $this->debug_text("del_acl(): ID: $acl_id");
1195 if (empty($acl_id) ) {
1196 $this->debug_text("del_acl(): ACL_ID ($acl_id) is empty, this is required");
1197 return false;
1200 $this->db->BeginTrans();
1202 // Delete all mappings to the ACL first
1203 foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
1204 $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. $this->db->quote($acl_id);
1205 $rs = $this->db->Execute($query);
1207 if (!is_object($rs)) {
1208 $this->debug_db('del_acl');
1209 $this->db->RollBackTrans();
1210 return false;
1214 // Delete the ACL
1215 $query = 'DELETE FROM '. $this->_db_table_prefix .'acl WHERE id='. $this->db->quote($acl_id);
1216 $this->debug_text('delete query: '. $query);
1217 $rs = $this->db->Execute($query);
1219 if (!is_object($rs)) {
1220 $this->debug_db('del_acl');
1221 $this->db->RollBackTrans();
1222 return false;
1225 $this->debug_text("del_acl(): deleted ACL ID: $acl_id");
1226 $this->db->CommitTrans();
1228 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1229 //Expire all cache.
1230 $this->Cache_Lite->clean('default');
1233 return TRUE;
1239 * Groups
1244 * sort_groups()
1246 * Grabs all the groups from the database doing preliminary grouping by parent
1248 * @return array Returns 2-Dimensional array: $array[<parent_id>][<group_id>] = <group_name>
1250 * @param string Group Type, either 'ARO' or 'AXO'
1252 function sort_groups($group_type='ARO') {
1254 switch(strtolower(trim($group_type))) {
1255 case 'axo':
1256 $table = $this->_db_table_prefix .'axo_groups';
1257 break;
1258 default:
1259 $table = $this->_db_table_prefix .'aro_groups';
1260 break;
1263 //Grab all groups from the database.
1264 $query = 'SELECT id, parent_id, name FROM '. $table .' ORDER BY parent_id, name';
1265 $rs = $this->db->Execute($query);
1267 if (!is_object($rs)) {
1268 $this->debug_db('sort_groups');
1269 return false;
1273 * Save groups in an array sorted by parent. Should be make it easier for later on.
1275 $sorted_groups = array();
1277 while ($row = $rs->FetchRow()) {
1278 $id = &$row[0];
1279 $parent_id = &$row[1];
1280 $name = &$row[2];
1282 $sorted_groups[$parent_id][$id] = $name;
1285 return $sorted_groups;
1289 * format_groups()
1291 * Takes the array returned by sort_groups() and formats for human
1292 * consumption. Recursively calls itself to produce the desired output.
1294 * @return array Array of formatted text, ordered by group id, formatted according to $type
1296 * @param array Output from gacl_api->sorted_groups($group_type)
1297 * @param array Output type desired, either 'TEXT', 'HTML', or 'ARRAY'
1298 * @param int Root of tree to produce
1299 * @param int Current level of depth
1300 * @param array Pass the current formatted groups object for appending via recursion.
1302 function format_groups($sorted_groups, $type='TEXT', $root_id=0, $level=0, $formatted_groups=NULL) {
1303 if ( !is_array ($sorted_groups) ) {
1304 return FALSE;
1307 if ( !is_array ($formatted_groups) ) {
1308 $formatted_groups = array ();
1311 //$this->showarray($formatted_groups);
1313 if (isset($sorted_groups[$root_id])) {
1314 //$last_id = end( array_keys($sorted_groups[$root_id]));
1315 //PHP5 compatibility
1316 $keys = array_keys($sorted_groups[$root_id]);
1317 $last_id = end($keys);
1318 unset($keys);
1320 foreach ($sorted_groups[$root_id] as $id => $name) {
1321 switch (strtoupper($type)) {
1322 case 'TEXT':
1324 * Formatting optimized for TEXT (combo box) output.
1327 if ( is_numeric($level) ) {
1328 $level = str_repeat('&nbsp;&nbsp; ', $level);
1331 if ( strlen($level) >= 8 ) {
1332 if ( $id == $last_id ) {
1333 $spacing = substr($level, 0, -8) .'\'- ';
1334 $level = substr($level, 0, -8) .'&nbsp;&nbsp; ';
1335 } else {
1336 $spacing = substr($level, 0, -8) .'|- ';
1338 } else {
1339 $spacing = $level;
1342 $next = $level .'|&nbsp; ';
1343 $text = $spacing.htmlspecialchars($name,ENT_QUOTES);
1344 break;
1345 case 'HTML':
1347 * Formatting optimized for HTML (tables) output.
1349 $width= $level * 20;
1350 $spacing = "<img src=\"s.gif\" width=\"$width\">";
1351 $next = $level + 1;
1352 $text = $spacing." ".htmlspecialchars($name,ENT_QUOTES);
1353 break;
1354 case 'ARRAY':
1355 $next = $level;
1356 $text = $name;
1357 break;
1358 default:
1359 return FALSE;
1362 $formatted_groups[$id] = $text;
1364 * Recurse if we can.
1367 //if (isset($sorted_groups[$id]) AND count($sorted_groups[$id]) > 0) {
1368 if (isset($sorted_groups[$id]) ) {
1369 //$this->debug_text("format_groups(): Recursing! Level: $level");
1370 $formatted_groups = $this->format_groups($sorted_groups, $type, $id, $next, $formatted_groups);
1371 } else {
1372 //$this->debug_text("format_groups(): Found last branch!");
1377 //$this->debug_text("format_groups(): Returning final array.");
1379 return $formatted_groups;
1383 * get_group_id()
1385 * Gets the group_id given the name or value.
1387 * Will only return one group id, so if there are duplicate names, it will return false.
1389 * @return int Returns Group ID if found and Group ID is unique in database, otherwise, returns FALSE
1391 * @param string Group Value
1392 * @param string Group Name
1393 * @param string Group Type, either 'ARO' or 'AXO'
1395 function get_group_id($value = NULL, $name = NULL, $group_type = 'ARO') {
1397 $this->debug_text("get_group_id(): Value: $value, Name: $name, Type: $group_type" );
1399 switch(strtolower(trim($group_type))) {
1400 case 'axo':
1401 $table = $this->_db_table_prefix .'axo_groups';
1402 break;
1403 default:
1404 $table = $this->_db_table_prefix .'aro_groups';
1405 break;
1408 $name = trim($name);
1409 $value = trim($value);
1411 if (empty($name) AND empty($value) ) {
1412 $this->debug_text("get_group_id(): name and value, at least one is required");
1413 return false;
1416 $query = 'SELECT id FROM '. $table .' WHERE ';
1417 if ( !empty($value) ) {
1418 $query .= ' value='. $this->db->quote($value);
1419 } else {
1420 $query .= ' name='. $this->db->quote($name);
1422 $rs = $this->db->Execute($query);
1424 if (!is_object($rs)) {
1425 $this->debug_db('get_group_id');
1426 return false;
1429 $row_count = $rs->RecordCount();
1431 if ($row_count > 1) {
1432 $this->debug_text("get_group_id(): Returned $row_count rows, can only return one. Please make your names unique.");
1433 return false;
1436 if ($row_count == 0) {
1437 $this->debug_text("get_group_id(): Returned $row_count rows");
1438 return false;
1441 $row = $rs->FetchRow();
1443 //Return the ID.
1444 return $row[0];
1448 * get_group_children()
1450 * Gets a groups child IDs
1452 * @return array Array of Child ID's of the referenced group
1454 * @param int Group ID #
1455 * @param int Group Type, either 'ARO' or 'AXO'
1456 * @param string Either 'RECURSE' or 'NO_RECURSE', to recurse while fetching group children.
1458 function get_group_children($group_id, $group_type = 'ARO', $recurse = 'NO_RECURSE') {
1459 $this->debug_text("get_group_children(): Group_ID: $group_id Group Type: $group_type Recurse: $recurse");
1461 switch (strtolower(trim($group_type))) {
1462 case 'axo':
1463 $group_type = 'axo';
1464 $table = $this->_db_table_prefix .'axo_groups';
1465 break;
1466 default:
1467 $group_type = 'aro';
1468 $table = $this->_db_table_prefix .'aro_groups';
1471 if (empty($group_id)) {
1472 $this->debug_text("get_group_children(): ID ($group_id) is empty, this is required");
1473 return FALSE;
1476 $query = '
1477 SELECT g1.id
1478 FROM '. $table .' g1';
1480 //FIXME-mikeb: Why is group_id in quotes?
1481 switch (strtoupper($recurse)) {
1482 case 'RECURSE':
1483 $query .= '
1484 LEFT JOIN '. $table .' g2 ON g2.lft<g1.lft AND g2.rgt>g1.rgt
1485 WHERE g2.id='. $this->db->quote($group_id);
1486 break;
1487 default:
1488 $query .= '
1489 WHERE g1.parent_id='. $this->db->quote($group_id);
1492 $query .= '
1493 ORDER BY g1.value';
1495 return $this->db->GetCol($query);
1499 * get_group_data()
1501 * Gets the group data given the GROUP_ID.
1503 * @return array Returns numerically indexed array with the following columns:
1504 * - array[0] = (int) Group ID #
1505 * - array[1] = (int) Parent Group ID #
1506 * - array[2] = (string) Group Value
1507 * - array[3] = (string) Group Name
1508 * - array[4] = (int) lft MPTT Value
1509 * - array[5] = (int) rgt MPTT Value
1511 * @param int Group ID #
1512 * @param string Group Type, either 'ARO' or 'AXO'
1514 function get_group_data($group_id, $group_type = 'ARO') {
1516 $this->debug_text("get_group_data(): Group_ID: $group_id Group Type: $group_type");
1518 switch(strtolower(trim($group_type))) {
1519 case 'axo':
1520 $group_type = 'axo';
1521 $table = $this->_db_table_prefix .'axo_groups';
1522 break;
1523 default:
1524 $group_type = 'aro';
1525 $table = $this->_db_table_prefix .'aro_groups';
1526 break;
1529 if (empty($group_id) ) {
1530 $this->debug_text("get_group_data(): ID ($group_id) is empty, this is required");
1531 return false;
1534 $query = 'SELECT id, parent_id, value, name, lft, rgt FROM '. $table .' WHERE id='. $this->db->quote($group_id);
1535 //$rs = $this->db->Execute($query);
1536 $row = $this->db->GetRow($query);
1538 if ($row) {
1539 return $row;
1542 $this->debug_text("get_object_data(): Group does not exist.");
1543 return false;
1547 * get_group_parent_id()
1549 * Grabs the parent_id of a given group
1551 * @return int Parent ID of the Group
1553 * @param int Group ID #
1554 * @param string Group Type, either 'ARO' or 'AXO'
1556 function get_group_parent_id($id, $group_type='ARO') {
1558 $this->debug_text("get_group_parent_id(): ID: $id Group Type: $group_type");
1560 switch(strtolower(trim($group_type))) {
1561 case 'axo':
1562 $table = $this->_db_table_prefix .'axo_groups';
1563 break;
1564 default:
1565 $table = $this->_db_table_prefix .'aro_groups';
1566 break;
1569 if (empty($id) ) {
1570 $this->debug_text("get_group_parent_id(): ID ($id) is empty, this is required");
1571 return false;
1574 $query = 'SELECT parent_id FROM '. $table .' WHERE id='. $this->db->quote($id);
1575 $rs = $this->db->Execute($query);
1577 if (!is_object($rs)) {
1578 $this->debug_db('get_group_parent_id');
1579 return false;
1582 $row_count = $rs->RecordCount();
1584 if ($row_count > 1) {
1585 $this->debug_text("get_group_parent_id(): Returned $row_count rows, can only return one. Please make your names unique.");
1586 return false;
1589 if ($row_count == 0) {
1590 $this->debug_text("get_group_parent_id(): Returned $row_count rows");
1591 return false;
1594 $row = $rs->FetchRow();
1596 //Return the ID.
1597 return $row[0];
1602 * get_root_group_id ()
1604 * Grabs the id of the root group for the specified tree
1606 * @return int Root Group ID #
1608 * @param string Group Type, either 'ARO' or 'AXO'
1610 function get_root_group_id($group_type='ARO') {
1612 $this->debug_text('get_root_group_id(): Group Type: '. $group_type);
1614 switch (strtolower($group_type)) {
1615 case 'axo':
1616 $table = $this->_db_table_prefix .'axo_groups';
1617 break;
1618 case 'aro':
1619 $table = $this->_db_table_prefix .'aro_groups';
1620 break;
1621 default:
1622 $this->debug_text('get_root_group_id(): Invalid Group Type: '. $group_type);
1623 return FALSE;
1626 $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
1627 $rs = $this->db->Execute($query);
1629 if (!is_object($rs)) {
1630 $this->debug_db('get_root_group_id');
1631 return FALSE;
1634 $row_count = $rs->RecordCount();
1636 switch ($row_count) {
1637 case 1:
1638 $row = $rs->FetchRow();
1639 // Return the ID.
1640 return $row[0];
1641 case 0:
1642 $this->debug_text('get_root_group_id(): Returned 0 rows, you do not have a root group defined yet.');
1643 return FALSE;
1646 $this->debug_text('get_root_group_id(): Returned '. $row_count .' rows, can only return one. Your tree is very broken.');
1647 return FALSE;
1650 /*======================================================================*\
1651 Function: map_path_to_root()
1652 Purpose: Maps a unique path to root to a specific group. Each group can only have
1653 one path to root.
1654 \*======================================================================*/
1655 /** REMOVED **/
1656 /*======================================================================*\
1657 Function: put_path_to_root()
1658 Purpose: Writes the unique path to root to the database. There should really only be
1659 one path to root for each level "deep" the groups go. If the groups are branched
1660 10 levels deep, there should only be 10 unique path to roots. These of course
1661 overlap each other more and more the closer to the root/trunk they get.
1662 \*======================================================================*/
1663 /** REMOVED **/
1664 /*======================================================================*\
1665 Function: clean_path_to_root()
1666 Purpose: Cleans up any paths that are not being used.
1667 \*======================================================================*/
1668 /** REMOVED **/
1669 /*======================================================================*\
1670 Function: get_path_to_root()
1671 Purpose: Generates the path to root for a given group.
1672 \*======================================================================*/
1673 /** REMOVED **/
1676 * add_group()
1678 * Inserts a group, defaults to be on the "root" branch.
1680 * Since v3.3.x you can only create one group with Parent_ID=0
1681 * So, its a good idea to create a "Virtual Root" group with Parent_ID=0
1682 * Then assign other groups to that.
1684 * @return int New Group ID # if successful, FALSE if otherwise.
1686 * @param string Group Value
1687 * @param string Group Name
1688 * @param int Parent Group ID #
1689 * @param string Group Type, either 'ARO' or 'AXO'
1691 function add_group($value, $name, $parent_id=0, $group_type='ARO') {
1693 switch(strtolower(trim($group_type))) {
1694 case 'axo':
1695 $group_type = 'axo';
1696 $table = $this->_db_table_prefix .'axo_groups';
1697 break;
1698 default:
1699 $group_type = 'aro';
1700 $table = $this->_db_table_prefix .'aro_groups';
1701 break;
1704 $this->debug_text("add_group(): Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
1706 $name = trim($name);
1707 $value = trim($value);
1709 if ( $name == '' ) {
1710 $this->debug_text("add_group(): name ($name) OR parent id ($parent_id) is empty, this is required");
1711 return false;
1714 //This has to be outside the transaction, because the first time it is run, it will say the sequence
1715 //doesn't exist. Then try to create it, but the transaction will already by aborted by then.
1716 $insert_id = $this->db->GenID($this->_db_table_prefix.$group_type.'_groups_id_seq',10);
1717 if ( $value === '' ) {
1718 $value = $insert_id;
1721 $this->db->BeginTrans();
1723 // special case for root group
1724 if ($parent_id == 0) {
1725 // check a root group is not already defined
1726 $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
1727 $rs = $this->db->Execute($query);
1729 if (!is_object($rs)) {
1730 $this->debug_db('add_group');
1731 $this->db->RollBackTrans();
1732 return FALSE;
1735 if ($rs->RowCount() > 0) {
1736 $this->debug_text('add_group (): A root group already exists.');
1737 $this->db->RollBackTrans();
1738 return FALSE;
1741 $parent_lft = 0;
1742 $parent_rgt = 1;
1743 } else {
1744 if (empty($parent_id)) {
1745 $this->debug_text("add_group (): parent id ($parent_id) is empty, this is required");
1746 $this->db->RollbackTrans();
1747 return FALSE;
1750 // grab parent details from database
1751 $query = 'SELECT id, lft, rgt FROM '. $table .' WHERE id='. $this->db->quote($parent_id);
1752 $row = $this->db->GetRow($query);
1754 if (!is_array($row)) {
1755 $this->debug_db('add_group');
1756 $this->db->RollBackTrans();
1757 return FALSE;
1760 if (empty($row)) {
1761 $this->debug_text('add_group (): Parent ID: '. $parent_id .' not found.');
1762 $this->db->RollBackTrans();
1763 return FALSE;
1766 $parent_lft = &$row[1];
1767 $parent_rgt = &$row[2];
1769 // make room for the new group
1770 $query = 'UPDATE '. $table .' SET rgt=rgt+2 WHERE rgt>='. $this->db->quote($parent_rgt);
1771 $rs = $this->db->Execute($query);
1773 if (!is_object($rs)) {
1774 $this->debug_db('add_group');
1775 $this->db->RollBackTrans();
1776 return FALSE;
1779 $query = 'UPDATE '. $table .' SET lft=lft+2 WHERE lft>'. $this->db->quote($parent_rgt);
1780 $rs = $this->db->Execute($query);
1782 if (!is_object($rs)) {
1783 $this->debug_db('add_group');
1784 $this->db->RollBackTrans();
1785 return FALSE;
1789 $query = 'INSERT INTO '. $table .' (id,parent_id,name,value,lft,rgt) VALUES ('. $this->db->quote($insert_id) .','. $this->db->quote($parent_id) .','. $this->db->quote($name) .','. $this->db->quote($value) .','. $this->db->quote($parent_rgt) .','. $this->db->quote($parent_rgt + 1) .')';
1790 $rs = $this->db->Execute($query);
1792 if (!is_object($rs)) {
1793 $this->debug_db('add_group');
1794 $this->db->RollBackTrans();
1795 return FALSE;
1798 $this->db->CommitTrans();
1800 $this->debug_text('add_group (): Added group as ID: '. $insert_id);
1801 return $insert_id;
1805 * get_group_objects()
1807 * Gets all objects assigned to a group.
1809 * If $option == 'RECURSE' it will get all objects in child groups as well.
1810 * defaults to omit child groups.
1812 * @return array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1815 * @param int Group ID #
1816 * @param string Group Type, either 'ARO' or 'AXO'
1817 * @param string Option, either 'RECURSE' or 'NO_RECURSE'
1819 function get_group_objects($group_id, $group_type='ARO', $option='NO_RECURSE') {
1821 switch(strtolower(trim($group_type))) {
1822 case 'axo':
1823 $group_type = 'axo';
1824 $object_table = $this->_db_table_prefix .'axo';
1825 $group_table = $this->_db_table_prefix .'axo_groups';
1826 $map_table = $this->_db_table_prefix .'groups_axo_map';
1827 break;
1828 default:
1829 $group_type = 'aro';
1830 $object_table = $this->_db_table_prefix .'aro';
1831 $group_table = $this->_db_table_prefix .'aro_groups';
1832 $map_table = $this->_db_table_prefix .'groups_aro_map';
1833 break;
1836 $this->debug_text("get_group_objects(): Group ID: $group_id");
1838 if (empty($group_id)) {
1839 $this->debug_text("get_group_objects(): Group ID: ($group_id) is empty, this is required");
1840 return false;
1843 $query = '
1844 SELECT o.section_value,o.value';
1846 if ($option == 'RECURSE') {
1847 $query .= '
1848 FROM '. $group_table .' g2
1849 JOIN '. $group_table .' g1 ON g1.lft>=g2.lft AND g1.rgt<=g2.rgt
1850 JOIN '. $map_table .' gm ON gm.group_id=g1.id
1851 JOIN '. $object_table .' o ON o.id=gm.'. $group_type .'_id
1852 WHERE g2.id='. $this->db->quote($group_id);
1853 } else {
1854 $query .= '
1855 FROM '. $map_table .' gm
1856 JOIN '. $object_table .' o ON o.id=gm.'. $group_type .'_id
1857 WHERE gm.group_id='. $this->db->quote($group_id);
1860 $rs = $this->db->Execute($query);
1862 if (!is_object($rs)) {
1863 $this->debug_db('get_group_objects');
1864 return false;
1867 $this->debug_text("get_group_objects(): Got group objects, formatting array.");
1869 $retarr = array();
1871 //format return array.
1872 while ($row = $rs->FetchRow()) {
1873 $section = &$row[0];
1874 $value = &$row[1];
1876 $retarr[$section][] = $value;
1879 return $retarr;
1883 * add_group_object()
1885 * Assigns an Object to a group
1887 * @return bool Returns TRUE if successful, FALSE otherwise.
1889 * @param int Group ID #
1890 * @param string Object Section Value
1891 * @param string Object Value
1892 * @param string Group Type, either 'ARO' or 'AXO'
1894 function add_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
1896 switch(strtolower(trim($group_type))) {
1897 case 'axo':
1898 $group_type = 'axo';
1899 $table = $this->_db_table_prefix .'groups_axo_map';
1900 $object_table = $this->_db_table_prefix .'axo';
1901 $group_table = $this->_db_table_prefix .'axo_groups';
1902 break;
1903 default:
1904 $group_type = 'aro';
1905 $table = $this->_db_table_prefix .'groups_aro_map';
1906 $object_table = $this->_db_table_prefix .'aro';
1907 $group_table = $this->_db_table_prefix .'aro_groups';
1908 break;
1911 $this->debug_text("add_group_object(): Group ID: $group_id Section Value: $object_section_value Value: $object_value Group Type: $group_type");
1913 $object_section_value = trim($object_section_value);
1914 $object_value = trim($object_value);
1916 if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
1917 $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");
1918 return false;
1921 // test to see if object & group exist and if object is already a member
1922 $query = '
1923 SELECT o.id AS id,g.id AS group_id,gm.group_id AS `member`
1924 FROM '. $object_table .' o
1925 LEFT JOIN '. $group_table .' g ON g.id='. $this->db->quote($group_id) .'
1926 LEFT JOIN '. $table .' gm ON (gm.'. $group_type .'_id=o.id AND gm.group_id=g.id)
1927 WHERE (o.section_value='. $this->db->quote($object_section_value) .' AND o.value='. $this->db->quote($object_value) .')';
1928 $rs = $this->db->Execute($query);
1930 if (!is_object($rs)) {
1931 $this->debug_db('add_group_object');
1932 return FALSE;
1935 if ($rs->RecordCount() != 1) {
1936 $this->debug_text('add_group_object(): Value ('. $object_value .') OR Section value ('. $object_section_value .') is invalid. Does this object exist?');
1937 return FALSE;
1940 $row = $rs->FetchRow();
1942 if ($row[1] != $group_id) {
1943 $this->debug_text('add_group_object(): Group ID ('. $group_id .') is invalid. Does this group exist?');
1944 return FALSE;
1947 //Group_ID == Member
1948 if ($row[1] == $row[2]) {
1949 $this->debug_text('add_group_object(): Object: ('. $object_section_value .' -> '. $object_value .') is already a member of Group: ('. $group_id .')');
1950 //Object is already assigned to group. Return true.
1951 return TRUE;
1954 $object_id = $row[0];
1956 $query = 'INSERT INTO '. $table .' (group_id,'. $group_type .'_id) VALUES ('. $this->db->quote($group_id) .','. $this->db->quote($object_id) .')';
1957 $rs = $this->db->Execute($query);
1959 if (!is_object($rs)) {
1960 $this->debug_db('add_group_object');
1961 return FALSE;
1964 $this->debug_text('add_group_object(): Added Object: '. $object_id .' to Group ID: '. $group_id);
1966 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1967 //Expire all cache.
1968 $this->Cache_Lite->clean('default');
1971 return TRUE;
1975 * del_group_object()
1977 * Removes an Object from a group.
1979 * @return bool Returns TRUE if successful, FALSE otherwise
1981 * @param int Group ID #
1982 * @param string Object Section Value
1983 * @param string Object Value
1984 * @param string Group Type, either 'ARO' or 'AXO'
1986 function del_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
1988 switch(strtolower(trim($group_type))) {
1989 case 'axo':
1990 $group_type = 'axo';
1991 $table = $this->_db_table_prefix .'groups_axo_map';
1992 break;
1993 default:
1994 $group_type = 'aro';
1995 $table = $this->_db_table_prefix .'groups_aro_map';
1996 break;
1999 $this->debug_text("del_group_object(): Group ID: $group_id Section value: $object_section_value Value: $object_value");
2001 $object_section_value = trim($object_section_value);
2002 $object_value = trim($object_value);
2004 if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
2005 $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");
2006 return false;
2009 if (!$object_id = $this->get_object_id($object_section_value, $object_value, $group_type)) {
2010 $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?");
2011 return FALSE;
2014 $query = 'DELETE FROM '. $table .' WHERE group_id='. $this->db->quote($group_id) .' AND '. $group_type .'_id='. $this->db->quote($object_id);
2015 $rs = $this->db->Execute($query);
2017 if (!is_object($rs)) {
2018 $this->debug_db('del_group_object');
2019 return false;
2022 $this->debug_text("del_group_object(): Deleted Value: $object_value to Group ID: $group_id assignment");
2024 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2025 //Expire all cache.
2026 $this->Cache_Lite->clean('default');
2029 return true;
2033 * edit_group()
2035 * Edits a group
2037 * @returns bool Returns TRUE if successful, FALSE otherwise
2039 * @param int Group ID #
2040 * @param string Group Value
2041 * @param string Group Name
2042 * @param int Parent ID #
2043 * @param string Group Type, either 'ARO' or 'AXO'
2045 function edit_group($group_id, $value=NULL, $name=NULL, $parent_id=NULL, $group_type='ARO') {
2046 $this->debug_text("edit_group(): ID: $group_id Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
2048 switch(strtolower(trim($group_type))) {
2049 case 'axo':
2050 $group_type = 'axo';
2051 $table = $this->_db_table_prefix .'axo_groups';
2052 break;
2053 default:
2054 $group_type = 'aro';
2055 $table = $this->_db_table_prefix .'aro_groups';
2056 break;
2059 if (empty($group_id) ) {
2060 $this->debug_text('edit_group(): Group ID ('. $group_id .') is empty, this is required');
2061 return FALSE;
2064 if ( !is_array($curr = $this->get_group_data($group_id, $group_type)) ) {
2065 $this->debug_text('edit_group(): Invalid Group ID: '. $group_id);
2066 return FALSE;
2069 $name = trim($name);
2071 // don't set name if it is unchanged
2072 if ($name == $curr[3]) {
2073 unset($name);
2076 // don't set parent_id if it is unchanged
2077 if ($parent_id == $curr[1]) {
2078 unset($parent_id);
2081 if (!empty($parent_id)) {
2082 if ($group_id == $parent_id) {
2083 $this->debug_text('edit_group(): Groups can\'t be a parent to themselves. Incest is bad. ;)');
2084 return FALSE;
2087 //Make sure we don't re-parent to our own children.
2088 //Grab all children of this group_id.
2089 $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
2090 if (is_array($children_ids)) {
2091 if (@in_array($parent_id, $children_ids) ) {
2092 $this->debug_text('edit_group(): Groups can\'t be re-parented to their own children, this would be incestuous!');
2093 return FALSE;
2096 unset($children_ids);
2098 // make sure parent exists
2099 if (!$this->get_group_data($parent_id, $group_type)) {
2100 $this->debug_text('edit_group(): Parent Group ('. $parent_id .') doesn\'t exist');
2101 return FALSE;
2105 $set = array();
2107 // update name if it is specified.
2108 if (!empty($name)) {
2109 $set[] = 'name='. $this->db->quote($name);
2112 // update parent_id if it is specified.
2113 if (!empty($parent_id)) {
2114 $set[] = 'parent_id='. $this->db->quote($parent_id);
2117 // update value if it is specified.
2118 if (!empty($value)) {
2119 $set[] = 'value='. $this->db->quote($value);
2122 if (empty($set)) {
2123 $this->debug_text('edit_group(): Nothing to update.');
2124 return FALSE;
2127 $this->db->BeginTrans();
2129 $query = 'UPDATE '. $table .' SET '. implode(',', $set) .' WHERE id='. $this->db->quote($group_id);
2130 $rs = $this->db->Execute($query);
2132 if (!is_object($rs)) {
2133 $this->debug_db('edit_group');
2134 $this->db->RollbackTrans();
2135 return FALSE;
2138 $this->debug_text('edit_group(): Modified group ID: '. $group_id);
2140 // rebuild group tree if parent_id has changed
2141 if (!empty($parent_id)) {
2142 if (!$this->_rebuild_tree($table, $this->get_root_group_id($group_type))) {
2143 $this->db->RollbackTrans();
2144 return FALSE;
2148 $this->db->CommitTrans();
2150 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2151 // Expire all cache.
2152 $this->Cache_Lite->clean('default');
2155 return TRUE;
2159 * rebuild_tree ()
2161 * rebuilds the group tree for the given type
2163 * @return bool Returns TRUE if successful, FALSE otherwise
2165 * @param string Group Type, either 'ARO' or 'AXO'
2166 * @param int Group ID #
2167 * @param int Left value of Group
2169 function rebuild_tree($group_type = 'ARO', $group_id = NULL, $left = 1) {
2170 $this->debug_text("rebuild_tree(): Group Type: $group_type Group ID: $group_id Left: $left");
2172 switch (strtolower(trim($group_type))) {
2173 case 'axo':
2174 $group_type = 'axo';
2175 $table = $this->_db_table_prefix .'axo_groups';
2176 break;
2177 default:
2178 $group_type = 'aro';
2179 $table = $this->_db_table_prefix .'aro_groups';
2180 break;
2183 if (!isset($group_id)) {
2184 if ($group_id = $this->get_root_group_id($group_type)) {
2185 $left = 1;
2186 $this->debug_text('rebuild_tree(): No Group ID Specified, using Root Group ID: '. $group_id);
2187 } else {
2188 $this->debug_text('rebuild_tree(): A Root group could not be found, are there any groups defined?');
2189 return FALSE;
2193 $this->db->BeginTrans();
2194 $rebuilt = $this->_rebuild_tree($table, $group_id, $left);
2196 if ($rebuilt === FALSE) {
2197 $this->debug_text('rebuild_tree(): Error rebuilding tree!');
2198 $this->db->RollBackTrans();
2199 return FALSE;
2202 $this->db->CommitTrans();
2203 $this->debug_text('rebuild_tree(): Tree rebuilt.');
2204 return TRUE;
2207 * _rebuild_tree ()
2209 * Utility recursive function called by rebuild_tree()
2211 * @return int Returns right value of this node + 1
2213 * @param string Table name of group type
2214 * @param int Group ID #
2215 * @param int Left value of Group
2217 function _rebuild_tree($table, $group_id, $left = 1) {
2218 $this->debug_text("_rebuild_tree(): Table: $table Group ID: $group_id Left: $left");
2220 // get all children of this node
2221 $query = 'SELECT id FROM '. $table .' WHERE parent_id='. $this->db->quote($group_id);
2222 $rs = $this->db->Execute($query);
2224 if (!is_object($rs)) {
2225 $this->debug_db('_rebuild_tree');
2226 return FALSE;
2229 // the right value of this node is the left value + 1
2230 $right = $left + 1;
2232 while ($row = $rs->FetchRow()) {
2233 // recursive execution of this function for each
2234 // child of this node
2235 // $right is the current right value, which is
2236 // incremented by the rebuild_tree function
2237 $right = $this->_rebuild_tree($table, $row[0], $right);
2239 if ($right === FALSE) {
2240 return FALSE;
2244 // we've got the left value, and now that we've processed
2245 // the children of this node we also know the right value
2246 $query = 'UPDATE '. $table .' SET lft='. $this->db->quote($left) .', rgt='. $this->db->quote($right) .' WHERE id='. $this->db->quote($group_id);
2247 $rs = $this->db->Execute($query);
2249 if (!is_object($rs)) {
2250 $this->debug_db('_rebuild_tree');
2251 return FALSE;
2254 // return the right value of this node + 1
2255 return $right + 1;
2259 * del_group()
2261 * deletes a given group
2263 * @return bool Returns TRUE if successful, FALSE otherwise.
2265 * @param int Group ID #
2266 * @param bool If TRUE, child groups of this group will be reparented to the current group's parent.
2267 * @param string Group Type, either 'ARO' or 'AXO'
2269 function del_group($group_id, $reparent_children=TRUE, $group_type='ARO') {
2271 switch(strtolower(trim($group_type))) {
2272 case 'axo':
2273 $group_type = 'axo';
2274 $table = $this->_db_table_prefix .'axo_groups';
2275 $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
2276 $groups_object_map_table = $this->_db_table_prefix .'groups_axo_map';
2277 break;
2278 default:
2279 $group_type = 'aro';
2280 $table = $this->_db_table_prefix .'aro_groups';
2281 $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
2282 $groups_object_map_table = $this->_db_table_prefix .'groups_aro_map';
2283 break;
2286 $this->debug_text("del_group(): ID: $group_id Reparent Children: $reparent_children Group Type: $group_type");
2288 if (empty($group_id) ) {
2289 $this->debug_text("del_group(): Group ID ($group_id) is empty, this is required");
2290 return false;
2293 // Get details of this group
2294 $query = 'SELECT id, parent_id, name, lft, rgt FROM '. $table .' WHERE id='. $this->db->quote($group_id);
2295 $group_details = $this->db->GetRow($query);
2297 if (!is_array($group_details)) {
2298 $this->debug_db('del_group');
2299 return false;
2302 $parent_id = $group_details[1];
2304 $left = $group_details[3];
2305 $right = $group_details[4];
2307 $this->db->BeginTrans();
2309 // grab list of all children
2310 $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
2312 // prevent deletion of root group & reparent of children if it has more than one immediate child
2313 if ($parent_id == 0) {
2314 $query = 'SELECT count(*) FROM '. $table .' WHERE parent_id='. $this->db->quote($group_id);
2315 $child_count = $this->db->GetOne($query);
2317 if (($child_count > 1) AND $reparent_children) {
2318 $this->debug_text ('del_group (): You cannot delete the root group and reparent children, this would create multiple root groups.');
2319 $this->db->RollbackTrans();
2320 return FALSE;
2324 $success = FALSE;
2327 * Handle children here.
2329 switch (TRUE) {
2330 // there are no child groups, just delete group
2331 case !is_array($children_ids):
2332 case count($children_ids) == 0:
2333 // remove acl maps
2334 $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $this->db->quote($group_id);
2335 $rs = $this->db->Execute($query);
2337 if (!is_object($rs)) {
2338 break;
2341 // remove group object maps
2342 $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $this->db->quote($group_id);
2343 $rs = $this->db->Execute($query);
2345 if (!is_object($rs)) {
2346 break;
2349 // remove group
2350 $query = 'DELETE FROM '. $table .' WHERE id='. $this->db->quote($group_id);
2351 $rs = $this->db->Execute($query);
2353 if (!is_object($rs)) {
2354 break;
2357 // move all groups right of deleted group left by width of deleted group
2358 $query = 'UPDATE '. $table .' SET lft=lft-' . ($right-$left+1) . ' WHERE lft>'. $this->db->quote($right);
2359 $rs = $this->db->Execute($query);
2361 if (!is_object($rs)) {
2362 break;
2365 $query = 'UPDATE '. $table .' SET rgt=rgt-' . ($right-$left+1) . ' WHERE rgt>'. $this->db->quote($right);
2366 $rs = $this->db->Execute($query);
2368 if (!is_object($rs)) {
2369 break;
2372 $success = TRUE;
2373 break;
2374 case $reparent_children == TRUE:
2375 // remove acl maps
2376 $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $this->db->quote($group_id);
2377 $rs = $this->db->Execute($query);
2379 if (!is_object($rs)) {
2380 break;
2383 // remove group object maps
2384 $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $this->db->quote($group_id);
2385 $rs = $this->db->Execute($query);
2387 if (!is_object($rs)) {
2388 break;
2391 // remove group
2392 $query = 'DELETE FROM '. $table .' WHERE id='. $this->db->quote($group_id);
2393 $rs = $this->db->Execute($query);
2395 if (!is_object($rs)) {
2396 break;
2399 // set parent of immediate children to parent group
2400 $query = 'UPDATE '. $table .' SET parent_id='. $this->db->quote($parent_id) .' WHERE parent_id='. $this->db->quote($group_id);
2401 $rs = $this->db->Execute($query);
2403 if (!is_object($rs)) {
2404 break;
2407 // move all children left by 1
2408 $query = 'UPDATE '. $table .' SET lft=lft-1, rgt=rgt-1 WHERE lft>'. $this->db->quote($left) .' AND rgt<'. $this->db->quote($right);
2409 $rs = $this->db->Execute($query);
2411 if (!is_object($rs)) {
2412 break;
2415 // move all groups right of deleted group left by 2
2416 $query = 'UPDATE '. $table .' SET lft=lft-2 WHERE lft>'. $this->db->quote($right);
2417 $rs = $this->db->Execute($query);
2419 if (!is_object($rs)) {
2420 break;
2423 $query = 'UPDATE '. $table .' SET rgt=rgt-2 WHERE rgt>'. $this->db->quote($right);
2424 $rs = $this->db->Execute($query);
2426 if (!is_object($rs)) {
2427 break;
2430 $success = TRUE;
2431 break;
2432 default:
2433 // make list of group and all children
2434 $group_ids = $children_ids;
2435 $group_ids[] = $group_id;
2437 // remove acl maps
2438 $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
2439 $rs = $this->db->Execute($query);
2441 if (!is_object($rs)) {
2442 break;
2445 // remove group object maps
2446 $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
2447 $rs = $this->db->Execute($query);
2449 if (!is_object($rs)) {
2450 break;
2453 // remove groups
2454 $query = 'DELETE FROM '. $table .' WHERE id IN ('. implode (',', $group_ids) .')';
2455 $rs = $this->db->Execute($query);
2457 if (!is_object($rs)) {
2458 break;
2461 // move all groups right of deleted group left by width of deleted group
2462 $query = 'UPDATE '. $table .' SET lft=lft-'. ($right - $left + 1) . ' WHERE lft>' . $this->db->quote($right);
2463 $rs = $this->db->Execute($query);
2465 if (!is_object($rs)) {
2466 break;
2469 $query = 'UPDATE '. $table .' SET rgt=rgt-'. ($right - $left + 1) . ' WHERE rgt>' . $this->db->quote($right);
2470 $rs = $this->db->Execute($query);
2472 if (!is_object($rs)) {
2473 break;
2476 $success = TRUE;
2479 // if the delete failed, rollback the trans and return false
2480 if (!$success) {
2482 $this->debug_db('del_group');
2483 $this->db->RollBackTrans();
2484 return false;
2487 $this->debug_text("del_group(): deleted group ID: $group_id");
2488 $this->db->CommitTrans();
2490 if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2491 //Expire all cache.
2492 $this->Cache_Lite->clean('default');
2495 return true;
2502 * Objects (ACO/ARO/AXO)
2507 * get_object()
2509 * Grabs all Objects's in the database, or specific to a section_value
2511 * @return ADORecordSet Returns recordset directly, with object ID only selected:
2513 * @param string Filter to this section value
2514 * @param int Returns hidden objects if 1, leaves them out otherwise.
2515 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
2517 function get_object($section_value = null, $return_hidden=1, $object_type=NULL) {
2519 switch(strtolower(trim($object_type))) {
2520 case 'aco':
2521 $object_type = 'aco';
2522 $table = $this->_db_table_prefix .'aco';
2523 break;
2524 case 'aro':
2525 $object_type = 'aro';
2526 $table = $this->_db_table_prefix .'aro';
2527 break;
2528 case 'axo':
2529 $object_type = 'axo';
2530 $table = $this->_db_table_prefix .'axo';
2531 break;
2532 case 'acl':
2533 $object_type = 'acl';
2534 $table = $this->_db_table_prefix .'acl';
2535 break;
2536 default:
2537 $this->debug_text('get_object(): Invalid Object Type: '. $object_type);
2538 return FALSE;
2541 $this->debug_text("get_object(): Section Value: $section_value Object Type: $object_type");
2543 $query = 'SELECT id FROM '. $table;
2545 $where = array();
2547 if (!empty($section_value)) {
2548 $where[] = 'section_value='. $this->db->quote($section_value);
2551 if ($return_hidden==0 AND $object_type != 'acl') {
2552 $where[] = 'hidden=0';
2555 if (!empty($where)) {
2556 $query .= ' WHERE '. implode(' AND ', $where);
2559 $rs = $this->db->GetCol($query);
2561 if (!is_array($rs)) {
2562 $this->debug_db('get_object');
2563 return false;
2566 // Return Object IDs
2567 return $rs;
2570 * get_ungrouped_objects()
2572 * Grabs ID's of all Objects (ARO's and AXO's only) in the database not assigned to a Group.
2574 * This function is useful for applications that synchronize user databases with an outside source.
2575 * If syncrhonization doesn't automatically place users in an appropriate group, this function can
2576 * quickly identify them so that they can be assigned to the correct group.
2578 * @return array Returns an array of object ID's
2580 * @param int Returns hidden objects if 1, does not if 0.
2581 * @param string Object Type, either 'ARO' or 'AXO' (groupable types)
2584 function get_ungrouped_objects($return_hidden=1, $object_type=NULL) {
2586 switch(strtolower(trim($object_type))) {
2587 case 'aro':
2588 $object_type = 'aro';
2589 $table = $this->_db_table_prefix .'aro';
2590 break;
2591 case 'axo':
2592 $object_type = 'axo';
2593 $table = $this->_db_table_prefix .'axo';
2594 break;
2595 default:
2596 $this->debug_text('get_ungrouped_objects(): Invalid Object Type: '. $object_type);
2597 return FALSE;
2600 $this->debug_text("get_ungrouped_objects(): Object Type: $object_type");
2602 $query = 'SELECT id FROM '. $table. ' a
2603 LEFT JOIN ' . $this->_db_table_prefix. 'groups_'.$object_type.'_map b ON a.id = b.'. $object_type .'_id';
2605 $where = array();
2606 $where[] = 'b.group_id IS NULL';
2608 if ($return_hidden==0) {
2609 $where[] = 'a.hidden=0';
2612 if (!empty($where)) {
2613 $query .= ' WHERE '. implode(' AND ', $where);
2616 $rs = $this->db->Execute($query);
2618 if (!is_object($rs)) {
2619 $this->debug_db('get_ungrouped_objects');
2620 return false;
2623 while(!$rs->EOF) {
2624 $retarr[] = $rs->fields[0];
2625 $rs->MoveNext();
2628 // Return Array of object IDS
2629 return $retarr;
2634 * get_objects ()
2636 * Grabs all Objects in the database, or specific to a section_value
2638 * @return array Returns objects in format suitable for add_acl and is_conflicting_acl
2639 * - i.e. Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
2641 * @param string Filter for section value
2642 * @param int Returns hidden objects if 1, does not if 0
2643 * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2645 function get_objects($section_value = NULL, $return_hidden = 1, $object_type = NULL) {
2646 switch (strtolower(trim($object_type))) {
2647 case 'aco':
2648 $object_type = 'aco';
2649 $table = $this->_db_table_prefix .'aco';
2650 break;
2651 case 'aro':
2652 $object_type = 'aro';
2653 $table = $this->_db_table_prefix .'aro';
2654 break;
2655 case 'axo':
2656 $object_type = 'axo';
2657 $table = $this->_db_table_prefix .'axo';
2658 break;
2659 default:
2660 $this->debug_text('get_objects(): Invalid Object Type: '. $object_type);
2661 return FALSE;
2664 $this->debug_text("get_objects(): Section Value: $section_value Object Type: $object_type");
2666 $query = 'SELECT section_value,value FROM '. $table;
2668 $where = array();
2670 if (!empty($section_value)) {
2671 $where[] = 'section_value='. $this->db->quote($section_value);
2674 if ($return_hidden==0) {
2675 $where[] = 'hidden=0';
2678 if (!empty($where)) {
2679 $query .= ' WHERE '. implode(' AND ', $where);
2682 $rs = $this->db->Execute($query);
2684 if (!is_object($rs)) {
2685 $this->debug_db('get_objects');
2686 return FALSE;
2689 $retarr = array();
2691 while ($row = $rs->FetchRow()) {
2692 $retarr[$row[0]][] = $row[1];
2695 // Return objects
2696 return $retarr;
2700 * get_object_data()
2702 * Gets all data pertaining to a specific Object.
2704 * @return array Returns 2-Dimensional array of rows with columns = ( section_value, value, order_value, name, hidden )
2706 * @param int Object ID #
2707 * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2709 function get_object_data($object_id, $object_type=NULL) {
2711 switch(strtolower(trim($object_type))) {
2712 case 'aco':
2713 $object_type = 'aco';
2714 $table = $this->_db_table_prefix .'aco';
2715 break;
2716 case 'aro':
2717 $object_type = 'aro';
2718 $table = $this->_db_table_prefix .'aro';
2719 break;
2720 case 'axo':
2721 $object_type = 'axo';
2722 $table = $this->_db_table_prefix .'axo';
2723 break;
2724 default:
2725 $this->debug_text('get_object_data(): Invalid Object Type: '. $object_type);
2726 return FALSE;
2729 $this->debug_text("get_object_data(): Object ID: $object_id Object Type: $object_type");
2731 if (empty($object_id) ) {
2732 $this->debug_text("get_object_data(): Object ID ($object_id) is empty, this is required");
2733 return false;
2736 if (empty($object_type) ) {
2737 $this->debug_text("get_object_data(): Object Type ($object_type) is empty, this is required");
2738 return false;
2741 $query = 'SELECT section_value,value,order_value,name,hidden FROM '. $table .' WHERE id='. $this->db->quote($object_id);
2742 $rs = $this->db->Execute($query);
2744 if (!is_object($rs)) {
2745 $this->debug_db('get_object_data');
2746 return false;
2749 if ($rs->RecordCount() < 1) {
2750 $this->debug_text('get_object_data(): Returned '. $row_count .' rows');
2751 return FALSE;
2754 // Return all objects
2755 return $rs->GetRows();
2759 * get_object_id()
2761 * Gets the object_id given the section_value AND value of the object.
2763 * @return int Object ID #
2765 * @param string Object Section Value
2766 * @param string Object Value
2767 * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2769 function get_object_id($section_value, $value, $object_type=NULL) {
2771 switch(strtolower(trim($object_type))) {
2772 case 'aco':
2773 $object_type = 'aco';
2774 $table = $this->_db_table_prefix .'aco';
2775 break;
2776 case 'aro':
2777 $object_type = 'aro';
2778 $table = $this->_db_table_prefix .'aro';
2779 break;
2780 case 'axo':
2781 $object_type = 'axo';
2782 $table = $this->_db_table_prefix .'axo';
2783 break;
2784 default:
2785 $this->debug_text('get_object_id(): Invalid Object Type: '. $object_type);
2786 return FALSE;
2789 $this->debug_text("get_object_id(): Section Value: $section_value Value: $value Object Type: $object_type");
2791 $section_value = trim($section_value);
2792 $value = trim($value);
2794 if (empty($section_value) AND empty($value) ) {
2795 $this->debug_text("get_object_id(): Section Value ($value) AND value ($value) is empty, this is required");
2796 return false;
2799 if (empty($object_type) ) {
2800 $this->debug_text("get_object_id(): Object Type ($object_type) is empty, this is required");
2801 return false;
2804 $query = 'SELECT id FROM '. $table .' WHERE section_value='. $this->db->quote($section_value) .' AND value='. $this->db->quote($value);
2805 $rs = $this->db->Execute($query);
2807 if (!is_object($rs)) {
2808 $this->debug_db('get_object_id');
2809 return false;
2812 $row_count = $rs->RecordCount();
2814 if ($row_count > 1) {
2815 $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.");
2816 return false;
2819 if ($row_count == 0) {
2820 $this->debug_text("get_object_id(): Returned $row_count rows");
2821 return false;
2824 $row = $rs->FetchRow();
2826 //Return the ID.
2827 return $row[0];
2831 * get_object_section_value()
2833 * Gets the object_section_value given object id
2835 * @return string Object Section Value
2837 * @param int Object ID #
2838 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
2840 function get_object_section_value($object_id, $object_type=NULL) {
2842 switch(strtolower(trim($object_type))) {
2843 case 'aco':
2844 $object_type = 'aco';
2845 $table = $this->_db_table_prefix .'aco';
2846 break;
2847 case 'aro':
2848 $object_type = 'aro';
2849 $table = $this->_db_table_prefix .'aro';
2850 break;
2851 case 'axo':
2852 $object_type = 'axo';
2853 $table = $this->_db_table_prefix .'axo';
2854 break;
2855 default:
2856 $this->debug_text('get_object_section_value(): Invalid Object Type: '. $object_type);
2857 return FALSE;
2860 $this->debug_text("get_object_section_value(): Object ID: $object_id Object Type: $object_type");
2862 if (empty($object_id) ) {
2863 $this->debug_text("get_object_section_value(): Object ID ($object_id) is empty, this is required");
2864 return false;
2867 if (empty($object_type) ) {
2868 $this->debug_text("get_object_section_value(): Object Type ($object_type) is empty, this is required");
2869 return false;
2872 $query = 'SELECT section_value FROM '. $table .' WHERE id='. $this->db->quote($object_id);
2873 $rs = $this->db->Execute($query);
2875 if (!is_object($rs)) {
2876 $this->debug_db('get_object_section_value');
2877 return false;
2880 $row_count = $rs->RecordCount();
2882 if ($row_count > 1) {
2883 $this->debug_text("get_object_section_value(): Returned $row_count rows, can only return one.");
2884 return false;
2887 if ($row_count == 0) {
2888 $this->debug_text("get_object_section_value(): Returned $row_count rows");
2889 return false;
2892 $row = $rs->FetchRow();
2894 //Return the ID.
2895 return $row[0];
2899 * get_object_groups()
2901 * Gets all groups an object is a member of.
2903 * If $option == 'RECURSE' it will get all ancestor groups.
2904 * defaults to only get direct parents.
2906 * @return array Array of Group ID #'s, or FALSE if Failed
2908 * @param int Object ID #
2909 * @param string Object Type, either 'ARO' or 'AXO'
2910 * @param string Option, either 'RECURSE', or 'NO_RECURSE'
2912 function get_object_groups($object_id, $object_type = 'ARO', $option = 'NO_RECURSE') {
2913 $this->debug_text('get_object_groups(): Object ID: '. $object_id .' Object Type: '. $object_type .' Option: '. $option);
2915 switch(strtolower(trim($object_type))) {
2916 case 'axo':
2917 $object_type = 'axo';
2918 $group_table = $this->_db_table_prefix .'axo_groups';
2919 $map_table = $this->_db_table_prefix .'groups_axo_map';
2920 break;
2921 case 'aro':
2922 $object_type = 'aro';
2923 $group_table = $this->_db_table_prefix .'aro_groups';
2924 $map_table = $this->_db_table_prefix .'groups_aro_map';
2925 break;
2926 default:
2927 $this->debug_text('get_object_groups(): Invalid Object Type: '. $object_type);
2928 return FALSE;
2931 if (empty($object_id)) {
2932 $this->debug_text('get_object_groups(): Object ID: ('. $object_id .') is empty, this is required');
2933 return FALSE;
2936 if (strtoupper($option) == 'RECURSE') {
2937 $query = '
2938 SELECT DISTINCT g.id AS group_id
2939 FROM '. $map_table .' gm
2940 LEFT JOIN '. $group_table .' g1 ON g1.id=gm.group_id
2941 LEFT JOIN '. $group_table .' g ON g.lft<=g1.lft AND g.rgt>=g1.rgt';
2942 } else {
2943 $query = '
2944 SELECT gm.group_id
2945 FROM '. $map_table .' gm';
2948 $query .= '
2949 WHERE gm.'. $object_type .'_id='. $this->db->quote($object_id);
2950 $rs = $this->db->Execute($query);
2952 if (!is_object($rs)) {
2953 $this->debug_db('get_object_groups');
2954 return FALSE;
2957 $retarr = array();
2959 while ($row = $rs->FetchRow()) {
2960 $retarr[] = $row[0];
2963 return $retarr;
2967 * add_object()
2969 * Inserts a new object
2971 * @return int Returns the ID # of the new object if successful, FALSE otherwise
2973 * @param string Object Section Value
2974 * @param string Object Name
2975 * @param string Object Value
2976 * @param int Display Order
2977 * @param int Hidden Flag, either 1 to hide, or 0 to show.
2978 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
2980 function add_object($section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
2982 switch(strtolower(trim($object_type))) {
2983 case 'aco':
2984 $object_type = 'aco';
2985 $table = $this->_db_table_prefix .'aco';
2986 $object_sections_table = $this->_db_table_prefix .'aco_sections';
2987 break;
2988 case 'aro':
2989 $object_type = 'aro';
2990 $table = $this->_db_table_prefix .'aro';
2991 $object_sections_table = $this->_db_table_prefix .'aro_sections';
2992 break;
2993 case 'axo':
2994 $object_type = 'axo';
2995 $table = $this->_db_table_prefix .'axo';
2996 $object_sections_table = $this->_db_table_prefix .'axo_sections';
2997 break;
2998 default:
2999 $this->debug_text('add_object(): Invalid Object Type: '. $object_type);
3000 return FALSE;
3003 $this->debug_text("add_object(): Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
3005 $section_value = trim($section_value);
3006 $name = trim($name);
3007 $value = trim($value);
3008 $order = trim($order);
3009 $hidden = intval($hidden);
3011 if ($order == NULL OR $order == '') {
3012 $order = 0;
3015 if (empty($name) OR empty($section_value) ) {
3016 $this->debug_text("add_object(): name ($name) OR section value ($section_value) is empty, this is required");
3017 return false;
3020 if (strlen($name) >= 255 OR strlen($value) >= 230 ) {
3021 $this->debug_text("add_object(): name ($name) OR value ($value) is too long.");
3022 return false;
3025 if (empty($object_type) ) {
3026 $this->debug_text("add_object(): Object Type ($object_type) is empty, this is required");
3027 return false;
3030 // Test to see if the section is invalid or object already exists.
3031 $query = '
3032 SELECT CASE WHEN o.id IS NULL THEN 0 ELSE 1 END AS object_exists
3033 FROM '. $object_sections_table .' s
3034 LEFT JOIN '. $table .' o ON (s.value=o.section_value AND o.value='. $this->db->quote($value) .')
3035 WHERE s.value='. $this->db->quote($section_value);
3036 $rs = $this->db->Execute($query);
3038 if (!is_object($rs)) {
3039 $this->debug_db('add_object');
3040 return FALSE;
3043 if ($rs->RecordCount() != 1) {
3044 // Section is invalid
3045 $this->debug_text("add_object(): Section Value: $section_value Object Type ($object_type) does not exist, this is required");
3046 return false;
3049 $row = $rs->FetchRow();
3051 if ($row[0] == 1) {
3052 //Object is already created.
3053 return true;
3056 $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_seq',10);
3057 $query = 'INSERT INTO '. $table .' (id,section_value,value,order_value,name,hidden) VALUES('. $this->db->quote($insert_id) .','. $this->db->quote($section_value) .','. $this->db->quote($value) .','. $this->db->quote($order) .','. $this->db->quote($name) .','. $this->db->quote($hidden) .')';
3058 $rs = $this->db->Execute($query);
3060 if (!is_object($rs)) {
3061 $this->debug_db('add_object');
3062 return false;
3065 $this->debug_text("add_object(): Added object as ID: $insert_id");
3066 return $insert_id;
3070 * edit_object()
3072 * Edits a given Object
3074 * @return bool Returns TRUE if successful, FALSE otherwise
3076 * @param int Object ID #
3077 * @param string Object Section Value
3078 * @param string Object Name
3079 * @param string Object Value
3080 * @param int Display Order
3081 * @param int Hidden Flag, either 1 to hide, or 0 to show
3082 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3084 function edit_object($object_id, $section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3086 switch(strtolower(trim($object_type))) {
3087 case 'aco':
3088 $object_type = 'aco';
3089 $table = $this->_db_table_prefix .'aco';
3090 $object_map_table = $this->_db_table_prefix .'aco_map';
3091 break;
3092 case 'aro':
3093 $object_type = 'aro';
3094 $table = $this->_db_table_prefix .'aro';
3095 $object_map_table = $this->_db_table_prefix .'aro_map';
3096 break;
3097 case 'axo':
3098 $object_type = 'axo';
3099 $table = $this->_db_table_prefix .'axo';
3100 $object_map_table = $this->_db_table_prefix .'axo_map';
3101 break;
3104 $this->debug_text("edit_object(): ID: $object_id Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
3106 $section_value = trim($section_value);
3107 $name = trim($name);
3108 $value = trim($value);
3109 $order = trim($order);
3110 $hidden = intval($hidden);
3112 if (empty($object_id) OR empty($section_value) ) {
3113 $this->debug_text("edit_object(): Object ID ($object_id) OR Section Value ($section_value) is empty, this is required");
3114 return false;
3117 if (empty($name) ) {
3118 $this->debug_text("edit_object(): name ($name) is empty, this is required");
3119 return false;
3122 if (empty($object_type) ) {
3123 $this->debug_text("edit_object(): Object Type ($object_type) is empty, this is required");
3124 return false;
3127 $this->db->BeginTrans();
3129 //Get old value incase it changed, before we do the update.
3130 $query = 'SELECT value, section_value FROM '. $table .' WHERE id='. $this->db->quote($object_id);
3131 $old = $this->db->GetRow($query);
3133 $query = '
3134 UPDATE '. $table .'
3135 SET section_value='. $this->db->quote($section_value) .',
3136 value='. $this->db->quote($value) .',
3137 order_value='. $this->db->quote($order) .',
3138 name='. $this->db->quote($name) .',
3139 hidden='. $this->db->quote($hidden) .'
3140 WHERE id='. $this->db->quote($object_id);
3141 $rs = $this->db->Execute($query);
3143 if (!is_object($rs)) {
3144 $this->debug_db('edit_object');
3145 $this->db->RollbackTrans();
3146 return false;
3149 $this->debug_text('edit_object(): Modified '. strtoupper($object_type) .' ID: '. $object_id);
3151 if ($old[0] != $value OR $old[1] != $section_value) {
3152 $this->debug_text("edit_object(): Value OR Section Value Changed, update other tables.");
3154 $query = '
3155 UPDATE '. $object_map_table .'
3156 SET value='. $this->db->quote($value) .',
3157 section_value='. $this->db->quote($section_value) .'
3158 WHERE section_value='. $this->db->quote($old[1]) .'
3159 AND value='. $this->db->quote($old[0]);
3160 $rs = $this->db->Execute($query);
3162 if (!is_object($rs)) {
3163 $this->debug_db('edit_object');
3164 $this->db->RollbackTrans();
3165 return FALSE;
3168 $this->debug_text ('edit_object(): Modified Map Value: '. $value .' Section Value: '. $section_value);
3171 $this->db->CommitTrans();
3173 return TRUE;
3177 * del_object()
3179 * Deletes a given Object and, if instructed to do so, erase all referencing objects
3181 * ERASE feature by: Martino Piccinato
3183 * @return bool Returns TRUE if successful, FALSE otherwise.
3185 * @param int Object ID #
3186 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3187 * @param bool Erases all referencing objects if TRUE, leaves them alone otherwise.
3189 function del_object($object_id, $object_type=NULL, $erase=FALSE) {
3191 switch(strtolower(trim($object_type))) {
3192 case 'aco':
3193 $object_type = 'aco';
3194 $table = $this->_db_table_prefix .'aco';
3195 $object_map_table = $this->_db_table_prefix .'aco_map';
3196 break;
3197 case 'aro':
3198 $object_type = 'aro';
3199 $table = $this->_db_table_prefix .'aro';
3200 $object_map_table = $this->_db_table_prefix .'aro_map';
3201 $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
3202 $object_group_table = $this->_db_table_prefix .'groups_aro_map';
3203 break;
3204 case 'axo':
3205 $object_type = 'axo';
3206 $table = $this->_db_table_prefix .'axo';
3207 $object_map_table = $this->_db_table_prefix .'axo_map';
3208 $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
3209 $object_group_table = $this->_db_table_prefix .'groups_axo_map';
3210 break;
3211 default:
3212 $this->debug_text('del_object(): Invalid Object Type: '. $object_type);
3213 return FALSE;
3216 $this->debug_text("del_object(): ID: $object_id Object Type: $object_type, Erase all referencing objects: $erase");
3218 if (empty($object_id) ) {
3219 $this->debug_text("del_object(): Object ID ($object_id) is empty, this is required");
3220 return false;
3223 if (empty($object_type) ) {
3224 $this->debug_text("del_object(): Object Type ($object_type) is empty, this is required");
3225 return false;
3228 $this->db->BeginTrans();
3230 // Get Object section_value/value (needed to look for referencing objects)
3231 $query = 'SELECT section_value,value FROM '. $table .' WHERE id='. $this->db->quote($object_id);
3232 $object = $this->db->GetRow($query);
3234 if (empty($object)) {
3235 $this->debug_text('del_object(): The specified object ('. strtoupper($object_type) .' ID: '. $object_id .') could not be found.');
3236 $this->db->RollbackTrans();
3237 return FALSE;
3240 $section_value = $object[0];
3241 $value = $object[1];
3243 // Get ids of acl referencing the Object (if any)
3244 $query = "SELECT acl_id FROM $object_map_table WHERE value=" . $this->db->quote($value) . " AND section_value=" . $this->db->quote($section_value);
3245 $acl_ids = $this->db->GetCol($query);
3247 if ($erase) {
3248 // We were asked to erase all acl referencing it
3250 $this->debug_text("del_object(): Erase was set to TRUE, delete all referencing objects");
3252 if ($object_type == "aro" OR $object_type == "axo") {
3253 // The object can be referenced in groups_X_map tables
3254 // in the future this branching may become useless because
3255 // ACO might me "groupable" too
3257 // Get rid of groups_map referencing the Object
3258 $query = 'DELETE FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $this->db->quote($object_id);
3259 $rs = $this->db->Execute($query);
3261 if (!is_object($rs)) {
3262 $this->debug_db('edit_object');
3263 $this->db->RollBackTrans();
3264 return false;
3268 if (!empty($acl_ids)) {
3269 //There are acls actually referencing the object
3271 if ($object_type == 'aco') {
3272 // I know it's extremely dangerous but
3273 // if asked to really erase an ACO
3274 // we should delete all acl referencing it
3275 // (and relative maps)
3277 // Do this below this branching
3278 // where it uses $orphan_acl_ids as
3279 // the array of the "orphaned" acl
3280 // in this case all referenced acl are
3281 // orhpaned acl
3283 $orphan_acl_ids = $acl_ids;
3284 } else {
3285 // The object is not an ACO and might be referenced
3286 // in still valid acls regarding also other object.
3287 // In these cases the acl MUST NOT be deleted
3289 // Get rid of $object_id map referencing erased objects
3290 $query = "DELETE FROM $object_map_table WHERE section_value=" . $this->db->quote($section_value) . " AND value=" . $this->db->quote($value);
3291 $this->db->Execute($query);
3293 if (!is_object($rs)) {
3294 $this->debug_db('edit_object');
3295 $this->db->RollBackTrans();
3296 return false;
3299 // Find the "orphaned" acl. I mean acl referencing the erased Object (map)
3300 // not referenced anymore by other objects
3302 $sql_acl_ids = implode(",", $acl_ids);
3304 $query = '
3305 SELECT a.id
3306 FROM '. $this->_db_table_prefix .'acl a
3307 LEFT JOIN '. $object_map_table .' b ON a.id=b.acl_id
3308 LEFT JOIN '. $groups_map_table .' c ON a.id=c.acl_id
3309 WHERE b.value IS NULL
3310 AND b.section_value IS NULL
3311 AND c.group_id IS NULL
3312 AND a.id in ('. $sql_acl_ids .')';
3313 $orphan_acl_ids = $this->db->GetCol($query);
3315 } // End of else section of "if ($object_type == "aco")"
3317 if ($orphan_acl_ids) {
3318 // If there are orphaned acls get rid of them
3320 foreach ($orphan_acl_ids as $acl) {
3321 $this->del_acl($acl);
3325 } // End of if ($acl_ids)
3327 // Finally delete the Object itself
3328 $query = "DELETE FROM $table WHERE id=" . $this->db->quote($object_id);
3329 $rs = $this->db->Execute($query);
3331 if (!is_object($rs)) {
3332 $this->debug_db('edit_object');
3333 $this->db->RollBackTrans();
3334 return false;
3337 $this->db->CommitTrans();
3338 return true;
3340 } // End of "if ($erase)"
3342 $groups_ids = FALSE;
3344 if ($object_type == 'axo' OR $object_type == 'aro') {
3345 // If the object is "groupable" (may become unnecessary,
3346 // see above
3348 // Get id of groups where the object is assigned:
3349 // you must explicitly remove the object from its groups before
3350 // deleting it (don't know if this is really needed, anyway it's safer ;-)
3352 $query = 'SELECT group_id FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $this->db->quote($object_id);
3353 $groups_ids = $this->db->GetCol($query);
3356 if ( ( isset($acl_ids) AND !empty($acl_ids) ) OR ( isset($groups_ids) AND !empty($groups_ids) ) ) {
3357 // The Object is referenced somewhere (group or acl), can't delete it
3359 $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,",").")");
3360 $this->db->RollBackTrans();
3361 return false;
3362 } else {
3363 // The Object is NOT referenced anywhere, delete it
3365 $query = "DELETE FROM $table WHERE id=" . $this->db->quote($object_id);
3366 $rs = $this->db->Execute($query);
3368 if ( !is_object($rs) ) {
3369 $this->debug_db('edit_object');
3370 $this->db->RollBackTrans();
3371 return false;
3374 $this->db->CommitTrans();
3375 return true;
3378 $this->db->RollbackTrans();
3379 return false;
3384 * Object Sections
3389 * get_object_section_section_id()
3391 * Gets the object_section_id given the name AND/OR value of the section.
3393 * Will only return one section id, so if there are duplicate names it will return false.
3395 * @return int Object Section ID if the object section is found AND is unique, or FALSE otherwise.
3397 * @param string Object Name
3398 * @param string Object Value
3399 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3402 function get_object_section_section_id($name = NULL, $value = NULL, $object_type = NULL) {
3403 $this->debug_text("get_object_section_section_id(): Value: $value Name: $name Object Type: $object_type");
3405 switch(strtolower(trim($object_type))) {
3406 case 'aco':
3407 case 'aro':
3408 case 'axo':
3409 case 'acl':
3410 $object_type = strtolower(trim($object_type));
3411 $table = $this->_db_table_prefix . $object_type;
3412 $object_sections_table = $this->_db_table_prefix . $object_type .'_sections';
3413 break;
3414 default:
3415 $this->debug_text('get_object_section_section_id(): Invalid Object Type ('. $object_type . ')');
3416 return FALSE;
3419 $name = trim($name ?? '');
3420 $value = trim($value);
3422 if (empty($name) AND empty($value) ) {
3423 $this->debug_text('get_object_section_section_id(): Both Name ('. $name .') and Value ('. $value .') are empty, you must specify at least one.');
3424 return FALSE;
3427 $query = 'SELECT id FROM '. $object_sections_table;
3428 $where = ' WHERE ';
3430 // limit by value if specified
3431 if (!empty($value)) {
3432 $query .= $where .'value='. $this->db->quote($value);
3433 $where = ' AND ';
3436 // only use name if asked, this is SLOW
3437 if (!empty($name)) {
3438 $query .= $where .'name='. $this->db->quote($name);
3441 $rs = $this->db->Execute($query);
3443 if (!is_object($rs)) {
3444 $this->debug_db('get_object_section_section_id');
3445 return FALSE;
3448 $row_count = $rs->RecordCount();
3450 // If only one row is returned
3451 if ($row_count == 1) {
3452 // Return only the ID in the first row.
3453 $row = $rs->FetchRow();
3454 return $row[0];
3457 // If more than one row is returned
3458 // should only ever occur when using name as values are unique.
3459 if ($row_count > 1) {
3460 $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.');
3461 return FALSE;
3464 // No rows returned, no matching section found
3465 $this->debug_text('get_object_section_section_id(): Returned '. $row_count .' rows, no matching section found.');
3466 return FALSE;
3470 * add_object_section()
3472 * Inserts an object Section
3474 * @return int Object Section ID of new section
3476 * @param string Object Name
3477 * @param string Object Value
3478 * @param int Display Order
3479 * @param int Hidden flag, hides section if 1, shows section if 0
3480 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3482 function add_object_section($name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3484 switch(strtolower(trim($object_type))) {
3485 case 'aco':
3486 $object_type = 'aco';
3487 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3488 break;
3489 case 'aro':
3490 $object_type = 'aro';
3491 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3492 break;
3493 case 'axo':
3494 $object_type = 'axo';
3495 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3496 break;
3497 case 'acl':
3498 $object_type = 'acl';
3499 $object_sections_table = $this->_db_table_prefix .'acl_sections';
3500 break;
3503 $this->debug_text("add_object_section(): Value: $value Order: $order Name: $name Object Type: $object_type");
3505 $name = trim($name);
3506 $value = trim($value);
3507 $order = trim($order);
3508 $hidden = intval($hidden);
3510 if ($order == NULL OR $order == '') {
3511 $order = 0;
3514 if (empty($name) ) {
3515 $this->debug_text("add_object_section(): name ($name) is empty, this is required");
3516 return false;
3519 if (empty($object_type) ) {
3520 $this->debug_text("add_object_section(): Object Type ($object_type) is empty, this is required");
3521 return false;
3524 $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_sections_seq',10);
3525 $query = 'insert into '. $object_sections_table .' (id,value,order_value,name,hidden) VALUES( '. $this->db->quote($insert_id) .', '. $this->db->quote($value) .', '. $this->db->quote($order) .', '. $this->db->quote($name) .', '. $this->db->quote($hidden) .')';
3526 $rs = $this->db->Execute($query);
3528 if (!is_object($rs)) {
3529 $this->debug_db('add_object_section');
3530 return false;
3531 } else {
3532 $this->debug_text("add_object_section(): Added object_section as ID: $insert_id");
3533 return $insert_id;
3538 * edit_object_section()
3540 * Edits a given Object Section
3542 * @return bool Returns TRUE if successful, FALSE otherwise
3544 * @param int Object Section ID #
3545 * @param string Object Section Name
3546 * @param string Object Section Value
3547 * @param int Display Order
3548 * @param int Hidden Flag, hide object section if 1, show if 0
3549 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3551 function edit_object_section($object_section_id, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3553 switch(strtolower(trim($object_type))) {
3554 case 'aco':
3555 $object_type = 'aco';
3556 $table = $this->_db_table_prefix .'aco';
3557 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3558 $object_map_table = $this->_db_table_prefix .'aco_map';
3559 break;
3560 case 'aro':
3561 $object_type = 'aro';
3562 $table = $this->_db_table_prefix .'aro';
3563 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3564 $object_map_table = $this->_db_table_prefix .'aro_map';
3565 break;
3566 case 'axo':
3567 $object_type = 'axo';
3568 $table = $this->_db_table_prefix .'axo';
3569 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3570 $object_map_table = $this->_db_table_prefix .'axo_map';
3571 break;
3572 case 'acl':
3573 $object_type = 'acl';
3574 $table = $this->_db_table_prefix .'acl';
3575 $object_sections_table = $this->_db_table_prefix .'acl_sections';
3576 break;
3577 default:
3578 $this->debug_text('edit_object_section(): Invalid Object Type: '. $object_type);
3579 return FALSE;
3582 $this->debug_text("edit_object_section(): ID: $object_section_id Value: $value Order: $order Name: $name Object Type: $object_type");
3584 $name = trim($name);
3585 $value = trim($value);
3586 $order = trim($order);
3587 $hidden = intval($hidden);
3589 if (empty($object_section_id) ) {
3590 $this->debug_text("edit_object_section(): Section ID ($object_section_id) is empty, this is required");
3591 return false;
3594 if (empty($name) ) {
3595 $this->debug_text("edit_object_section(): name ($name) is empty, this is required");
3596 return false;
3599 if (empty($object_type) ) {
3600 $this->debug_text("edit_object_section(): Object Type ($object_type) is empty, this is required");
3601 return false;
3604 $this->db->BeginTrans();
3606 //Get old value incase it changed, before we do the update.
3607 $query = "select value from $object_sections_table where id=" . $this->db->quote($object_section_id);
3608 $old_value = $this->db->GetOne($query);
3610 $query = "update $object_sections_table set
3611 value=" . $this->db->quote($value) . ",
3612 order_value=" .$this->db->quote($order) . ",
3613 name=" . $this->db->quote($name) . ",
3614 hidden=" . $this->db->quote($hidden) . "
3615 where id=" . $this->db->quote($object_section_id);
3616 $rs = $this->db->Execute($query);
3618 if (!is_object($rs)) {
3619 $this->debug_db('edit_object_section');
3621 $this->db->RollbackTrans();
3623 return false;
3624 } else {
3625 $this->debug_text("edit_object_section(): Modified aco_section ID: $object_section_id");
3627 if ($old_value != $value) {
3628 $this->debug_text("edit_object_section(): Value Changed, update other tables.");
3630 $query = "update $table set
3631 section_value=" . $this->db->quote($value) . "
3632 where section_value = " . $this->db->quote($old_value);
3633 $rs = $this->db->Execute($query);
3635 if (!is_object($rs)) {
3636 $this->debug_db('edit_object_section');
3638 $this->db->RollbackTrans();
3640 return false;
3641 } else {
3642 if (!empty($object_map_table)) {
3643 $query = "update $object_map_table set
3644 section_value=" . $this->db->quote($value) . "
3645 where section_value = " . $this->db->quote($old_value);
3646 $rs = $this->db->Execute($query);
3648 if ( !is_object($rs) ) {
3649 $this->debug_db('edit_object_section');
3651 $this->db->RollbackTrans();
3653 return false;
3654 } else {
3655 $this->debug_text("edit_object_section(): Modified ojbect_map value: $value");
3657 $this->db->CommitTrans();
3658 return true;
3660 } else {
3661 //ACL sections, have no mapping table. Return true.
3663 $this->db->CommitTrans();
3665 return true;
3670 $this->db->CommitTrans();
3671 return true;
3676 * del_object_section()
3678 * Deletes a given Object Section and, if explicitly asked, all the section objects
3680 * ERASE feature by: Martino Piccinato
3682 * @return bool Returns TRUE if successful, FALSE otherwise
3684 * @param int Object Section ID # to delete
3685 * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3686 * @param bool Erases all section objects assigned to the section
3688 function del_object_section($object_section_id, $object_type=NULL, $erase=FALSE) {
3690 switch(strtolower(trim($object_type))) {
3691 case 'aco':
3692 $object_type = 'aco';
3693 $object_sections_table = $this->_db_table_prefix .'aco_sections';
3694 break;
3695 case 'aro':
3696 $object_type = 'aro';
3697 $object_sections_table = $this->_db_table_prefix .'aro_sections';
3698 break;
3699 case 'axo':
3700 $object_type = 'axo';
3701 $object_sections_table = $this->_db_table_prefix .'axo_sections';
3702 break;
3703 case 'acl':
3704 $object_type = 'acl';
3705 $object_sections_table = $this->_db_table_prefix .'acl_sections';
3706 break;
3709 $this->debug_text("del_object_section(): ID: $object_section_id Object Type: $object_type, Erase all: $erase");
3711 if (empty($object_section_id) ) {
3712 $this->debug_text("del_object_section(): Section ID ($object_section_id) is empty, this is required");
3713 return false;
3716 if (empty($object_type) ) {
3717 $this->debug_text("del_object_section(): Object Type ($object_type) is empty, this is required");
3718 return false;
3721 // Get the value of the section
3722 $query="SELECT value FROM $object_sections_table WHERE id=" . $this->db->quote($object_section_id);
3723 $section_value = $this->db->GetOne($query);
3725 // Get all objects ids in the section
3726 $object_ids = $this->get_object($section_value, 1, $object_type);
3728 if($erase) {
3729 // Delete all objects in the section and for
3730 // each object delete the referencing object
3731 // (see del_object method)
3732 if (is_array($object_ids)) {
3733 foreach ($object_ids as $id) {
3734 if ( $object_type === 'acl' ) {
3735 $this->del_acl($id);
3736 } else {
3737 $this->del_object($id, $object_type, TRUE);
3743 if($object_ids AND !$erase) {
3744 // There are objects in the section and we
3745 // were not asked to erase them: don't delete it
3747 $this->debug_text("del_object_section(): Could not delete the section ($section_value) as it is not empty.");
3749 return false;
3751 } else {
3752 // The section is empty (or emptied by this method)
3754 $query = "DELETE FROM $object_sections_table where id=" . $this->db->quote($object_section_id);
3755 $rs = $this->db->Execute($query);
3757 if (!is_object($rs)) {
3758 $this->debug_db('del_object_section');
3759 return false;
3760 } else {
3761 $this->debug_text("del_object_section(): deleted section ID: $object_section_id Value: $section_value");
3762 return true;
3767 return false;
3771 * get_section_data()
3773 * Gets the section data given the Section Value
3775 * @return array Returns numerically indexed array with the following columns:
3776 * - array[0] = (int) Section ID #
3777 * - array[1] = (string) Section Value
3778 * - array[2] = (int) Section Order
3779 * - array[3] = (string) Section Name
3780 * - array[4] = (int) Section Hidden?
3781 * @param string Section Value
3782 * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3784 function get_section_data($section_value, $object_type=NULL) {
3786 switch(strtolower(trim($object_type))) {
3787 case 'aco':
3788 $object_type = 'aco';
3789 $table = $this->_db_table_prefix .'aco_sections';
3790 break;
3791 case 'aro':
3792 $object_type = 'aro';
3793 $table = $this->_db_table_prefix .'aro_sections';
3794 break;
3795 case 'axo':
3796 $object_type = 'axo';
3797 $table = $this->_db_table_prefix .'axo_sections';
3798 break;
3799 default:
3800 $this->debug_text('get_section_data(): Invalid Object Type: '. $object_type);
3801 return FALSE;
3804 $this->debug_text("get_section_data(): Section Value: $section_value Object Type: $object_type");
3806 if (empty($section_value) ) {
3807 $this->debug_text("get_section_data(): Section Value ($section_value) is empty, this is required");
3808 return false;
3811 if (empty($object_type) ) {
3812 $this->debug_text("get_section_data(): Object Type ($object_type) is empty, this is required");
3813 return false;
3816 $query = "SELECT id, value, order_value, name, hidden FROM $table WHERE value=" . $this->db->quote($section_value);
3817 $row = $this->db->GetRow($query);
3819 if ($row) {
3820 return $row;
3823 $this->debug_text("get_section_data(): Section does not exist.");
3824 return false;
3828 * clear_database()
3830 * Deletes all data from the phpGACL tables. USE WITH CAUTION.
3832 * @return bool Returns TRUE if successful, FALSE otherwise
3835 function clear_database(){
3837 $tablesToClear = array(
3838 $this->_db_table_prefix.'acl',
3839 $this->_db_table_prefix.'aco',
3840 $this->_db_table_prefix.'aco_map',
3841 $this->_db_table_prefix.'aco_sections',
3842 $this->_db_table_prefix.'aro',
3843 $this->_db_table_prefix.'aro_groups',
3844 $this->_db_table_prefix.'aro_groups_map',
3845 $this->_db_table_prefix.'aro_map',
3846 $this->_db_table_prefix.'aro_sections',
3847 $this->_db_table_prefix.'axo',
3848 $this->_db_table_prefix.'axo_groups',
3849 $this->_db_table_prefix.'axo_groups_map',
3850 $this->_db_table_prefix.'axo_map',
3851 $this->_db_table_prefix.'axo_sections',
3852 $this->_db_table_prefix.'groups_aro_map',
3853 $this->_db_table_prefix.'groups_axo_map'
3856 // Get all the table names and loop
3857 $tableNames = $this->db->MetaTables('TABLES');
3858 $query = array();
3859 foreach ($tableNames as $key => $value){
3860 if (in_array($value, $tablesToClear) ) {
3861 $query[] = 'TRUNCATE TABLE '.$value.';';
3865 // Loop the queries and return.
3866 foreach ($query as $key => $value){
3867 $result = $this->db->Execute($value);
3870 return TRUE;