[ Index ]

PHP Cross Reference of Mambo 4.6.5

[ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/includes/ -> gacl_api.class.php (source)

   1  <?php
   2  /**
   3  * @package Mambo
   4  * @author Mambo Foundation Inc see README.php
   5  * @copyright (C) 2000 - 2009 Mambo Foundation Inc.
   6  * See COPYRIGHT.php for copyright notices and details.
   7  * @license GNU/GPL Version 2, see LICENSE.php
   8  *
   9  * Redistributions of files must retain the above copyright notice.
  10  *
  11  * Mambo is free software; you can redistribute it and/or
  12  * modify it under the terms of the GNU General Public License
  13  * as published by the Free Software Foundation; version 2 of the License.
  14  */
  15  
  16  /*
  17   * phpGACL - Generic Access Control List
  18   * Copyright (C) 2002,2003 Mike Benoit
  19   *
  20   * This library is free software; you can redistribute it and/or
  21   * modify it under the terms of the GNU Lesser General Public
  22   * License as published by the Free Software Foundation; either
  23   * version 2.1 of the License, or (at your option) any later version.
  24   *
  25   * This library is distributed in the hope that it will be useful,
  26   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  28   * Lesser General Public License for more details.
  29   *
  30   * You should have received a copy of the GNU Lesser General Public
  31   * License along with this library; if not, write to the Free Software
  32   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  33   *
  34   * For questions, help, comments, discussion, etc., please join the
  35   * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
  36   *
  37   * You may contact the author of phpGACL by e-mail at:
  38   * ipso@snappymail.ca
  39   *
  40   * The latest version of phpGACL can be obtained from:
  41   * http://phpgacl.sourceforge.net/
  42   *
  43   */
  44  
  45  /** ensure this file is being included by a parent file */
  46  defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
  47  
  48  /*
  49   *
  50   *
  51   *  == If you find a feature may be missing from this API, please email me: ipso@snappymail.ca and I will be happy to add it. ==
  52   *
  53   *
  54   * Example:
  55   *    $gacl_api = new gacl_api;
  56   *
  57   *    $section_id = $gacl_api->get_aco_section_id('System');
  58   *    $aro_id= $gacl_api->add_aro($section_id, 'John Doe', 10);
  59   *
  60   * For more examples, see the Administration interface, as it makes use of nearly every API Call.
  61   *
  62   */
  63  
  64  class gacl_api extends gacl {
  65      /*
  66       * Administration interface settings
  67       */
  68      var $_items_per_page = 100;
  69      var $_max_select_box_items = 100;
  70      var $_max_search_return_items = 100;
  71  
  72      /*
  73       *
  74       * Misc helper functions.
  75       *
  76       */
  77  
  78      /*======================================================================*\
  79          Function:   showarray()
  80          Purpose:    Dump all contents of an array in HTML (kinda).
  81      \*======================================================================*/
  82  	function showarray($array) {
  83          echo "<br /><pre>\n";
  84          var_dump($array);
  85          echo "</pre><br />\n";
  86      }
  87  
  88      /*======================================================================*\
  89          Function:   $gacl_api->return_page()
  90          Purpose:    Sends the user back to a passed URL, unless debug is enabled, then we don't redirect.
  91                          If no URL is passed, try the REFERER
  92      \*======================================================================*/
  93  	function return_page($url="") {
  94          global $_SERVER, $debug;
  95  
  96          if (empty($url) AND !empty($_SERVER[HTTP_REFERER])) {
  97              $this->debug_text("return_page(): URL not set, using referer!");
  98              $url = $_SERVER[HTTP_REFERER];
  99          }
 100  
 101          if (!$debug OR $debug==0) {
 102              header("Location: $url\n\n");
 103          } else {
 104              $this->debug_text("return_page(): URL: $url -- Referer: $_SERVER[HTTP_REFERRER]");
 105          }
 106      }
 107  
 108      /*======================================================================*\
 109          Function:   get_paging_data()
 110          Purpose:    Creates a basic array for Smarty to deal with paging large recordsets.
 111                          Pass it the ADODB recordset.
 112      \*======================================================================*/
 113  	function get_paging_data($rs) {
 114                  return array(
 115                                  'prevpage' => $rs->absolutepage() - 1,
 116                                  'currentpage' => $rs->absolutepage(),
 117                                  'nextpage' => $rs->absolutepage() + 1,
 118                                  'atfirstpage' => $rs->atfirstpage(),
 119                                  'atlastpage' => $rs->atlastpage(),
 120                                  'lastpageno' => $rs->lastpageno()
 121                          );
 122      }
 123  
 124      /*======================================================================*\
 125          Function:    count_all()
 126          Purpose:    Recursively counts elements in an array and sub-arrays.
 127                      The returned count is a count of all scalar elements found.
 128                      
 129                      This is different from count($arg, COUNT_RECURSIVE)
 130                      in PHP >= 4.2.0, which includes sub-arrays in the count.
 131      \*======================================================================*/
 132  	function count_all($arg = NULL) {
 133          switch (TRUE) {
 134              case is_scalar($arg):
 135              case is_object($arg):
 136                  // single object
 137                  return 1;
 138              case is_array($arg):
 139                  // call recursively for all elements of $arg
 140                  $count = 0;
 141                  foreach ($arg as $val) {
 142                      $count += $this->count_all($val);
 143                  }
 144                  return $count;
 145          }
 146          return FALSE;
 147      }
 148  
 149      /*======================================================================*\
 150          Function:    get_version()
 151          Purpose:    Grabs phpGACL version from the database.
 152      \*======================================================================*/
 153  
 154  
 155      /*======================================================================*\
 156          Function:    get_schema_version()
 157          Purpose:    Grabs phpGACL schema version from the database.
 158      \*======================================================================*/
 159      /*
 160       *
 161       * ACL
 162       *
 163       */
 164  
 165      /*======================================================================*\
 166          Function:    consolidated_edit_acl()
 167          Purpose:    Add's an ACL but checks to see if it can consolidate it with another one first.
 168                      This ONLY works with ACO's and ARO's. Groups, and AXO are excluded.
 169                      As well this function is designed for handling ACLs with return values,
 170                      and consolidating on the return_value, in hopes of keeping the ACL count to a minimum.
 171  
 172                      A return value of false must _always_ be handled outside this function.
 173                      As this function will remove AROs from ACLs and return false, in most cases
 174                      you will need to a create a completely new ACL on a false return.
 175      \*======================================================================*/
 176      
 177      /*======================================================================*\
 178          Function:    shift_acl()
 179          Purpose:    Opposite of append_acl(). Removes objects from a specific ACL. (named after PHP's array_shift())
 180      \*======================================================================*/
 181  
 182      /*======================================================================*\
 183          Function:    get_acl()
 184          Purpose:    Grabs ACL data.
 185      \*======================================================================*/
 186      
 187      /*======================================================================*\
 188          Function:    is_conflicting_acl()
 189          Purpose:    Checks for conflicts when adding a specific ACL.
 190      \*======================================================================*/
 191      
 192      /*======================================================================*\
 193          Function:    add_acl()
 194          Purpose:    Add's an ACL. ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
 195      \*======================================================================*/
 196  
 197      /*======================================================================*\
 198          Function:    edit_acl()
 199          Purpose:    Edit's an ACL, ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
 200      \*======================================================================*/
 201  
 202      /*======================================================================*\
 203          Function:    del_acl()
 204          Purpose:    Deletes a given ACL
 205      \*======================================================================*/
 206  
 207  
 208      /*
 209       *
 210       * Groups
 211       *
 212       */
 213  
 214      /*======================================================================*\
 215          Function:    sort_groups()
 216          Purpose:    Grabs all the groups from the database doing preliminary grouping by parent
 217      \*======================================================================*/
 218  
 219      /*======================================================================*\
 220          Function:    format_groups()
 221          Purpose:    Takes the array returned by sort_groups() and formats for human consumption.
 222      \*======================================================================*/
 223  
 224      /*======================================================================*\
 225          Function:    get_group_id()
 226          Purpose:    Gets the group_id given the name.
 227                          Will only return one group id, so if there are duplicate names, it will return false.
 228      \*======================================================================*/
 229  	function get_group_id($name = null, $group_type = 'ARO') {
 230  
 231          $this->debug_text("get_group_id(): Name: $name");
 232  
 233          switch(strtolower(trim($group_type))) {
 234              case 'axo':
 235                  $table = $this->_db_table_prefix .'axo_groups';
 236                  break;
 237              default:
 238                  $table = $this->_db_table_prefix .'aro_groups';
 239                  break;
 240          }
 241  
 242          $name = trim($name);
 243  
 244          if (empty($name) ) {
 245              $this->debug_text("get_group_id(): name ($name) is empty, this is required");
 246              return false;
 247          }
 248  
 249          $this->db->setQuery( "SELECT group_id FROM $table WHERE name='$name'" );
 250  
 251          $rows = $this->db->loadRowList();
 252          if ($this->db->getErrorNum()) {
 253              $this->debug_db('get_group_id');
 254              return false;
 255          }
 256  
 257          $row_count = count( $rows );
 258  
 259          if ($row_count > 1) {
 260              $this->debug_text("get_group_id(): Returned $row_count rows, can only return one. Please make your names unique.");
 261              return false;
 262          }
 263  
 264          if ($row_count == 0) {
 265              $this->debug_text("get_group_id(): Returned $row_count rows");
 266              return false;
 267          }
 268  
 269          $row = $rows[0];
 270  
 271          //Return the ID.
 272          return $row[0];
 273      }
 274  
 275      /*======================================================================*\
 276          Function:    get_group_name()
 277          Purpose:    Gets the name given the group_id.
 278                          Will only return one group id, so if there are duplicate names, it will return false.
 279      \*======================================================================*/
 280  	function get_group_name($group_id = null, $group_type = 'ARO') {
 281  
 282          $this->debug_text("get_group_name(): ID: $group_id");
 283  
 284          switch(strtolower(trim($group_type))) {
 285              case 'axo':
 286                  $table = $this->_db_table_prefix .'axo_groups';
 287                  break;
 288              default:
 289                  $table = $this->_db_table_prefix .'aro_groups';
 290                  break;
 291          }
 292  
 293          $group_id = intval($group_id);
 294  
 295          if (!$group_id) {
 296              $this->debug_text("get_group_name(): group_id ($group_id) is empty, this is required");
 297              return false;
 298          }
 299  
 300          $this->db->setQuery( "SELECT name FROM $table WHERE group_id='$group_id'" );
 301  
 302          $rows = $this->db->loadRowList();
 303          if ($this->db->getErrorNum()) {
 304              $this->debug_db('get_group_name');
 305              return false;
 306          }
 307  
 308          $row_count = count( $rows );
 309  
 310          if ($row_count > 1) {
 311              $this->debug_text("get_group_name(): Returned $row_count rows, can only return one. Please make your names unique.");
 312              return false;
 313          }
 314  
 315          if ($row_count == 0) {
 316              $this->debug_text("get_group_name(): Returned $row_count rows");
 317              return false;
 318          }
 319  
 320          $row = $rows[0];
 321  
 322          //Return the ID.
 323          return $row[0];
 324      }
 325  
 326      /*======================================================================*\
 327          Function:    get_group_children()
 328          Purpose:    Gets a groups child IDs
 329      \*======================================================================*/
 330  	function get_group_children($group_id, $group_type = 'ARO', $recurse = 'NO_RECURSE') {
 331          $this->debug_text("get_group_children(): Group_ID: $group_id Group Type: $group_type Recurse: $recurse");
 332  
 333          switch (strtolower(trim($group_type))) {
 334              case 'axo':
 335                  $group_type = 'axo';
 336                  $table = $this->_db_table_prefix .'axo_groups';
 337                  break;
 338              default:
 339                  $group_type = 'aro';
 340                  $table = $this->_db_table_prefix .'aro_groups';
 341          }
 342  
 343          if (empty($group_id)) {
 344              $this->debug_text("get_group_children(): ID ($group_id) is empty, this is required");
 345              return FALSE;
 346          }
 347  
 348          $query  = '
 349                  SELECT        g1.group_id
 350                  FROM        '. $table .' g1';
 351  
 352          //FIXME-mikeb: Why is group_id in quotes?
 353          switch (strtoupper($recurse)) {
 354              case 'RECURSE':
 355                  $query .= '
 356                  LEFT JOIN     '. $table .' g2 ON g2.lft<g1.lft AND g2.rgt>g1.rgt
 357                  WHERE        g2.group_id='. $group_id;
 358                  break;
 359              default:
 360                  $query .= '
 361                  WHERE        g1.parent_id='. $group_id;
 362          }
 363  
 364          $query .= '
 365                  ORDER BY    g1.name';
 366          
 367  
 368          $this->db->setQuery( $query );
 369          return $this->db->loadResultArray();
 370      }
 371  
 372      /*======================================================================*\
 373          Function:    get_group_data()
 374          Purpose:    Gets the group data given the GROUP_ID.                        
 375      \*======================================================================*/
 376  
 377      /*======================================================================*\
 378          Function:    get_group_parent_id()
 379          Purpose:    Grabs the parent_id of a given group
 380      \*======================================================================*/
 381  
 382      /*======================================================================*\
 383          Function:    get_group_children()
 384          Purpose:    Gets a groups child IDs
 385      \*======================================================================*/
 386  	function get_group_parents($group_id, $group_type = 'ARO', $recurse = 'NO_RECURSE') {
 387          $this->debug_text("get_group_parents(): Group_ID: $group_id Group Type: $group_type Recurse: $recurse");
 388  
 389          switch (strtolower(trim($group_type))) {
 390              case 'axo':
 391                  $group_type = 'axo';
 392                  $table = $this->_db_table_prefix .'axo_groups';
 393                  break;
 394              default:
 395                  $group_type = 'aro';
 396                  $table = $this->_db_table_prefix .'aro_groups';
 397          }
 398  
 399          if (empty($group_id)) {
 400              $this->debug_text("get_group_parents(): ID ($group_id) is empty, this is required");
 401              return FALSE;
 402          }
 403  
 404          $query  = '
 405                  SELECT        g2.group_id
 406                  FROM        '. $table .' g1';
 407  
 408          //FIXME-mikeb: Why is group_id in quotes?
 409          switch (strtoupper($recurse)) {
 410              case 'RECURSE':
 411                  $query .= '
 412                  LEFT JOIN     '. $table .' g2 ON g1.lft > g2.lft AND g1.lft < g2.rgt
 413                  WHERE        g1.group_id='. $group_id;
 414                  break;
 415              case 'RECURSE_INCL':
 416                  // inclusive resurse
 417                  $query .= '
 418                  LEFT JOIN     '. $table .' g2 ON g1.lft >= g2.lft AND g1.lft <= g2.rgt
 419                  WHERE        g1.group_id='. $group_id;
 420                  break;
 421              default:
 422                  $query .= '
 423                  WHERE        g1.parent_id='. $group_id;
 424          }
 425  
 426          $query .= '
 427                  ORDER BY    g2.lft';
 428          
 429  
 430          $this->db->setQuery( $query );
 431          return $this->db->loadResultArray();
 432      }
 433  
 434      /*======================================================================*\
 435          Function:    get_root_group_id ()
 436          Purpose:    Grabs the id of the root group for the specified tree
 437      \*======================================================================*/
 438  
 439      /*======================================================================*\
 440          Function:    map_path_to_root()
 441          Purpose:    Maps a unique path to root to a specific group. Each group can only have
 442                          one path to root.
 443      \*======================================================================*/
 444      /** REMOVED **/
 445      /*======================================================================*\
 446          Function:    put_path_to_root()
 447          Purpose:    Writes the unique path to root to the database. There should really only be
 448                          one path to root for each level "deep" the groups go. If the groups are branched
 449                          10 levels deep, there should only be 10 unique path to roots. These of course
 450                          overlap each other more and more the closer to the root/trunk they get.
 451      \*======================================================================*/
 452      /** REMOVED **/
 453      /*======================================================================*\
 454          Function:    clean_path_to_root()
 455          Purpose:    Cleans up any paths that are not being used.
 456      \*======================================================================*/
 457      /** REMOVED **/
 458      /*======================================================================*\
 459          Function:    get_path_to_root()
 460          Purpose:    Generates the path to root for a given group.
 461      \*======================================================================*/
 462      /** REMOVED **/
 463  
 464      /*======================================================================*\
 465          Function:    add_group()
 466          Purpose:    Inserts a group, defaults to be on the "root" branch.
 467      \*======================================================================*/
 468  	function add_group($name, $parent_id=0, $group_type='ARO') {
 469          
 470          switch(strtolower(trim($group_type))) {
 471              case 'axo':
 472                  $group_type = 'axo';
 473                  $table = $this->_db_table_prefix .'axo_groups';
 474                  break;
 475              default:
 476                  $group_type = 'aro';
 477                  $table = $this->_db_table_prefix .'aro_groups';
 478                  break;
 479          }
 480  
 481          $this->debug_text("add_group(): Name: $name Parent ID: $parent_id Group Type: $group_type");
 482  
 483          $name = trim($name);
 484          
 485          if (empty($name)) {
 486              $this->debug_text("add_group(): name ($name) OR parent id ($parent_id) is empty, this is required");
 487              return false;
 488          }
 489  
 490          //This has to be outside the transaction, because the first time it is run, it will say the sequence
 491          //doesn't exist. Then try to create it, but the transaction will already by aborted by then.
 492          //$insert_id = $this->db->GenID($this->_db_table_prefix.$group_type.'_groups_id_seq',10);
 493          $this->db->setQuery( "SELECT MAX(group_id)+1 FROM $table" );
 494          $insert_id = intval( $this->db->loadResult() );
 495          
 496          // <mos> $this->db->BeginTrans();
 497          
 498          // special case for root group
 499          if ($parent_id == 0) {
 500              // check a root group is not already defined
 501              $this->db->setQuery( 'SELECT group_id FROM '. $table .' WHERE parent_id=0' );
 502              $rs = $this->db->loadResultArray();
 503              
 504              if (!is_array( $rs )) {
 505                  $this->debug_db('add_group');
 506                  $this->db->RollBackTrans();
 507                  return FALSE;
 508              }
 509              
 510              if (count( $rs ) > 0) {
 511                  $this->debug_text('add_group (): A root group already exists.');
 512                  // <mos> $this->db->RollBackTrans();
 513                  return FALSE;
 514              }
 515              
 516              $parent_lft = 0;
 517              $parent_rgt = 1;
 518          } else {
 519              if (empty($parent_id)) {
 520                  $this->debug_text("add_group (): parent id ($parent_id) is empty, this is required");
 521                  return FALSE;
 522              }
 523              
 524              // grab parent details from database
 525              $this->db->setQuery( 'SELECT group_id, lft, rgt FROM '. $table .' WHERE group_id='. $parent_id );
 526              $rows = $this->db->loadRowList();
 527              
 528              if (!is_array($rows) OR $this->db->getErrorNum() > 0) {
 529                  $this->debug_db('add_group');
 530                  // <mos> $this->db->RollBackTrans();
 531                  return FALSE;
 532              }
 533              
 534              if (empty($rows)) {
 535                  $this->debug_text('add_group (): Parent ID: '. $parent_id .' not found.');
 536                  // <mos> $this->db->RollBackTrans();
 537                  return FALSE;
 538              }
 539              $row = $rows[0];
 540              $parent_lft = &$row[1];
 541              $parent_rgt = &$row[2];
 542  
 543              // make room for the new group
 544              $this->db->setQuery( 'UPDATE '. $table .' SET rgt=rgt+2 WHERE rgt>='. $parent_rgt );
 545              $rs = $this->db->query();
 546              
 547              if (!$rs) {
 548                  $this->debug_db('add_group: make room for the new group - right');
 549                  // <mos> $this->db->RollBackTrans();
 550                  return FALSE;
 551              }
 552              
 553              $this->db->setQuery( 'UPDATE '. $table .' SET lft=lft+2 WHERE lft>'. $parent_rgt );
 554              $rs = $this->db->query();
 555              
 556              if (!$rs) {
 557                  $this->debug_db('add_group: make room for the new group - left');
 558                  // <mos> $this->db->RollBackTrans();
 559                  return FALSE;
 560              }
 561          }
 562          
 563          $this->db->setQuery( 'INSERT INTO '. $table .' (group_id,parent_id,name,lft,rgt) VALUES ('. $insert_id .','. $parent_id .',\''. $this->db->getEscaped($name) .'\','. $parent_rgt .','. ($parent_rgt + 1) .')' );
 564          $rs = $this->db->query();
 565          
 566          if (!$rs) {
 567              $this->debug_db('add_group: insert record');
 568              // <mos> $this->db->RollBackTrans();
 569              return FALSE;
 570          }
 571          
 572          // <mos> $this->db->CommitTrans();
 573          
 574          $this->debug_text('add_group (): Added group as ID: '. $insert_id);
 575          return $insert_id;
 576      }
 577      
 578      /*======================================================================*\
 579          Function:    get_group_objects()
 580          Purpose:    Gets all objects assigned to a group.
 581                          If $option == 'RECURSE' it will get all objects in child groups as well.
 582                          defaults to omit child groups.
 583      \*======================================================================*/
 584  	function get_group_objects($group_id, $group_type='ARO', $option='NO_RECURSE') {
 585  
 586          switch(strtolower(trim($group_type))) {
 587              case 'axo':
 588                  $group_type = 'axo';
 589                  $object_table = $this->_db_table_prefix .'axo';
 590                  $group_table = $this->_db_table_prefix .'axo_groups';
 591                  $map_table = $this->_db_table_prefix .'groups_axo_map';
 592                  break;
 593              default:
 594                  $group_type = 'aro';
 595                  $object_table = $this->_db_table_prefix .'aro';
 596                  $group_table = $this->_db_table_prefix .'aro_groups';
 597                  $map_table = $this->_db_table_prefix .'groups_aro_map';
 598                  break;
 599          }
 600  
 601          $this->debug_text("get_group_objects(): Group ID: $group_id");
 602  
 603          if (empty($group_id)) {
 604              $this->debug_text("get_group_objects(): Group ID:  ($group_id) is empty, this is required");
 605              return false;
 606          }
 607  
 608          $query = '
 609                  SELECT        o.section_value,o.value
 610                  FROM        '. $object_table .' o
 611                  LEFT JOIN    '. $map_table .' gm ON o.'. $group_type .'_id=gm.'. $group_type .'_id';
 612  
 613          if ($option == 'RECURSE') {
 614              $query .= '
 615                  LEFT JOIN    '. $group_table .' g1 ON g1.group_id=gm.group_id
 616                  LEFT JOIN    '. $group_table .' g2 ON g2.lft<=g1.lft AND g2.rgt>=g1.rgt
 617                  WHERE        g2.group_id='. $group_id;
 618          } else {
 619              $query .= '
 620                  WHERE        gm.group_id='. $group_id;
 621          }
 622  
 623          $this->db->setQuery( $query );
 624  
 625          $rs = $this->db->loadRowList();
 626  
 627          if (!is_array( $rs )) {
 628              $this->debug_db('get_group_objects');
 629              return false;
 630          }
 631  
 632          $this->debug_text("get_group_objects(): Got group objects, formatting array.");
 633  
 634          $retarr = array();
 635  
 636          //format return array.
 637          foreach ($rs as $row) {
 638              $section = &$row[0];
 639              $value = &$row[1];
 640  
 641              $retarr[$section][] = $value;
 642          }
 643  
 644          return $retarr;
 645      }
 646  
 647      /*======================================================================*\
 648          Function:    add_group_object()
 649          Purpose:    Assigns an Object to a group
 650      \*======================================================================*/
 651  	function add_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
 652  
 653          switch(strtolower(trim($group_type))) {
 654              case 'axo':
 655                  $group_type = 'axo';
 656                  $table = $this->_db_table_prefix .'groups_axo_map';
 657                  $object_table = $this->_db_table_prefix .'axo';
 658                  $group_table = $this->_db_table_prefix .'axo_groups';
 659                  break;
 660              default:
 661                  $group_type = 'aro';
 662                  $table = $this->_db_table_prefix .'groups_aro_map';
 663                  $object_table = $this->_db_table_prefix .'aro';
 664                  $group_table = $this->_db_table_prefix .'aro_groups';
 665                  break;
 666          }
 667  
 668          $this->debug_text("add_group_object(): Group ID: $group_id, Section Value: $object_section_value, Value: $object_value, Group Type: $group_type");
 669  
 670          $object_section_value = trim($object_section_value);
 671          $object_value = trim($object_value);
 672  
 673          if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
 674              $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");
 675              return false;
 676          }
 677  
 678          // test to see if object & group exist and if object is already a member
 679          $this->db->setQuery( '
 680              SELECT        g.group_id,o.'. $group_type .'_id,gm.group_id AS member
 681              FROM        '. $object_table .' o
 682              LEFT JOIN    '. $group_table .' g ON g.group_id='. $group_id .'
 683              LEFT JOIN    '. $table .' gm ON (gm.group_id=g.group_id AND gm.'. $group_type .'_id=o.'. $group_type .'_id)
 684              WHERE        (o.section_value=\''. $this->db->getEscaped($object_section_value) .'\' AND o.value=\''. $this->db->getEscaped($object_value) .'\')'
 685          );
 686  
 687          $rows = $this->db->loadRowList();
 688          if ($this->db->getErrorNum()) {
 689              $this->debug_db('add_group_object');
 690              return FALSE;
 691          }
 692  
 693          if (count( $rows ) != 1) {
 694              $this->debug_text("add_group_object (): Group ID ($group_id) OR Value ($object_value) OR Section value ($object_section_value) is invalid. Does this object exist?");
 695              return FALSE;
 696          }
 697  
 698          $row = $rows[0];
 699  
 700          if ($row[2] == 1) {
 701              $this->debug_text("add_group_object (): Object: $object_value is already a member of Group ID: $group_id");
 702              //Object is already assigned to group. Return true.
 703              return true;
 704          }
 705  
 706          $object_id = $row[1];
 707  
 708          $this->db->setQuery( 'INSERT INTO '. $table .' (group_id,'. $group_type .'_id) VALUES ('. $group_id .','. $object_id .')' );
 709  
 710          if (!$this->db->query()) {
 711              $this->debug_db('add_group_object');
 712              return FALSE;
 713          }
 714  
 715          $this->debug_text('add_group_object(): Added Object: '. $object_id .' to Group ID: '. $group_id);
 716  
 717          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
 718              //Expire all cache.
 719              $this->Cache_Lite->clean('default');
 720          }
 721  
 722          return TRUE;
 723      }
 724  
 725      /*======================================================================*\
 726          Function:    del_group_object()
 727          Purpose:    Removes an Object from a group.
 728      \*======================================================================*/
 729  	function del_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
 730  
 731          switch(strtolower(trim($group_type))) {
 732              case 'axo':
 733                  $group_type = 'axo';
 734                  $table = $this->_db_table_prefix .'groups_axo_map';
 735                  break;
 736              default:
 737                  $group_type = 'aro';
 738                  $table = $this->_db_table_prefix .'groups_aro_map';
 739                  break;
 740          }
 741  
 742          $this->debug_text("del_group_object(): Group ID: $group_id Section value: $object_section_value Value: $object_value");
 743  
 744          $object_section_value = trim($object_section_value);
 745          $object_value = trim($object_value);
 746  
 747          if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
 748              $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");
 749              return false;
 750          }
 751  
 752           if (!$object_id = $this->get_object_id($object_section_value, $object_value, $group_type)) {
 753              $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?");
 754              return FALSE;
 755          }
 756  
 757          $this->db->setQuery( 'DELETE FROM '. $table .' WHERE group_id='. $group_id .' AND '. $group_type .'_id='. $object_id );
 758          $this->db->query();
 759  
 760          if ($this->db->getErrorNum()) {
 761              $this->debug_db('del_group_object');
 762              return false;
 763          }
 764  
 765          $this->debug_text("del_group_object(): Deleted Value: $object_value to Group ID: $group_id assignment");
 766  
 767          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
 768              //Expire all cache.
 769              $this->Cache_Lite->clean('default');
 770          }
 771  
 772          return true;
 773      }
 774  
 775      /*======================================================================*\
 776          Function:    edit_group()
 777          Purpose:    Edits a group
 778      \*======================================================================*/
 779      
 780      /*======================================================================*\
 781          Function:    rebuild_tree ()
 782          Purpose:    rebuilds the group tree for the given type
 783      \*======================================================================*/
 784      
 785      /*======================================================================*\
 786          Function:    del_group()
 787          Purpose:    deletes a given group
 788      \*======================================================================*/
 789  	function del_group($group_id, $reparent_children=TRUE, $group_type='ARO') {
 790          
 791          switch(strtolower(trim($group_type))) {
 792              case 'axo':
 793                  $group_type = 'axo';
 794                  $table = $this->_db_table_prefix .'axo_groups';
 795                  $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
 796                  $groups_object_map_table = $this->_db_table_prefix .'groups_axo_map';
 797                  break;
 798              default:
 799                  $group_type = 'aro';
 800                  $table = $this->_db_table_prefix .'aro_groups';
 801                  $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
 802                  $groups_object_map_table = $this->_db_table_prefix .'groups_aro_map';
 803                  break;
 804          }
 805  
 806          $this->debug_text("del_group(): ID: $group_id Reparent Children: $reparent_children Group Type: $group_type");
 807          
 808          if (empty($group_id) ) {
 809              $this->debug_text("del_group(): Group ID ($group_id) is empty, this is required");
 810              return false;
 811          }
 812  
 813          // Get details of this group
 814          $this->db->setQuery( 'SELECT group_id, parent_id, name, lft, rgt FROM '. $table .' WHERE group_id='. $group_id );
 815          $group_details = $this->db->loadRow($query);
 816          
 817          if (!is_array($group_details)) {
 818              $this->debug_db('del_group: get group details');
 819              return false;
 820          }
 821          
 822          $parent_id = $group_details[1];
 823          
 824          $left = $group_details[3];
 825          $right = $group_details[4];
 826          
 827          // <mos> $this->db->BeginTrans();
 828  
 829          // grab list of all children
 830          $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
 831          
 832          // prevent deletion of root group & reparent of children if it has more than one immediate child
 833          if ($parent_id == 0) {
 834              $this->db->setQuery( 'SELECT count(*) FROM '. $table .' WHERE parent_id='. $group_id );
 835              $child_count = $this->db->loadResult($query);
 836              
 837              if ($child_count > 1 && $reparent_children) {
 838                  $this->debug_text ('del_group (): You cannot delete the root group and reparent children, this would create multiple root groups.');
 839                  return FALSE;
 840              }
 841          }
 842          
 843          $success = FALSE;
 844          
 845          /*
 846           * Handle children here.
 847           */
 848          switch (TRUE) {
 849              // there are no child groups, just delete group
 850              case !is_array($children_ids):
 851              case count($children_ids) == 0:
 852                  // remove acl maps
 853              /* Reapply when ACL's implemented
 854                  $this->db->setQuery( 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $group_id );
 855                  $rs = $this->db->Execute($query);
 856                  
 857                  if (!is_object($rs)) {
 858                      break;
 859                  }*/
 860                  
 861                  // remove group object maps
 862                  $this->db->setQuery( 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $group_id );
 863                  $rs = $this->db->query();
 864                  
 865                  if (!$rs) {
 866                      break;
 867                  }
 868                  
 869                  // remove group
 870                  $this->db->setQuery( 'DELETE FROM '. $table .' WHERE group_id='. $group_id );
 871                  $rs = $this->db->query();
 872  
 873                  if (!$rs) {
 874                      break;
 875                  }
 876                  
 877                  // move all groups right of deleted group left by width of deleted group
 878                  $this->db->setQuery( 'UPDATE '. $table .' SET lft=lft-'. ($right-$left+1) .' WHERE lft>'. $right );
 879                  $rs = $this->db->query();
 880                  
 881                  if (!$rs) {
 882                      break;
 883                  }
 884                  
 885                  $this->db->setQuery( 'UPDATE '. $table .' SET rgt=rgt-'. ($right-$left+1) .' WHERE rgt>'. $right );
 886                  $rs = $this->db->query();
 887                  
 888                  if (!$rs) {
 889                      break;
 890                  }
 891                  
 892                  $success = TRUE;
 893                  break;
 894              case $reparent_children == TRUE:
 895                  // remove acl maps
 896              /* Reapply when ACL's implemented
 897                  $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $group_id;
 898                  $rs = $this->db->Execute($query);
 899                  
 900                  if (!is_object($rs)) {
 901                      break;
 902                  }*/
 903                  
 904                  // remove group object maps
 905                  $this->db->setQuery( 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $group_id );
 906                  $rs = $this->db->query();
 907                  
 908                  if (!$rs) {
 909                      break;
 910                  }
 911                  
 912                  // remove group
 913                  $this->db->setQuery( 'DELETE FROM '. $table .' WHERE group_id='. $group_id );
 914                  $rs = $this->db->query();
 915                  
 916                  if (!$rs) {
 917                      break;
 918                  }
 919                  
 920                  // set parent of immediate children to parent group
 921                  $this->db->setQuery( 'UPDATE '. $table .' SET parent_id='. $parent_id .' WHERE parent_id='. $group_id );
 922                  $rs = $this->db->query();
 923                  
 924                  if (!$rs) {
 925                      break;
 926                  }
 927                  
 928                  // move all children left by 1
 929                  $this->db->setQuery( 'UPDATE '. $table .' SET lft=lft-1, rgt=rgt-1 WHERE lft>'. $left .' AND rgt<'. $right );
 930                  $rs = $this->db->query();
 931                  
 932                  if (!$rs) {
 933                      break;
 934                  }
 935                  
 936                  // move all groups right of deleted group left by 2
 937                  $this->db->setQuery( 'UPDATE '. $table .' SET lft=lft-2 WHERE lft>'. $right );
 938                  $rs = $this->db->query();
 939                  
 940                  if (!$rs) {
 941                      break;
 942                  }
 943                  
 944                  $this->db->setQuery( 'UPDATE '. $table .' SET rgt=rgt-2 WHERE rgt>'. $right );
 945                  $rs = $this->db->query();
 946                  
 947                  if (!$rs) {
 948                      break;
 949                  }
 950                  
 951                  $success = TRUE;
 952                  break;
 953              default:
 954                  // make list of group and all children
 955                  $group_ids = $children_ids;
 956                  $group_ids[] = $group_id;
 957                  
 958                  // remove acl maps
 959              /* Reapply when ACL's implemented
 960                  $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
 961                  $rs = $this->db->Execute($query);
 962                  
 963                  if (!is_object($rs)) {
 964                      break;
 965                  }*/
 966                  
 967                  // remove group object maps
 968                  $this->db->setQuery( 'DELETE FROM '. $groups_object_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')' );
 969                  $rs = $this->db->query();
 970                  
 971                  if (!$rs) {
 972                      break;
 973                  }
 974                  
 975                  // remove groups
 976                  $this->db->setQuery( 'DELETE FROM '. $table .' WHERE group_id IN ('. implode (',', $group_ids) .')' );
 977                  $rs = $this->db->query();
 978                  
 979                  if (!$rs) {
 980                      break;
 981                  }
 982                  
 983                  // move all groups right of deleted group left by width of deleted group
 984                  $this->db->setQuery( 'UPDATE '. $table .' SET lft=lft-'. ($right - $left + 1) .' WHERE lft>'. $right );
 985                  $rs = $this->db->query();
 986                  
 987                  if (!$rs) {
 988                      break;
 989                  }
 990                  
 991                  $this->db->setQuery( 'UPDATE '. $table .' SET rgt=rgt-'. ($right - $left + 1) .' WHERE rgt>'. $right );
 992                  $rs = $this->db->query();
 993                  
 994                  if (!$rs) {
 995                      break;
 996                  }
 997                  
 998                  $success = TRUE;
 999          }
1000          
1001          // if the delete failed, rollback the trans and return false
1002          if (!$success) {
1003  
1004              $this->debug_db('del_group');
1005              $this->db->RollBackTrans();
1006              return false;
1007          }
1008          
1009          $this->debug_text("del_group(): deleted group ID: $group_id");
1010          // <mos> $this->db->CommitTrans();
1011  
1012          if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
1013              //Expire all cache.    
1014              $this->Cache_Lite->clean('default');
1015          }
1016  
1017          return true;
1018  
1019      }
1020  
1021  
1022      /*
1023       *
1024       * Objects (ACO/ARO/AXO)
1025       *
1026       */
1027      /*======================================================================*\
1028          Function:    get_object()
1029          Purpose:    Grabs all Objects's in the database, or specific to a section_value
1030      \*======================================================================*/
1031  	function get_object($section_value = null, $return_hidden=1, $object_type=NULL) {
1032  
1033          switch(strtolower(trim($object_type))) {
1034              case 'aco':
1035                  $object_type = 'aco';
1036                  $table = $this->_db_table_prefix .'aco';
1037                  break;
1038              case 'aro':
1039                  $object_type = 'aro';
1040                  $table = $this->_db_table_prefix .'aro';
1041                  break;
1042              case 'axo':
1043                  $object_type = 'axo';
1044                  $table = $this->_db_table_prefix .'axo';
1045                  break;
1046              default:
1047                  $this->debug_text('get_object(): Invalid Object Type: '. $object_type);
1048                  return FALSE;
1049          }
1050  
1051          $this->debug_text("get_object(): Section Value: $section_value Object Type: $object_type");
1052  
1053          $$this->db->setQuery( 'SELECT '. $object_type .'_id FROM '. $table );
1054  
1055          $where = array();
1056  
1057          if (!empty($section_value)) {
1058              $where[] = 'section_value='. $this->db->getEscaped($section_value);
1059          }
1060  
1061          if ($return_hidden==0) {
1062              $where[] = 'hidden=0';
1063          }
1064  
1065          if (!empty($where)) {
1066              $query .= ' WHERE '. implode(' AND ', $where);
1067          }
1068  
1069          $rs = $this->db->loadResultArray();
1070  
1071          if (!is_array($rs)) {
1072              $this->debug_db('get_object');
1073              return false;
1074          }
1075  
1076          // Return Object IDs
1077          return $rs;
1078      }
1079  
1080      /*======================================================================*\
1081          Function:    get_objects ()
1082          Purpose:    Grabs all Objects in the database, or specific to a section_value
1083                      returns format suitable for add_acl and is_conflicting_acl
1084      \*======================================================================*/
1085  
1086      /*======================================================================*\
1087          Function:    get_object_data()
1088          Purpose:    Gets all data pertaining to a specific Object.
1089      \*======================================================================*/
1090  
1091      /*======================================================================*\
1092          Function:    get_object_groups()
1093          Purpose:    Gets the group_id's for the given the section_value AND value
1094          of the object.
1095      \*======================================================================*/
1096  	function get_object_groups($object_section_value, $object_value, $object_type=NULL) {
1097  
1098          switch(strtolower(trim($object_type))) {
1099              case 'aro':
1100                  $group_type = 'aro';
1101                  $table = $this->_db_table_prefix .'groups_aro_map';
1102                  $object_table = $this->_db_table_prefix .'aro';
1103                  $group_table = $this->_db_table_prefix .'aro_groups';
1104                  break;
1105              case 'axo':
1106                  $group_type = 'axo';
1107                  $table = $this->_db_table_prefix .'groups_axo_map';
1108                  $object_table = $this->_db_table_prefix .'axo';
1109                  $group_table = $this->_db_table_prefix .'axo_groups';
1110                  break;
1111              default:
1112                  $this->debug_text('get_object_groups(): Invalid Object Type: '. $object_type);
1113                  return FALSE;
1114          }
1115  
1116          $this->debug_text("get_object_groups(): Section Value: $object_section_value Value: $object_value Object Type: $object_type");
1117  
1118          $object_section_value = trim($object_section_value);
1119          $object_value = trim($object_value);
1120  
1121          if (empty($object_section_value) AND empty($object_value) ) {
1122              $this->debug_text("get_object_groups(): Section Value ($object_section_value) AND value ($object_value) is empty, this is required");
1123              return false;
1124          }
1125  
1126          if (empty($object_type) ) {
1127              $this->debug_text("get_object_groups(): Object Type ($object_type) is empty, this is required");
1128              return false;
1129          }
1130  //            SELECT        g.group_id,o.'. $group_type .'_id,(gm.group_id IS NOT NULL) AS member
1131  
1132          $this->db->setQuery( '
1133              SELECT        g.group_id,o.'. $group_type .'_id,(gm.group_id IS NOT NULL) AS member
1134              FROM        '. $group_table .' g
1135              LEFT JOIN    '. $table .' gm ON gm.group_id=g.group_id
1136              LEFT JOIN    '. $object_table .' o ON o.'. $group_type .'_id = gm.'. $group_type .'_id
1137              WHERE        (o.section_value=\''. $this->db->getEscaped($object_section_value) .'\' AND o.value=\''. $this->db->getEscaped($object_value) .'\')'
1138          );
1139          $rs = $this->db->loadResultArray();
1140  
1141          if ($this->db->getErrorNum()) {
1142              $this->debug_db('get_object_id');
1143              return false;
1144          }
1145  
1146          //Return the array of group id's
1147          return $rs;
1148      }
1149  
1150      /*======================================================================*\
1151          Function:    get_object_id()
1152          Purpose:    Gets the object_id given the section_value AND value of the object.
1153      \*======================================================================*/
1154  	function get_object_id($section_value, $value, $object_type=NULL) {
1155  
1156          switch(strtolower(trim($object_type))) {
1157              case 'aco':
1158                  $object_type = 'aco';
1159                  $table = $this->_db_table_prefix .'aco';
1160                  break;
1161              case 'aro':
1162                  $object_type = 'aro';
1163                  $table = $this->_db_table_prefix .'aro';
1164                  break;
1165              case 'axo':
1166                  $object_type = 'axo';
1167                  $table = $this->_db_table_prefix .'axo';
1168                  break;
1169              default:
1170                  $this->debug_text('get_object_id(): Invalid Object Type: '. $object_type);
1171                  return FALSE;
1172          }
1173  
1174          $this->debug_text("get_object_id(): Section Value: $section_value Value: $value Object Type: $object_type");
1175  
1176          $section_value = trim($section_value);
1177          $value = trim($value);
1178  
1179          if (empty($section_value) AND empty($value) ) {
1180              $this->debug_text("get_object_id(): Section Value ($value) AND value ($value) is empty, this is required");
1181              return false;
1182          }
1183  
1184          if (empty($object_type) ) {
1185              $this->debug_text("get_object_id(): Object Type ($object_type) is empty, this is required");
1186              return false;
1187          }
1188  
1189          $this->db->setQuery( 'SELECT '. $object_type .'_id FROM '. $table .' WHERE section_value=\''. $this->db->getEscaped($section_value) .'\' AND value=\''. $this->db->getEscaped($value) .'\''
1190          );
1191          $rs = $this->db->loadRowList();
1192  
1193          if ($this->db->getErrorNum()) {
1194              $this->debug_db('get_object_id');
1195              return false;
1196          }
1197  
1198          $row_count = count( $rs );
1199  
1200          if ($row_count > 1) {
1201              $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.");
1202              return false;
1203          }
1204  
1205          if ($row_count == 0) {
1206              $this->debug_text("get_object_id(): Returned $row_count rows");
1207              return false;
1208          }
1209  
1210          $row = $rs[0];
1211  
1212          //Return the ID.
1213          return $row[0];
1214      }
1215  
1216      /*======================================================================*\
1217          Function:    get_object_section_value()
1218          Purpose:    Gets the object_section_value given object id
1219      \*======================================================================*/
1220  
1221      /*======================================================================*\
1222          Function:    get_object_groups()
1223          Purpose:    Gets all groups an object is a member of.
1224                      If $option == 'RECURSE' it will get all ancestor groups.
1225                      defaults to only get direct parents.
1226      \*======================================================================*/
1227  
1228      /*======================================================================*\
1229          Function:    add_object()
1230          Purpose:    Inserts a new object
1231      \*======================================================================*/
1232  	function add_object($section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
1233  
1234          switch(strtolower(trim($object_type))) {
1235              case 'aco':
1236                  $object_type = 'aco';
1237                  $table = $this->_db_table_prefix .'aco';
1238                  $object_sections_table = $this->_db_table_prefix .'aco_sections';
1239                  break;
1240              case 'aro':
1241                  $object_type = 'aro';
1242                  $table = $this->_db_table_prefix .'aro';
1243                  $object_sections_table = $this->_db_table_prefix .'aro_sections';
1244                  break;
1245              case 'axo':
1246                  $object_type = 'axo';
1247                  $table = $this->_db_table_prefix .'axo';
1248                  $object_sections_table = $this->_db_table_prefix .'axo_sections';
1249                  break;
1250              default:
1251                  $this->debug_text('add_object(): Invalid Object Type: '. $object_type);
1252                  return FALSE;
1253          }
1254  
1255          $this->debug_text("add_object(): Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
1256  
1257          $section_value = trim($section_value);
1258          $name = trim($name);
1259          $value = trim($value);
1260          $order = trim($order);
1261  
1262          if ($order == NULL OR $order == '') {
1263              $order = 0;
1264          }
1265  
1266          if (empty($name) OR empty($section_value) ) {
1267              $this->debug_text("add_object(): name ($name) OR section value ($section_value) is empty, this is required");
1268              return false;
1269          }
1270  
1271          if (strlen($name) >= 255 OR strlen($value) >= 230 ) {
1272              $this->debug_text("add_object(): name ($name) OR value ($value) is too long.");
1273              return false;
1274          }
1275  
1276          if (empty($object_type) ) {
1277              $this->debug_text("add_object(): Object Type ($object_type) is empty, this is required");
1278              return false;
1279          }
1280  
1281          // Test to see if the section is invalid or object already exists.
1282          $this->db->setQuery( '
1283              SELECT		(o.'. $object_type .'_id IS NOT NULL) AS object_exists
1284              FROM        '. $object_sections_table .' s
1285              LEFT JOIN    '. $table .' o ON (s.value=o.section_value AND o.value=\''. $this->db->getEscaped($value) .'\')
1286              WHERE        s.value=\''. $this->db->getEscaped($section_value). '\''
1287          );
1288  
1289          $rows = $this->db->loadRowList();
1290          if ($this->db->getErrorNum()) {
1291              $this->debug_db('add_object');
1292              return FALSE;
1293          }
1294  
1295          if (count( $rows ) != 1) {
1296              // Section is invalid
1297              $this->debug_text("add_object(): Section Value: $section_value Object Type ($object_type) does not exist, this is required");
1298              return false;
1299          }
1300  
1301          $row = $rows[0];
1302  
1303          if ($row[0] == 1) {
1304              //Object is already created.
1305              return true;
1306          }
1307  
1308          $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_seq',10);
1309          $this->db->setQuery( "INSERT INTO $table ({$object_type}_id,section_value,value,order_value,name,hidden) VALUES($insert_id,'$section_value','$value','$order','$name','$hidden')" );
1310  
1311          if (!$this->db->query()) {
1312              $this->debug_db('add_object');
1313              return false;
1314          }
1315  
1316          $insert_id = $this->db->insertid();
1317          $this->debug_text("add_object(): Added object as ID: $insert_id");
1318          return $insert_id;
1319      }
1320      /*======================================================================*\
1321          Function:    edit_object()
1322          Purpose:    Edits a given Object
1323      \*======================================================================*/
1324  	function edit_object($object_id, $section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
1325  
1326          switch(strtolower(trim($object_type))) {
1327              case 'aco':
1328                  $object_type = 'aco';
1329                  $table = $this->_db_table_prefix .'aco';
1330                  $object_map_table = 'aco_map';
1331                  break;
1332              case 'aro':
1333                  $object_type = 'aro';
1334                  $table = $this->_db_table_prefix .'aro';
1335                  $object_map_table = 'aro_map';
1336                  break;
1337              case 'axo':
1338                  $object_type = 'axo';
1339                  $table = $this->_db_table_prefix .'axo';
1340                  $object_map_table = 'axo_map';
1341                  break;
1342          }
1343  
1344          $this->debug_text("edit_object(): ID: $object_id, Section Value: $section_value, Value: $value, Order: $order, Name: $name, Object Type: $object_type");
1345  
1346          $section_value = trim($section_value);
1347          $name = trim($name);
1348          $value = trim($value);
1349          $order = trim($order);
1350  
1351          if (empty($object_id) OR empty($section_value) ) {
1352              $this->debug_text("edit_object(): Object ID ($object_id) OR Section Value ($section_value) is empty, this is required");
1353              return false;
1354          }
1355  
1356          if (empty($name) ) {
1357              $this->debug_text("edit_object(): name ($name) is empty, this is required");
1358              return false;
1359          }
1360  
1361          if (empty($object_type) ) {
1362              $this->debug_text("edit_object(): Object Type ($object_type) is empty, this is required");
1363              return false;
1364          }
1365  
1366          //Get old value incase it changed, before we do the update.
1367          $this->db->setQuery( 'SELECT value, section_value FROM '. $table .' WHERE '. $object_type .'_id='. $object_id );
1368          $old = $this->db->loadRow();
1369  
1370          $this->db->setQuery( '
1371              UPDATE    '. $table .'
1372              SET        section_value=\''. $this->db->getEscaped($section_value) .'\',
1373                      value='. $this->db->getEscaped($value) .',
1374                      order_value='. $this->db->getEscaped($order) .',
1375                      name=\''. $this->db->getEscaped($name) .'\',
1376                      hidden='. $hidden .'
1377              WHERE    '. $object_type .'_id='. $object_id
1378          );
1379          $this->db->query();
1380  
1381          if (!$this->db->getErrorNum()) {
1382              $this->debug_db('edit_object');
1383              return false;
1384          }
1385  
1386          $this->debug_text('edit_object(): Modified '. strtoupper($object_type) .' ID: '. $object_id);
1387  
1388          if ($old[0] != $value OR $old[1] != $section_value) {
1389              $this->debug_text("edit_object(): Value OR Section Value Changed, update other tables.");
1390  
1391              $this->db->setQuery( '
1392                  UPDATE    '. $object_map_table .'
1393                  SET        value=\''. $this->db->getEscaped($value) .'\',
1394                          section_value=\''. $this->db->getEscaped($section_value) .'\'
1395                  WHERE    section_value=\''. $this->db->getEscaped($old[1]) .'\'
1396                      AND    value='. $this->db->getEscaped($old[0])
1397              );
1398              $this->db->query();
1399  
1400          if (!$this->db->getErrorNum()) {
1401                  $this->debug_db('edit_object');
1402                  return FALSE;
1403              }
1404  
1405              $this->debug_text ('edit_object(): Modified Map Value: '. $value .' Section Value: '. $section_value);
1406          }
1407  
1408          return TRUE;
1409      }
1410  
1411      /*======================================================================*\
1412          Function:    del_object()
1413          Purpose:    Deletes a given Object and, if instructed to do so,
1414                          erase all referencing objects
1415                          ERASE feature by: Martino Piccinato
1416      \*======================================================================*/
1417  	function del_object($object_id, $object_type=NULL, $erase=FALSE) {
1418  
1419          switch(strtolower(trim($object_type))) {
1420              case 'aco':
1421                  $object_type = 'aco';
1422                  $table = $this->_db_table_prefix .'aco';
1423                  $object_map_table = $this->_db_table_prefix .'aco_map';
1424                  break;
1425              case 'aro':
1426                  $object_type = 'aro';
1427                  $table = $this->_db_table_prefix .'aro';
1428                  $object_map_table = $this->_db_table_prefix .'aro_map';
1429                  $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
1430                  $object_group_table = $this->_db_table_prefix .'groups_aro_map';
1431                  break;
1432              case 'axo':
1433                  $object_type = 'axo';
1434                  $table = $this->_db_table_prefix .'axo';
1435                  $object_map_table = $this->_db_table_prefix .'axo_map';
1436                  $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
1437                  $object_group_table = $this->_db_table_prefix .'groups_axo_map';
1438                  break;
1439              default:
1440                  $this->debug_text('del_object(): Invalid Object Type: '. $object_type);
1441                  return FALSE;
1442          }
1443  
1444          $this->debug_text("del_object(): ID: $object_id Object Type: $object_type, Erase all referencing objects: $erase");
1445  
1446          if (empty($object_id) ) {
1447              $this->debug_text("del_object(): Object ID ($object_id) is empty, this is required");
1448              return false;
1449          }
1450  
1451          if (empty($object_type) ) {
1452              $this->debug_text("del_object(): Object Type ($object_type) is empty, this is required");
1453              return false;
1454          }
1455  
1456          // <mos> $this->db->BeginTrans();
1457  
1458          // Get Object section_value/value (needed to look for referencing objects)
1459          $this->db->setQuery( 'SELECT section_value,value FROM '. $table .' WHERE '. $object_type .'_id='. $object_id );
1460          $object = $this->db->loadRow();
1461  
1462          if (empty($object)) {
1463              $this->debug_text('del_object(): The specified object ('. strtoupper($object_type) .' ID: '. $object_id .') could not be found.<br />SQL = '.$this->db->stderr());
1464              return FALSE;
1465          }
1466  
1467          $section_value = $object[0];
1468          $value = $object[1];
1469  
1470          // Get ids of acl referencing the Object (if any)
1471          $this->db->setQuery( "SELECT acl_id FROM $object_map_table WHERE value='$value' AND section_value='$section_value'" );
1472          $acl_ids = $this->db->loadResultArray();
1473  
1474          if ($erase) {
1475              // We were asked to erase all acl referencing it
1476  
1477              $this->debug_text("del_object(): Erase was set to TRUE, delete all referencing objects");
1478  
1479              if ($object_type == "aro" OR $object_type == "axo") {
1480                  // The object can be referenced in groups_X_map tables
1481                  // in the future this branching may become useless because
1482                  // ACO might me "groupable" too
1483  
1484                  // Get rid of groups_map referencing the Object
1485                  $this->db->setQuery( 'DELETE FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id );
1486                  $rs = $this->db->query();
1487  
1488                  if (!$rs) {
1489                      $this->debug_db('edit_object');
1490                      // <mos> $this->db->RollBackTrans();
1491                      return false;
1492                  }
1493              }
1494  
1495              if ($acl_ids) {
1496                  //There are acls actually referencing the object
1497  
1498                  if ($object_type == 'aco') {
1499                      // I know it's extremely dangerous but
1500                      // if asked to really erase an ACO
1501                      // we should delete all acl referencing it
1502                      // (and relative maps)
1503  
1504                      // Do this below this branching
1505                      // where it uses $orphan_acl_ids as
1506                      // the array of the "orphaned" acl
1507                      // in this case all referenced acl are
1508                      // orhpaned acl
1509  
1510                      $orphan_acl_ids = $acl_ids;
1511                  } else {
1512                      // The object is not an ACO and might be referenced
1513                      // in still valid acls regarding also other object.
1514                      // In these cases the acl MUST NOT be deleted
1515  
1516                      // Get rid of $object_id map referencing erased objects
1517                      $this->db->setQuery( "DELETE FROM $object_map_table WHERE section_value='$section_value' AND value='$value'" );
1518                      $rs = $this->db->query();
1519  
1520                      if (!$rs) {
1521                          $this->debug_db('edit_object');
1522                          $this->db->RollBackTrans();
1523                          return false;
1524                      }
1525  
1526                      // Find the "orphaned" acl. I mean acl referencing the erased Object (map)
1527                      // not referenced anymore by other objects
1528  
1529                      $sql_acl_ids = implode(",", $acl_ids);
1530  
1531                      $this->db->setQuery( '
1532                          SELECT        a.id
1533                          FROM        '. $this->_db_table_prefix .'acl a
1534                          LEFT JOIN    '. $object_map_table .' b ON a.id=b.acl_id
1535                          './* <mos return for full acl stuff> LEFT JOIN    '. $groups_map_table .' c ON a.id=c.acl_id*/'
1536                          WHERE        value IS NULL
1537                              AND        section_value IS NULL
1538                              AND        group_id IS NULL
1539                              AND        a.id in ('. $sql_acl_ids .')');
1540                      $orphan_acl_ids = $this->db->loadResultArray();
1541  
1542                  } // End of else section of "if ($object_type == "aco")"
1543  
1544                  if ($orphan_acl_ids) {
1545                  // If there are orphaned acls get rid of them
1546  
1547                      foreach ($orphan_acl_ids as $acl) {
1548                          $this->del_acl($acl);
1549                      }
1550                  }
1551  
1552              } // End of if ($acl_ids)
1553  
1554              // Finally delete the Object itself
1555              $this->db->setQuery( "DELETE FROM $table WHERE {$object_type}_id='$object_id'" );
1556              $rs = $this->db->query();
1557  
1558              if (!$rs) {
1559                  $this->debug_db('edit_object');
1560                  // <mos> $this->db->RollBackTrans();
1561                  return false;
1562              }
1563  
1564              // <mos> $this->db->CommitTrans();
1565              return true;
1566  
1567          } // End of "if ($erase)"
1568  
1569          $groups_ids = FALSE;
1570  
1571          if ($object_type == 'axo' OR $object_type == 'aro') {
1572              // If the object is "groupable" (may become unnecessary,
1573              // see above
1574  
1575              // Get id of groups where the object is assigned:
1576              // you must explicitly remove the object from its groups before
1577              // deleting it (don't know if this is really needed, anyway it's safer ;-)
1578  
1579              $this->db->setQuery( 'SELECT group_id FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id );
1580              $groups_ids = $this->db->loadResultArray();
1581          }
1582  
1583          if ( ( isset($acl_ids) AND $acl_ids !== FALSE ) OR ( isset($groups_ids) AND $groups_ids !== FALSE) ) {
1584              // The Object is referenced somewhere (group or acl), can't delete it
1585  
1586              $this->debug_text("del_object(): Can't delete the object as it is being referenced by GROUPs (".@implode($group_ids).") or ACLs (".@implode($acl_ids,",").")");
1587  
1588              return false;
1589          } else {
1590              // The Object is NOT referenced anywhere, delete it
1591  
1592              $this->db->setQuery( "DELETE FROM $table WHERE {$object_type}_id='$object_id'" );
1593              $this->db->query();
1594  
1595              if ( $this->db->getErrorNum() ) {
1596                  $this->debug_db('edit_object');
1597                  // <mos> $this->db->RollBackTrans();
1598                  return false;
1599              }
1600  
1601              // <mos> $this->db->CommitTrans();
1602              return true;
1603          }
1604  
1605          return false;
1606      }
1607  
1608      /*
1609       *
1610       * Object Sections
1611       *
1612       */
1613  
1614      /*======================================================================*\
1615          Function:    get_object_section_section_id()
1616          Purpose:    Gets the object_section_id given the name AND/OR value of the section.
1617                      Will only return one section id, so if there are duplicate names it will return false.
1618      \*======================================================================*/
1619  
1620      /*======================================================================*\
1621          Function:    add_object_section()
1622          Purpose:    Inserts an object Section
1623      \*======================================================================*/
1624  
1625      /*======================================================================*\
1626          Function:    edit_object_section()
1627          Purpose:    Edits a given Object Section
1628      \*======================================================================*/
1629  
1630      /*======================================================================*\
1631          Function:    del_object_section()
1632          Purpose:    Deletes a given Object Section and, if explicitly
1633                          asked, all the section objects
1634                          ERASE feature by: Martino Piccinato
1635      \*======================================================================*/
1636  
1637      /*
1638       *
1639       * Mambo Utility Methods
1640       *
1641       */
1642  
1643      /*======================================================================*\
1644          Function:    has_group_parent
1645          Purpose:    Checks whether the 'source' group is a child of the 'target'
1646      \*======================================================================*/
1647  	function is_group_child_of( $grp_src, $grp_tgt, $group_type='ARO' ) {
1648          $this->debug_text("has_group_parent(): Source=$grp_src, Target=$grp_tgt, Type=$group_type");
1649  
1650          switch(strtolower(trim($group_type))) {
1651              case 'axo':
1652                  $table = $this->_db_table_prefix .'axo_groups';
1653                  break;
1654              default:
1655                  $table = $this->_db_table_prefix .'aro_groups';
1656                  break;
1657          }
1658  
1659          if (is_int( $grp_src ) && is_int($grp_tgt)) {
1660              $this->db->setQuery( "SELECT COUNT(*)"
1661                  . "\nFROM $table AS g1"
1662                  . "\nLEFT JOIN $table AS g2 ON g1.lft > g2.lft AND g1.lft < g2.rgt"
1663                  . "\nWHERE g1.group_id=$grp_src AND g2.group_id=$grp_tgt"
1664              );
1665          } else if (is_string( $grp_src ) && is_string($grp_tgt)) {
1666              $this->db->setQuery( "SELECT COUNT(*)"
1667                  . "\nFROM $table AS g1"
1668                  . "\nLEFT JOIN $table AS g2 ON g1.lft > g2.lft AND g1.lft < g2.rgt"
1669                  . "\nWHERE g1.name='$grp_src' AND g2.name='$grp_tgt'"
1670              );
1671          } else if (is_int( $grp_src ) && is_string($grp_tgt)) {
1672              $this->db->setQuery( "SELECT COUNT(*)"
1673                  . "\nFROM $table AS g1"
1674                  . "\nLEFT JOIN $table AS g2 ON g1.lft > g2.lft AND g1.lft < g2.rgt"
1675                  . "\nWHERE g1.group_id='$grp_src' AND g2.name='$grp_tgt'"
1676              );
1677          } else {
1678              $this->db->setQuery( "SELECT COUNT(*)"
1679                  . "\nFROM $table AS g1"
1680                  . "\nLEFT JOIN $table AS g2 ON g1.lft > g2.lft AND g1.lft < g2.rgt"
1681                  . "\nWHERE g1.name=$grp_src AND g2.group_id='$grp_tgt'"
1682              );
1683          }
1684  
1685          return $this->db->loadResult();
1686      }
1687  
1688  	function getAroGroup( $value ) {
1689          return $this->_getGroup( 'aro', $value );
1690      }
1691  
1692  	function _getGroup( $type, $value ) {
1693          global $database;
1694  
1695          $database->setQuery( "SELECT g.*"
1696              . "\nFROM #__core_acl_{$type}_groups AS g"
1697              . "\nINNER JOIN #__core_acl_groups_{$type}_map AS gm ON gm.group_id = g.group_id"
1698              . "\nINNER JOIN #__core_acl_{$type} AS ao ON ao.{$type}_id = gm.{$type}_id"
1699              . "\nWHERE ao.value='$value'"
1700          );
1701          $obj = null;
1702          $database->loadObject( $obj );
1703          return $obj;
1704      }
1705  
1706  	function _getAbove() {
1707      }
1708  
1709  	function _getBelow( $table, $fields, $groupby=null, $root_id=null, $root_name=null, $inclusive=true ) {
1710          global $database;
1711  
1712          $root = new stdClass();
1713          $root->lft = 0;
1714          $root->rgt = 0;
1715  
1716          if ($root_id) {
1717          } else if ($root_name) {
1718              $database->setQuery( "SELECT lft, rgt FROM $table WHERE name='$root_name'" );
1719              $database->loadObject( $root );
1720          }
1721  
1722          $where = '';
1723          if ($root->lft+$root->rgt <> 0) {
1724              if ($inclusive) {
1725                  $where = "WHERE g1.lft BETWEEN $root->lft AND $root->rgt";
1726              } else {
1727                  $where = "WHERE g1.lft BETWEEN $root->lft+1 AND $root->rgt-1";
1728              }
1729          }
1730  
1731          $database->setQuery( "SELECT $fields"
1732              . "\nFROM $table AS g1"
1733              . "\nINNER JOIN $table AS g2 ON g1.lft BETWEEN g2.lft AND g2.rgt"
1734              . "\n$where"
1735              . ($groupby ? "\nGROUP BY $groupby" : "")
1736              . "\nORDER BY g1.lft"
1737          );
1738  
1739          //echo $database->getQuery();
1740          return $database->loadObjectList();
1741      }
1742  
1743  	function get_group_children_tree( $root_id=null, $root_name=null, $inclusive=true ) {
1744          global $database;
1745  
1746          $tree = gacl_api::_getBelow( '#__core_acl_aro_groups',
1747              'g1.group_id, g1.name, COUNT(g2.name) AS level',
1748              'g1.name',
1749              $root_id, $root_name, $inclusive );
1750  
1751          // first pass get level limits
1752          $n = count( $tree );
1753          $min = $tree[0]->level;
1754          $max = $tree[0]->level;
1755          for ($i=0; $i < $n; $i++) {
1756              $min = min( $min, $tree[$i]->level );
1757              $max = max( $max, $tree[$i]->level );
1758          }
1759  
1760          $indents = array();
1761          foreach (range( $min, $max ) as $i) {
1762              $indents[$i] = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
1763          }
1764          // correction for first indent
1765          $indents[$min] = '';
1766  
1767          $list = array();
1768          for ($i=$n-1; $i >= 0; $i--) {
1769              $shim = '';
1770              foreach (range( $min, $tree[$i]->level ) as $j) {
1771                  $shim .= $indents[$j];
1772              }
1773  
1774              if (@$indents[$tree[$i]->level+1] == '.&nbsp;') {
1775                  $twist = '&nbsp;';
1776              } else {
1777                  $twist = "-&nbsp;";
1778              }
1779  
1780              //$list[$i] = $tree[$i]->level.$shim.$twist.$tree[$i]->name;
1781              $list[$i] = mosHTML::makeOption( $tree[$i]->group_id, $shim.$twist.$tree[$i]->name );
1782              if ($tree[$i]->level < @$tree[$i-1]->level) {
1783                  $indents[$tree[$i]->level+1] = '.&nbsp;';
1784              }
1785          }
1786  
1787          ksort($list);
1788          return $list;
1789      }
1790  }
1791  
1792  class mosARO extends mosDBTable {
1793  /** @var int Primary key */
1794      var $aro_id=null;
1795      var $section_value=null;
1796      var $value=null;
1797      var $order_value=null;
1798      var $name=null;
1799      var $hidden=null;
1800  
1801  	function mosARO( &$db ) {
1802          $this->mosDBTable( '#__core_acl_aro', 'aro_id', $db );
1803      }
1804  
1805  /**
1806  * Utility function for returning groups
1807  */
1808  
1809  }
1810  
1811  class mosAroGroup extends mosDBTable {
1812  /** @var int Primary key */
1813      var $group_id=null;
1814      var $parent_id=null;
1815      var $name=null;
1816      var $lft=null;
1817      var $rgt=null;
1818  
1819  	function mosAroGroup( &$db ) {
1820          $this->mosDBTable( '#__core_acl_aro_groups', 'group_id', $db );
1821      }
1822  }
1823  
1824  ?>