PageRenderTime 72ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/include/phpgacl/gacl_api.class.php

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