[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

/libraries/phpgacl/ -> gacl_api.php (source)

   1  <?php
   2  /**
   3   * phpGACL - Generic Access Control List
   4   * Copyright (C) 2002,2003 Mike Benoit
   5   *
   6   * This library is free software; you can redistribute it and/or
   7   * modify it under the terms of the GNU Lesser General Public
   8   * License as published by the Free Software Foundation; either
   9   * version 2.1 of the License, or (at your option) any later version.
  10   *
  11   * This library is distributed in the hope that it will be useful,
  12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14   * Lesser General Public License for more details.
  15   *
  16   * You should have received a copy of the GNU Lesser General Public
  17   * License along with this library; if not, write to the Free Software
  18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19   *
  20   * For questions, help, comments, discussion, etc., please join the
  21   * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
  22   *
  23   * You may contact the author of phpGACL by e-mail at:
  24   * ipso@snappymail.ca
  25   *
  26   * The latest version of phpGACL can be obtained from:
  27   * http://phpgacl.sourceforge.net/
  28   *
  29   * @package phpGACL
  30   *
  31   */
  32  
  33  // Check to ensure this file is within the rest of the framework
  34  defined('JPATH_BASE') or die();
  35  
  36  /*
  37   *
  38   * For examples, see example.php or the Administration interface,
  39   * as it makes use of nearly every API Call.
  40   *
  41   */
  42  /**
  43   * gacl_api Extended API Class
  44   *
  45   * Class gacl_api should be used for applications that must interface directly with
  46   * phpGACL's data structures, objects, and rules.
  47   *
  48   * @package phpGACL
  49   * @author Mike Benoit <ipso@snappymail.ca>
  50   *
  51   */
  52  
  53  class gacl_api extends gacl {
  54  
  55      /*
  56       *
  57       * Misc helper functions.
  58       *
  59       */
  60  
  61      /**
  62       * showarray()
  63       *
  64       * Dump all contents of an array in HTML (kinda)
  65       *
  66       * @param array
  67       *
  68       */
  69  	function showarray($array) {
  70          echo "<br><pre>\n";
  71          var_dump($array);
  72          echo "</pre><br>\n";
  73      }
  74  
  75      /**
  76       * count_all()
  77       *
  78       * Recursively counts elements in an array and sub-arrays.
  79       *
  80       * This is different from count($arg, COUNT_RECURSIVE)
  81       * in PHP >= 4.2.0, which includes sub-arrays in the count.
  82       *
  83       * @return int The returned count is a count of all scalar elements found.
  84       *
  85       * @param array Array to count
  86       */
  87  	function count_all($arg = NULL) {
  88          switch (TRUE) {
  89              case is_scalar($arg):
  90              case is_object($arg):
  91                  // single object
  92                  return 1;
  93              case is_array($arg):
  94                  // call recursively for all elements of $arg
  95                  $count = 0;
  96                  foreach ($arg as $val) {
  97                      $count += $this->count_all($val);
  98                  }
  99                  return $count;
 100          }
 101          return FALSE;
 102      }
 103  
 104      /**
 105       * get_version()
 106       *
 107       * Grabs phpGACL version from the database.
 108       *
 109       * @return string Version of phpGACL
 110       */
 111  	function get_version() {
 112          $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'version'";
 113          $version = $this->db->GetOne($query);
 114  
 115          return $version;
 116      }
 117  
 118      /**
 119       * get_schema_version()
 120       *
 121       * Grabs phpGACL schema version from the database.
 122       *
 123       * @return string Schema Version
 124       */
 125  	function get_schema_version() {
 126          $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'schema_version'";
 127          $version = $this->db->GetOne($query);
 128  
 129          return $version;
 130      }
 131  
 132      /*
 133       *
 134       * ACL
 135       *
 136       */
 137  
 138      /**
 139       * consolidated_edit_acl()
 140       *
 141       * Add's an ACL but checks to see if it can consolidate it with another one first.
 142       *
 143       * This ONLY works with ACO's and ARO's. Groups, and AXO are excluded.
 144       * As well this function is designed for handling ACLs with return values,
 145       * and consolidating on the return_value, in hopes of keeping the ACL count to a minimum.
 146       *
 147       * A return value of false must _always_ be handled outside this function.
 148       * As this function will remove AROs from ACLs and return false, in most cases
 149       * you will need to a create a completely new ACL on a false return.
 150       *
 151       * @return bool Special boolean return value. See note.
 152       *
 153       * @param string ACO Section Value
 154       * @param string ACO Value
 155       * @param string ARO Section Value
 156       * @param string ARO Value
 157       * @param string Return Value of ACL
 158       */
 159  	function consolidated_edit_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, $return_value) {
 160  
 161          $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");
 162  
 163          $acl_ids = array();
 164  
 165          if (empty($aco_section_value) ) {
 166              $this->debug_text("consolidated_edit_acl(): ACO Section Value ($aco_section_value) is empty, this is required!");
 167              return false;
 168          }
 169  
 170          if (empty($aco_value) ) {
 171              $this->debug_text("consolidated_edit_acl(): ACO Value ($aco_value) is empty, this is required!");
 172              return false;
 173          }
 174  
 175          if (empty($aro_section_value) ) {
 176              $this->debug_text("consolidated_edit_acl(): ARO Section Value ($aro_section_value) is empty, this is required!");
 177              return false;
 178          }
 179  
 180          if (empty($aro_value) ) {
 181              $this->debug_text("consolidated_edit_acl(): ARO Value ($aro_value) is empty, this is required!");
 182              return false;
 183          }
 184  
 185          if (empty($return_value) ) {
 186              $this->debug_text("consolidated_edit_acl(): Return Value ($return_value) is empty, this is required!");
 187              return false;
 188          }
 189  
 190          //See if a current ACL exists with the current objects, excluding return value
 191          $current_acl_ids = $this->search_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, FALSE, FALSE, FALSE, FALSE, FALSE);
 192          //showarray($current_acl_ids);
 193  
 194          if (is_array($current_acl_ids)) {
 195              $this->debug_text("add_consolidated_acl(): Found current ACL_IDs, counting ACOs");
 196  
 197              foreach ($current_acl_ids as $current_acl_id) {
 198                  //Check to make sure these ACLs only have a single ACO mapped to them.
 199                  $current_acl_array = &$this->get_acl($current_acl_id);
 200  
 201                  //showarray($current_acl_array);
 202                  $this->debug_text("add_consolidated_acl(): Current Count: ".$this->count_all($current_acl_array['aco'])."");
 203  
 204                  if ( $this->count_all($current_acl_array['aco']) == 1) {
 205                      $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO.");
 206  
 207                      //Test to see if the return values match, if they do, no need removing or appending ARO. Just return true.
 208                      if ($current_acl_array['return_value'] == $return_value) {
 209                          $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO, and the same return value. No need to modify.");
 210                          return true;
 211                      }
 212  
 213                      $acl_ids[] = $current_acl_id;
 214                  }
 215  
 216              }
 217          }
 218  
 219          //showarray($acl_ids);
 220          $acl_ids_count = count($acl_ids);
 221  
 222          //If acl_id's turns up more then one ACL, lets remove the ARO from all of them in hopes to
 223          //eliminate any conflicts.
 224          if (is_array($acl_ids) AND $acl_ids_count > 0) {
 225              $this->debug_text("add_consolidated_acl(): Removing specified ARO from existing ACL.");
 226  
 227              foreach ($acl_ids as $acl_id) {
 228                  //Remove ARO from current ACLs, so we don't create conflicting ACLs later on.
 229                  if (!$this->shift_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
 230                      $this->debug_text("add_consolidated_acl(): Error removing specified ARO from ACL ID: $acl_id");
 231                      return false;
 232                  }
 233              }
 234          } else {
 235              $this->debug_text("add_consolidated_acl(): Didn't find any current ACLs with a single ACO. ");
 236          }
 237          //unset($acl_ids);
 238      $acl_ids = array();
 239          unset($acl_ids_count);
 240  
 241          //At this point there should be no conflicting ACLs, searching for an existing ACL with the new values.
 242          $new_acl_ids = $this->search_acl($aco_section_value, $aco_value, FALSE, FALSE, NULL, NULL, NULL, NULL, $return_value);
 243          $new_acl_count = count($new_acl_ids);
 244          //showarray($new_acl_ids);
 245  
 246          if (is_array($new_acl_ids)) {
 247              $this->debug_text("add_consolidated_acl(): Found new ACL_IDs, counting ACOs");
 248  
 249              foreach ($new_acl_ids as $new_acl_id) {
 250                  //Check to make sure these ACLs only have a single ACO mapped to them.
 251                  $new_acl_array = &$this->get_acl($new_acl_id);
 252                  //showarray($new_acl_array);
 253                  $this->debug_text("add_consolidated_acl(): New Count: ".$this->count_all($new_acl_array['aco'])."");
 254                  if ( $this->count_all($new_acl_array['aco']) == 1) {
 255  
 256                      $this->debug_text("add_consolidated_acl(): ACL ID: $new_acl_id has 1 ACO, append should be able to take place.");
 257                      $acl_ids[] = $new_acl_id;
 258                  }
 259  
 260              }
 261          }
 262  
 263          //showarray($acl_ids);
 264          $acl_ids_count = count($acl_ids);
 265  
 266          if (is_array($acl_ids) AND $acl_ids_count == 1) {
 267              $this->debug_text("add_consolidated_acl(): Appending specified ARO to existing ACL.");
 268  
 269              $acl_id=$acl_ids[0];
 270  
 271              if (!$this->append_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
 272                  $this->debug_text("add_consolidated_acl(): Error appending specified ARO to ACL ID: $acl_id");
 273                  return false;
 274              }
 275  
 276              $this->debug_text("add_consolidated_acl(): Hot damn, ACL consolidated!");
 277              return true;
 278          } elseif($acl_ids_count > 1) {
 279              $this->debug_text("add_consolidated_acl(): Found more then one ACL with a single ACO. Possible conflicting ACLs.");
 280              return false;
 281          } elseif ($acl_ids_count == 0) {
 282              $this->debug_text("add_consolidated_acl(): No existing ACLs found, create a new one.");
 283  
 284              if (!$this->add_acl(    array( $aco_section_value => array($aco_value) ),
 285                                      array( $aro_section_value => array($aro_value) ),
 286                                      NULL,
 287                                      NULL,
 288                                      NULL,
 289                                      TRUE,
 290                                      TRUE,
 291                                      $return_value,
 292                                      NULL)
 293                                  ) {
 294                  $this->debug_text("add_consolidated_acl(): Error adding new ACL for ACO Section: $aco_section_value ACO Value: $aco_value Return Value: $return_value");
 295                  return false;
 296              }
 297  
 298              $this->debug_text("add_consolidated_acl(): ADD_ACL() successfull, returning True.");
 299              return true;
 300          }
 301  
 302          $this->debug_text("add_consolidated_acl(): Returning false.");
 303          return false;
 304      }
 305  
 306      /**
 307       * search_acl()
 308       *
 309       * Searches for ACL's with specified objects mapped to them.
 310       *
 311       * NULL values are included in the search, if you want to ignore
 312       * for instance aro_groups use FALSE instead of NULL.
 313       *
 314       * @return array containing ACL IDs if search is successful
 315       *
 316       * @param string ACO Section Value
 317       * @param string ACO Value
 318       * @param string ARO Section Value
 319       * @param string ARO Value
 320       * @param string ARO Group Name
 321       * @param string AXO Section Value
 322       * @param string AXO Value
 323       * @param string AXO Group Name
 324       * @param string Return Value
 325       */
 326  	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) {
 327          $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");
 328  
 329          $query = '
 330                  SELECT        a.id
 331                  FROM        '. $this->_db_table_prefix .'acl a';
 332  
 333          $where_query = array();
 334  
 335          // ACO
 336          if ($aco_section_value !== FALSE AND $aco_value !== FALSE) {
 337              $query .= '
 338                  LEFT JOIN    '. $this->_db_table_prefix .'aco_map ac ON a.id=ac.acl_id';
 339  
 340              if ($aco_section_value == NULL AND $aco_value == NULL) {
 341                  $where_query[] = '(ac.section_value IS NULL AND ac.value IS NULL)';
 342              } else {
 343                  $where_query[] = '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value='. $this->db->quote($aco_value) .')';
 344              }
 345          }
 346  
 347          // ARO
 348          if ($aro_section_value !== FALSE AND $aro_value !== FALSE) {
 349              $query .= '
 350                  LEFT JOIN    '. $this->_db_table_prefix .'aro_map ar ON a.id=ar.acl_id';
 351  
 352              if ($aro_section_value == NULL AND $aro_value == NULL) {
 353                  $where_query[] = '(ar.section_value IS NULL AND ar.value IS NULL)';
 354              } else {
 355                  $where_query[] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value='. $this->db->quote($aro_value) .')';
 356              }
 357          }
 358  
 359          // AXO
 360          if ($axo_section_value !== FALSE AND $axo_value !== FALSE) {
 361              $query .= '
 362                  LEFT JOIN    '. $this->_db_table_prefix .'axo_map ax ON a.id=ax.acl_id';
 363  
 364              if ($axo_section_value == NULL AND $axo_value == NULL) {
 365                  $where_query[] = '(ax.section_value IS NULL AND ax.value IS NULL)';
 366              } else {
 367                  $where_query[] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value='. $this->db->quote($axo_value) .')';
 368              }
 369          }
 370  
 371          // ARO Group
 372          if ($aro_group_name !== FALSE) {
 373              $query .= '
 374                  LEFT JOIN    '. $this->_db_table_prefix .'aro_groups_map arg ON a.id=arg.acl_id
 375                  LEFT JOIN    '. $this->_db_table_prefix .'aro_groups rg ON arg.group_id=rg.id';
 376  
 377              if ($aro_group_name == NULL) {
 378                  $where_query[] = '(rg.name IS NULL)';
 379              } else {
 380                  $where_query[] = '(rg.name='. $this->db->quote($aro_group_name) .')';
 381              }
 382          }
 383  
 384          // AXO Group
 385          if ($axo_group_name !== FALSE) {
 386              $query .= '
 387                  LEFT JOIN    '. $this->_db_table_prefix .'axo_groups_map axg ON a.id=axg.acl_id
 388                  LEFT JOIN    '. $this->_db_table_prefix .'axo_groups xg ON axg.group_id=xg.id';
 389  
 390              if ($axo_group_name == NULL) {
 391                  $where_query[] = '(xg.name IS NULL)';
 392              } else {
 393                  $where_query[] = '(xg.name='. $this->db->quote($axo_group_name) .')';
 394              }
 395          }
 396          if ($return_value != FALSE) {
 397              if ($return_value == NULL) {
 398                  $where_query[] = '(a.return_value IS NULL)';
 399              } else {
 400                  $where_query[] = '(a.return_value='. $this->db->quote($return_value) .')';
 401              }
 402          }
 403  
 404          if (count($where_query) > 0) {
 405              $query .= '
 406                  WHERE        '. implode (' AND ', $where_query);
 407          }
 408  
 409          return $this->db->GetCol($query);
 410      }
 411  
 412      /**
 413       * append_acl()
 414       *
 415       * Appends objects on to a specific ACL.
 416       *
 417       * @return bool TRUE if successful, FALSE otherwise.
 418       *
 419       * @param int ACL ID #
 420       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 421       * @param array Array of Group IDs
 422       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 423       * @param array Array of Group IDs
 424       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 425       */
 426  	function append_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
 427          $this->debug_text("append_acl(): ACL_ID: $acl_id");
 428  
 429          $update = 0;
 430  
 431          if (empty($acl_id)) {
 432              $this->debug_text("append_acl(): No ACL_ID specified! ACL_ID: $acl_id");
 433              return false;
 434          }
 435  
 436          //Grab ACL data.
 437          $acl_array = &$this->get_acl($acl_id);
 438  
 439          //Append each object type seperately.
 440          if (is_array($aro_array) AND count($aro_array) > 0) {
 441              $this->debug_text("append_acl(): Appending ARO's");
 442  
 443              while (list($aro_section_value,$aro_value_array) = @each($aro_array)) {
 444                  foreach ($aro_value_array as $aro_value) {
 445                      if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
 446                          if (!in_array($aro_value, $acl_array['aro'][$aro_section_value])) {
 447                              $this->debug_text("append_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
 448                              $acl_array['aro'][$aro_section_value][] = $aro_value;
 449                              $update=1;
 450                          } else {
 451                              $this->debug_text("append_acl(): Duplicate ARO, ignoring... ");
 452                          }
 453                      } else { //Array is empty so add this aro value.
 454                          $acl_array['aro'][$aro_section_value][] = $aro_value;
 455                          $update = 1;
 456                      }
 457                  }
 458              }
 459          }
 460  
 461          if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
 462              $this->debug_text("append_acl(): Appending ARO_GROUP_ID's");
 463  
 464              while (list(,$aro_group_id) = @each($aro_group_ids)) {
 465                  if (!is_array($acl_array['aro_groups']) OR !in_array($aro_group_id, $acl_array['aro_groups'])) {
 466                      $this->debug_text("append_acl(): ARO Group ID: $aro_group_id");
 467                      $acl_array['aro_groups'][] = $aro_group_id;
 468                      $update = 1;
 469                  } else {
 470                      $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
 471                  }
 472              }
 473          }
 474  
 475          if (is_array($axo_array) AND count($axo_array) > 0) {
 476              $this->debug_text("append_acl(): Appending AXO's");
 477  
 478              while (list($axo_section_value,$axo_value_array) = @each($axo_array)) {
 479                  foreach ($axo_value_array as $axo_value) {
 480                      if (!in_array($axo_value, $acl_array['axo'][$axo_section_value])) {
 481                          $this->debug_text("append_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
 482                          $acl_array['axo'][$axo_section_value][] = $axo_value;
 483                          $update = 1;
 484                      } else {
 485                          $this->debug_text("append_acl(): Duplicate AXO, ignoring... ");
 486                      }
 487  
 488                  }
 489              }
 490          }
 491  
 492          if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
 493              $this->debug_text("append_acl(): Appending AXO_GROUP_ID's");
 494              while (list(,$axo_group_id) = @each($axo_group_ids)) {
 495                  if (!is_array($acl_array['axo_groups']) OR !in_array($axo_group_id, $acl_array['axo_groups'])) {
 496                      $this->debug_text("append_acl(): AXO Group ID: $axo_group_id");
 497                      $acl_array['axo_groups'][] = $axo_group_id;
 498                      $update = 1;
 499                  } else {
 500                      $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
 501                  }
 502              }
 503          }
 504  
 505          if (is_array($aco_array) AND count($aco_array) > 0) {
 506              $this->debug_text("append_acl(): Appending ACO's");
 507  
 508              while (list($aco_section_value,$aco_value_array) = @each($aco_array)) {
 509                  foreach ($aco_value_array as $aco_value) {
 510                      if (!in_array($aco_value, $acl_array['aco'][$aco_section_value])) {
 511                          $this->debug_text("append_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
 512                          $acl_array['aco'][$aco_section_value][] = $aco_value;
 513                          $update = 1;
 514                      } else {
 515                          $this->debug_text("append_acl(): Duplicate ACO, ignoring... ");
 516                      }
 517                  }
 518              }
 519          }
 520  
 521          if ($update == 1) {
 522              $this->debug_text("append_acl(): Update flag set, updating ACL.");
 523              //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) {
 524              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']);
 525          }
 526  
 527          //Return true if everything is duplicate and no ACL id updated.
 528          $this->debug_text("append_acl(): Update flag not set, NOT updating ACL.");
 529          return true;
 530      }
 531  
 532      /**
 533       * shift_acl()
 534       *
 535       * Opposite of append_acl(). Removes objects from a specific ACL. (named after PHP's array_shift())
 536       *
 537       * @return bool TRUE if successful, FALSE otherwise.
 538       *
 539       * @param int ACL ID #
 540       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 541       * @param array Array of Group IDs
 542       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 543       * @param array Array of Group IDs
 544       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 545       */
 546  	function shift_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
 547          $this->debug_text("shift_acl(): ACL_ID: $acl_id");
 548  
 549          $update = 0;
 550  
 551          if (empty($acl_id)) {
 552              $this->debug_text("shift_acl(): No ACL_ID specified! ACL_ID: $acl_id");
 553              return false;
 554          }
 555  
 556          //Grab ACL data.
 557          $acl_array = &$this->get_acl($acl_id);
 558  
 559          //showarray($acl_array);
 560          //Remove each object type seperately.
 561          if (is_array($aro_array) AND count($aro_array) > 0) {
 562              $this->debug_text("shift_acl(): Removing ARO's");
 563  
 564              while (list($aro_section_value,$aro_value_array) = @each($aro_array)) {
 565                  foreach ($aro_value_array as $aro_value) {
 566                      $this->debug_text("shift_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
 567  
 568                      //Only search if aro array contains data.
 569                      if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
 570                          $aro_key = array_search($aro_value, $acl_array['aro'][$aro_section_value]);
 571  
 572                          if ($aro_key !== FALSE) {
 573                              $this->debug_text("shift_acl(): Removing ARO. ($aro_key)");
 574                              unset($acl_array['aro'][$aro_section_value][$aro_key]);
 575                              $update = 1;
 576                          } else {
 577                              $this->debug_text("shift_acl(): ARO doesn't exist, can't remove it.");
 578                          }
 579                      }
 580  
 581                  }
 582              }
 583          }
 584  
 585          if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
 586              $this->debug_text("shift_acl(): Removing ARO_GROUP_ID's");
 587  
 588              while (list(,$aro_group_id) = @each($aro_group_ids)) {
 589                  $this->debug_text("shift_acl(): ARO Group ID: $aro_group_id");
 590                  $aro_group_key = array_search($aro_group_id, $acl_array['aro_groups']);
 591  
 592                  if ($aro_group_key !== FALSE) {
 593                      $this->debug_text("shift_acl(): Removing ARO Group. ($aro_group_key)");
 594                      unset($acl_array['aro_groups'][$aro_group_key]);
 595                      $update = 1;
 596                  } else {
 597                      $this->debug_text("shift_acl(): ARO Group doesn't exist, can't remove it.");
 598                  }
 599              }
 600          }
 601  
 602          if (is_array($axo_array) AND count($axo_array) > 0) {
 603              $this->debug_text("shift_acl(): Removing AXO's");
 604  
 605              while (list($axo_section_value,$axo_value_array) = @each($axo_array)) {
 606                  foreach ($axo_value_array as $axo_value) {
 607                      $this->debug_text("shift_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
 608                      $axo_key = array_search($axo_value, $acl_array['axo'][$axo_section_value]);
 609  
 610                      if ($axo_key !== FALSE) {
 611                          $this->debug_text("shift_acl(): Removing AXO. ($axo_key)");
 612                          unset($acl_array['axo'][$axo_section_value][$axo_key]);
 613                          $update = 1;
 614                      } else {
 615                          $this->debug_text("shift_acl(): AXO doesn't exist, can't remove it.");
 616                      }
 617                  }
 618              }
 619          }
 620  
 621          if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
 622              $this->debug_text("shift_acl(): Removing AXO_GROUP_ID's");
 623  
 624              while (list(,$axo_group_id) = @each($axo_group_ids)) {
 625                  $this->debug_text("shift_acl(): AXO Group ID: $axo_group_id");
 626                  $axo_group_key = array_search($axo_group_id, $acl_array['axo_groups']);
 627  
 628                  if ($axo_group_key !== FALSE) {
 629                      $this->debug_text("shift_acl(): Removing AXO Group. ($axo_group_key)");
 630                      unset($acl_array['axo_groups'][$axo_group_key]);
 631                      $update = 1;
 632                  } else {
 633                      $this->debug_text("shift_acl(): AXO Group doesn't exist, can't remove it.");
 634                  }
 635              }
 636          }
 637  
 638          if (is_array($aco_array) AND count($aco_array) > 0) {
 639              $this->debug_text("shift_acl(): Removing ACO's");
 640  
 641              while (list($aco_section_value,$aco_value_array) = @each($aco_array)) {
 642                  foreach ($aco_value_array as $aco_value) {
 643                      $this->debug_text("shift_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
 644                      $aco_key = array_search($aco_value, $acl_array['aco'][$aco_section_value]);
 645  
 646                      if ($aco_key !== FALSE) {
 647                          $this->debug_text("shift_acl(): Removing ACO. ($aco_key)");
 648                          unset($acl_array['aco'][$aco_section_value][$aco_key]);
 649                          $update = 1;
 650                      } else {
 651                          $this->debug_text("shift_acl(): ACO doesn't exist, can't remove it.");
 652                      }
 653                  }
 654              }
 655          }
 656  
 657          if ($update == 1) {
 658              //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.
 659              //$this->showarray($acl_array);
 660              $this->debug_text("shift_acl(): ACOs: ". $this->count_all($acl_array['aco']) ." AROs: ".$this->count_all($acl_array['aro'])."");
 661  
 662              if ( $this->count_all($acl_array['aco']) == 0
 663                      OR ( $this->count_all($acl_array['aro']) == 0
 664                          AND ( $this->count_all($acl_array['axo']) == 0 OR $acl_array['axo'] == FALSE)
 665                          AND (count($acl_array['aro_groups']) == 0 OR $acl_array['aro_groups'] == FALSE)
 666                          AND (count($acl_array['axo_groups']) == 0 OR $acl_array['axo_groups'] == FALSE)
 667                          ) ) {
 668                  $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.");
 669  
 670                  return $this->del_acl($acl_id);
 671              }
 672  
 673              $this->debug_text("shift_acl(): Update flag set, updating ACL.");
 674  
 675              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']);
 676          }
 677  
 678          //Return true if everything is duplicate and no ACL id updated.
 679          $this->debug_text("shift_acl(): Update flag not set, NOT updating ACL.");
 680          return true;
 681      }
 682  
 683      /**
 684       * get_acl()
 685       *
 686       * Grabs ACL data.
 687       *
 688       * @return mixed    bool FALSE if not found, or Associative Array with the following items:
 689       *
 690       *    - 'aco' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 691       *    - 'aro' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 692       *    - 'axo' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 693       *    - 'aro_groups' => Array of Group IDs
 694       *    - 'axo_groups' => Array of Group IDs
 695       *    - 'acl_id' => int ACL ID #
 696       *    - 'allow' => int Allow flag
 697       *    - 'enabled' => int Enabled flag
 698       *    - 'return_value' => string Return Value
 699       *    - 'note' => string Note
 700       *
 701       * @param int ACL ID #
 702       */
 703  	function get_acl($acl_id) {
 704  
 705          $this->debug_text("get_acl(): ACL_ID: $acl_id");
 706  
 707          if (empty($acl_id)) {
 708              $this->debug_text("get_acl(): No ACL_ID specified! ACL_ID: $acl_id");
 709              return false;
 710          }
 711          $acl_id = (int) $acl_id;
 712  
 713          //Grab ACL information
 714          $query = "select id, allow, enabled, return_value, note from ".$this->_db_table_prefix."acl where id = ".$acl_id."";
 715          $acl_row = $this->db->GetRow($query);
 716  
 717          // return false if not found
 718          if (!$acl_row) {
 719              $this->debug_text("get_acl(): No ACL found for that ID! ACL_ID: $acl_id");
 720              return false;
 721          }
 722  
 723          list($retarr['acl_id'], $retarr['allow'], $retarr['enabled'], $retarr['return_value'], $retarr['note']) = $acl_row;
 724  
 725          //Grab selected ACO's
 726          $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
 727                              where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
 728          $rs = $this->db->Execute($query);
 729          $rows = $rs->GetRows();
 730  
 731          $retarr['aco'] = array();
 732          while (list(,$row) = @each($rows)) {
 733              list($section_value, $value, $section, $aco) = $row;
 734              $this->debug_text("Section Value: $section_value Value: $value Section: $section ACO: $aco");
 735  
 736              $retarr['aco'][$section_value][] = $value;
 737  
 738          }
 739          //showarray($aco);
 740  
 741          //Grab selected ARO's
 742          $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
 743                              where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
 744          $rs = $this->db->Execute($query);
 745          $rows = $rs->GetRows();
 746  
 747          $retarr['aro'] = array();
 748          while (list(,$row) = @each($rows)) {
 749              list($section_value, $value, $section, $aro) = $row;
 750              $this->debug_text("Section Value: $section_value Value: $value Section: $section ARO: $aro");
 751  
 752              $retarr['aro'][$section_value][] = $value;
 753  
 754          }
 755          //showarray($options_aro);
 756  
 757          //Grab selected AXO's
 758          $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
 759                              where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
 760          $rs = $this->db->Execute($query);
 761          $rows = $rs->GetRows();
 762  
 763          $retarr['axo'] = array();
 764          while (list(,$row) = @each($rows)) {
 765              list($section_value, $value, $section, $axo) = $row;
 766              $this->debug_text("Section Value: $section_value Value: $value Section: $section AXO: $axo");
 767  
 768              $retarr['axo'][$section_value][] = $value;
 769  
 770          }
 771          //showarray($options_aro);
 772  
 773          //Grab selected ARO groups.
 774          $retarr['aro_groups'] = array();
 775          $query = "select distinct group_id from ".$this->_db_table_prefix."aro_groups_map where  acl_id = $acl_id";
 776          $retarr['aro_groups'] = $this->db->GetCol($query);
 777          //showarray($selected_groups);
 778  
 779          //Grab selected AXO groups.
 780          $retarr['axo_groups'] = array();
 781          $query = "select distinct group_id from ".$this->_db_table_prefix."axo_groups_map where  acl_id = $acl_id";
 782          $retarr['axo_groups'] = $this->db->GetCol($query);
 783          //showarray($selected_groups);
 784  
 785          return $retarr;
 786      }
 787  
 788      /**
 789       * is_conflicting_acl()
 790       *
 791       * Checks for conflicts when adding a specific ACL.
 792       *
 793       * @return bool Returns true if conflict is found.
 794       *
 795       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 796       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 797       * @param array Array of Group IDs
 798       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 799       * @param array Array of Group IDs
 800       * @param array Array of ACL IDs to ignore from the result set.
 801       *
 802       */
 803  	function is_conflicting_acl($aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $ignore_acl_ids=NULL) {
 804          //Check for potential conflicts. Ignore groups, as groups will almost always have "conflicting" ACLs.
 805          //Thats part of inheritance.
 806  
 807          if (!is_array($aco_array)) {
 808              $this->debug_text('is_conflicting_acl(): Invalid ACO Array.');
 809              return FALSE;
 810          }
 811  
 812          if (!is_array($aro_array)) {
 813              $this->debug_text('is_conflicting_acl(): Invalid ARO Array.');
 814              return FALSE;
 815          }
 816  
 817          $query  = '
 818              SELECT        a.id
 819              FROM        '. $this->_db_table_prefix .'acl a
 820              LEFT JOIN    '. $this->_db_table_prefix .'aco_map ac ON ac.acl_id=a.id
 821              LEFT JOIN    '. $this->_db_table_prefix .'aro_map ar ON ar.acl_id=a.id
 822              LEFT JOIN    '. $this->_db_table_prefix .'axo_map ax ON ax.acl_id=a.id
 823              LEFT JOIN    '. $this->_db_table_prefix .'axo_groups_map axg ON axg.acl_id=a.id
 824              LEFT JOIN    '. $this->_db_table_prefix .'axo_groups xg ON xg.id=axg.group_id
 825              ';
 826  
 827          //ACO
 828          foreach ($aco_array as $aco_section_value => $aco_value_array) {
 829              $this->debug_text("is_conflicting_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value_array");
 830              //showarray($aco_array);
 831  
 832              if (!is_array($aco_value_array)) {
 833                  $this->debug_text('is_conflicting_acl(): Invalid Format for ACO Array item. Skipping...');
 834                  continue;
 835                  // return TRUE;
 836              }
 837              //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
 838              //'ac1' => 'ac.acl_id=a.id',
 839              $where_query = array(
 840                  'ac2' => '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value IN (\''. implode ('\',\'', $aco_value_array) .'\'))'
 841              );
 842  
 843              //ARO
 844              foreach ($aro_array as $aro_section_value => $aro_value_array) {
 845                  $this->debug_text("is_conflicting_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value_array");
 846  
 847                  if (!is_array($aro_value_array))
 848                  {
 849                      $this->debug_text('is_conflicting_acl(): Invalid Format for ARO Array item. Skipping...');
 850                      continue;
 851                      // return TRUE;
 852                  }
 853  
 854                  $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");
 855  
 856                  //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
 857                  //$where_query['ar1'] = 'ar.acl_id=a.id';
 858                  $where_query['ar2'] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value IN (\''. implode ('\',\'', $aro_value_array) .'\'))';
 859  
 860                  if (is_array($axo_array) AND count($axo_array) > 0) {
 861                      foreach ($axo_array as $axo_section_value => $axo_value_array) {
 862                          $this->debug_text("is_conflicting_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value_array");
 863  
 864                          if (!is_array($axo_value_array)) {
 865                              $this->debug_text('is_conflicting_acl(): Invalid Format for AXO Array item. Skipping...');
 866                              continue;
 867                              // return TRUE;
 868                          }
 869  
 870                          $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");
 871  
 872                          //$where_query['ax1'] = 'ax.acl_id=x.id';
 873                          $where_query['ax1'] = 'ax.acl_id=a.id';
 874                          $where_query['ax2'] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value IN (\''. implode ('\',\'', $axo_value_array) .'\'))';
 875  
 876                          $where  = 'WHERE ' . implode(' AND ', $where_query);
 877  
 878                          $conflict_result = $this->db->GetCol($query . $where);
 879  
 880                          if (is_array($conflict_result) AND !empty($conflict_result)) {
 881                              // showarray($conflict_result);
 882  
 883                              if (is_array($ignore_acl_ids)) {
 884                                  $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
 885                              }
 886  
 887                              if (count($conflict_result) > 0) {
 888                                  $conflicting_acls_str = implode(',', $conflict_result);
 889                                  $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
 890                                  return TRUE;
 891                              }
 892                          }
 893                      }
 894                  } else {
 895                      $where_query['ax1'] = '(ax.section_value IS NULL AND ax.value IS NULL)';
 896                      $where_query['ax2'] = 'xg.name IS NULL';
 897  
 898                      $where  = 'WHERE ' . implode(' AND ', $where_query);
 899  
 900                      $conflict_result = $this->db->GetCol($query . $where);
 901  
 902                      if (is_array($conflict_result) AND !empty($conflict_result)) {
 903                          // showarray($conflict_result);
 904  
 905                          if (is_array($ignore_acl_ids)) {
 906                              $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
 907                          }
 908  
 909                          if (count($conflict_result) > 0) {
 910                              $conflicting_acls_str = implode(',', $conflict_result);
 911                              $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
 912                              return TRUE;
 913                          }
 914                      }
 915                  }
 916              }
 917          }
 918  
 919          $this->debug_text('is_conflicting_acl(): No conflicting ACL found.');
 920          return FALSE;
 921      }
 922  
 923      /**
 924       * add_acl()
 925       *
 926       * Add's an ACL. ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
 927       *
 928       * @return bool Return ACL ID of new ACL if successful, FALSE otherewise.
 929       *
 930       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 931       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 932       * @param array Array of Group IDs
 933       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
 934       * @param array Array of Group IDs
 935       * @param int Allow flag
 936       * @param int Enabled flag
 937       * @param string Return Value
 938       * @param string Note
 939       * @param string ACL Section Value
 940       * @param int ACL ID # Specific Request
 941  
 942       */
 943  	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 ) {
 944  
 945          $this->debug_text("add_acl():");
 946  
 947          if (count($aco_array) == 0) {
 948              $this->debug_text("Must select at least one Access Control Object");
 949              return false;
 950          }
 951  
 952          if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
 953              $this->debug_text("Must select at least one Access Request Object or Group");
 954              return false;
 955          }
 956  
 957          if (empty($allow)) {
 958              $allow=0;
 959          }
 960  
 961          if (empty($enabled)) {
 962              $enabled=0;
 963          }
 964  
 965          if (!empty($section_value)
 966              AND !$this->get_object_section_section_id(NULL, $section_value, 'ACL')) {
 967              $this->debug_text("add_acl(): Section Value: $section_value DOES NOT exist in the database.");
 968              return false;
 969          }
 970  
 971          //Unique the group arrays. Later one we unique ACO/ARO/AXO arrays.
 972          if (is_array($aro_group_ids)) {
 973              $aro_group_ids = array_unique($aro_group_ids);
 974          }
 975          if (is_array($axo_group_ids)) {
 976              $axo_group_ids = array_unique($axo_group_ids);
 977          }
 978  
 979          //Check for conflicting ACLs.
 980          if ($this->is_conflicting_acl($aco_array,$aro_array,$aro_group_ids,$axo_array,$axo_group_ids,array($acl_id))) {
 981              $this->debug_text("add_acl(): Detected possible ACL conflict, not adding ACL!");
 982              return false;
 983          }
 984  
 985          //Edit ACL if acl_id is set. This is simply if we're being called by edit_acl().
 986          if ($this->get_acl($acl_id) == FALSE) {
 987              if ( empty($section_value) ) {
 988                  $section_value='system';
 989                  if( !$this->get_object_section_section_id(NULL, $section_value, 'ACL') ) {
 990                      // Use the acl section with the lowest order value.
 991                      $acl_sections_table = $this->_db_table_prefix .'acl_sections';
 992                      $acl_section_order_value = $this->db->GetOne("SELECT min(order_value) from $acl_sections_table");
 993  
 994                      $query = "
 995                          SELECT value
 996                          FROM $acl_sections_table
 997                          WHERE order_value = $acl_section_order_value
 998                      ";
 999                      $section_value = $this->db->GetOne($query);
1000  
1001                      if ( empty($section_value) ) {
1002                          $this->debug_text("add_acl(): No valid acl section found.");
1003                          return false;
1004                      } else {
1005                          $this->debug_text("add_acl(): Using default section value: $section_value.");
1006                      }
1007                  }
1008              }
1009  
1010              //ACL not specified, so create acl_id
1011              if (empty($acl_id)) {
1012                  //Create ACL row first, so we have the acl_id
1013                  $acl_id = $this->db->GenID($this->_db_table_prefix.'acl_seq',10);
1014  
1015                  //Double check the ACL ID was generated.
1016                  if (empty($acl_id)) {
1017                      // Not Required in Joomla! (yet)
1018                      //$this->debug_text("add_acl(): ACL_ID generation failed!");
1019                      //return false;
1020                  }
1021              }
1022  
1023              //Begin transaction _after_ GenID. Because on the first run, if GenID has to create the sequence,
1024              //the transaction will fail.
1025              $this->db->BeginTrans();
1026  
1027              $query = 'INSERT INTO '.$this->_db_table_prefix."acl (id,section_value,allow,enabled,return_value,note,updated_date) VALUES($acl_id,".$this->db->quote($section_value).",$allow,$enabled,".$this->db->quote($return_value).','.$this->db->quote($note).','.time().')';
1028              $result = $this->db->Execute($query);
1029  
1030              // Joomla/MySQL
1031              $acl_id = $this->db->insertid();
1032          } else {
1033              $section_sql = '';
1034              if ( !empty($section_value) ) {
1035                  $section_sql = 'section_value='. $this->db->quote ($section_value) .',';
1036              }
1037  
1038              $this->db->BeginTrans();
1039  
1040              //Update ACL row, and remove all mappings so they can be re-inserted.
1041              $query  = '
1042                  UPDATE    '. $this->_db_table_prefix .'acl
1043                  SET             ' . $section_sql . '
1044                          allow='. (int) $allow .',
1045                          enabled='. (int) $enabled .',
1046                          return_value='. $this->db->quote($return_value) .',
1047                          note='. $this->db->quote($note) .',
1048                          updated_date='. time() .'
1049                  WHERE    id='. (int) $acl_id;
1050              $result = $this->db->Execute($query);
1051  
1052              if ($result) {
1053                  $this->debug_text("Update completed without error, delete mappings...");
1054                  //Delete all mappings so they can be re-inserted.
1055                  foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
1056                      $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. (int) $acl_id;
1057                      $rs = $this->db->Execute($query);
1058  
1059                      if (!is_object($rs))
1060                      {
1061                          $this->debug_db('add_acl');
1062                          $this->db->RollBackTrans();
1063                          return FALSE;
1064                      }
1065                  }
1066              }
1067          }
1068  
1069          if (!is_object($result)) {
1070              $this->debug_db('add_acl');
1071              $this->db->RollBackTrans();
1072              return false;
1073          }
1074  
1075          $this->debug_text("Insert or Update completed without error, insert new mappings.");
1076          // Insert ACO/ARO/AXO mappings
1077          foreach (array('aco', 'aro', 'axo') as $map) {
1078              $map_array = ${$map .'_array'};
1079  
1080              if (!is_array ($map_array)) {
1081                  continue;
1082              }
1083  
1084              foreach ($map_array as $section_value => $value_array) {
1085                  $this->debug_text ('Insert: '. strtoupper($map) .' Section Value: '. $section_value .' '. strtoupper($map) .' VALUE: '. $value_array);
1086                  // $this->showarray ($aco_value_array);
1087  
1088                  if (!is_array($value_array)) {
1089                      $this->debug_text ('add_acl (): Invalid Format for '. strtoupper ($map) .' Array item. Skipping...');
1090                      continue;
1091                      // return true;
1092                  }
1093  
1094                  $value_array = array_unique($value_array);
1095  
1096                  foreach ($value_array as $value) {
1097                      $object_id = &$this->get_object_id($section_value, $value, $map);
1098  
1099                      if (empty($object_id))
1100                      {
1101                          $this->debug_text('add_acl(): '. strtoupper($map) . " Object Section Value: $section_value Value: $value DOES NOT exist in the database. Skipping...");
1102                          $this->db->RollBackTrans();
1103                          return false;
1104                      }
1105  
1106                      $query  = 'INSERT INTO '. $this->_db_table_prefix . $map .'_map (acl_id,section_value,value) VALUES ('. $acl_id .', '. $this->db->quote($section_value) .', '. $this->db->quote($value) .')';
1107                      $rs = $this->db->Execute($query);
1108  
1109                      if (!is_object($rs))
1110                      {
1111                          $this->debug_db('add_acl');
1112                          $this->db->RollBackTrans();
1113                          return false;
1114                      }
1115                  }
1116              }
1117          }
1118  
1119          // Insert ARO/AXO GROUP mappings
1120          foreach (array('aro', 'axo') as $map) {
1121              $map_group_ids = ${$map .'_group_ids'};
1122  
1123              if (!is_array($map_group_ids)) {
1124                  continue;
1125              }
1126  
1127              foreach ($map_group_ids as $group_id) {
1128                  $this->debug_text ('Insert: '. strtoupper($map) .' GROUP ID: '. $group_id);
1129  
1130                  $group_data = &$this->get_group_data($group_id, $map);
1131  
1132                  if (empty($group_data)) {
1133                      $this->debug_text('add_acl(): '. strtoupper($map) . " Group: $group_id DOES NOT exist in the database. Skipping...");
1134                      $this->db->RollBackTrans();
1135                      return false;
1136                  }
1137  
1138                  $query  = 'INSERT INTO '. $this->_db_table_prefix . $map .'_groups_map (acl_id,group_id) VALUES ('. (int) $acl_id .', '. (int) $group_id .')';
1139                  $rs = $this->db->Execute($query);
1140  
1141                  if (!is_object($rs)) {
1142                      $this->debug_db('add_acl');
1143                      $this->db->RollBackTrans();
1144                      return false;
1145                  }
1146              }
1147          }
1148  
1149          $this->db->CommitTrans();
1150  
1151          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1152              //Expire all cache.
1153              $this->Cache_Lite->clean('default');
1154          }
1155  
1156          //Return only the ID in the first row.
1157          return $acl_id;
1158      }
1159  
1160      /**
1161       * edit_acl()
1162       *
1163       * Edit's an ACL, ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
1164       *
1165       * @return bool Return TRUE if successful, FALSE otherewise.
1166       *
1167       * @param int ACL ID # to edit
1168       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1169       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1170       * @param array Array of Group IDs
1171       * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1172       * @param array Array of Group IDs
1173       * @param int Allow flag
1174       * @param int Enabled flag
1175       * @param string Return Value
1176       * @param string Note
1177       * @param string ACL Section Value
1178       */
1179  	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) {
1180  
1181          $this->debug_text("edit_acl():");
1182  
1183          if (empty($acl_id) ) {
1184              $this->debug_text("edit_acl(): Must specify a single ACL_ID to edit");
1185              return false;
1186          }
1187          if (count($aco_array) == 0) {
1188              $this->debug_text("edit_acl(): Must select at least one Access Control Object");
1189              return false;
1190          }
1191  
1192          if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
1193              $this->debug_text("edit_acl(): Must select at least one Access Request Object or Group");
1194              return false;
1195          }
1196  
1197          if (empty($allow)) {
1198              $allow=0;
1199          }
1200  
1201          if (empty($enabled)) {
1202              $enabled=0;
1203          }
1204  
1205          //if ($this->add_acl($aco_array, $aro_array, $group_ids, $allow, $enabled, $acl_id)) {
1206          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)) {
1207              return true;
1208          } else {
1209              $this->debug_text("edit_acl(): error in add_acl()");
1210              return false;
1211          }
1212      }
1213  
1214      /**
1215       * del_acl()
1216       *
1217       * Deletes a given ACL
1218       *
1219       * @return bool Returns TRUE if successful, FALSE otherwise.
1220       *
1221       * @param int ACL ID # to delete
1222       */
1223  	function del_acl($acl_id) {
1224  
1225          $this->debug_text("del_acl(): ID: $acl_id");
1226  
1227          if (empty($acl_id) ) {
1228              $this->debug_text("del_acl(): ACL_ID ($acl_id) is empty, this is required");
1229              return false;
1230          }
1231  
1232          $this->db->BeginTrans();
1233  
1234          // Delete all mappings to the ACL first
1235          foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
1236              $query  = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. (int) $acl_id;
1237              $rs = $this->db->Execute($query);
1238  
1239              if (!is_object($rs)) {
1240                  $this->debug_db('del_acl');
1241                  $this->db->RollBackTrans();
1242                  return false;
1243              }
1244          }
1245  
1246          // Delete the ACL
1247          $query  = 'DELETE FROM '. $this->_db_table_prefix .'acl WHERE id='. (int) $acl_id;
1248          $this->debug_text('delete query: '. $query);
1249          $rs = $this->db->Execute($query);
1250  
1251          if (!is_object($rs)) {
1252              $this->debug_db('del_acl');
1253              $this->db->RollBackTrans();
1254              return false;
1255          }
1256  
1257          $this->debug_text("del_acl(): deleted ACL ID: $acl_id");
1258          $this->db->CommitTrans();
1259  
1260          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1261              //Expire all cache.
1262              $this->Cache_Lite->clean('default');
1263          }
1264  
1265          return TRUE;
1266      }
1267  
1268  
1269      /*
1270       *
1271       * Groups
1272       *
1273       */
1274  
1275      /**
1276       * sort_groups()
1277       *
1278       * Grabs all the groups from the database doing preliminary grouping by parent
1279       *
1280       * @return array Returns 2-Dimensional array: $array[<parent_id>][<group_id>] = <group_name>
1281       *
1282       * @param string Group Type, either 'ARO' or 'AXO'
1283       */
1284  	function sort_groups($group_type='ARO') {
1285  
1286          switch(strtolower(trim($group_type))) {
1287              case 'axo':
1288                  $table = $this->_db_table_prefix .'axo_groups';
1289                  break;
1290              default:
1291                  $table = $this->_db_table_prefix .'aro_groups';
1292                  break;
1293          }
1294  
1295          //Grab all groups from the database.
1296          $query  = 'SELECT id, parent_id, name FROM '. $table .' ORDER BY parent_id, name';
1297          $rs = $this->db->Execute($query);
1298  
1299          if (!is_object($rs)) {
1300              $this->debug_db('sort_groups');
1301              return false;
1302          }
1303  
1304          /*
1305           * Save groups in an array sorted by parent. Should be make it easier for later on.
1306           */
1307          $sorted_groups = array();
1308  
1309          while ($row = $rs->FetchRow()) {
1310              $id = &$row[0];
1311              $parent_id = &$row[1];
1312              $name = &$row[2];
1313  
1314              $sorted_groups[$parent_id][$id] = $name;
1315          }
1316  
1317          return $sorted_groups;
1318      }
1319  
1320      /**
1321       * format_groups()
1322       *
1323       * Takes the array returned by sort_groups() and formats for human
1324       * consumption. Recursively calls itself to produce the desired output.
1325       *
1326       * @return array Array of formatted text, ordered by group id, formatted according to $type
1327       *
1328       * @param array Output from gacl_api->sorted_groups($group_type)
1329       * @param array Output type desired, either 'TEXT', 'TEXT_ASSOC', 'HTML', 'ARRAY' or 'ASSOC'
1330       * @param int Root of tree to produce
1331       * @param int Current level of depth
1332       * @param array Pass the current formatted groups object for appending via recursion.
1333       */
1334  	function format_groups($sorted_groups, $type='TEXT', $root_id=0, $level=0, $formatted_groups=NULL) {
1335  
1336          if ( !is_array ($sorted_groups) ) {
1337              return FALSE;
1338          }
1339  
1340          if ( !is_array ($formatted_groups) ) {
1341              $formatted_groups = array ();
1342          }
1343  
1344          $type = strtoupper($type);
1345  
1346          //$this->showarray($formatted_groups);
1347  
1348          //while (list($id,$name) = @each($sorted_groups[$root_id])) {
1349          if (isset($sorted_groups[$root_id])) {
1350              $temp = array_keys( $sorted_groups[$root_id] );
1351              $last_id = end( $temp );
1352  
1353              foreach ($sorted_groups[$root_id] as $id => $name) {
1354                  switch ($type) {
1355                      case 'TEXT':
1356                      case 'TEXT_ASSOC':
1357                          /*
1358                           * Formatting optimized for TEXT (combo box) output.
1359                           */
1360  
1361                          if ( is_numeric($level) ) {
1362                              $level = str_repeat('&nbsp;&nbsp; ', $level);
1363                          }
1364  
1365                          if ( strlen($level) >= 8 ) {
1366                              if ( $id == $last_id ) {
1367                                  $spacing = substr($level, 0, -8) .'\'- ';
1368                                  $level = substr($level, 0, -8) .'&nbsp;&nbsp; ';
1369                              } else {
1370                                  $spacing = substr($level, 0, -8) .'|- ';
1371                              }
1372                          } else {
1373                              $spacing = $level;
1374                          }
1375  
1376                          $next = $level .'|&nbsp; ';
1377  
1378                          if ($type == 'TEXT_ASSOC') {
1379                              $formatted_groups[] = array( 'value'=>$id, 'text'=>$spacing.$name );
1380                          } else {
1381                              $formatted_groups[$id] = $spacing.$name;
1382                          }
1383                          break;
1384                      case 'HTML':
1385                          /*
1386                           * Formatting optimized for HTML (tables) output.
1387                           */
1388                          $width = $level * 12;
1389                          $spacing = "<img src=\"images/blank.png\" width=\"$width\" height=\"0\" alt=\"\" />";
1390                          $next = $level + 1;
1391                          $formatted_groups[$id] = $spacing." ".$name;
1392                          break;
1393                      case 'ARRAY':
1394                          $next = $level;
1395                          $formatted_groups[$id] = $name;
1396                          break;
1397                      case 'ASSOC':
1398                          /*
1399                           * Formatting optimized for HTML: <option value="value">text</option>.
1400                           */
1401                          $next = $level;
1402                          $formatted_groups[] = array( 'value'=>$id, 'text'=>$name, 'level'=>$level );
1403                          break;
1404                      default:
1405                          return FALSE;
1406                  }
1407  
1408                  /*
1409                   * Recurse if we can.
1410                   */
1411  
1412                  //if (isset($sorted_groups[$id]) AND count($sorted_groups[$id]) > 0) {
1413                  if (isset($sorted_groups[$id]) ) {
1414                      //$this->debug_text("format_groups(): Recursing! Level: $level");
1415                      $formatted_groups = $this->format_groups($sorted_groups, $type, $id, $next, $formatted_groups);
1416                  } else {
1417                      //$this->debug_text("format_groups(): Found last branch!");
1418                  }
1419              }
1420          }
1421  
1422          //$this->debug_text("format_groups(): Returning final array.");
1423  
1424          return $formatted_groups;
1425      }
1426  
1427      /**
1428       * get_group_id()
1429       *
1430       * Gets the group_id given the name or value.
1431       *
1432       * Will only return one group id, so if there are duplicate names, it will return false.
1433       *
1434       * @return int Returns Group ID if found and Group ID is unique in database, otherwise, returns FALSE
1435       *
1436       * @param string Group Value
1437       * @param string Group Name
1438       * @param string Group Type, either 'ARO' or 'AXO'
1439       */
1440  	function get_group_id($value = NULL, $name = NULL, $group_type = 'ARO') {
1441  
1442          $this->debug_text("get_group_id(): Value: $value, Name: $name, Type: $group_type" );
1443  
1444          switch(strtolower(trim($group_type))) {
1445              case 'axo':
1446                  $table = $this->_db_table_prefix .'axo_groups';
1447                  break;
1448              default:
1449                  $table = $this->_db_table_prefix .'aro_groups';
1450                  break;
1451          }
1452  
1453          $name = trim($name);
1454          $value = trim($value);
1455  
1456          if (empty($name) AND $value === '') {
1457              $this->debug_text("get_group_id(): name and value, at least one is required");
1458              return false;
1459          }
1460  
1461          $query = 'SELECT id FROM '. $table .' WHERE ';
1462          if ($value !== '') {
1463            $query .= ' value='. $this->db->quote($value);
1464          } else {
1465            $query .= ' name='. $this->db->quote($name);
1466          }
1467  
1468          $this->db->setQuery( $query );
1469  
1470          $rows = $this->db->loadResultArray();
1471          if ($this->db->getErrorNum()) {
1472              $this->debug_db('get_group_id');
1473              return false;
1474          }
1475  
1476          $row_count = count( $rows );
1477  
1478          if ($row_count > 1) {
1479              $this->debug_text("get_group_id(): Returned $row_count rows, can only return one. Please make your names unique.");
1480              return false;
1481          }
1482  
1483          if ($row_count == 0) {
1484              $this->debug_text("get_group_id(): Returned $row_count rows");
1485              return false;
1486          }
1487  
1488          //Return the ID.
1489          return $rows[0];
1490      }
1491  
1492      /**
1493       * get_group_children()
1494       *
1495       * Gets a groups child IDs
1496       *
1497       * @return array Array of Child ID's of the referenced group
1498       *
1499       * @param int Group ID #
1500       * @param int Group Type, either 'ARO' or 'AXO'
1501       * @param string Either 'RECURSE' or 'NO_RECURSE', to recurse while fetching group children.
1502       */
1503  	function get_group_children($group_id, $group_type = 'ARO', $recurse = 'NO_RECURSE') {
1504          $this->debug_text("get_group_children(): Group_ID: $group_id Group Type: $group_type Recurse: $recurse");
1505  
1506          switch (strtolower(trim($group_type))) {
1507              case 'axo':
1508                  $group_type = 'axo';
1509                  $table = $this->_db_table_prefix .'axo_groups';
1510                  break;
1511              default:
1512                  $group_type = 'aro';
1513                  $table = $this->_db_table_prefix .'aro_groups';
1514          }
1515  
1516          if (empty($group_id)) {
1517              $this->debug_text("get_group_children(): ID ($group_id) is empty, this is required");
1518              return FALSE;
1519          }
1520  
1521          $query  = '
1522                  SELECT        g1.id
1523                  FROM        '. $table .' g1';
1524  
1525          //FIXME-mikeb: Why is group_id in quotes?
1526          switch (strtoupper($recurse)) {
1527              case 'RECURSE':
1528                  $query .= '
1529                  LEFT JOIN     '. $table .' g2 ON g2.lft<g1.lft AND g2.rgt>g1.rgt
1530                  WHERE        g2.id='. (int) $group_id;
1531                  break;
1532              default:
1533                  $query .= '
1534                  WHERE        g1.parent_id='. (int) $group_id;
1535          }
1536  
1537          $query .= '
1538                  ORDER BY    g1.value';
1539  
1540          return $this->db->GetCol($query);
1541      }
1542  
1543      /**
1544       * get_group_data()
1545       *
1546       * Gets the group data given the GROUP_ID.
1547       *
1548       * @return array Returns numerically indexed array with the following columns:
1549       *    - array[0] = (int) Group ID #
1550       *    - array[1] = (int) Parent Group ID #
1551       *    - array[2] = (string) Group Value
1552       *    - array[3] = (string) Group Name
1553       *    - array[4] = (int) lft MPTT Value
1554       *    - array[5] = (int) rgt MPTT Value
1555       *
1556       * @param int Group ID #
1557       * @param string Group Type, either 'ARO' or 'AXO'
1558       */
1559  	function get_group_data($group_id, $group_type = 'ARO') {
1560  
1561          $this->debug_text("get_group_data(): Group_ID: $group_id Group Type: $group_type");
1562  
1563          switch(strtolower(trim($group_type))) {
1564              case 'axo':
1565                  $group_type = 'axo';
1566                  $table = $this->_db_table_prefix .'axo_groups';
1567                  break;
1568              default:
1569                  $group_type = 'aro';
1570                  $table = $this->_db_table_prefix .'aro_groups';
1571                  break;
1572          }
1573  
1574          if (empty($group_id) ) {
1575              $this->debug_text("get_group_data(): ID ($group_id) is empty, this is required");
1576              return false;
1577          }
1578  
1579          $query  = 'SELECT id, parent_id, value, name, lft, rgt FROM '. $table .' WHERE id='. (int) $group_id;
1580          //$rs = $this->db->Execute($query);
1581          $row = $this->db->GetRow($query);
1582  
1583          if ($row) {
1584              return $row;
1585          }
1586  
1587          $this->debug_text("get_object_data(): Group does not exist.");
1588          return false;
1589      }
1590  
1591      /**
1592       * get_group_parent_id()
1593       *
1594       * Grabs the parent_id of a given group
1595       *
1596       * @return int Parent ID of the Group
1597       *
1598       * @param int Group ID #
1599       * @param string Group Type, either 'ARO' or 'AXO'
1600       */
1601  	function get_group_parent_id($id, $group_type='ARO') {
1602  
1603          $this->debug_text("get_group_parent_id(): ID: $id Group Type: $group_type");
1604  
1605          switch(strtolower(trim($group_type))) {
1606              case 'axo':
1607                  $table = $this->_db_table_prefix .'axo_groups';
1608                  break;
1609              default:
1610                  $table = $this->_db_table_prefix .'aro_groups';
1611                  break;
1612          }
1613  
1614          if (empty($id) ) {
1615              $this->debug_text("get_group_parent_id(): ID ($id) is empty, this is required");
1616              return false;
1617          }
1618  
1619          $query = 'SELECT parent_id FROM '. $table .' WHERE id='. (int) $id;
1620          $rs = $this->db->Execute($query);
1621  
1622          if (!is_object($rs)) {
1623              $this->debug_db('get_group_parent_id');
1624              return false;
1625          }
1626  
1627          $row_count = $rs->RecordCount();
1628  
1629          if ($row_count > 1) {
1630              $this->debug_text("get_group_parent_id(): Returned $row_count rows, can only return one. Please make your names unique.");
1631              return false;
1632          }
1633  
1634          if ($row_count == 0) {
1635              $this->debug_text("get_group_parent_id(): Returned $row_count rows");
1636              return false;
1637          }
1638  
1639          $row = $rs->FetchRow();
1640  
1641          //Return the ID.
1642          return $row[0];
1643      }
1644  
1645  
1646      /**
1647       * get_root_group_id ()
1648       *
1649       * Grabs the id of the root group for the specified tree
1650       *
1651       * @return int Root Group ID #
1652       *
1653       * @param string Group Type, either 'ARO' or 'AXO'
1654       */
1655  	function get_root_group_id($group_type='ARO') {
1656  
1657          $this->debug_text('get_root_group_id(): Group Type: '. $group_type);
1658  
1659          switch (strtolower($group_type)) {
1660              case 'axo':
1661                  $table = $this->_db_table_prefix .'axo_groups';
1662                  break;
1663              case 'aro':
1664                  $table = $this->_db_table_prefix .'aro_groups';
1665                  break;
1666              default:
1667                  $this->debug_text('get_root_group_id(): Invalid Group Type: '. $group_type);
1668                  return FALSE;
1669          }
1670  
1671          $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
1672          $rs = $this->db->Execute($query);
1673  
1674          if (!is_object($rs)) {
1675              $this->debug_db('get_root_group_id');
1676              return FALSE;
1677          }
1678  
1679          $row_count = $rs->RecordCount();
1680  
1681          switch ($row_count) {
1682              case 1:
1683                  $row = $rs->FetchRow();
1684                  // Return the ID.
1685                  return $row[0];
1686              case 0:
1687                  $this->debug_text('get_root_group_id(): Returned 0 rows, you do not have a root group defined yet.');
1688                  return FALSE;
1689          }
1690  
1691          $this->debug_text('get_root_group_id(): Returned '. $row_count .' rows, can only return one. Your tree is very broken.');
1692          return FALSE;
1693      }
1694  
1695      /*======================================================================*\
1696          Function:    map_path_to_root()
1697          Purpose:    Maps a unique path to root to a specific group. Each group can only have
1698                          one path to root.
1699      \*======================================================================*/
1700      /** REMOVED **/
1701      /*======================================================================*\
1702          Function:    put_path_to_root()
1703          Purpose:    Writes the unique path to root to the database. There should really only be
1704                          one path to root for each level "deep" the groups go. If the groups are branched
1705                          10 levels deep, there should only be 10 unique path to roots. These of course
1706                          overlap each other more and more the closer to the root/trunk they get.
1707      \*======================================================================*/
1708      /** REMOVED **/
1709      /*======================================================================*\
1710          Function:    clean_path_to_root()
1711          Purpose:    Cleans up any paths that are not being used.
1712      \*======================================================================*/
1713      /** REMOVED **/
1714      /*======================================================================*\
1715          Function:    get_path_to_root()
1716          Purpose:    Generates the path to root for a given group.
1717      \*======================================================================*/
1718      /** REMOVED **/
1719  
1720      /**
1721       * add_group()
1722       *
1723       * Inserts a group, defaults to be on the "root" branch.
1724       *
1725       * Since v3.3.x you can only create one group with Parent_ID=0
1726       * So, its a good idea to create a "Virtual Root" group with Parent_ID=0
1727       * Then assign other groups to that.
1728       *
1729       * @return int New Group ID # if successful, FALSE if otherwise.
1730       *
1731       * @param string Group Value
1732       * @param string Group Name
1733       * @param int Parent Group ID #
1734       * @param string Group Type, either 'ARO' or 'AXO'
1735       */
1736  	function add_group($value, $name, $parent_id=0, $group_type='ARO') {
1737  
1738          switch(strtolower(trim($group_type))) {
1739              case 'axo':
1740                  $group_type = 'axo';
1741                  $table = $this->_db_table_prefix .'axo_groups';
1742                  break;
1743              default:
1744                  $group_type = 'aro';
1745                  $table = $this->_db_table_prefix .'aro_groups';
1746                  break;
1747          }
1748  
1749          $this->debug_text("add_group(): Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
1750  
1751          $name = trim($name);
1752          $value = trim($value);
1753  
1754          if ( $name == '' ) {
1755              $this->debug_text("add_group(): name ($name) OR parent id ($parent_id) is empty, this is required");
1756              return false;
1757          }
1758  
1759          //This has to be outside the transaction, because the first time it is run, it will say the sequence
1760          //doesn't exist. Then try to create it, but the transaction will already by aborted by then.
1761          $insert_id = $this->db->GenID($table.'_id_seq', $this->_defaultGenID( $table ));
1762          if ( $value === '' ) {
1763              $value = $insert_id;
1764          }
1765  
1766          $this->db->BeginTrans();
1767  
1768          // special case for root group
1769          if ($parent_id == 0) {
1770              // check a root group is not already defined
1771              $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
1772              $rs = $this->db->Execute($query);
1773  
1774              if (!is_object($rs)) {
1775                  $this->debug_db('add_group');
1776                  $this->db->RollBackTrans();
1777                  return FALSE;
1778              }
1779  
1780              if ($rs->RowCount() > 0) {
1781                  $this->debug_text('add_group (): A root group already exists.');
1782                  $this->db->RollBackTrans();
1783                  return FALSE;
1784              }
1785  
1786              $parent_lft = 0;
1787              $parent_rgt = 1;
1788          } else {
1789              if (empty($parent_id)) {
1790                  $this->debug_text("add_group (): parent id ($parent_id) is empty, this is required");
1791                  $this->db->RollbackTrans();
1792                  return FALSE;
1793              }
1794  
1795              // grab parent details from database
1796              $query = 'SELECT id, lft, rgt FROM '. $table .' WHERE id='. (int) $parent_id;
1797              $row = $this->db->GetRow($query);
1798  
1799              if (!is_array($row)) {
1800                  $this->debug_db('add_group');
1801                  $this->db->RollBackTrans();
1802                  return FALSE;
1803              }
1804  
1805              if (empty($row)) {
1806                  $this->debug_text('add_group (): Parent ID: '. $parent_id .' not found.');
1807                  $this->db->RollBackTrans();
1808                  return FALSE;
1809              }
1810  
1811              $parent_lft = &$row[1];
1812              $parent_rgt = &$row[2];
1813  
1814              // make room for the new group
1815              $query  = 'UPDATE '. $table .' SET rgt=rgt+2 WHERE rgt>='. (int) $parent_rgt;
1816              $rs = $this->db->Execute($query);
1817  
1818              if (!is_object($rs)) {
1819                  $this->debug_db('add_group');
1820                  $this->db->RollBackTrans();
1821                  return FALSE;
1822              }
1823  
1824              $query  = 'UPDATE '. $table .' SET lft=lft+2 WHERE lft>'. $parent_rgt;
1825              $rs = $this->db->Execute($query);
1826  
1827              if (!is_object($rs)) {
1828                  $this->debug_db('add_group');
1829                  $this->db->RollBackTrans();
1830                  return FALSE;
1831              }
1832          }
1833  
1834          $query = 'INSERT INTO '. $table .' (id,parent_id,name,value,lft,rgt) VALUES ('. $insert_id .','. $parent_id .','. $this->db->quote($name) .','. $this->db->quote($value) .','. $parent_rgt .','. ($parent_rgt + 1) .')';
1835          $rs = $this->db->Execute($query);
1836  
1837          if (!is_object($rs)) {
1838              $this->debug_db('add_group');
1839              $this->db->RollBackTrans();
1840              return FALSE;
1841          }
1842  
1843          $this->db->CommitTrans();
1844  
1845          // Joomla/MySQL
1846          $insert_id = $this->db->insertid();
1847  
1848          $this->debug_text('add_group (): Added group as ID: '. $insert_id);
1849          return $insert_id;
1850      }
1851  
1852      /**
1853       * get_group_objects()
1854       *
1855       * Gets all objects assigned to a group.
1856       *
1857       * If $option == 'RECURSE' it will get all objects in child groups as well.
1858       * defaults to omit child groups.
1859       *
1860       * @return array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
1861  
1862       *
1863       * @param int Group ID #
1864       * @param string Group Type, either 'ARO' or 'AXO'
1865       * @param string Option, either 'RECURSE' or 'NO_RECURSE'
1866       */
1867  	function get_group_objects($group_id, $group_type='ARO', $option='NO_RECURSE') {
1868  
1869          switch(strtolower(trim($group_type))) {
1870              case 'axo':
1871                  $group_type = 'axo';
1872                  $object_table = $this->_db_table_prefix .'axo';
1873                  $group_table = $this->_db_table_prefix .'axo_groups';
1874                  $map_table = $this->_db_table_prefix .'groups_axo_map';
1875                  break;
1876              default:
1877                  $group_type = 'aro';
1878                  $object_table = $this->_db_table_prefix .'aro';
1879                  $group_table = $this->_db_table_prefix .'aro_groups';
1880                  $map_table = $this->_db_table_prefix .'groups_aro_map';
1881                  break;
1882          }
1883  
1884          $this->debug_text("get_group_objects(): Group ID: $group_id");
1885  
1886          if (empty($group_id)) {
1887              $this->debug_text("get_group_objects(): Group ID:  ($group_id) is empty, this is required");
1888              return false;
1889          }
1890  
1891          $query  = '
1892                  SELECT        o.section_value,o.value';
1893  
1894          if ($option == 'RECURSE') {
1895              $query .= '
1896                  FROM        '. $group_table .' g2
1897                  JOIN        '. $group_table .' g1 ON g1.lft>=g2.lft AND g1.rgt<=g2.rgt
1898                  JOIN        '. $map_table .' AS gm ON gm.group_id=g1.id
1899                  JOIN        '. $object_table .' AS o ON o.id=gm.'. $group_type .'_id
1900                  WHERE        g2.id='. (int) $group_id;
1901          } else {
1902              $query .= '
1903                  FROM        '. $map_table .' AS gm
1904                  JOIN        '. $object_table .' AS o ON o.id=gm.'. $group_type .'_id
1905                  WHERE        gm.group_id='. (int) $group_id;
1906          }
1907  
1908          $rs = $this->db->Execute($query);
1909  
1910          if (!is_object($rs)) {
1911              $this->debug_db('get_group_objects');
1912              return false;
1913          }
1914  
1915          $this->debug_text("get_group_objects(): Got group objects, formatting array.");
1916  
1917          $retarr = array();
1918  
1919          //format return array.
1920          while ($row = $rs->FetchRow()) {
1921              $section = &$row[0];
1922              $value = &$row[1];
1923  
1924              $retarr[$section][] = $value;
1925          }
1926  
1927          return $retarr;
1928      }
1929  
1930      /**
1931       * add_group_object()
1932       *
1933       * Assigns an Object to a group
1934       *
1935       * @return bool Returns TRUE if successful, FALSE otherwise.
1936       *
1937       * @param int Group ID #
1938       * @param string Object Section Value
1939       * @param string Object Value
1940       * @param string Group Type, either 'ARO' or 'AXO'
1941       */
1942  	function add_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
1943  
1944          switch(strtolower(trim($group_type))) {
1945              case 'axo':
1946                  $group_type = 'axo';
1947                  $table = $this->_db_table_prefix .'groups_axo_map';
1948                  $object_table = $this->_db_table_prefix .'axo';
1949                  $group_table = $this->_db_table_prefix .'axo_groups';
1950                  break;
1951              default:
1952                  $group_type = 'aro';
1953                  $table = $this->_db_table_prefix .'groups_aro_map';
1954                  $object_table = $this->_db_table_prefix .'aro';
1955                  $group_table = $this->_db_table_prefix .'aro_groups';
1956                  break;
1957          }
1958  
1959          $this->debug_text("add_group_object(): Group ID: $group_id Section Value: $object_section_value Value: $object_value Group Type: $group_type");
1960  
1961          $object_section_value = trim($object_section_value);
1962          $object_value = trim($object_value);
1963  
1964          if (empty($group_id) OR $object_value === '' OR $object_section_value === '') {
1965              $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");
1966              return false;
1967          }
1968  
1969          // test to see if object & group exist and if object is already a member
1970          $query  = '
1971                  SELECT        o.id AS id,g.id AS group_id,gm.group_id AS member
1972                  FROM        '. $object_table .' o
1973                  LEFT JOIN    '. $group_table .' g ON g.id='. (int) $group_id .'
1974                  LEFT JOIN    '. $table .' gm ON (gm.'. $group_type .'_id=o.id AND gm.group_id=g.id)
1975                  WHERE        (o.section_value='. $this->db->quote($object_section_value) .' AND o.value='. $this->db->quote($object_value) .')';
1976          $rs = $this->db->Execute($query);
1977  
1978          if (!is_object($rs)) {
1979              $this->debug_db('add_group_object');
1980              return FALSE;
1981          }
1982  
1983          if ($rs->RecordCount() != 1) {
1984              $this->debug_text('add_group_object(): Value ('. $object_value .') OR Section value ('. $object_section_value .') is invalid. Does this object exist?');
1985              return FALSE;
1986          }
1987  
1988          $row = $rs->FetchRow();
1989  
1990          if ($row[1] != $group_id) {
1991              $this->debug_text('add_group_object(): Group ID ('. $group_id .') is invalid. Does this group exist?');
1992              return FALSE;
1993          }
1994  
1995          //Group_ID == Member
1996          if ($row[1] == $row[2]) {
1997              $this->debug_text('add_group_object(): Object: ('. $object_section_value .' -> '. $object_value .') is already a member of Group: ('. $group_id .')');
1998              //Object is already assigned to group. Return true.
1999              return TRUE;
2000          }
2001  
2002          $object_id = $row[0];
2003  
2004          $query = 'INSERT INTO '. $table .' (group_id,'. $group_type .'_id) VALUES ('. (int) $group_id .','. (int) $object_id .')';
2005          $rs = $this->db->Execute($query);
2006  
2007          if (!is_object($rs)) {
2008              $this->debug_db('add_group_object');
2009              return FALSE;
2010          }
2011  
2012          $this->debug_text('add_group_object(): Added Object: '. $object_id .' to Group ID: '. $group_id);
2013  
2014          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2015              //Expire all cache.
2016              $this->Cache_Lite->clean('default');
2017          }
2018  
2019          return TRUE;
2020      }
2021  
2022      /**
2023       * del_group_object()
2024       *
2025       * Removes an Object from a group.
2026       *
2027       * @return bool Returns TRUE if successful, FALSE otherwise
2028       *
2029       * @param int Group ID #
2030       * @param string Object Section Value
2031       * @param string Object Value
2032       * @param string Group Type, either 'ARO' or 'AXO'
2033       */
2034  	function del_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
2035  
2036          switch(strtolower(trim($group_type))) {
2037              case 'axo':
2038                  $group_type = 'axo';
2039                  $table = $this->_db_table_prefix .'groups_axo_map';
2040                  break;
2041              default:
2042                  $group_type = 'aro';
2043                  $table = $this->_db_table_prefix .'groups_aro_map';
2044                  break;
2045          }
2046  
2047          $this->debug_text("del_group_object(): Group ID: $group_id Section value: $object_section_value Value: $object_value");
2048  
2049          $object_section_value = trim($object_section_value);
2050          $object_value = trim($object_value);
2051  
2052          if (empty($group_id) OR $object_value === '' OR $object_section_value === '') {
2053              $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");
2054              return false;
2055          }
2056  
2057           if (!$object_id = $this->get_object_id($object_section_value, $object_value, $group_type)) {
2058              $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?");
2059              return FALSE;
2060          }
2061  
2062          $query = 'DELETE FROM '. $table .' WHERE group_id='. (int) $group_id .' AND '. $group_type .'_id='. (int) $object_id;
2063          $rs = $this->db->Execute($query);
2064  
2065          if (!is_object($rs)) {
2066              $this->debug_db('del_group_object');
2067              return false;
2068          }
2069  
2070          $this->debug_text("del_group_object(): Deleted Value: $object_value to Group ID: $group_id assignment");
2071  
2072          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2073              //Expire all cache.
2074              $this->Cache_Lite->clean('default');
2075          }
2076  
2077          return true;
2078      }
2079  
2080      /**
2081       * edit_group()
2082       *
2083       * Edits a group
2084       *
2085       * @returns bool Returns TRUE if successful, FALSE otherwise
2086       *
2087       * @param int Group ID #
2088       * @param string Group Value
2089       * @param string Group Name
2090       * @param int Parent ID #
2091       * @param string Group Type, either 'ARO' or 'AXO'
2092       */
2093  	function edit_group($group_id, $value=NULL, $name=NULL, $parent_id=NULL, $group_type='ARO') {
2094          $this->debug_text("edit_group(): ID: $group_id Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
2095  
2096          switch(strtolower(trim($group_type))) {
2097              case 'axo':
2098                  $group_type = 'axo';
2099                  $table = $this->_db_table_prefix .'axo_groups';
2100                  break;
2101              default:
2102                  $group_type = 'aro';
2103                  $table = $this->_db_table_prefix .'aro_groups';
2104                  break;
2105          }
2106  
2107          if (empty($group_id) ) {
2108              $this->debug_text('edit_group(): Group ID ('. $group_id .') is empty, this is required');
2109              return FALSE;
2110          }
2111  
2112          if ( !is_array($curr = $this->get_group_data($group_id, $group_type)) ) {
2113              $this->debug_text('edit_group(): Invalid Group ID: '. $group_id);
2114              return FALSE;
2115          }
2116  
2117          $name = trim($name);
2118  
2119          // don't set name if it is unchanged
2120          if ($name == $curr[3]) {
2121              unset($name);
2122          }
2123  
2124          // don't set parent_id if it is unchanged
2125          if ($parent_id == $curr[1]) {
2126              unset($parent_id);
2127          }
2128  
2129          if (!empty($parent_id)) {
2130              if ($group_id == $parent_id) {
2131                  $this->debug_text('edit_group(): Groups can\'t be a parent to themselves. Incest is bad. ;)');
2132                  return FALSE;
2133              }
2134  
2135              //Make sure we don't re-parent to our own children.
2136              //Grab all children of this group_id.
2137              $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
2138              if (is_array($children_ids)) {
2139                  if (@in_array($parent_id, $children_ids) ) {
2140                      $this->debug_text('edit_group(): Groups can\'t be re-parented to their own children, this would be incestuous!');
2141                      return FALSE;
2142                  }
2143              }
2144              unset($children_ids);
2145  
2146              // make sure parent exists
2147              if (!$this->get_group_data($parent_id, $group_type)) {
2148                  $this->debug_text('edit_group(): Parent Group ('. $parent_id .') doesn\'t exist');
2149                  return FALSE;
2150              }
2151          }
2152  
2153          $set = array();
2154  
2155          // update name if it is specified.
2156          if (!empty($name)) {
2157              $set[] = 'name='. $this->db->quote($name);
2158          }
2159  
2160          // update parent_id if it is specified.
2161          if (!empty($parent_id)) {
2162              $set[] = 'parent_id='. (int) $parent_id;
2163          }
2164  
2165          // update value if it is specified.
2166          if ($value !== '' OR $value !== null) {
2167              $set[] = 'value='. $this->db->quote($value);
2168          }
2169  
2170          if (empty($set)) {
2171              $this->debug_text('edit_group(): Nothing to update.');
2172              return FALSE;
2173          }
2174  
2175          $this->db->BeginTrans();
2176  
2177          $query  = 'UPDATE '. $table .' SET '. implode(',', $set) .' WHERE id='. (int) $group_id;
2178          $rs = $this->db->Execute($query);
2179  
2180          if (!is_object($rs)) {
2181              $this->debug_db('edit_group');
2182              $this->db->RollbackTrans();
2183              return FALSE;
2184          }
2185  
2186          $this->debug_text('edit_group(): Modified group ID: '. $group_id);
2187  
2188          // rebuild group tree if parent_id has changed
2189          if (!empty($parent_id)) {
2190              if (!$this->_rebuild_tree($table, $this->get_root_group_id($group_type))) {
2191                  $this->db->RollbackTrans();
2192                  return FALSE;
2193              }
2194          }
2195  
2196          $this->db->CommitTrans();
2197  
2198          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2199              // Expire all cache.
2200              $this->Cache_Lite->clean('default');
2201          }
2202  
2203          return TRUE;
2204      }
2205  
2206      /**
2207       * rebuild_tree ()
2208       *
2209       * rebuilds the group tree for the given type
2210       *
2211       * @return bool Returns TRUE if successful, FALSE otherwise
2212       *
2213       * @param string Group Type, either 'ARO' or 'AXO'
2214       * @param int Group ID #
2215       * @param int Left value of Group
2216       */
2217  	function rebuild_tree($group_type = 'ARO', $group_id = NULL, $left = 1) {
2218          $this->debug_text("rebuild_tree(): Group Type: $group_type Group ID: $group_id Left: $left");
2219  
2220          switch (strtolower(trim($group_type))) {
2221              case 'axo':
2222                  $group_type = 'axo';
2223                  $table = $this->_db_table_prefix .'axo_groups';
2224                  break;
2225              default:
2226                  $group_type = 'aro';
2227                  $table = $this->_db_table_prefix .'aro_groups';
2228                  break;
2229          }
2230  
2231          if (!isset($group_id)) {
2232              if ($group_id = $this->get_root_group_id($group_type)) {
2233                  $left = 1;
2234                  $this->debug_text('rebuild_tree(): No Group ID Specified, using Root Group ID: '. $group_id);
2235              } else {
2236                  $this->debug_text('rebuild_tree(): A Root group could not be found, are there any groups defined?');
2237                  return FALSE;
2238              }
2239          }
2240  
2241          $this->db->BeginTrans();
2242          $rebuilt = $this->_rebuild_tree($table, $group_id, $left);
2243  
2244          if ($rebuilt === FALSE) {
2245              $this->debug_text('rebuild_tree(): Error rebuilding tree!');
2246              $this->db->RollBackTrans();
2247              return FALSE;
2248          }
2249  
2250          $this->db->CommitTrans();
2251          $this->debug_text('rebuild_tree(): Tree rebuilt.');
2252          return TRUE;
2253      }
2254      /**
2255       * _rebuild_tree ()
2256       *
2257       * Utility recursive function called by rebuild_tree()
2258       *
2259       * @return int Returns right value of this node + 1
2260       *
2261       * @param string Table name of group type
2262       * @param int Group ID #
2263       * @param int Left value of Group
2264       */
2265  	function _rebuild_tree($table, $group_id, $left = 1) {
2266          $this->debug_text("_rebuild_tree(): Table: $table Group ID: $group_id Left: $left");
2267  
2268          // get all children of this node
2269          $query = 'SELECT id FROM '. $table .' WHERE parent_id='. (int) $group_id;
2270          $rs = $this->db->Execute($query);
2271  
2272          if (!is_object($rs)) {
2273              $this->debug_db('_rebuild_tree');
2274              return FALSE;
2275          }
2276  
2277          // the right value of this node is the left value + 1
2278          $right = $left + 1;
2279  
2280          while ($row = $rs->FetchRow()) {
2281              // recursive execution of this function for each
2282              // child of this node
2283              // $right is the current right value, which is
2284              // incremented by the rebuild_tree function
2285              $right = $this->_rebuild_tree($table, $row[0], $right);
2286  
2287              if ($right === FALSE) {
2288                  return FALSE;
2289              }
2290          }
2291  
2292          // we've got the left value, and now that we've processed
2293          // the children of this node we also know the right value
2294          $query  = 'UPDATE '. $table .' SET lft='. (int) $left .', rgt='. (int) $right .' WHERE id='. (int) $group_id;
2295          $rs = $this->db->Execute($query);
2296  
2297          if (!is_object($rs)) {
2298              $this->debug_db('_rebuild_tree');
2299              return FALSE;
2300          }
2301  
2302          // return the right value of this node + 1
2303          return $right + 1;
2304      }
2305  
2306      /**
2307       * del_group()
2308       *
2309       * deletes a given group
2310       *
2311       * @return bool Returns TRUE if successful, FALSE otherwise.
2312       *
2313       * @param int Group ID #
2314       * @param bool If TRUE, child groups of this group will be reparented to the current group's parent.
2315       * @param string Group Type, either 'ARO' or 'AXO'
2316       */
2317  	function del_group($group_id, $reparent_children=TRUE, $group_type='ARO') {
2318  
2319          switch(strtolower(trim($group_type))) {
2320              case 'axo':
2321                  $group_type = 'axo';
2322                  $table = $this->_db_table_prefix .'axo_groups';
2323                  $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
2324                  $groups_object_map_table = $this->_db_table_prefix .'groups_axo_map';
2325                  break;
2326              default:
2327                  $group_type = 'aro';
2328                  $table = $this->_db_table_prefix .'aro_groups';
2329                  $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
2330                  $groups_object_map_table = $this->_db_table_prefix .'groups_aro_map';
2331                  break;
2332          }
2333  
2334          $this->debug_text("del_group(): ID: $group_id Reparent Children: $reparent_children Group Type: $group_type");
2335  
2336          if (empty($group_id) ) {
2337              $this->debug_text("del_group(): Group ID ($group_id) is empty, this is required");
2338              return false;
2339          }
2340  
2341          // Get details of this group
2342          $query = 'SELECT id, parent_id, name, lft, rgt FROM '. $table .' WHERE id='. (int) $group_id;
2343          $group_details = $this->db->GetRow($query);
2344  
2345          if (!is_array($group_details)) {
2346              $this->debug_db('del_group');
2347              return false;
2348          }
2349  
2350          $parent_id = $group_details[1];
2351  
2352          $left = $group_details[3];
2353          $right = $group_details[4];
2354  
2355          $this->db->BeginTrans();
2356  
2357          // grab list of all children
2358          $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
2359  
2360          // prevent deletion of root group & reparent of children if it has more than one immediate child
2361          if ($parent_id == 0) {
2362              $query = 'SELECT count(*) FROM '. $table .' WHERE parent_id='. (int) $group_id;
2363              $child_count = $this->db->GetOne($query);
2364  
2365              if (($child_count > 1) AND $reparent_children) {
2366                  $this->debug_text ('del_group (): You cannot delete the root group and reparent children, this would create multiple root groups.');
2367                  $this->db->RollbackTrans();
2368                  return FALSE;
2369              }
2370          }
2371  
2372          $success = FALSE;
2373  
2374          /*
2375           * Handle children here.
2376           */
2377          switch (TRUE) {
2378              // there are no child groups, just delete group
2379              case !is_array($children_ids):
2380              case count($children_ids) == 0:
2381                  // remove acl maps
2382                  $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. (int) $group_id;
2383                  $rs = $this->db->Execute($query);
2384  
2385                  if (!is_object($rs)) {
2386                      break;
2387                  }
2388  
2389                  // remove group object maps
2390                  $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. (int) $group_id;
2391                  $rs = $this->db->Execute($query);
2392  
2393                  if (!is_object($rs)) {
2394                      break;
2395                  }
2396  
2397                  // remove group
2398                  $query = 'DELETE FROM '. $table .' WHERE id='. (int) $group_id;
2399                  $rs = $this->db->Execute($query);
2400  
2401                  if (!is_object($rs)) {
2402                      break;
2403                  }
2404  
2405                  // move all groups right of deleted group left by width of deleted group
2406                  $query = 'UPDATE '. $table .' SET lft=lft-'. (int)($right-$left+1) .' WHERE lft>'. (int) $right;
2407                  $rs = $this->db->Execute($query);
2408  
2409                  if (!is_object($rs)) {
2410                      break;
2411                  }
2412  
2413                  $query = 'UPDATE '. $table .' SET rgt=rgt-'. (int)($right-$left+1) .' WHERE rgt>'. (int) $right;
2414                  $rs = $this->db->Execute($query);
2415  
2416                  if (!is_object($rs)) {
2417                      break;
2418                  }
2419  
2420                  $success = TRUE;
2421                  break;
2422              case $reparent_children == TRUE:
2423                  // remove acl maps
2424                  $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. (int) $group_id;
2425                  $rs = $this->db->Execute($query);
2426  
2427                  if (!is_object($rs)) {
2428                      break;
2429                  }
2430  
2431                  // remove group object maps
2432                  $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. (int) $group_id;
2433                  $rs = $this->db->Execute($query);
2434  
2435                  if (!is_object($rs)) {
2436                      break;
2437                  }
2438  
2439                  // remove group
2440                  $query = 'DELETE FROM '. $table .' WHERE id='. (int) $group_id;
2441                  $rs = $this->db->Execute($query);
2442  
2443                  if (!is_object($rs)) {
2444                      break;
2445                  }
2446  
2447                  // set parent of immediate children to parent group
2448                  $query = 'UPDATE '. $table .' SET parent_id='. (int) $parent_id .' WHERE parent_id='. (int) $group_id;
2449                  $rs = $this->db->Execute($query);
2450  
2451                  if (!is_object($rs)) {
2452                      break;
2453                  }
2454  
2455                  // move all children left by 1
2456                  $query = 'UPDATE '. $table .' SET lft=lft-1, rgt=rgt-1 WHERE lft>'. (int) $left .' AND rgt<'. (int) $right;
2457                  $rs = $this->db->Execute($query);
2458  
2459                  if (!is_object($rs)) {
2460                      break;
2461                  }
2462  
2463                  // move all groups right of deleted group left by 2
2464                  $query = 'UPDATE '. $table .' SET lft=lft-2 WHERE lft>'. (int) $right;
2465                  $rs = $this->db->Execute($query);
2466  
2467                  if (!is_object($rs)) {
2468                      break;
2469                  }
2470  
2471                  $query = 'UPDATE '. $table .' SET rgt=rgt-2 WHERE rgt>'. (int) $right;
2472                  $rs = $this->db->Execute($query);
2473  
2474                  if (!is_object($rs)) {
2475                      break;
2476                  }
2477  
2478                  $success = TRUE;
2479                  break;
2480              default:
2481                  // make list of group and all children
2482                  $group_ids = $children_ids;
2483                  $group_ids[] = (int) $group_id;
2484  
2485                  // remove acl maps
2486                  $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
2487                  $rs = $this->db->Execute($query);
2488  
2489                  if (!is_object($rs)) {
2490                      break;
2491                  }
2492  
2493                  // remove group object maps
2494                  $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
2495                  $rs = $this->db->Execute($query);
2496  
2497                  if (!is_object($rs)) {
2498                      break;
2499                  }
2500  
2501                  // remove groups
2502                  $query = 'DELETE FROM '. $table .' WHERE id IN ('. implode (',', $group_ids) .')';
2503                  $rs = $this->db->Execute($query);
2504  
2505                  if (!is_object($rs)) {
2506                      break;
2507                  }
2508  
2509                  // move all groups right of deleted group left by width of deleted group
2510                  $query = 'UPDATE '. $table .' SET lft=lft-'. ($right - $left + 1) .' WHERE lft>'. (int) $right;
2511                  $rs = $this->db->Execute($query);
2512  
2513                  if (!is_object($rs)) {
2514                      break;
2515                  }
2516  
2517                  $query = 'UPDATE '. $table .' SET rgt=rgt-'. ($right - $left + 1) .' WHERE rgt>'. (int) $right;
2518                  $rs = $this->db->Execute($query);
2519  
2520                  if (!is_object($rs)) {
2521                      break;
2522                  }
2523  
2524                  $success = TRUE;
2525          }
2526  
2527          // if the delete failed, rollback the trans and return false
2528          if (!$success) {
2529  
2530              $this->debug_db('del_group');
2531              $this->db->RollBackTrans();
2532              return false;
2533          }
2534  
2535          $this->debug_text("del_group(): deleted group ID: $group_id");
2536          $this->db->CommitTrans();
2537  
2538          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
2539              //Expire all cache.
2540              $this->Cache_Lite->clean('default');
2541          }
2542  
2543          return true;
2544  
2545      }
2546  
2547  
2548      /*
2549       *
2550       * Objects (ACO/ARO/AXO)
2551       *
2552       */
2553  
2554      /**
2555       * get_object()
2556       *
2557       * Grabs all Objects's in the database, or specific to a section_value
2558       *
2559       * @return ADORecordSet  Returns recordset directly, with object ID only selected:
2560       *
2561       * @param string Filter to this section value
2562       * @param int Returns hidden objects if 1, leaves them out otherwise.
2563       * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
2564       */
2565  	function get_object($section_value = null, $return_hidden=1, $object_type=NULL) {
2566  
2567          switch(strtolower(trim($object_type))) {
2568              case 'aco':
2569                  $object_type = 'aco';
2570                  $table = $this->_db_table_prefix .'aco';
2571                  break;
2572              case 'aro':
2573                  $object_type = 'aro';
2574                  $table = $this->_db_table_prefix .'aro';
2575                  break;
2576              case 'axo':
2577                  $object_type = 'axo';
2578                  $table = $this->_db_table_prefix .'axo';
2579                  break;
2580              case 'acl':
2581                  $object_type = 'acl';
2582                  $table = $this->_db_table_prefix .'acl';
2583                  break;
2584              default:
2585                  $this->debug_text('get_object(): Invalid Object Type: '. $object_type);
2586                  return FALSE;
2587          }
2588  
2589          $this->debug_text("get_object(): Section Value: $section_value Object Type: $object_type");
2590  
2591          $query = 'SELECT id FROM '. $table;
2592  
2593          $where = array();
2594  
2595          if (!empty($section_value)) {
2596              $where[] = 'section_value='. $this->db->quote($section_value);
2597          }
2598  
2599          if ($return_hidden==0 AND $object_type != 'acl') {
2600              $where[] = 'hidden=0';
2601          }
2602  
2603          if (!empty($where)) {
2604              $query .= ' WHERE '. implode(' AND ', $where);
2605          }
2606  
2607          $rs = $this->db->GetCol($query);
2608  
2609          if (!is_array($rs)) {
2610              $this->debug_db('get_object');
2611              return false;
2612          }
2613  
2614          // Return Object IDs
2615          return $rs;
2616      }
2617      /**
2618       * get_ungrouped_objects()
2619       *
2620       * Grabs ID's of all Objects (ARO's and AXO's only) in the database not assigned to a Group.
2621       *
2622       * This function is useful for applications that synchronize user databases with an outside source.
2623       * If syncrhonization doesn't automatically place users in an appropriate group, this function can
2624       * quickly identify them so that they can be assigned to the correct group.
2625       *
2626       * @return array Returns an array of object ID's
2627       *
2628       * @param int Returns hidden objects if 1, does not if 0.
2629       * @param string Object Type, either 'ARO' or 'AXO' (groupable types)
2630       */
2631  
2632  	function get_ungrouped_objects($return_hidden=1, $object_type=NULL) {
2633  
2634             switch(strtolower(trim($object_type))) {
2635                     case 'aro':
2636                             $object_type = 'aro';
2637                             $table = $this->_db_table_prefix .'aro';
2638                             break;
2639                     case 'axo':
2640                             $object_type = 'axo';
2641                             $table = $this->_db_table_prefix .'axo';
2642                             break;
2643                     default:
2644                             $this->debug_text('get_ungrouped_objects(): Invalid Object Type: '. $object_type);
2645                             return FALSE;
2646             }
2647  
2648             $this->debug_text("get_ungrouped_objects(): Object Type: $object_type");
2649  
2650             $query = 'SELECT id FROM '. $table . '
2651                             LEFT JOIN groups_' . $table . '_map
2652                             ON ' . $table . '.id = groups_' . $table . '_map.' . $table . '_id';
2653  
2654             $where = array();
2655             $where[] = 'groups_' . $table . '_map.group_id IS NULL';
2656  
2657             if ($return_hidden==0) {
2658                     $where[] = 'a.hidden=0';
2659             }
2660  
2661             if (!empty($where)) {
2662                     $query .= ' WHERE '. implode(' AND ', $where);
2663             }
2664  
2665             $rs = $this->db->Execute($query);
2666  
2667             if (!is_object($rs)) {
2668                     $this->debug_db('get_ungrouped_objects');
2669                     return false;
2670             }
2671  
2672             while(!$rs->EOF) {
2673                     $retarr[] = $rs->fields[0];
2674                     $rs->MoveNext();
2675             }
2676  
2677             // Return Array of object IDS
2678             return $retarr;
2679      }
2680  
2681  
2682      /**
2683       * get_objects ()
2684       *
2685       * Grabs all Objects in the database, or specific to a section_value
2686       *
2687       * @return array Returns objects in format suitable for add_acl and is_conflicting_acl
2688       *    - i.e. Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
2689       *
2690       * @param string Filter for section value
2691       * @param int Returns hidden objects if 1, does not if 0
2692       * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2693       */
2694  	function get_objects($section_value = NULL, $return_hidden = 1, $object_type = NULL) {
2695          switch (strtolower(trim($object_type))) {
2696              case 'aco':
2697                  $object_type = 'aco';
2698                  $table = $this->_db_table_prefix .'aco';
2699                  break;
2700              case 'aro':
2701                  $object_type = 'aro';
2702                  $table = $this->_db_table_prefix .'aro';
2703                  break;
2704              case 'axo':
2705                  $object_type = 'axo';
2706                  $table = $this->_db_table_prefix .'axo';
2707                  break;
2708              default:
2709                  $this->debug_text('get_objects(): Invalid Object Type: '. $object_type);
2710                  return FALSE;
2711          }
2712  
2713          $this->debug_text("get_objects(): Section Value: $section_value Object Type: $object_type");
2714  
2715          $query = 'SELECT section_value,value FROM '. $table;
2716  
2717          $where = array();
2718  
2719          if (!empty($section_value)) {
2720              $where[] = 'section_value='. $this->db->quote($section_value);
2721          }
2722  
2723          if ($return_hidden==0) {
2724              $where[] = 'hidden=0';
2725          }
2726  
2727          if (!empty($where)) {
2728              $query .= ' WHERE '. implode(' AND ', $where);
2729          }
2730  
2731          $rs = $this->db->Execute($query);
2732  
2733          if (!is_object($rs)) {
2734              $this->debug_db('get_objects');
2735              return FALSE;
2736          }
2737  
2738          $retarr = array();
2739  
2740          while ($row = $rs->FetchRow()) {
2741              $retarr[$row[0]][] = $row[1];
2742          }
2743  
2744          // Return objects
2745          return $retarr;
2746      }
2747  
2748      /**
2749       * get_object_data()
2750       *
2751       * Gets all data pertaining to a specific Object.
2752       *
2753       * @return array Returns 2-Dimensional array of rows with columns = ( section_value, value, order_value, name, hidden )
2754       *
2755       * @param int Object ID #
2756       * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2757       */
2758  	function get_object_data($object_id, $object_type=NULL) {
2759  
2760          switch(strtolower(trim($object_type))) {
2761              case 'aco':
2762                  $object_type = 'aco';
2763                  $table = $this->_db_table_prefix .'aco';
2764                  break;
2765              case 'aro':
2766                  $object_type = 'aro';
2767                  $table = $this->_db_table_prefix .'aro';
2768                  break;
2769              case 'axo':
2770                  $object_type = 'axo';
2771                  $table = $this->_db_table_prefix .'axo';
2772                  break;
2773              default:
2774                  $this->debug_text('get_object_data(): Invalid Object Type: '. $object_type);
2775                  return FALSE;
2776          }
2777  
2778          $this->debug_text("get_object_data(): Object ID: $object_id Object Type: $object_type");
2779  
2780          if (empty($object_id) ) {
2781              $this->debug_text("get_object_data(): Object ID ($object_id) is empty, this is required");
2782              return false;
2783          }
2784  
2785          if (empty($object_type) ) {
2786              $this->debug_text("get_object_data(): Object Type ($object_type) is empty, this is required");
2787              return false;
2788          }
2789  
2790          $query  = 'SELECT section_value,value,order_value,name,hidden FROM '. $table .' WHERE id='. (int) $object_id;
2791          $rs = $this->db->Execute($query);
2792  
2793          if (!is_object($rs)) {
2794              $this->debug_db('get_object_data');
2795              return false;
2796          }
2797  
2798          if ($rs->RecordCount() < 1) {
2799              $this->debug_text('get_object_data(): Returned  '. $row_count .' rows');
2800              return FALSE;
2801          }
2802  
2803          // Return all objects
2804          return $rs->GetRows();
2805      }
2806  
2807      /**
2808       * get_object_id()
2809       *
2810       * Gets the object_id given the section_value AND value of the object.
2811       *
2812       * @return int Object ID #
2813       *
2814       * @param string Object Section Value
2815       * @param string Object Value
2816       * @param string Object Type, either 'ACO', 'ARO', 'AXO'
2817       */
2818  	function get_object_id($section_value, $value, $object_type=NULL) {
2819  
2820          switch(strtolower(trim($object_type))) {
2821              case 'aco':
2822                  $object_type = 'aco';
2823                  $table = $this->_db_table_prefix .'aco';
2824                  break;
2825              case 'aro':
2826                  $object_type = 'aro';
2827                  $table = $this->_db_table_prefix .'aro';
2828                  break;
2829              case 'axo':
2830                  $object_type = 'axo';
2831                  $table = $this->_db_table_prefix .'axo';
2832                  break;
2833              default:
2834                  $this->debug_text('get_object_id(): Invalid Object Type: '. $object_type);
2835                  return FALSE;
2836          }
2837  
2838          $this->debug_text("get_object_id(): Section Value: $section_value Value: $value Object Type: $object_type");
2839  
2840          $section_value = trim($section_value);
2841          $value = trim($value);
2842  
2843          if (empty($section_value) AND $value === '') {
2844              $this->debug_text("get_object_id(): Section Value ($value) AND value ($value) is empty, this is required");
2845              return false;
2846          }
2847  
2848          if (empty($object_type) ) {
2849              $this->debug_text("get_object_id(): Object Type ($object_type) is empty, this is required");
2850              return false;
2851          }
2852  
2853          $query = 'SELECT id FROM '. $table .' WHERE section_value='. $this->db->quote($section_value) .' AND value='. $this->db->quote($value);
2854          $rs = $this->db->Execute($query);
2855  
2856          if (!is_object($rs)) {
2857              $this->debug_db('get_object_id');
2858              return false;
2859          }
2860  
2861          $row_count = $rs->RecordCount();
2862  
2863          if ($row_count > 1) {
2864              $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.");
2865              return false;
2866          }
2867  
2868          if ($row_count == 0) {
2869              $this->debug_text("get_object_id(): Returned $row_count rows");
2870              return false;
2871          }
2872  
2873          $row = $rs->FetchRow();
2874  
2875          //Return the ID.
2876          return $row[0];
2877      }
2878  
2879      /**
2880       * get_object_section_value()
2881       *
2882       * Gets the object_section_value given object id
2883       *
2884       * @return string Object Section Value
2885       *
2886       * @param int Object ID #
2887       * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
2888       */
2889  	function get_object_section_value($object_id, $object_type=NULL) {
2890  
2891          switch(strtolower(trim($object_type))) {
2892              case 'aco':
2893                  $object_type = 'aco';
2894                  $table = $this->_db_table_prefix .'aco';
2895                  break;
2896              case 'aro':
2897                  $object_type = 'aro';
2898                  $table = $this->_db_table_prefix .'aro';
2899                  break;
2900              case 'axo':
2901                  $object_type = 'axo';
2902                  $table = $this->_db_table_prefix .'axo';
2903                  break;
2904              default:
2905                  $this->debug_text('get_object_section_value(): Invalid Object Type: '. $object_type);
2906                  return FALSE;
2907          }
2908  
2909          $this->debug_text("get_object_section_value(): Object ID: $object_id Object Type: $object_type");
2910  
2911          if (empty($object_id) ) {
2912              $this->debug_text("get_object_section_value(): Object ID ($object_id) is empty, this is required");
2913              return false;
2914          }
2915  
2916          if (empty($object_type) ) {
2917              $this->debug_text("get_object_section_value(): Object Type ($object_type) is empty, this is required");
2918              return false;
2919          }
2920  
2921          $query = 'SELECT section_value FROM '. $table .' WHERE id='. (int) $object_id;
2922          $rs = $this->db->Execute($query);
2923  
2924          if (!is_object($rs)) {
2925              $this->debug_db('get_object_section_value');
2926              return false;
2927          }
2928  
2929          $row_count = $rs->RecordCount();
2930  
2931          if ($row_count > 1) {
2932              $this->debug_text("get_object_section_value(): Returned $row_count rows, can only return one.");
2933              return false;
2934          }
2935  
2936          if ($row_count == 0) {
2937              $this->debug_text("get_object_section_value(): Returned $row_count rows");
2938              return false;
2939          }
2940  
2941          $row = $rs->FetchRow();
2942  
2943          //Return the ID.
2944          return $row[0];
2945      }
2946  
2947      /**
2948       * get_object_groups()
2949       *
2950       * Gets all groups an object is a member of.
2951       *
2952       * If $option == 'RECURSE' it will get all ancestor groups.
2953       * defaults to only get direct parents.
2954       *
2955       * @return array Array of Group ID #'s, or FALSE if Failed
2956       *
2957       * @param int Object ID #
2958       * @param string Object Type, either 'ARO' or 'AXO'
2959       * @param string Option, either 'RECURSE', or 'NO_RECURSE'
2960       */
2961  	function get_object_groups($object_id, $object_type = 'ARO', $option = 'NO_RECURSE') {
2962          $this->debug_text('get_object_groups(): Object ID: '. $object_id .' Object Type: '. $object_type .' Option: '. $option);
2963  
2964          switch(strtolower(trim($object_type))) {
2965              case 'axo':
2966                  $object_type = 'axo';
2967                  $group_table = $this->_db_table_prefix .'axo_groups';
2968                  $map_table = $this->_db_table_prefix .'groups_axo_map';
2969                  break;
2970              case 'aro':
2971                  $object_type = 'aro';
2972                  $group_table = $this->_db_table_prefix .'aro_groups';
2973                  $map_table = $this->_db_table_prefix .'groups_aro_map';
2974                  break;
2975              default:
2976                  $this->debug_text('get_object_groups(): Invalid Object Type: '. $object_type);
2977                  return FALSE;
2978          }
2979  
2980          if (empty($object_id)) {
2981              $this->debug_text('get_object_groups(): Object ID: ('. $object_id .') is empty, this is required');
2982              return FALSE;
2983          }
2984  
2985          if (strtoupper($option) == 'RECURSE') {
2986              $query = '
2987                  SELECT        DISTINCT g.id AS group_id
2988                  FROM        '. $map_table .' gm
2989                  LEFT JOIN    '. $group_table .' g1 ON g1.id=gm.group_id
2990                  LEFT JOIN    '. $group_table .' g ON g.lft<=g1.lft AND g.rgt>=g1.rgt';
2991          } else {
2992              $query = '
2993                  SELECT        gm.group_id
2994                  FROM        '. $map_table .' gm';
2995          }
2996  
2997          $query .= '
2998                  WHERE        gm.'. $object_type .'_id='. (int) $object_id;
2999          $rs = $this->db->Execute($query);
3000  
3001          if (!is_object($rs)) {
3002              $this->debug_db('get_object_groups');
3003              return FALSE;
3004          }
3005  
3006          $retarr = array();
3007  
3008          while ($row = $rs->FetchRow()) {
3009              $retarr[] = $row[0];
3010          }
3011  
3012          return $retarr;
3013      }
3014  
3015      /**
3016       * add_object()
3017       *
3018       * Inserts a new object
3019       *
3020       * @return int Returns the ID # of the new object if successful, FALSE otherwise
3021       *
3022       * @param string Object Section Value
3023       * @param string Object Name
3024       * @param string Object Value
3025       * @param int Display Order
3026       * @param int Hidden Flag, either 1 to hide, or 0 to show.
3027       * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3028       */
3029  	function add_object($section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3030  
3031          switch(strtolower(trim($object_type))) {
3032              case 'aco':
3033                  $object_type = 'aco';
3034                  $table = $this->_db_table_prefix .'aco';
3035                  $object_sections_table = $this->_db_table_prefix .'aco_sections';
3036                  break;
3037              case 'aro':
3038                  $object_type = 'aro';
3039                  $table = $this->_db_table_prefix .'aro';
3040                  $object_sections_table = $this->_db_table_prefix .'aro_sections';
3041                  break;
3042              case 'axo':
3043                  $object_type = 'axo';
3044                  $table = $this->_db_table_prefix .'axo';
3045                  $object_sections_table = $this->_db_table_prefix .'axo_sections';
3046                  break;
3047              default:
3048                  $this->debug_text('add_object(): Invalid Object Type: '. $object_type);
3049                  return FALSE;
3050          }
3051  
3052          $this->debug_text("add_object(): Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
3053  
3054          $section_value = trim($section_value);
3055          $name = trim($name);
3056          $value = trim($value);
3057          $order = (int) $order;
3058          $hidden = (int) $hidden;
3059  
3060          if ($order == NULL OR $order == '') {
3061              $order = 0;
3062          }
3063  
3064          if (empty($name) OR empty($section_value) ) {
3065              $this->debug_text("add_object(): name ($name) OR section value ($section_value) is empty, this is required");
3066              return false;
3067          }
3068  
3069          if (strlen($name) >= 255 OR strlen($value) >= 230 ) {
3070              $this->debug_text("add_object(): name ($name) OR value ($value) is too long.");
3071              return false;
3072          }
3073  
3074          if (empty($object_type) ) {
3075              $this->debug_text("add_object(): Object Type ($object_type) is empty, this is required");
3076              return false;
3077          }
3078  
3079          // Test to see if the section is invalid or object already exists.
3080          $query  = '
3081              SELECT        CASE WHEN o.id IS NULL THEN 0 ELSE 1 END AS object_exists
3082              FROM        '. $object_sections_table .' s
3083              LEFT JOIN    '. $table .' o ON (s.value=o.section_value AND o.value='. $this->db->quote($value) .')
3084              WHERE        s.value='. $this->db->quote($section_value);
3085          $rs = $this->db->Execute($query);
3086  
3087          if (!is_object($rs)) {
3088              $this->debug_db('add_object');
3089              return FALSE;
3090          }
3091  
3092          if ($rs->RecordCount() != 1) {
3093              // Section is invalid
3094              $this->debug_text("add_object(): Section Value: $section_value Object Type ($object_type) does not exist, this is required");
3095              return false;
3096          }
3097  
3098          $row = $rs->FetchRow();
3099  
3100          if ($row[0] == 1) {
3101              //Object is already created.
3102              return true;
3103          }
3104  
3105          $insert_id = $this->db->GenID($table . '_seq', $this->_defaultGenID( $table ));
3106          $query = "INSERT INTO $table (id,section_value,value,order_value,name,hidden) " .
3107                  "VALUES(". (int) $insert_id . "," . $this->db->quote($section_value) . "," .
3108                  $this->db->quote($value) . ",$order," . $this->db->quote($name) . ",$hidden)";
3109          $rs = $this->db->Execute($query);
3110  
3111          if (!is_object($rs)) {
3112              $this->debug_db('add_object');
3113              return false;
3114          }
3115  
3116          // Joomla/MySQL
3117          $insert_id = $this->db->insertid();
3118  
3119          $this->debug_text("add_object(): Added object as ID: $insert_id");
3120          return $insert_id;
3121      }
3122  
3123      /**
3124       * edit_object()
3125       *
3126       * Edits a given Object
3127       *
3128       * @return bool Returns TRUE if successful, FALSE otherwise
3129       *
3130       * @param int Object ID #
3131       * @param string Object Section Value
3132       * @param string Object Name
3133       * @param string Object Value
3134       * @param int Display Order
3135       * @param int Hidden Flag, either 1 to hide, or 0 to show
3136       * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3137       */
3138  	function edit_object($object_id, $section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3139  
3140          switch(strtolower(trim($object_type))) {
3141              case 'aco':
3142                  $object_type = 'aco';
3143                  $table = $this->_db_table_prefix .'aco';
3144                  $object_map_table = $this->_db_table_prefix .'aco_map';
3145                  break;
3146              case 'aro':
3147                  $object_type = 'aro';
3148                  $table = $this->_db_table_prefix .'aro';
3149                  $object_map_table = $this->_db_table_prefix .'aro_map';
3150                  break;
3151              case 'axo':
3152                  $object_type = 'axo';
3153                  $table = $this->_db_table_prefix .'axo';
3154                  $object_map_table = $this->_db_table_prefix .'axo_map';
3155                  break;
3156          }
3157  
3158          $this->debug_text("edit_object(): ID: $object_id Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
3159  
3160          $object_id = (int) $object_id;
3161          $section_value = trim($section_value);
3162          $name = trim($name);
3163          $value = trim($value);
3164          $order = (int) $order;
3165          $hidden = (int) $hidden;
3166  
3167          if (empty($object_id) OR empty($section_value) ) {
3168              $this->debug_text("edit_object(): Object ID ($object_id) OR Section Value ($section_value) is empty, this is required");
3169              return false;
3170          }
3171  
3172          if (empty($name) ) {
3173              $this->debug_text("edit_object(): name ($name) is empty, this is required");
3174              return false;
3175          }
3176  
3177          if (empty($object_type) ) {
3178              $this->debug_text("edit_object(): Object Type ($object_type) is empty, this is required");
3179              return false;
3180          }
3181  
3182          $this->db->BeginTrans();
3183  
3184          //Get old value incase it changed, before we do the update.
3185          $query = 'SELECT value, section_value FROM '. $table .' WHERE id='. $object_id;
3186          $old = $this->db->GetRow($query);
3187  
3188          $query  = '
3189              UPDATE    '. $table .'
3190              SET        section_value='. $this->db->quote($section_value) .',
3191                      value='. $this->db->quote($value) .',
3192                      order_value='. $order .',
3193                      name='. $this->db->quote($name) .',
3194                      hidden='. $hidden .'
3195              WHERE    id='. $object_id;
3196          $rs = $this->db->Execute($query);
3197  
3198          if (!is_object($rs)) {
3199              $this->debug_db('edit_object');
3200              $this->db->RollbackTrans();
3201              return false;
3202          }
3203  
3204          $this->debug_text('edit_object(): Modified '. strtoupper($object_type) .' ID: '. $object_id);
3205  
3206          if ($old[0] != $value OR $old[1] != $section_value) {
3207              $this->debug_text("edit_object(): Value OR Section Value Changed, update other tables.");
3208  
3209              $query  = '
3210                  UPDATE    '. $object_map_table .'
3211                  SET        value='. $this->db->quote($value) .',
3212                          section_value='. $this->db->quote($section_value) .'
3213                  WHERE    section_value='. $this->db->quote($old[1]) .'
3214                      AND    value='. $this->db->quote($old[0]);
3215              $rs = $this->db->Execute($query);
3216  
3217              if (!is_object($rs)) {
3218                  $this->debug_db('edit_object');
3219                  $this->db->RollbackTrans();
3220                  return FALSE;
3221              }
3222  
3223              $this->debug_text ('edit_object(): Modified Map Value: '. $value .' Section Value: '. $section_value);
3224          }
3225  
3226          $this->db->CommitTrans();
3227  
3228          return TRUE;
3229      }
3230  
3231      /**
3232       * del_object()
3233       *
3234       * Deletes a given Object and, if instructed to do so, erase all referencing objects
3235       *
3236       * ERASE feature by: Martino Piccinato
3237       *
3238       * @return bool Returns TRUE if successful, FALSE otherwise.
3239       *
3240       * @param int Object ID #
3241       * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3242       * @param bool Erases all referencing objects if TRUE, leaves them alone otherwise.
3243       */
3244  	function del_object($object_id, $object_type=NULL, $erase=FALSE) {
3245  
3246          switch(strtolower(trim($object_type))) {
3247              case 'aco':
3248                  $object_type = 'aco';
3249                  $table = $this->_db_table_prefix .'aco';
3250                  $object_map_table = $this->_db_table_prefix .'aco_map';
3251                  break;
3252              case 'aro':
3253                  $object_type = 'aro';
3254                  $table = $this->_db_table_prefix .'aro';
3255                  $object_map_table = $this->_db_table_prefix .'aro_map';
3256                  $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
3257                  $object_group_table = $this->_db_table_prefix .'groups_aro_map';
3258                  break;
3259              case 'axo':
3260                  $object_type = 'axo';
3261                  $table = $this->_db_table_prefix .'axo';
3262                  $object_map_table = $this->_db_table_prefix .'axo_map';
3263                  $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
3264                  $object_group_table = $this->_db_table_prefix .'groups_axo_map';
3265                  break;
3266              default:
3267                  $this->debug_text('del_object(): Invalid Object Type: '. $object_type);
3268                  return FALSE;
3269          }
3270  
3271          $this->debug_text("del_object(): ID: $object_id Object Type: $object_type, Erase all referencing objects: $erase");
3272  
3273          if (empty($object_id) ) {
3274              $this->debug_text("del_object(): Object ID ($object_id) is empty, this is required");
3275              return false;
3276          }
3277  
3278          if (empty($object_type) ) {
3279              $this->debug_text("del_object(): Object Type ($object_type) is empty, this is required");
3280              return false;
3281          }
3282  
3283          // sanitise input
3284          $object_id = (int) $object_id;
3285  
3286          $this->db->BeginTrans();
3287  
3288          // Get Object section_value/value (needed to look for referencing objects)
3289          $query = 'SELECT section_value,value FROM '. $table .' WHERE id='. $object_id;
3290          $object = $this->db->GetRow($query);
3291  
3292          if (empty($object)) {
3293              $this->debug_text('del_object(): The specified object ('. strtoupper($object_type) .' ID: '. $object_id .') could not be found.');
3294              $this->db->RollbackTrans();
3295              return FALSE;
3296          }
3297  
3298          $section_value = $this->db->quote( $object[0] );
3299          $value = $this->db->quote( $object[1] );
3300  
3301          // Get ids of acl referencing the Object (if any)
3302          $query = "SELECT acl_id FROM $object_map_table WHERE value=$value AND section_value=$section_value";
3303          $acl_ids = $this->db->GetCol($query);
3304  
3305          if ($erase) {
3306              // We were asked to erase all acl referencing it
3307  
3308              $this->debug_text("del_object(): Erase was set to TRUE, delete all referencing objects");
3309  
3310              if ($object_type == "aro" OR $object_type == "axo") {
3311                  // The object can be referenced in groups_X_map tables
3312                  // in the future this branching may become useless because
3313                  // ACO might me "groupable" too
3314  
3315                  // Get rid of groups_map referencing the Object
3316                  $query = 'DELETE FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id;
3317                  $rs = $this->db->Execute($query);
3318  
3319                  if (!is_object($rs)) {
3320                      $this->debug_db('edit_object');
3321                      $this->db->RollBackTrans();
3322                      return false;
3323                  }
3324              }
3325  
3326              if (!empty($acl_ids)) {
3327                  //There are acls actually referencing the object
3328  
3329                  if ($object_type == 'aco') {
3330                      // I know it's extremely dangerous but
3331                      // if asked to really erase an ACO
3332                      // we should delete all acl referencing it
3333                      // (and relative maps)
3334  
3335                      // Do this below this branching
3336                      // where it uses $orphan_acl_ids as
3337                      // the array of the "orphaned" acl
3338                      // in this case all referenced acl are
3339                      // orhpaned acl
3340  
3341                      $orphan_acl_ids = $acl_ids;
3342                  } else {
3343                      // The object is not an ACO and might be referenced
3344                      // in still valid acls regarding also other object.
3345                      // In these cases the acl MUST NOT be deleted
3346  
3347                      // Get rid of $object_id map referencing erased objects
3348                      $query = "DELETE FROM $object_map_table WHERE section_value=$section_value AND value=$value";
3349                      $this->db->Execute($query);
3350  
3351                      if (!is_object($rs)) {
3352                          $this->debug_db('edit_object');
3353                          $this->db->RollBackTrans();
3354                          return false;
3355                      }
3356  
3357                      // Find the "orphaned" acl. I mean acl referencing the erased Object (map)
3358                      // not referenced anymore by other objects
3359  
3360                      $sql_acl_ids = implode(",", $acl_ids);
3361  
3362                      $query = '
3363                          SELECT        a.id
3364                          FROM        '. $this->_db_table_prefix .'acl a
3365                          LEFT JOIN    '. $object_map_table .' b ON a.id=b.acl_id
3366                          LEFT JOIN    '. $groups_map_table .' c ON a.id=c.acl_id
3367                          WHERE        b.value IS NULL
3368                              AND        b.section_value IS NULL
3369                              AND        c.group_id IS NULL
3370                              AND        a.id in ('. $sql_acl_ids .')';
3371                      $orphan_acl_ids = $this->db->GetCol($query);
3372  
3373                  } // End of else section of "if ($object_type == "aco")"
3374  
3375                  if ($orphan_acl_ids) {
3376                      // If there are orphaned acls get rid of them
3377  
3378                      foreach ($orphan_acl_ids as $acl) {
3379                          $this->del_acl($acl);
3380                      }
3381                  }
3382  
3383              } // End of if ($acl_ids)
3384  
3385              // Finally delete the Object itself
3386              $query = "DELETE FROM $table WHERE id=$object_id";
3387              $rs = $this->db->Execute($query);
3388  
3389              if (!is_object($rs)) {
3390                  $this->debug_db('edit_object');
3391                  $this->db->RollBackTrans();
3392                  return false;
3393              }
3394  
3395              $this->db->CommitTrans();
3396              return true;
3397  
3398          } // End of "if ($erase)"
3399  
3400          $groups_ids = FALSE;
3401  
3402          if ($object_type == 'axo' OR $object_type == 'aro') {
3403              // If the object is "groupable" (may become unnecessary,
3404              // see above
3405  
3406              // Get id of groups where the object is assigned:
3407              // you must explicitly remove the object from its groups before
3408              // deleting it (don't know if this is really needed, anyway it's safer ;-)
3409  
3410              $query = 'SELECT group_id FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id;
3411              $groups_ids = $this->db->GetCol($query);
3412          }
3413  
3414          if ( ( isset($acl_ids) AND !empty($acl_ids) ) OR ( isset($groups_ids) AND !empty($groups_ids) ) ) {
3415              // The Object is referenced somewhere (group or acl), can't delete it
3416  
3417              $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,",").")");
3418              $this->db->RollBackTrans();
3419              return false;
3420          } else {
3421              // The Object is NOT referenced anywhere, delete it
3422  
3423              $query = "DELETE FROM $table WHERE id=$object_id";
3424              $rs = $this->db->Execute($query);
3425  
3426              if ( !is_object($rs) ) {
3427                  $this->debug_db('edit_object');
3428                  $this->db->RollBackTrans();
3429                  return false;
3430              }
3431  
3432              $this->db->CommitTrans();
3433              return true;
3434          }
3435  
3436          $this->db->RollbackTrans();
3437          return false;
3438      }
3439  
3440      /*
3441       *
3442       * Object Sections
3443       *
3444       */
3445  
3446      /**
3447       * get_object_section_section_id()
3448       *
3449       * Gets the object_section_id given the name AND/OR value of the section.
3450       *
3451       * Will only return one section id, so if there are duplicate names it will return false.
3452       *
3453       * @return int Object Section ID if the object section is found AND is unique, or FALSE otherwise.
3454       *
3455       * @param string Object Name
3456       * @param string Object Value
3457       * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3458       *
3459       */
3460  	function get_object_section_section_id($name = NULL, $value = NULL, $object_type = NULL) {
3461          $this->debug_text("get_object_section_section_id(): Value: $value Name: $name Object Type: $object_type");
3462  
3463          switch(strtolower(trim($object_type))) {
3464              case 'aco':
3465              case 'aro':
3466              case 'axo':
3467              case 'acl':
3468                  $object_type = strtolower(trim($object_type));
3469                  $table = $this->_db_table_prefix . $object_type;
3470                  $object_sections_table = $this->_db_table_prefix . $object_type .'_sections';
3471                  break;
3472              default:
3473                  $this->debug_text('get_object_section_section_id(): Invalid Object Type ('. $object_type . ')');
3474                  return FALSE;
3475          }
3476  
3477          $name = trim($name);
3478          $value = trim($value);
3479  
3480          if (empty($name) AND $value === '') {
3481              $this->debug_text('get_object_section_section_id(): Both Name ('. $name .') and Value ('. $value .') are empty, you must specify at least one.');
3482              return FALSE;
3483          }
3484  
3485          $query = 'SELECT id FROM '. $object_sections_table;
3486          $where = ' WHERE ';
3487  
3488          // limit by value if specified
3489          if ($value !== '') {
3490              $query .= $where .'value='. $this->db->quote($value);
3491              $where = ' AND ';
3492          }
3493  
3494          // only use name if asked, this is SLOW
3495          if (!empty($name)) {
3496              $query .= $where .'name='. $this->db->quote($name);
3497          }
3498  
3499          $rs = $this->db->Execute($query);
3500  
3501          if (!is_object($rs)) {
3502              $this->debug_db('get_object_section_section_id');
3503              return FALSE;
3504          }
3505  
3506          $row_count = $rs->RecordCount();
3507  
3508          // If only one row is returned
3509          if ($row_count == 1) {
3510              // Return only the ID in the first row.
3511              $row = $rs->FetchRow();
3512              return $row[0];
3513          }
3514  
3515          // If more than one row is returned
3516          // should only ever occur when using name as values are unique.
3517          if ($row_count > 1) {
3518              $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.');
3519              return FALSE;
3520          }
3521  
3522          // No rows returned, no matching section found
3523          $this->debug_text('get_object_section_section_id(): Returned '. $row_count .' rows, no matching section found.');
3524          return FALSE;
3525      }
3526  
3527      /**
3528       * add_object_section()
3529       *
3530       * Inserts an object Section
3531       *
3532       * @return int Object Section ID of new section
3533       *
3534       * @param string Object Name
3535       * @param string Object Value
3536       * @param int Display Order
3537       * @param int Hidden flag, hides section if 1, shows section if 0
3538       * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3539       */
3540  	function add_object_section($name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3541  
3542          switch(strtolower(trim($object_type))) {
3543              case 'aco':
3544                  $object_type = 'aco';
3545                  $object_sections_table = $this->_db_table_prefix .'aco_sections';
3546                  break;
3547              case 'aro':
3548                  $object_type = 'aro';
3549                  $object_sections_table = $this->_db_table_prefix .'aro_sections';
3550                  break;
3551              case 'axo':
3552                  $object_type = 'axo';
3553                  $object_sections_table = $this->_db_table_prefix .'axo_sections';
3554                  break;
3555              case 'acl':
3556                  $object_type = 'acl';
3557                  $object_sections_table = $this->_db_table_prefix .'acl_sections';
3558                  break;
3559          }
3560  
3561          $this->debug_text("add_object_section(): Value: $value Order: $order Name: $name Object Type: $object_type");
3562  
3563          $name = trim($name);
3564          $value = trim($value);
3565          $order = (int) $order;
3566          $hidden = (int) $hidden;
3567  
3568          if ($order == NULL OR $order == '') {
3569              $order = 0;
3570          }
3571  
3572          if (empty($name) ) {
3573              $this->debug_text("add_object_section(): name ($name) is empty, this is required");
3574              return false;
3575          }
3576  
3577          if (empty($object_type) ) {
3578              $this->debug_text("add_object_section(): Object Type ($object_type) is empty, this is required");
3579              return false;
3580          }
3581  
3582          $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_sections_seq',10);
3583          $query = "insert into $object_sections_table (id,value,order_value,name,hidden) VALUES($insert_id, '$value', '$order', '$name', $hidden)";
3584          $rs = $this->db->Execute($query);
3585  
3586          if (!is_object($rs)) {
3587              $this->debug_db('add_object_section');
3588              return false;
3589          } else {
3590              $this->debug_text("add_object_section(): Added object_section as ID: $insert_id");
3591              return $insert_id;
3592          }
3593      }
3594  
3595      /**
3596       * edit_object_section()
3597       *
3598       * Edits a given Object Section
3599       *
3600       * @return bool Returns TRUE if successful, FALSE otherwise
3601       *
3602       * @param int Object Section ID #
3603       * @param string Object Section Name
3604       * @param string Object Section Value
3605       * @param int Display Order
3606       * @param int Hidden Flag, hide object section if 1, show if 0
3607       * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3608       */
3609  	function edit_object_section($object_section_id, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
3610  
3611          switch(strtolower(trim($object_type))) {
3612              case 'aco':
3613                  $object_type = 'aco';
3614                  $table = $this->_db_table_prefix .'aco';
3615                  $object_sections_table = $this->_db_table_prefix .'aco_sections';
3616                  $object_map_table = $this->_db_table_prefix .'aco_map';
3617                  break;
3618              case 'aro':
3619                  $object_type = 'aro';
3620                  $table = $this->_db_table_prefix .'aro';
3621                  $object_sections_table = $this->_db_table_prefix .'aro_sections';
3622                  $object_map_table = $this->_db_table_prefix .'aro_map';
3623                  break;
3624              case 'axo':
3625                  $object_type = 'axo';
3626                  $table = $this->_db_table_prefix .'axo';
3627                  $object_sections_table = $this->_db_table_prefix .'axo_sections';
3628                  $object_map_table = $this->_db_table_prefix .'axo_map';
3629                  break;
3630              case 'acl':
3631                  $object_type = 'acl';
3632                  $table = $this->_db_table_prefix .'acl';
3633                  $object_sections_table = $this->_db_table_prefix .'acl_sections';
3634                  break;
3635              default:
3636                  $this->debug_text('edit_object_section(): Invalid Object Type: '. $object_type);
3637                  return FALSE;
3638          }
3639  
3640          $this->debug_text("edit_object_section(): ID: $object_section_id Value: $value Order: $order Name: $name Object Type: $object_type");
3641  
3642          $name = trim($name);
3643          $value = trim($value);
3644          $order = (int) $order;
3645          $hidden = (int) $hidden;
3646  
3647          if (empty($object_section_id) ) {
3648              $this->debug_text("edit_object_section(): Section ID ($object_section_id) is empty, this is required");
3649              return false;
3650          }
3651  
3652          if (empty($name) ) {
3653              $this->debug_text("edit_object_section(): name ($name) is empty, this is required");
3654              return false;
3655          }
3656  
3657          if (empty($object_type) ) {
3658              $this->debug_text("edit_object_section(): Object Type ($object_type) is empty, this is required");
3659              return false;
3660          }
3661  
3662          // sanitise input
3663          $object_section_id = (int) $object_section_id;
3664  
3665          $this->db->BeginTrans();
3666  
3667          //Get old value incase it changed, before we do the update.
3668          $query = "select value from $object_sections_table where id=$object_section_id";
3669          $old_value = $this->db->GetOne($query);
3670  
3671          $query = "update $object_sections_table set
3672                                                                  value=" . $this->db-quote($value) . "',
3673                                                                  order_value=$order,
3674                                                                  name=" . $this->db-quote($name) . ",
3675                                                                  hidden=$hidden
3676                                                      where   id=$object_section_id";
3677          $rs = $this->db->Execute($query);
3678  
3679          if (!is_object($rs)) {
3680              $this->debug_db('edit_object_section');
3681  
3682              $this->db->RollbackTrans();
3683  
3684              return false;
3685          } else {
3686              $this->debug_text("edit_object_section(): Modified aco_section ID: $object_section_id");
3687  
3688              if ($old_value != $value) {
3689                  $this->debug_text("edit_object_section(): Value Changed, update other tables.");
3690  
3691                  $query = "update $table set
3692                                                      section_value=" . $this->db-quote($value) . "
3693                                                      where section_value = " . $this->db-quote($old_value);
3694                  $rs = $this->db->Execute($query);
3695  
3696                  if (!is_object($rs)) {
3697                      $this->debug_db('edit_object_section');
3698  
3699                      $this->db->RollbackTrans();
3700  
3701                      return false;
3702                  } else {
3703                      if (!empty($object_map_table)) {
3704                          $query = "update $object_map_table set
3705                                                      section_value=" . $this->db-quote($value) . "
3706                                                      where section_value = " . $this->db-quote($old_value);
3707                          $rs = $this->db->Execute($query);
3708  
3709                          if ( !is_object($rs) ) {
3710                              $this->debug_db('edit_object_section');
3711  
3712                              $this->db->RollbackTrans();
3713  
3714                              return false;
3715                          } else {
3716                              $this->debug_text("edit_object_section(): Modified ojbect_map value: $value");
3717  
3718                              $this->db->CommitTrans();
3719                              return true;
3720                          }
3721                      } else {
3722                          //ACL sections, have no mapping table. Return true.
3723  
3724                          $this->db->CommitTrans();
3725  
3726                          return true;
3727                      }
3728                  }
3729              }
3730  
3731        $this->db->CommitTrans();
3732              return true;
3733          }
3734      }
3735  
3736      /**
3737       * del_object_section()
3738       *
3739       * Deletes a given Object Section and, if explicitly asked, all the section objects
3740       *
3741       * ERASE feature by: Martino Piccinato
3742       *
3743       * @return bool Returns TRUE if successful, FALSE otherwise
3744       *
3745       * @param int Object Section ID # to delete
3746       * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
3747       * @param bool Erases all section objects assigned to the section
3748       */
3749  	function del_object_section($object_section_id, $object_type=NULL, $erase=FALSE) {
3750  
3751          switch(strtolower(trim($object_type))) {
3752              case 'aco':
3753                  $object_type = 'aco';
3754                  $object_sections_table = $this->_db_table_prefix .'aco_sections';
3755                  break;
3756              case 'aro':
3757                  $object_type = 'aro';
3758                  $object_sections_table = $this->_db_table_prefix .'aro_sections';
3759                  break;
3760              case 'axo':
3761                  $object_type = 'axo';
3762                  $object_sections_table = $this->_db_table_prefix .'axo_sections';
3763                  break;
3764              case 'acl':
3765                  $object_type = 'acl';
3766                  $object_sections_table = $this->_db_table_prefix .'acl_sections';
3767                  break;
3768          }
3769  
3770          $this->debug_text("del_object_section(): ID: $object_section_id Object Type: $object_type, Erase all: $erase");
3771  
3772          if (empty($object_section_id) ) {
3773              $this->debug_text("del_object_section(): Section ID ($object_section_id) is empty, this is required");
3774              return false;
3775          }
3776  
3777          if (empty($object_type) ) {
3778              $this->debug_text("del_object_section(): Object Type ($object_type) is empty, this is required");
3779              return false;
3780          }
3781  
3782          // sanitise input
3783          $object_section_id = (int) $object_section_id;
3784  
3785          // Get the value of the section
3786          $query="SELECT value FROM $object_sections_table WHERE id=$object_section_id";
3787          $section_value = $this->db->GetOne($query);
3788  
3789          // Get all objects ids in the section
3790          $object_ids = $this->get_object($section_value, 1, $object_type);
3791  
3792          if($erase) {
3793              // Delete all objects in the section and for
3794              // each object delete the referencing object
3795              // (see del_object method)
3796              if (is_array($object_ids)) {
3797                      foreach ($object_ids as $id) {
3798                          if ( $object_type === 'acl' ) {
3799                              $this->del_acl($id);
3800                          } else {
3801                              $this->del_object($id, $object_type, TRUE);
3802                          }
3803                      }
3804              }
3805          }
3806  
3807          if($object_ids AND !$erase) {
3808              // There are objects in the section and we
3809              // were not asked to erase them: don't delete it
3810  
3811              $this->debug_text("del_object_section(): Could not delete the section ($section_value) as it is not empty.");
3812  
3813              return false;
3814  
3815          } else {
3816              // The section is empty (or emptied by this method)
3817  
3818              $query = "DELETE FROM $object_sections_table where id=$object_section_id";
3819              $rs = $this->db->Execute($query);
3820  
3821              if (!is_object($rs)) {
3822                  $this->debug_db('del_object_section');
3823                  return false;
3824              } else {
3825                  $this->debug_text("del_object_section(): deleted section ID: $object_section_id Value: $section_value");
3826                  return true;
3827              }
3828  
3829          }
3830  
3831          return false;
3832      }
3833  
3834      /**
3835       * get_section_data()
3836       *
3837       * Gets the section data given the Section Value
3838       *
3839       * @return array Returns numerically indexed array with the following columns:
3840       *    - array[0] = (int) Section ID #
3841       *    - array[1] = (string) Section Value
3842       *    - array[2] = (int) Section Order
3843       *    - array[3] = (string) Section Name
3844       *    - array[4] = (int) Section Hidden?
3845       * @param string Section Value
3846       * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
3847       */
3848  	function get_section_data($section_value, $object_type=NULL) {
3849  
3850          switch(strtolower(trim($object_type))) {
3851              case 'aco':
3852                  $object_type = 'aco';
3853                  $table = $this->_db_table_prefix .'aco_sections';
3854                  break;
3855              case 'aro':
3856                  $object_type = 'aro';
3857                  $table = $this->_db_table_prefix .'aro_sections';
3858                  break;
3859              case 'axo':
3860                  $object_type = 'axo';
3861                  $table = $this->_db_table_prefix .'axo_sections';
3862                  break;
3863              default:
3864                  $this->debug_text('get_section_data(): Invalid Object Type: '. $object_type);
3865                  return FALSE;
3866          }
3867  
3868          $this->debug_text("get_section_data(): Section Value: $section_value Object Type: $object_type");
3869  
3870          if (empty($section_value) ) {
3871              $this->debug_text("get_section_data(): Section Value ($section_value) is empty, this is required");
3872              return false;
3873          }
3874  
3875          if (empty($object_type) ) {
3876              $this->debug_text("get_section_data(): Object Type ($object_type) is empty, this is required");
3877              return false;
3878          }
3879  
3880          $query = 'SELECT id, value, order_value, name, hidden FROM '. $table .' WHERE value='.$this->db->Quote( $section_value );
3881          $row = $this->db->GetRow($query);
3882  
3883          if ($row) {
3884              return $row;
3885          }
3886  
3887          $this->debug_text("get_section_data(): Section does not exist.");
3888          return false;
3889      }
3890  
3891      /**
3892       * clear_database()
3893       *
3894       * Deletes all data from the phpGACL tables. USE WITH CAUTION.
3895       *
3896       * @return bool Returns TRUE if successful, FALSE otherwise
3897       *
3898       */
3899      function clear_database()
3900      {
3901          $tablesToClear = array(
3902              $this->_db_table_prefix.'acl',
3903              $this->_db_table_prefix.'aco',
3904              $this->_db_table_prefix.'aco_map',
3905              $this->_db_table_prefix.'aco_sections',
3906              $this->_db_table_prefix.'aro',
3907              $this->_db_table_prefix.'aro_groups',
3908              $this->_db_table_prefix.'aro_groups_map',
3909              $this->_db_table_prefix.'aro_map',
3910              $this->_db_table_prefix.'aro_sections',
3911              $this->_db_table_prefix.'axo',
3912              $this->_db_table_prefix.'axo_groups',
3913              $this->_db_table_prefix.'axo_groups_map',
3914              $this->_db_table_prefix.'axo_map',
3915              $this->_db_table_prefix.'axo_sections',
3916              $this->_db_table_prefix.'groups_aro_map',
3917              $this->_db_table_prefix.'groups_axo_map'
3918              );
3919  
3920          // Get all the table names and loop
3921          $tableNames = $this->db->MetaTables('TABLES');
3922          $query = array();
3923          foreach ($tableNames as $key => $value){
3924                  if (in_array($value, $tablesToClear) ) {
3925                          $query[] = 'TRUNCATE TABLE '.$value.';';
3926                  }
3927          }
3928  
3929          // Loop the queries and return.
3930          foreach ($query as $key => $value){
3931                  $result = $this->db->Execute($value);
3932          }
3933  
3934          return TRUE;
3935      }
3936  
3937      /**
3938       * Calculates the start number for a sequence table
3939       * @protected
3940       * @param string The name of the table
3941       * @return int The highest id plus one
3942       */
3943  	function _defaultGenID( $table ) {
3944          $query = "SELECT MAX(id) from " . $table;
3945          $id = $this->db->GetOne( $query ) + 1;
3946  
3947          return $id;
3948      }
3949  }


Generated: Wed Mar 28 15:54:07 2012 Cross-referenced by PHPXref 0.7.1