incremented database counter for prior feature
[openemr.git] / library / acl.inc
blob6b586c2946e0e95bc8d970d5d5c5b380d46c356a
1 <?php
2 /**
3  * library/acl.inc 
4  * 
5  * Functions wrapping php-GACL's functionality, to create a generic OpenEMR access control system.
6  *
7  * LICENSE: This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  * This program 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
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see 
17  * http://www.gnu.org/licenses/licenses.html#GPL .
18  *
19  * @package OpenEMR
20  * @license http://www.gnu.org/licenses/licenses.html#GPL GNU GPL V3+
21  * @author  Brady Miller <brady@sparmy.com>
22  * @author  Rod Roark <rod@sunsetsystems.com>
23  * @link    http://www.open-emr.org
24  */
26 // php-GACL access controls are included in OpenEMR. The below
27 // function will automatically create the path where gacl.class.php
28 // can be found. Note that this path can be manually set below
29 // for users who are using an external version of php-GACL.
30 // Also note that php-GACL access controls can be turned off
31 // below.
33   $phpgacl_location = dirname(__FILE__).'/../gacl';
35 // If using an external version of phpGACL, then uncomment the following
36 // line and manually place the path below.  IN THIS CASE YOU MUST ALSO
37 // COMMENT OUT ABOVE $phpgacl_location ASSIGNMENT ABOVE, OR BACKUPS WILL
38 // NOT RESTORE PROPERLY!
40 //$phpgacl_location = "/var/www/gacl";
42 // If you want to turn off php-GACL, then uncomment the following line.
43 // IN THIS CASE YOU MUST ALSO COMMENT OUT ABOVE $phpgacl_location ASSIGNMENT(S)
44 // ABOVE, OR BACKUPS WILL NOT RESTORE PROPERLY!
46 //unset($phpgacl_location);
49   // The following Access Control Objects (ACO) are currently supported.
50   // These are the "things to be protected":
51   //
52   // Section "admin" (Administration):
53   //   super       Superuser - can delete patients, encounters, issues
54   //   calendar    Calendar Settings
55   //   database    Database Reporting
56   //   forms       Forms Administration
57   //   practice    Practice Settings
58   //   superbill   Superbill Codes Administration
59   //   users       Users/Groups/Logs Administration
60   //   batchcom    Batch Communication Tool
61   //   language    Language Interface Tool
62   //   drugs       Pharmacy Dispensary
63   //   acl         ACL Administration
64   //
65   // Section "acct" (Accounting):
66   //   bill        Billing (write optional)
67   //   disc        Allowed to discount prices (in Fee Sheet or Checkout form)
68   //   eob         EOB Data Entry
69   //   rep         Financial Reporting - my encounters
70   //   rep_a       Financial Reporting - anything
71   //
72   // Section "patients" (Patient Information):
73   //   appt        Appointments (write,wsome optional)
74   //   demo        Demographics (write,addonly optional)
75   //   med         Medical Records and History (write,addonly optional)
76   //   trans       Transactions, e.g. referrals (write optional)
77   //   docs        Documents (write,addonly optional)
78   //   notes       Patient Notes (write,addonly optional)
79   //   sign        Sign Lab Results (write,addonly optional)
80   //
81   // Section "encounters" (Encounter Information):
82   //   auth        Authorize - my encounters
83   //   auth_a      Authorize - any encounters
84   //   coding      Coding - my encounters (write,wsome optional)
85   //   coding_a    Coding - any encounters (write,wsome optional)
86   //   notes       Notes - my encounters (write,addonly optional)
87   //   notes_a     Notes - any encounters (write,addonly optional)
88   //   date_a      Fix encounter dates - any encounters
89   //   relaxed     Less-private information (write,addonly optional)
90   //               (e.g. the Sports Fitness encounter form)
91   //
92   // Section "squads" applies to sports team use only:
93   //   acos in this section define the user-specified list of squads
94   //
95   // Section "sensitivities" (Sensitivities):
96   //   normal     Normal
97   //   high       High
98   //
99   // Section "lists" (Lists):
100   //   default    Default List (write,addonly optional)
101   //   state      State List (write,addonly optional)
102   //   country    Country List (write,addonly optional)
103   //   language   Language List (write,addonly optional)
104   //   ethrace    Ethnicity-Race List (write,addonly optional)
105   //
106   // Section "placeholder" (Placeholder):
107   //   filler     Placeholder (Maintains empty ACLs)
108   //
109   // Section "nationnotes" (Nation Notes):
110   //   nn_configure     Nation Notes
111   //
112   // Section "patientportal" (Patient Portal):
113   //   portal     Patient Portal
114   // Section "menus" (Menus):
115   //   modle      Module
116   
117   if (isset ($phpgacl_location)) {
118     $GLOBALS['phpgacl_location_global'] = $phpgacl_location;
119     require_once("$phpgacl_location/gacl.class.php");
120     $gacl_object = new gacl();
121     //DO NOT CHANGE BELOW VARIABLE
122     $section_aro_value = 'users';
123     $GLOBALS['section_aro_value_global'] = $section_aro_value;
124   }
127  * Check if a user has a given type or types of access to an access control object.
129  * Globals that can use are:
130  *  $GLOBALS['phpgacl_location_global']
131  *  $GLOBALS['section_aro_value_global']
132  * 
133  * This function will check for access to the given ACO.
134  * view    - The user may view but not add or modify entries
135  * write   - The user may add or modify the ACO
136  * wsome   - The user has limited add/modify access to the ACO
137  * addonly - The user may view and add but not modify entries
139  * @param string       $section      Category of ACO
140  * @param string       $value        Subcategory of ACO
141  * @param string       $user         Optional user being checked for access.
142  * @param string|array $return_value Type or types of access being requested.
143  * @return bool|array  FALSE if access is denied, TRUE if allowed. An
144  *                     array() of bools is returned if $return_value is an
145  *                     array, representing results for each type of access
146  *                     requested.
147  */
148   function acl_check($section, $value, $user = '', $return_value = '') {
149     if (! $user) $user = $_SESSION['authUser'];
151     if ($GLOBALS['phpgacl_location_global']) {
152       // This will return all pertinent ACL's (including return_values and whether allow/deny)
153       // Walk through them to assess for access
154       $gacl_object = new gacl();
155       $acl_results = $gacl_object->acl_query($section, $value, $GLOBALS['section_aro_value_global'], $user,NULL,NULL,NULL,NULL,NULL,TRUE);
156       if (empty($acl_results)) {
157         return FALSE; //deny access
158       }
159       $access=FALSE; //flag
160       $deny=FALSE; //flag
161       foreach ($acl_results as $acl_result) {
162         if (empty($acl_result['acl_id'])) return FALSE; //deny access, since this happens if no pertinent ACL's are returned
163         if (is_array($return_value)) {
164           foreach ($return_value as $single_return_value) {
165             if (empty($single_return_value)) {
166               // deal with case if not looking for specific return value
167               if ($acl_result['allow']) {
168                 $access=TRUE;
169               }
170               else {
171                 $deny=TRUE;
172               }
173             }
174             else { //!empty($single_return_value)
175               // deal with case if looking for specific return value
176               if ($acl_result['return_value'] == $single_return_value) {
177                 if ($acl_result['allow']) {
178                   $access=TRUE;
179                 }
180                 else{
181                   $deny=TRUE;
182                 }
183               }
184             }
185           }
186         }
187         else { // $return_value is not an array (either empty or with one value)
188           if (empty($return_value)) {
189             // deal with case if not looking for specific return value
190             if ($acl_result['allow']) {
191               $access=TRUE;
192             }
193             else {
194               $deny=TRUE;
195             }
196           }
197           else { //!empty($return_value)
198             // deal with case if looking for specific return value
199             if ($acl_result['return_value'] == $return_value) {
200               if ($acl_result['allow']) {
201                 $access=TRUE;
202               }
203               else{
204                 $deny=TRUE;
205               }
206             }
207           }
208         }
209       }
211       // Now decide whether user has access
212       // (Note a denial takes precedence)
213       if ($deny) return FALSE;
214       if ($access) return TRUE;
215       return FALSE;
216     }
219     // If no phpgacl, then apply the old static rules whereby "authorized"
220     // users (providers) can do anything, and other users can do most things.
221     // If you want custom access control but don't want to mess with phpGACL,
222     // then you could customize the code below instead.
224     if ($user == 'admin') return 'write';
225     if ($section == 'admin' && $value == 'super') return 0;
226     if ($_SESSION['userauthorized']) return 'write';
228     if ($section == 'patients') {
229       if ($value == 'med') return 1;
230       return 'write';
231     }
232     else if ($section == 'encounters') {
233       if (strpos($value, 'coding' ) === 0) return 'write';
234       if (strpos($value, 'notes'  ) === 0) return 'write';
235       if ($value == 'relaxed') return 'write';
236     }
237     else if ($section != 'admin') {
238       return 'write';
239     }
241     return 0;
242   }
244   // Get the ACO name/value pairs for a designated section.  Each value
245   // is an array (section_value, value, order_value, name, hidden).
246   //
247   function acl_get_section_acos($section) {
248     global $phpgacl_location;
249     if ($phpgacl_location) {
250       include_once("$phpgacl_location/gacl_api.class.php");
251       $gacl = new gacl_api();
252       $arr1 = $gacl->get_objects($section, 1, 'ACO');
253       $arr = array();
254       if (!empty($arr1[$section])) {
255         foreach ($arr1[$section] as $value) {
256           $odata = $gacl->get_object_data($gacl->get_object_id($section, $value, 'ACO'), 'ACO');
257           $arr[$value] = $odata[0];
258         }
259       }
260       return $arr;
261     }
262     return 0;
263   }
265   // Sort squads by their order value.  Used only by acl_get_squads().
266   function _acl_squad_compare($a, $b) {
267     if ($a[2] == $b[2]) {
268       // If order value is the same, sort by squad name.
269       if ($a[3] == $b[3]) return 0;
270       return ($a[3] < $b[3]) ? -1 : 1;
271     }
272     return ($a[2] < $b[2]) ? -1 : 1;
273   }
275   // Return an array keyed on squad ACO names.
276   // This is only applicable for sports team use.
277   //
278   function acl_get_squads() {
279     $squads = acl_get_section_acos('squads');
280     uasort($squads, "_acl_squad_compare");
281     return $squads;
282   }
284   // Return an array keyed on encounter sensitivity level ACO names.
285   // Sensitivities are useful when some encounter notes are not
286   // medically sensitive (e.g. a physical fitness test), and/or if
287   // some will be "for doctor's eyes only" (e.g. STD treatment).
288   //
289   // When a non-blank sensitivity value exists in the new encounter
290   // form, it names an additional ACO required for access to all forms
291   // in the encounter.  If you want some encounters to be non-sensitive,
292   // then you also need some default nonblank sensitivity for normal
293   // encounters, as well as greater encounter notes permissions for
294   // those allowed to view non-sensitive encounters.
295   //
296   function acl_get_sensitivities() {
297     return acl_get_section_acos('sensitivities');
298   }
300   //
301   // Returns true if aco exist
302   // Returns false if aco doesn't exist
303   //    $section_name = name of section (string)
304   //    $aco_name = name of aco (string)
305   //
306   function aco_exist($section_name, $aco_name) {
307    global $phpgacl_location;
308    if (isset ($phpgacl_location)) {
309     include_once("$phpgacl_location/gacl_api.class.php");
310     $gacl = new gacl_api();
311     $aco_id = $gacl->get_object_id($section_name,  $aco_name, 'ACO');
312     if ($aco_id) {
313      return true;
314     }
315    }
316    return false;
317   }
319   //
320   // Returns a sorted array of all available Group Titles.
321   //
322   function acl_get_group_title_list() {
323     global $phpgacl_location;
324     if (isset ($phpgacl_location)) {
325       include_once("$phpgacl_location/gacl_api.class.php");
326       $gacl = new gacl_api();
327       $parent_id = $gacl->get_root_group_id();
328       $arr_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
329       $arr_group_titles = array();
330       foreach ($arr_group_ids as $value) {
331         $arr_group_data = $gacl->get_group_data($value, 'ARO');
332         $arr_group_titles[$value] = $arr_group_data[3];
333       }
334       sort($arr_group_titles);
335       return $arr_group_titles;
336     }
337     return 0;
338   }
340   //
341   // Returns a sorted array of group Titles that a user belongs to.
342   // Returns 0 if does not belong to any group yet.
343   //   $user_name = Username, which is login name.
344   //
345   function acl_get_group_titles($user_name) {
346     global $phpgacl_location, $section_aro_value;
347     if (isset ($phpgacl_location)) {
348       include_once("$phpgacl_location/gacl_api.class.php");
349       $gacl = new gacl_api();
350       $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
351       if ($user_aro_id) {
352         $arr_group_id = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
353         if ($arr_group_id) {
354           foreach ($arr_group_id as $key => $value) {
355             $arr_group_data = $gacl->get_group_data($value, 'ARO');
356             $arr_group_titles[$key] =  $arr_group_data[3];
357           }
358         sort($arr_group_titles);
359         return $arr_group_titles;
360         }
361       }
362     }
363     return 0;
364   }
366   //
367   // This will place the user aro object into selected group(s)
368   // It uses the set_user_aro() function
369   //   $username = username (string)
370   //   $group = title of group(s) (string or array)
371   //
372   function add_user_aros($username, $group) {
373    $current_user_groups = acl_get_group_titles($username);
374    if (!$current_user_groups) {
375     $current_user_groups = array();
376    }
377    if (is_array($group)){
378     foreach ($group as $value) {
379        if (!in_array($value, $current_user_groups)) { 
380         array_push($current_user_groups, $value);
381        }
382     }
383    }
384    else {
385     if (!in_array($group, $current_user_groups)) {
386      array_push($current_user_groups, $group);
387     }
388    }
389    $user_data = sqlFetchArray(sqlStatement("select * from users where username='" .
390     $username . "'"));
391    set_user_aro($current_user_groups, $username, $user_data["fname"],
392     $user_data["mname"], $user_data["lname"]);
393    return;
394   }
396   //
397   // This will remove the user aro object from the selected group(s)
398   // It uses the set_user_aro() function
399   //   $username = username (string)
400   //   $group = title of group(s) (string or array)
401   //
402   function remove_user_aros($username, $group) {
403    $current_user_groups = acl_get_group_titles($username);
404    $new_user_groups = array();
405    if (is_array($group)){
406     foreach ($current_user_groups as $value) {
407      if (!in_array($value, $group)) {
408       array_push($new_user_groups, $value);
409      }
410     }
411    }
412    else {
413     foreach ($current_user_groups as $value) {
414      if ($value != $group) {
415       array_push($new_user_groups, $value);
416      }
417     }
418    }
419    $user_data = sqlFetchArray(sqlStatement("select * from users where username='" .
420     $username . "'"));
421    set_user_aro($new_user_groups, $username, $user_data["fname"],
422     $user_data["mname"], $user_data["lname"]);
423    return;
424   }
426   //
427   // This will either create or edit a user aro object, and then place it
428   // in the requested groups. It will not allow removal of the 'admin'
429   // user or gacl_protected users from the 'admin' group.
430   //   $arr_group_titles = titles of the groups that user will be added to.
431   //   $user_name = username, which is login name.
432   //   $first_name = first name
433   //   $middle_name = middle name
434   //   $last_name = last name
435   //
436   function set_user_aro($arr_group_titles, $user_name, $first_name, $middle_name, $last_name) {
437     global $phpgacl_location, $section_aro_value;
439     if (isset ($phpgacl_location)) {
440       include_once("$phpgacl_location/gacl_api.class.php");
441       $gacl = new gacl_api();
443       //see if this user is gacl protected (ie. do not allow
444       //removal from the Administrators group)
445       require_once(dirname(__FILE__).'/user.inc');
446       require_once(dirname(__FILE__).'/calendar.inc');
447       $userNametoID = getIDfromUser($user_name);
448       if (checkUserSetting("gacl_protect","1",$userNametoID) || $user_name == "admin") {
449         $gacl_protect = true;
450       }
451       else {
452         $gacl_protect = false;
453       }
455       //get array of all available group ID numbers
456       $parent_id = $gacl->get_root_group_id();
457       $arr_all_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
459       //Cycle through ID array to find and process each selected group
460       //Create a counter since processing of first hit is unique
461       $counter = 0;
462       foreach ($arr_all_group_ids as $value) {
463         $arr_group_data = $gacl->get_group_data($value, 'ARO');
464         if ((empty($arr_group_titles)) ||
465          (in_array($arr_group_data[3], $arr_group_titles))) {
466           //We have a hit, so need to add group and increment counter
467           // because processing of first hit is unique
468           //This will also deal with an empty $arr_group_titles array
469           // removing user from all groups unless 'admin'
470           $counter = $counter + 1;
471           //create user full name field
472           if ($middle_name) {
473             $full_name = $first_name . " " . $middle_name . " " .  $last_name;
474           }
475           else {
476             if ($last_name) {
477               $full_name = $first_name . " " . $last_name;
478             }
479             else {
480               $full_name = $first_name;
481             }
482           }
484           //If this is not the first group to be added, then will skip below
485           // and will be added. If this is the first group, then need to
486           // go thru several steps before adding the group.
487           if ($counter == 1) {
488             //get ID of user ARO object, if it exist
489             $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
490             if ($user_aro_id) {
491               //user ARO object already exist, so will edit it
492               $gacl->edit_object($user_aro_id, $section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
494               //remove all current user ARO object group associations
495               $arr_remove_group_ids = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
496               foreach ($arr_remove_group_ids as $value2) {
497                 $gacl->del_group_object($value2, $section_aro_value, $user_name, 'ARO');
498               }
499             }
500             else {
501               //user ARO object does not exist, so will create it
502               $gacl->add_object($section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
503             }
504           }
506           //place the user ARO object in the selected group (if group(s) is selected)
507           if (!empty($arr_group_titles)) {
508             $gacl->add_group_object($value, $section_aro_value, $user_name, 'ARO');
509           }
511           //
512           //Below will not allow 'admin' or gacl_protected user to be removed from 'admin' group
513           //
514           if ($gacl_protect) {
515             $boolean_admin=0;
516             $admin_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
517             $arr_admin = $gacl->get_object_groups($admin_id, 'ARO', 'NO_RECURSE');
518             foreach ($arr_admin as $value3) {
519               $arr_admin_data = $gacl->get_group_data($value3, 'ARO');
520               if (strcmp($arr_admin_data[2], 'admin') == 0) {
521                 $boolean_admin=1;
522               }
523             }
524             if (!$boolean_admin) {
525               foreach ($arr_all_group_ids as $value4) {
526                 $arr_temp = $gacl->get_group_data($value4, 'ARO');
527                 if ($arr_temp[2] == 'admin') {
528                   $gacl->add_group_object($value4, $section_aro_value, $user_name, 'ARO');
529                 }
530               }
531             }
532           }
533         }
534         //if array of groups was empty, then we are done, and can break from loop
535         if (empty($arr_group_titles)) break;
536       }
537       return true;
538     }
539    return false;
540   }
542   //
543   // Returns true if acl exist
544   // Returns false if acl doesn't exist
545   //  EITHER $title or $name is required(send FALSE in variable
546   //  not being used). If both are sent, then only $title will be
547   //  used.
548   //  $return_value is required
549   //    $title = title of acl (string)
550   //    $name = name of acl (string)
551   //    $return_value = return value of acl (string)
552   //
553   function acl_exist($title, $name, $return_value) {
554    global $phpgacl_location;
555    if (isset ($phpgacl_location)) {
556     include_once("$phpgacl_location/gacl_api.class.php");
557     $gacl = new gacl_api();
558     if (!$name) {
559      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
560     }
561     else if (!$title) {
562      $group_id = $gacl->get_group_id($name, NULL, 'ARO');
563      if ($group_id) {
564       $group_data = $gacl->get_group_data($group_id, 'ARO');
565       $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $group_data[3], FALSE, FALSE, FALSE, $return_value);
566      }
567      else {
568      return false;
569      }
570     }
571     else {
572      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
573     }
574     if (!empty($acl)) {
575      return true;
576     }
577     else {
578      return false;
579     }
580    }
581   }
583   //
584   // This will add a new acl and group(if group doesn't yet exist)
585   // with one aco in it.
586   //   $acl_title = title of acl (string)
587   //   $acl_name = name of acl (string)
588   //   $return_value = return value of acl (string)
589   //   $note = description of acl (array)
590   //
591   function acl_add($acl_title, $acl_name, $return_value, $note) {
592    global $phpgacl_location;
593    if (isset ($phpgacl_location)) {
594     include_once("$phpgacl_location/gacl_api.class.php");
595     $gacl = new gacl_api();
596     $group_id = $gacl->get_group_id($acl_name, $acl_title, 'ARO');
597     if ($group_id) {
598      //group already exist, so just create acl
599      $gacl->add_acl(array("placeholder"=>array("filler")),
600       NULL, array($group_id), NULL, NULL, 1, 1, $return_value, $note);
601     }
602     else {
603      //create group, then create acl
604      $parent_id = $gacl->get_root_group_id();
605      $aro_id = $gacl->add_group($acl_name, $acl_title, $parent_id, 'ARO');
606      $gacl->add_acl(array("placeholder"=>array("filler")),
607       NULL, array($aro_id), NULL, NULL, 1, 1, $return_value, $note);
608     }
609     return;
610    }
611    return 0;
612   }
614   //
615   // This will remove acl. It will also remove group(if the group
616   // is no longer associated with any acl's).
617   //   $acl_title = title of acl (string)
618   //   $acl_name = name of acl (string)
619   //   $return_value = return value of acl (string)
620   //   $note = description of acl (array)
621   //
622   function acl_remove($acl_title, $return_value) {
623    global $phpgacl_location;
624    if (isset ($phpgacl_location)) {
625     include_once("$phpgacl_location/gacl_api.class.php");
626     $gacl = new gacl_api();
627     //First, delete the acl
628     $acl_id=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
629     $gacl->del_acl($acl_id[0]);
630     //Then, remove the group(if no more acl's are remaining)
631     $acl_search=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, FALSE);
632     if (empty($acl_search)){
633      $group_id=$gacl-> get_group_id(NULL, $acl_title, 'ARO');
634      $gacl->del_group($group_id, TRUE, 'ARO');
635     }
636     return;
637    }
638    return 0;
639   }
641   //
642   // This will place the aco(s) into the selected acl
643   //   $acl_title = title of acl (string)
644   //   $return_value = return value of acl (string)
645   //   $aco_id = id of aco (array)
646   //
647   function acl_add_acos($acl_title, $return_value, $aco_id) {
648    global $phpgacl_location;
649    if (isset ($phpgacl_location)) {
650     include_once("$phpgacl_location/gacl_api.class.php");
651     $gacl = new gacl_api();
652     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
653     foreach ($aco_id as $value) { 
654      $aco_data = $gacl->get_object_data($value, 'ACO');
655      $aco_section = $aco_data[0][0];
656      $aco_name = $aco_data[0][1];   
657      $gacl->append_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
658     }
659     return;
660    }
661    return 0;
662   }
664   //
665   // This will remove the aco(s) from the selected acl
666   //  Note if all aco's are removed, then will place the filler-placeholder
667   //  into the acl to avoid complete removal of the acl.
668   //   $acl_title = title of acl (string)
669   //   $return_value = return value of acl (string)
670   //   $aco_id = id of aco (array)
671   //
672   function acl_remove_acos($acl_title, $return_value, $aco_id) {
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);
679     // Check to see if removing all acos. If removing all acos then will
680     //  ensure the filler-placeholder aco in acl to avoid complete
681     //  removal of the acl.
682     if (count($aco_id) == acl_count_acos($acl_title, $return_value)) {
683      //1-get the filler-placeholder aco id
684      $filler_aco_id = $gacl->get_object_id('placeholder','filler','ACO');     
685      //2-add filler-placeholder aco
686      acl_add_acos($acl_title, $return_value, array($filler_aco_id));
687      //3-ensure filler-placeholder aco is not to be deleted
688      $safeListaco = remove_element($_POST["selection"],$filler_aco_id);
689      //4-prepare to safely delete the acos
690      $aco_id = $safeListaco;
691     }
693     foreach ($aco_id as $value) {
694      $aco_data = $gacl->get_object_data($value, 'ACO');
695      $aco_section = $aco_data[0][0];
696      $aco_name = $aco_data[0][1];
697      $gacl->shift_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
698      }
699     return;
700    }
701    return 0;
702   }
704   //
705   // This will return the number of aco objects
706   //  in a specified acl.
707   //   $acl_title = title of acl (string)
708   //   $return_value = return value of acl (string)
709   //
710   function acl_count_acos($acl_title, $return_value) {
711    global $phpgacl_location;
712    if (isset ($phpgacl_location)) {
713     include_once("$phpgacl_location/gacl_api.class.php");
714     $gacl = new gacl_api();
715     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
716     $acl_data = $gacl->get_acl($acl_id[0]);
717     $aco_count = 0;
718     foreach ($acl_data['aco'] as $key => $value) {
719      $aco_count = $aco_count + count($acl_data['aco'][$key]);
720     }
721     return $aco_count;
722    }
723    return 0;
724   }
726   //
727   // Function to remove an element from an array
728   //
729   function remove_element($arr, $val){
730    $arr2 = array();
731    foreach ($arr as $value){
732     if ($value != $val) {
733      array_push($arr2,$value);
734     }
735    }
736    return $arr2;
737   }
738   /**
739   * Checks ACL
740   * 
741   * Same Functionality in the Zend Module
742   * for ACL Check in Zend
743   * Path openemr/interface/modules/zend_modules/module/Application/src/Application/Model/ApplicationTable
744   * Function Name zAclCheck
745   * 
746   * @param String $user_id Auth user Id
747   * $param String $section_identifier ACL Section id
748   * @return boolean
749   */
750   function zh_acl_check($user_id,$section_identifier){
751     $sql_user_acl = " SELECT 
752                         COUNT(allowed) AS count 
753                       FROM
754                         module_acl_user_settings AS usr_settings 
755                         LEFT JOIN module_acl_sections AS acl_sections 
756                             ON usr_settings.section_id = acl_sections.`section_id` 
757                       WHERE 
758                           acl_sections.section_identifier = ? AND usr_settings.user_id = ? AND usr_settings.allowed = ?";
759     $sql_user_group = " SELECT 
760                           gagp.id AS group_id
761                         FROM
762                           gacl_aro AS garo 
763                           LEFT JOIN `gacl_groups_aro_map` AS gamp 
764                             ON garo.id = gamp.aro_id 
765                           LEFT JOIN `gacl_aro_groups` AS gagp
766                             ON gagp.id = gamp.group_id
767                           RIGHT JOIN `users_secure` usr 
768                             ON usr. username =  garo.value
769                         WHERE
770                           garo.section_value = ? AND usr. id = ?";    
771     $res_groups     = sqlStatement($sql_user_group,array('users',$user_id));
773     // Prepare the group queries with the placemakers and binding array for the IN part
774     $groups_sql_param = array();
775     $groupPlacemakers = "";
776     $firstFlag = TRUE;
777     while($row = sqlFetchArray($res_groups)){
778       array_push($groups_sql_param,$row['group_id']);
779       if ($firstFlag) {
780         $groupPlacemakers = "?";
781         $firstFlag = FALSE;
782       }
783       else {
784         $groupPlacemakers .= ",?";
785       }
786     }
787     $sql_group_acl_base  = " SELECT 
788                         COUNT(allowed) AS count 
789                       FROM
790                         module_acl_group_settings AS group_settings 
791                         LEFT JOIN module_acl_sections AS  acl_sections
792                           ON group_settings.section_id = acl_sections.section_id
793                       WHERE
794                         group_settings.group_id IN (".$groupPlacemakers.") AND acl_sections.`section_identifier` = ? ";
795     $sql_group_acl_denied  = $sql_group_acl_base . " AND group_settings.allowed = '0'";
796     $sql_group_acl_allowed = $sql_group_acl_base . " AND group_settings.allowed = '1'";
798     // Complete the group queries sql binding array
799     array_push($groups_sql_param, $section_identifier);
800                                 
801         $count_user_denied      = 0;
802         $count_user_allowed     = 0;
803         $count_group_denied     = 0;
804         $count_group_allowed    = 0;
806         $res_user_denied        = sqlQuery($sql_user_acl,array($section_identifier,$user_id,0));
807         $count_user_denied      = $res_user_denied['count'];
808         
809         $res_user_allowed       = sqlQuery($sql_user_acl,array($section_identifier,$user_id,1));
810         $count_user_allowed     = $res_user_allowed['count'];
812         $res_group_denied       = sqlQuery($sql_group_acl_denied, $groups_sql_param);
813         $count_group_denied     = $res_group_denied['count'];
815         $res_group_allowed      = sqlQuery($sql_group_acl_allowed, $groups_sql_param);
816         $count_group_allowed    = $res_group_allowed['count'];
818         if($count_user_denied > 0)
819             return false;
820         elseif($count_user_allowed > 0)
821             return true;
822         elseif($count_group_denied > 0)
823             return false;
824         elseif($count_group_allowed > 0)
825             return true;
826         else
827             return false;
828     }