Assorted minor corrections per code review.
[openemr.git] / library / acl.inc
blob3b0b3a894c1ba80bed04c78080af0a6e82dbdc37
1 <?php
2 // php-GACL access controls are included in OpenEMR. The below
3 // function will automatically create the path where gacl.class.php
4 // can be found. Note that this path can be manually set below
5 // for users who are using an external version of php-GACL.
6 // Also note that php-GACL access controls can be turned off
7 // below.
9   $phpgacl_location = dirname(__FILE__).'/../gacl';
12 // If using an external version of phpGACL, then uncomment the following
13 // line and manually place the path below.  IN THIS CASE YOU MUST ALSO
14 // COMMENT OUT ABOVE $phpgacl_location ASSIGNMENT ABOVE, OR BACKUPS WILL
15 // NOT RESTORE PROPERLY!
17 //$phpgacl_location = "/var/www/gacl";
19 // If you want to turn off php-GACL, then uncomment the following line.
20 // IN THIS CASE YOU MUST ALSO COMMENT OUT ABOVE $phpgacl_location ASSIGNMENT(S)
21 // ABOVE, OR BACKUPS WILL NOT RESTORE PROPERLY!
23 //unset($phpgacl_location);
26   // The following Access Control Objects (ACO) are currently supported.
27   // These are the "things to be protected":
28   //
29   // Section "admin" (Administration):
30   //   super       Superuser - can delete patients, encounters, issues
31   //   calendar    Calendar Settings
32   //   database    Database Reporting
33   //   forms       Forms Administration
34   //   practice    Practice Settings
35   //   superbill   Superbill Codes Administration
36   //   users       Users/Groups/Logs Administration
37   //   batchcom    Batch Communication Tool
38   //   language    Language Interface Tool
39   //   drugs       Pharmacy Dispensary
40   //   acl         ACL Administration
41   //
42   // Section "acct" (Accounting):
43   //   bill        Billing (write optional)
44   //   disc        Allowed to discount prices (in Fee Sheet or Checkout form)
45   //   eob         EOB Data Entry
46   //   rep         Financial Reporting - my encounters
47   //   rep_a       Financial Reporting - anything
48   //
49   // Section "patients" (Patient Information):
50   //   appt        Appointments (write,wsome optional)
51   //   demo        Demographics (write,addonly optional)
52   //   med         Medical Records and History (write,addonly optional)
53   //   trans       Transactions, e.g. referrals (write optional)
54   //   docs        Documents (write,addonly optional)
55   //   notes       Patient Notes (write,addonly optional)
56   //   sign        Sign Lab Results (write,addonly optional)
57   //
58   // Section "encounters" (Encounter Information):
59   //   auth        Authorize - my encounters
60   //   auth_a      Authorize - any encounters
61   //   coding      Coding - my encounters (write,wsome optional)
62   //   coding_a    Coding - any encounters (write,wsome optional)
63   //   notes       Notes - my encounters (write,addonly optional)
64   //   notes_a     Notes - any encounters (write,addonly optional)
65   //   date_a      Fix encounter dates - any encounters
66   //   relaxed     Less-private information (write,addonly optional)
67   //               (e.g. the Sports Fitness encounter form)
68   //
69   // Section "squads" applies to sports team use only:
70   //   acos in this section define the user-specified list of squads
71   //
72   // Section "sensitivities" (Sensitivities):
73   //   normal     Normal
74   //   high       High
75   //
76   // Section "lists" (Lists):
77   //   default    Default List (write,addonly optional)
78   //   state      State List (write,addonly optional)
79   //   country    Country List (write,addonly optional)
80   //   language   Language List (write,addonly optional)
81   //   ethrace    Ethnicity-Race List (write,addonly optional)
82   //
83   // Section "placeholder" (Placeholder):
84   //   filler     Placeholder (Maintains empty ACLs)
85   //
86   // Section "nationnotes" (Nation Notes):
87   //   nn_configure     Nation Notes
88   //
89   // Section "patientportal" (Patient Portal):
90   //   portal     Patient Portal
91   
92   if (isset ($phpgacl_location)) {
93     include_once("$phpgacl_location/gacl.class.php");
94     $gacl_object = new gacl();
95     //DO NOT CHANGE BELOW VARIABLE
96     $section_aro_value = 'users';
97   }
99   // acl_check should return FALSE if access is denied and will return TRUE
100   // if access is allowed. The following return_value(s) can be evaluated
101   // for by placing in the $return_value parameter; it can be placed
102   // as a single value or can send as an array of values (so $return_value
103   // can be a string or an array).
104   //
105   // * view    - the user may view but not add or modify entries
106   // * write   - the user may add or modify the ACO
107   // * wsome   - the user has limited add/modify access to the ACO
108   // * addonly - the user may view and add but not modify entries
109   //
110   function acl_check($section, $value, $user = '', $return_value = '') {
111     global $gacl_object, $phpgacl_location, $section_aro_value;
112     if (! $user) $user = $_SESSION['authUser'];
114     if ($phpgacl_location) {
115       // This will return all pertinent ACL's (including return_values and whether allow/deny)
116       // Walk through them to assess for access
117       $acl_results = $gacl_object->acl_query($section, $value, $section_aro_value, $user,NULL,NULL,NULL,NULL,NULL,TRUE);
118       if (empty($acl_results)) {
119         return FALSE; //deny access
120       }
121       $access=FALSE; //flag
122       $deny=FALSE; //flag
123       foreach ($acl_results as $acl_result) {
124         if (empty($acl_result['acl_id'])) return FALSE; //deny access, since this happens if no pertinent ACL's are returned
125         if (is_array($return_value)) {
126           foreach ($return_value as $single_return_value) {
127             if (empty($single_return_value)) {
128               // deal with case if not looking for specific return value
129               if ($acl_result['allow']) {
130                 $access=TRUE;
131               }
132               else {
133                 $deny=TRUE;
134               }
135             }
136             else { //!empty($single_return_value)
137               // deal with case if looking for specific return value
138               if ($acl_result['return_value'] == $single_return_value) {
139                 if ($acl_result['allow']) {
140                   $access=TRUE;
141                 }
142                 else{
143                   $deny=TRUE;
144                 }
145               }
146             }
147           }
148         }
149         else { // $return_value is not an array (either empty or with one value)
150           if (empty($return_value)) {
151             // deal with case if not looking for specific return value
152             if ($acl_result['allow']) {
153               $access=TRUE;
154             }
155             else {
156               $deny=TRUE;
157             }
158           }
159           else { //!empty($return_value)
160             // deal with case if looking for specific return value
161             if ($acl_result['return_value'] == $return_value) {
162               if ($acl_result['allow']) {
163                 $access=TRUE;
164               }
165               else{
166                 $deny=TRUE;
167               }
168             }
169           }
170         }
171       }
173       // Now decide whether user has access
174       // (Note a denial takes precedence)
175       if ($deny) return FALSE;
176       if ($access) return TRUE;
177       return FALSE;
178     }
181     // If no phpgacl, then apply the old static rules whereby "authorized"
182     // users (providers) can do anything, and other users can do most things.
183     // If you want custom access control but don't want to mess with phpGACL,
184     // then you could customize the code below instead.
186     if ($user == 'admin') return 'write';
187     if ($section == 'admin' && $value == 'super') return 0;
188     if ($_SESSION['userauthorized']) return 'write';
190     if ($section == 'patients') {
191       if ($value == 'med') return 1;
192       return 'write';
193     }
194     else if ($section == 'encounters') {
195       if (strpos($value, 'coding' ) === 0) return 'write';
196       if (strpos($value, 'notes'  ) === 0) return 'write';
197       if ($value == 'relaxed') return 'write';
198     }
199     else if ($section != 'admin') {
200       return 'write';
201     }
203     return 0;
204   }
206   // Get the ACO name/value pairs for a designated section.  Each value
207   // is an array (section_value, value, order_value, name, hidden).
208   //
209   function acl_get_section_acos($section) {
210     global $phpgacl_location;
211     if ($phpgacl_location) {
212       include_once("$phpgacl_location/gacl_api.class.php");
213       $gacl = new gacl_api();
214       $arr1 = $gacl->get_objects($section, 1, 'ACO');
215       $arr = array();
216       if (!empty($arr1[$section])) {
217         foreach ($arr1[$section] as $value) {
218           $odata = $gacl->get_object_data($gacl->get_object_id($section, $value, 'ACO'), 'ACO');
219           $arr[$value] = $odata[0];
220         }
221       }
222       return $arr;
223     }
224     return 0;
225   }
227   // Sort squads by their order value.  Used only by acl_get_squads().
228   function _acl_squad_compare($a, $b) {
229     if ($a[2] == $b[2]) {
230       // If order value is the same, sort by squad name.
231       if ($a[3] == $b[3]) return 0;
232       return ($a[3] < $b[3]) ? -1 : 1;
233     }
234     return ($a[2] < $b[2]) ? -1 : 1;
235   }
237   // Return an array keyed on squad ACO names.
238   // This is only applicable for sports team use.
239   //
240   function acl_get_squads() {
241     $squads = acl_get_section_acos('squads');
242     uasort($squads, "_acl_squad_compare");
243     return $squads;
244   }
246   // Return an array keyed on encounter sensitivity level ACO names.
247   // Sensitivities are useful when some encounter notes are not
248   // medically sensitive (e.g. a physical fitness test), and/or if
249   // some will be "for doctor's eyes only" (e.g. STD treatment).
250   //
251   // When a non-blank sensitivity value exists in the new encounter
252   // form, it names an additional ACO required for access to all forms
253   // in the encounter.  If you want some encounters to be non-sensitive,
254   // then you also need some default nonblank sensitivity for normal
255   // encounters, as well as greater encounter notes permissions for
256   // those allowed to view non-sensitive encounters.
257   //
258   function acl_get_sensitivities() {
259     return acl_get_section_acos('sensitivities');
260   }
262   //
263   // Returns true if aco exist
264   // Returns false if aco doesn't exist
265   //    $section_name = name of section (string)
266   //    $aco_name = name of aco (string)
267   //
268   function aco_exist($section_name, $aco_name) {
269    global $phpgacl_location;
270    if (isset ($phpgacl_location)) {
271     include_once("$phpgacl_location/gacl_api.class.php");
272     $gacl = new gacl_api();
273     $aco_id = $gacl->get_object_id($section_name,  $aco_name, 'ACO');
274     if ($aco_id) {
275      return true;
276     }
277    }
278    return false;
279   }
281   //
282   // Returns a sorted array of all available Group Titles.
283   //
284   function acl_get_group_title_list() {
285     global $phpgacl_location;
286     if (isset ($phpgacl_location)) {
287       include_once("$phpgacl_location/gacl_api.class.php");
288       $gacl = new gacl_api();
289       $parent_id = $gacl->get_root_group_id();
290       $arr_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
291       $arr_group_titles = array();
292       foreach ($arr_group_ids as $value) {
293         $arr_group_data = $gacl->get_group_data($value, 'ARO');
294         $arr_group_titles[$value] = $arr_group_data[3];
295       }
296       sort($arr_group_titles);
297       return $arr_group_titles;
298     }
299     return 0;
300   }
302   //
303   // Returns a sorted array of group Titles that a user belongs to.
304   // Returns 0 if does not belong to any group yet.
305   //   $user_name = Username, which is login name.
306   //
307   function acl_get_group_titles($user_name) {
308     global $phpgacl_location, $section_aro_value;
309     if (isset ($phpgacl_location)) {
310       include_once("$phpgacl_location/gacl_api.class.php");
311       $gacl = new gacl_api();
312       $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
313       if ($user_aro_id) {
314         $arr_group_id = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
315         if ($arr_group_id) {
316           foreach ($arr_group_id as $key => $value) {
317             $arr_group_data = $gacl->get_group_data($value, 'ARO');
318             $arr_group_titles[$key] =  $arr_group_data[3];
319           }
320         sort($arr_group_titles);
321         return $arr_group_titles;
322         }
323       }
324     }
325     return 0;
326   }
328   //
329   // This will place the user aro object into selected group(s)
330   // It uses the set_user_aro() function
331   //   $username = username (string)
332   //   $group = title of group(s) (string or array)
333   //
334   function add_user_aros($username, $group) {
335    $current_user_groups = acl_get_group_titles($username);
336    if (!$current_user_groups) {
337     $current_user_groups = array();
338    }
339    if (is_array($group)){
340     foreach ($group as $value) {
341        if (!in_array($value, $current_user_groups)) { 
342         array_push($current_user_groups, $value);
343        }
344     }
345    }
346    else {
347     if (!in_array($group, $current_user_groups)) {
348      array_push($current_user_groups, $group);
349     }
350    }
351    $user_data = mysql_fetch_array(sqlStatement("select * from users where username='" .
352     $username . "'"));
353    set_user_aro($current_user_groups, $username, $user_data["fname"],
354     $user_data["mname"], $user_data["lname"]);
355    return;
356   }
358   //
359   // This will remove the user aro object from the selected group(s)
360   // It uses the set_user_aro() function
361   //   $username = username (string)
362   //   $group = title of group(s) (string or array)
363   //
364   function remove_user_aros($username, $group) {
365    $current_user_groups = acl_get_group_titles($username);
366    $new_user_groups = array();
367    if (is_array($group)){
368     foreach ($current_user_groups as $value) {
369      if (!in_array($value, $group)) {
370       array_push($new_user_groups, $value);
371      }
372     }
373    }
374    else {
375     foreach ($current_user_groups as $value) {
376      if ($value != $group) {
377       array_push($new_user_groups, $value);
378      }
379     }
380    }
381    $user_data = mysql_fetch_array(sqlStatement("select * from users where username='" .
382     $username . "'"));
383    set_user_aro($new_user_groups, $username, $user_data["fname"],
384     $user_data["mname"], $user_data["lname"]);
385    return;
386   }
388   //
389   // This will either create or edit a user aro object, and then place it
390   // in the requested groups. It will not allow removal of the 'admin'
391   // user or gacl_protected users from the 'admin' group.
392   //   $arr_group_titles = titles of the groups that user will be added to.
393   //   $user_name = username, which is login name.
394   //   $first_name = first name
395   //   $middle_name = middle name
396   //   $last_name = last name
397   //
398   function set_user_aro($arr_group_titles, $user_name, $first_name, $middle_name, $last_name) {
399     global $phpgacl_location, $section_aro_value;
401     if (isset ($phpgacl_location)) {
402       include_once("$phpgacl_location/gacl_api.class.php");
403       $gacl = new gacl_api();
405       //see if this user is gacl protected (ie. do not allow
406       //removal from the Administrators group)
407       require_once(dirname(__FILE__).'/user.inc');
408       require_once(dirname(__FILE__).'/calendar.inc');
409       $userNametoID = getIDfromUser($user_name);
410       if (checkUserSetting("gacl_protect","1",$userNametoID) || $user_name == "admin") {
411         $gacl_protect = true;
412       }
413       else {
414         $gacl_protect = false;
415       }
417       //get array of all available group ID numbers
418       $parent_id = $gacl->get_root_group_id();
419       $arr_all_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
421       //Cycle through ID array to find and process each selected group
422       //Create a counter since processing of first hit is unique
423       $counter = 0;
424       foreach ($arr_all_group_ids as $value) {
425         $arr_group_data = $gacl->get_group_data($value, 'ARO');
426         if ((empty($arr_group_titles)) ||
427          (in_array($arr_group_data[3], $arr_group_titles))) {
428           //We have a hit, so need to add group and increment counter
429           // because processing of first hit is unique
430           //This will also deal with an empty $arr_group_titles array
431           // removing user from all groups unless 'admin'
432           $counter = $counter + 1;
433           //create user full name field
434           if ($middle_name) {
435             $full_name = $first_name . " " . $middle_name . " " .  $last_name;
436           }
437           else {
438             if ($last_name) {
439               $full_name = $first_name . " " . $last_name;
440             }
441             else {
442               $full_name = $first_name;
443             }
444           }
446           //If this is not the first group to be added, then will skip below
447           // and will be added. If this is the first group, then need to
448           // go thru several steps before adding the group.
449           if ($counter == 1) {
450             //get ID of user ARO object, if it exist
451             $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
452             if ($user_aro_id) {
453               //user ARO object already exist, so will edit it
454               $gacl->edit_object($user_aro_id, $section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
456               //remove all current user ARO object group associations
457               $arr_remove_group_ids = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
458               foreach ($arr_remove_group_ids as $value2) {
459                 $gacl->del_group_object($value2, $section_aro_value, $user_name, 'ARO');
460               }
461             }
462             else {
463               //user ARO object does not exist, so will create it
464               $gacl->add_object($section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
465             }
466           }
468           //place the user ARO object in the selected group (if group(s) is selected)
469           if (!empty($arr_group_titles)) {
470             $gacl->add_group_object($value, $section_aro_value, $user_name, 'ARO');
471           }
473           //
474           //Below will not allow 'admin' or gacl_protected user to be removed from 'admin' group
475           //
476           if ($gacl_protect) {
477             $boolean_admin=0;
478             $admin_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
479             $arr_admin = $gacl->get_object_groups($admin_id, 'ARO', 'NO_RECURSE');
480             foreach ($arr_admin as $value3) {
481               $arr_admin_data = $gacl->get_group_data($value3, 'ARO');
482               if (strcmp($arr_admin_data[2], 'admin') == 0) {
483                 $boolean_admin=1;
484               }
485             }
486             if (!$boolean_admin) {
487               foreach ($arr_all_group_ids as $value4) {
488                 $arr_temp = $gacl->get_group_data($value4, 'ARO');
489                 if ($arr_temp[2] == 'admin') {
490                   $gacl->add_group_object($value4, $section_aro_value, $user_name, 'ARO');
491                 }
492               }
493             }
494           }
495         }
496         //if array of groups was empty, then we are done, and can break from loop
497         if (empty($arr_group_titles)) break;
498       }
499       return true;
500     }
501    return false;
502   }
504   //
505   // Returns true if acl exist
506   // Returns false if acl doesn't exist
507   //  EITHER $title or $name is required(send FALSE in variable
508   //  not being used). If both are sent, then only $title will be
509   //  used.
510   //  $return_value is required
511   //    $title = title of acl (string)
512   //    $name = name of acl (string)
513   //    $return_value = return value of acl (string)
514   //
515   function acl_exist($title, $name, $return_value) {
516    global $phpgacl_location;
517    if (isset ($phpgacl_location)) {
518     include_once("$phpgacl_location/gacl_api.class.php");
519     $gacl = new gacl_api();
520     if (!$name) {
521      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
522     }
523     else if (!$title) {
524      $group_id = $gacl->get_group_id($name, NULL, 'ARO');
525      if ($group_id) {
526       $group_data = $gacl->get_group_data($group_id, 'ARO');
527       $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $group_data[3], FALSE, FALSE, FALSE, $return_value);
528      }
529      else {
530      return false;
531      }
532     }
533     else {
534      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
535     }
536     if (!empty($acl)) {
537      return true;
538     }
539     else {
540      return false;
541     }
542    }
543   }
545   //
546   // This will add a new acl and group(if group doesn't yet exist)
547   // with one aco in it.
548   //   $acl_title = title of acl (string)
549   //   $acl_name = name of acl (string)
550   //   $return_value = return value of acl (string)
551   //   $note = description of acl (array)
552   //
553   function acl_add($acl_title, $acl_name, $return_value, $note) {
554    global $phpgacl_location;
555    if (isset ($phpgacl_location)) {
556     include_once("$phpgacl_location/gacl_api.class.php");
557     $gacl = new gacl_api();
558     $group_id = $gacl->get_group_id($acl_name, $acl_title, 'ARO');
559     if ($group_id) {
560      //group already exist, so just create acl
561      $gacl->add_acl(array("placeholder"=>array("filler")),
562       NULL, array($group_id), NULL, NULL, 1, 1, $return_value, $note);
563     }
564     else {
565      //create group, then create acl
566      $parent_id = $gacl->get_root_group_id();
567      $aro_id = $gacl->add_group($acl_name, $acl_title, $parent_id, 'ARO');
568      $gacl->add_acl(array("placeholder"=>array("filler")),
569       NULL, array($aro_id), NULL, NULL, 1, 1, $return_value, $note);
570     }
571     return;
572    }
573    return 0;
574   }
576   //
577   // This will remove acl. It will also remove group(if the group
578   // is no longer associated with any acl's).
579   //   $acl_title = title of acl (string)
580   //   $acl_name = name of acl (string)
581   //   $return_value = return value of acl (string)
582   //   $note = description of acl (array)
583   //
584   function acl_remove($acl_title, $return_value) {
585    global $phpgacl_location;
586    if (isset ($phpgacl_location)) {
587     include_once("$phpgacl_location/gacl_api.class.php");
588     $gacl = new gacl_api();
589     //First, delete the acl
590     $acl_id=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
591     $gacl->del_acl($acl_id[0]);
592     //Then, remove the group(if no more acl's are remaining)
593     $acl_search=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, FALSE);
594     if (empty($acl_search)){
595      $group_id=$gacl-> get_group_id(NULL, $acl_title, 'ARO');
596      $gacl->del_group($group_id, TRUE, 'ARO');
597     }
598     return;
599    }
600    return 0;
601   }
603   //
604   // This will place the aco(s) into the selected acl
605   //   $acl_title = title of acl (string)
606   //   $return_value = return value of acl (string)
607   //   $aco_id = id of aco (array)
608   //
609   function acl_add_acos($acl_title, $return_value, $aco_id) {
610    global $phpgacl_location;
611    if (isset ($phpgacl_location)) {
612     include_once("$phpgacl_location/gacl_api.class.php");
613     $gacl = new gacl_api();
614     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
615     foreach ($aco_id as $value) { 
616      $aco_data = $gacl->get_object_data($value, 'ACO');
617      $aco_section = $aco_data[0][0];
618      $aco_name = $aco_data[0][1];   
619      $gacl->append_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
620     }
621     return;
622    }
623    return 0;
624   }
626   //
627   // This will remove the aco(s) from the selected acl
628   //  Note if all aco's are removed, then will place the filler-placeholder
629   //  into the acl to avoid complete removal of the acl.
630   //   $acl_title = title of acl (string)
631   //   $return_value = return value of acl (string)
632   //   $aco_id = id of aco (array)
633   //
634   function acl_remove_acos($acl_title, $return_value, $aco_id) {
635    global $phpgacl_location;
636    if (isset ($phpgacl_location)) {
637     include_once("$phpgacl_location/gacl_api.class.php");
638     $gacl = new gacl_api();
639     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
641     // Check to see if removing all acos. If removing all acos then will
642     //  ensure the filler-placeholder aco in acl to avoid complete
643     //  removal of the acl.
644     if (count($aco_id) == acl_count_acos($acl_title, $return_value)) {
645      //1-get the filler-placeholder aco id
646      $filler_aco_id = $gacl->get_object_id('placeholder','filler','ACO');     
647      //2-add filler-placeholder aco
648      acl_add_acos($acl_title, $return_value, array($filler_aco_id));
649      //3-ensure filler-placeholder aco is not to be deleted
650      $safeListaco = remove_element($_POST["selection"],$filler_aco_id);
651      //4-prepare to safely delete the acos
652      $aco_id = $safeListaco;
653     }
655     foreach ($aco_id as $value) {
656      $aco_data = $gacl->get_object_data($value, 'ACO');
657      $aco_section = $aco_data[0][0];
658      $aco_name = $aco_data[0][1];
659      $gacl->shift_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
660      }
661     return;
662    }
663    return 0;
664   }
666   //
667   // This will return the number of aco objects
668   //  in a specified acl.
669   //   $acl_title = title of acl (string)
670   //   $return_value = return value of acl (string)
671   //
672   function acl_count_acos($acl_title, $return_value) {
673    global $phpgacl_location;
674    if (isset ($phpgacl_location)) {
675     include_once("$phpgacl_location/gacl_api.class.php");
676     $gacl = new gacl_api();
677     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
678     $acl_data = $gacl->get_acl($acl_id[0]);
679     $aco_count = 0;
680     foreach ($acl_data['aco'] as $key => $value) {
681      $aco_count = $aco_count + count($acl_data['aco'][$key]);
682     }
683     return $aco_count;
684    }
685    return 0;
686   }
688   //
689   // Function to remove an element from an array
690   //
691   function remove_element($arr, $val){
692    $arr2 = array();
693    foreach ($arr as $value){
694     if ($value != $val) {
695      array_push($arr2,$value);
696     }
697    }
698    return $arr2;
699   }