Fully responsive globals.php with vertical menu (#2460)
[openemr.git] / library / acl.inc
blobf2c97d0ae5dcf63c7cf0494563e40f25e4735614
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.g.miller@gmail.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   //   multipledb  Multipledb
65   //   menu        Menu
66   //
67   // Section "acct" (Accounting):
68   //   bill        Billing (write optional)
69   //   disc        Allowed to discount prices (in Fee Sheet or Checkout form)
70   //   eob         EOB Data Entry
71   //   rep         Financial Reporting - my encounters
72   //   rep_a       Financial Reporting - anything
73   //
74   // Section "patients" (Patient Information):
75   //   appt        Appointments (write,wsome optional)
76   //   demo        Demographics (write,addonly optional)
77   //   med         Medical Records and History (write,addonly optional)
78   //   trans       Transactions, e.g. referrals (write optional)
79   //   docs        Documents (write,addonly optional)
80   //   docs_rm     Documents Delete
81   //   pat_rep     Patient Report
82   //   notes       Patient Notes (write,addonly optional)
83   //   sign        Sign Lab Results (write,addonly optional)
84   //   reminder    Patient Reminders (write,addonly optional)
85   //   alert       Clinical Reminders/Alerts (write,addonly optional)
86   //   disclosure  Disclosures (write,addonly optional)
87   //   rx          Prescriptions (write,addonly optional)
88   //   amendment   Amendments (write,addonly optional)
89   //   lab         Lab Results (write,addonly optional)
90   //
91   // Section "encounters" (Encounter Information):
92   //   auth        Authorize - my encounters
93   //   auth_a      Authorize - any encounters
94   //   coding      Coding - my encounters (write,wsome optional)
95   //   coding_a    Coding - any encounters (write,wsome optional)
96   //   notes       Notes - my encounters (write,addonly optional)
97   //   notes_a     Notes - any encounters (write,addonly optional)
98   //   date_a      Fix encounter dates - any encounters
99   //   relaxed     Less-private information (write,addonly optional)
100   //               (e.g. the Sports Fitness encounter form)
101   //
102   // Section "squads" applies to sports team use only:
103   //   acos in this section define the user-specified list of squads
104   //
105   // Section "sensitivities" (Sensitivities):
106   //   normal     Normal
107   //   high       High
108   //
109   // Section "lists" (Lists):
110   //   default    Default List (write,addonly optional)
111   //   state      State List (write,addonly optional)
112   //   country    Country List (write,addonly optional)
113   //   language   Language List (write,addonly optional)
114   //   ethrace    Ethnicity-Race List (write,addonly optional)
115   //
116   // Section "placeholder" (Placeholder):
117   //   filler     Placeholder (Maintains empty ACLs)
118   //
119   // Section "nationnotes" (Nation Notes):
120   //   nn_configure     Nation Notes
121   //
122   // Section "patientportal" (Patient Portal):
123   //   portal     Patient Portal
124   //
125   // Section "menus" (Menus):
126   //   modle      Module
127   //
128   // Section "groups" (Groups):
129   //   gadd       View/Add/Update groups
130   //   gcalendar  View/Create/Update groups appointment in calendar
131   //   glog       Group encounter log
132   //   gdlog      Group detailed log of appointment in patient record
133   //   gm         Send message from the permanent group therapist to the personal therapist
135 if (isset($phpgacl_location)) {
136     $GLOBALS['phpgacl_location_global'] = $phpgacl_location;
137     require_once("$phpgacl_location/gacl.class.php");
138     $gacl_object = new gacl();
139     //DO NOT CHANGE BELOW VARIABLE
140     $section_aro_value = 'users';
141     $GLOBALS['section_aro_value_global'] = $section_aro_value;
145  * Check if a user has a given type or types of access to an access control object.
147  * Globals that can use are:
148  *  $GLOBALS['phpgacl_location_global']
149  *  $GLOBALS['section_aro_value_global']
151  * This function will check for access to the given ACO.
152  * view    - The user may view but not add or modify entries
153  * write   - The user may add or modify the ACO
154  * wsome   - The user has limited add/modify access to the ACO
155  * addonly - The user may view and add but not modify entries
157  * @param string       $section      Category of ACO
158  * @param string       $value        Subcategory of ACO
159  * @param string       $user         Optional user being checked for access.
160  * @param string|array $return_value Type or types of access being requested.
161  * @return bool|array  FALSE if access is denied, TRUE if allowed. An
162  *                     array() of bools is returned if $return_value is an
163  *             array, representing results for each type of access
164  *             requested.
165  */
166 function acl_check($section, $value, $user = '', $return_value = '')
168     if (! $user) {
169         $user = $_SESSION['authUser'];
170     }
172     // Superuser always gets access to everything.
173     if (($section != 'admin' || $value != 'super') && acl_check('admin', 'super', $user)) {
174         return true;
175     }
177     if ($GLOBALS['phpgacl_location_global']) {
178       // This will return all pertinent ACL's (including return_values and whether allow/deny)
179       // Walk through them to assess for access
180         global $gacl_object;
181         $acl_results = $gacl_object->acl_query($section, $value, $GLOBALS['section_aro_value_global'], $user, null, null, null, null, null, true);
182         if (empty($acl_results)) {
183             return false; //deny access
184         }
185         $access=false; //flag
186         $deny=false; //flag
187         foreach ($acl_results as $acl_result) {
188             if (empty($acl_result['acl_id'])) {
189                 return false; //deny access, since this happens if no pertinent ACL's are returned
190             }
191             if (is_array($return_value)) {
192                 foreach ($return_value as $single_return_value) {
193                     if (empty($single_return_value)) {
194                         // deal with case if not looking for specific return value
195                         if ($acl_result['allow']) {
196                             $access=true;
197                         } else {
198                             $deny=true;
199                         }
200                     } else { //!empty($single_return_value)
201                         // deal with case if looking for specific return value
202                         if ($acl_result['return_value'] == $single_return_value) {
203                             if ($acl_result['allow']) {
204                                 $access=true;
205                             } else {
206                                 $deny=true;
207                             }
208                         }
209                     }
210                 }
211             } else { // $return_value is not an array (either empty or with one value)
212                 if (empty($return_value)) {
213                     // deal with case if not looking for specific return value
214                     if ($acl_result['allow']) {
215                         $access=true;
216                     } else {
217                         $deny=true;
218                     }
219                 } else { //!empty($return_value)
220                     // deal with case if looking for specific return value
221                     if ($acl_result['return_value'] == $return_value) {
222                         if ($acl_result['allow']) {
223                             $access=true;
224                         } else {
225                             $deny=true;
226                         }
227                     }
228                 }
229             }
230         }
232       // Now decide whether user has access
233       // (Note a denial takes precedence)
234         if (!$deny && $access) {
235             return true;
236         }
237         return false;
238     }
240     // If no phpgacl, then apply the old static rules whereby "authorized"
241     // users (providers) can do anything, and other users can do most things.
242     // If you want custom access control but don't want to mess with phpGACL,
243     // then you could customize the code below instead.
245     if ($user == 'admin') {
246         return 'write';
247     }
248     if ($section == 'admin' && $value == 'super') {
249         return 0;
250     }
251     if ($_SESSION['userauthorized']) {
252         return 'write';
253     }
255     if ($section == 'patients') {
256         if ($value == 'med') {
257             return 1;
258         }
259         return 'write';
260     } else if ($section == 'encounters') {
261         if (strpos($value, 'coding') === 0) {
262             return 'write';
263         }
264         if (strpos($value, 'notes') === 0) {
265             return 'write';
266         }
267         if ($value == 'relaxed') {
268             return 'write';
269         }
270     } else if ($section != 'admin') {
271         return 'write';
272     }
274     return 0;
277   // Get the ACO name/value pairs for a designated section.  Each value
278   // is an array (section_value, value, order_value, name, hidden).
279   //
280 function acl_get_section_acos($section)
282     global $phpgacl_location;
283     if ($phpgacl_location) {
284         include_once("$phpgacl_location/gacl_api.class.php");
285         $gacl = new gacl_api();
286         $arr1 = $gacl->get_objects($section, 1, 'ACO');
287         $arr = array();
288         if (!empty($arr1[$section])) {
289             foreach ($arr1[$section] as $value) {
290                 $odata = $gacl->get_object_data($gacl->get_object_id($section, $value, 'ACO'), 'ACO');
291                 $arr[$value] = $odata[0];
292             }
293         }
294         return $arr;
295     }
296     return 0;
299   // Sort squads by their order value.  Used only by acl_get_squads().
300 function _acl_squad_compare($a, $b)
302     if ($a[2] == $b[2]) {
303       // If order value is the same, sort by squad name.
304         if ($a[3] == $b[3]) {
305             return 0;
306         }
307         return ($a[3] < $b[3]) ? -1 : 1;
308     }
309     return ($a[2] < $b[2]) ? -1 : 1;
312   // Return an array keyed on squad ACO names.
313   // This is only applicable for sports team use.
314   //
315 function acl_get_squads()
317     $squads = acl_get_section_acos('squads');
318     uasort($squads, "_acl_squad_compare");
319     return $squads;
322   // Return an array keyed on encounter sensitivity level ACO names.
323   // Sensitivities are useful when some encounter notes are not
324   // medically sensitive (e.g. a physical fitness test), and/or if
325   // some will be "for doctor's eyes only" (e.g. STD treatment).
326   //
327   // When a non-blank sensitivity value exists in the new encounter
328   // form, it names an additional ACO required for access to all forms
329   // in the encounter.  If you want some encounters to be non-sensitive,
330   // then you also need some default nonblank sensitivity for normal
331   // encounters, as well as greater encounter notes permissions for
332   // those allowed to view non-sensitive encounters.
333   //
334 function acl_get_sensitivities()
336     return acl_get_section_acos('sensitivities');
339   //
340   // Returns true if aco exist
341   // Returns false if aco doesn't exist
342   //    $section_name = name of section (string)
343   //    $aco_name = name of aco (string)
344   //
345 function aco_exist($section_name, $aco_name)
347     global $phpgacl_location;
348     if (isset($phpgacl_location)) {
349         include_once("$phpgacl_location/gacl_api.class.php");
350         $gacl = new gacl_api();
351         $aco_id = $gacl->get_object_id($section_name, $aco_name, 'ACO');
352         if ($aco_id) {
353             return true;
354         }
355     }
356     return false;
359   //
360   // Returns a sorted array of all available Group Titles.
361   //
362 function acl_get_group_title_list($include_superusers = true)
364     global $phpgacl_location;
365     if (isset($phpgacl_location)) {
366         include_once("$phpgacl_location/gacl_api.class.php");
367         $gacl = new gacl_api();
368         $parent_id = $gacl->get_root_group_id();
369         $arr_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
370         $arr_group_titles = array();
371         foreach ($arr_group_ids as $value) {
372             $arr_group_data = $gacl->get_group_data($value, 'ARO');
373             // add if $include_superusers is true or group not include admin|super rule.
374             if ($include_superusers || !is_group_include_superuser($arr_group_data[3])) {
375                 $arr_group_titles[$value] = $arr_group_data[3];
376             }
377         }
378         sort($arr_group_titles);
379         return $arr_group_titles;
380     }
381     return 0;
384   //
385   // Returns a sorted array of group Titles that a user belongs to.
386   // Returns 0 if does not belong to any group yet.
387   //   $user_name = Username, which is login name.
388   //
389 function acl_get_group_titles($user_name)
391     global $phpgacl_location, $section_aro_value;
392     if (isset($phpgacl_location)) {
393         include_once("$phpgacl_location/gacl_api.class.php");
394         $gacl = new gacl_api();
395         $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
396         if ($user_aro_id) {
397             $arr_group_id = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
398             if ($arr_group_id) {
399                 foreach ($arr_group_id as $key => $value) {
400                     $arr_group_data = $gacl->get_group_data($value, 'ARO');
401                     $arr_group_titles[$key] =  $arr_group_data[3];
402                 }
403                 sort($arr_group_titles);
404                 return $arr_group_titles;
405             }
406         }
407     }
408     return 0;
411   //
412   // This will place the user aro object into selected group(s)
413   // It uses the set_user_aro() function
414   //   $username = username (string)
415   //   $group = title of group(s) (string or array)
416   //
417 function add_user_aros($username, $group)
419     $current_user_groups = acl_get_group_titles($username);
420     if (!$current_user_groups) {
421         $current_user_groups = array();
422     }
423     if (is_array($group)) {
424         foreach ($group as $value) {
425             if (!in_array($value, $current_user_groups)) {
426                 array_push($current_user_groups, $value);
427             }
428         }
429     } else {
430         if (!in_array($group, $current_user_groups)) {
431             array_push($current_user_groups, $group);
432         }
433     }
434     $user_data = sqlFetchArray(sqlStatement("SELECT * FROM users WHERE username = ?", array($username)));
435     set_user_aro(
436         $current_user_groups,
437         $username,
438         $user_data["fname"],
439         $user_data["mname"],
440         $user_data["lname"]
441     );
442     return;
445   //
446   // This will remove the user aro object from the selected group(s)
447   // It uses the set_user_aro() function
448   //   $username = username (string)
449   //   $group = title of group(s) (string or array)
450   //
451 function remove_user_aros($username, $group)
453     $current_user_groups = acl_get_group_titles($username);
454     $new_user_groups = array();
455     if (is_array($group)) {
456         foreach ($current_user_groups as $value) {
457             if (!in_array($value, $group)) {
458                 array_push($new_user_groups, $value);
459             }
460         }
461     } else {
462         foreach ($current_user_groups as $value) {
463             if ($value != $group) {
464                 array_push($new_user_groups, $value);
465             }
466         }
467     }
468     $user_data = sqlFetchArray(sqlStatement("SELECT * FROM users WHERE username = ?", array($username)));
469     set_user_aro(
470         $new_user_groups,
471         $username,
472         $user_data["fname"],
473         $user_data["mname"],
474         $user_data["lname"]
475     );
476     return;
479   //
480   // This will either create or edit a user aro object, and then place it
481   // in the requested groups. It will not allow removal of the 'admin'
482   // user or gacl_protected users from the 'admin' group.
483   //   $arr_group_titles = titles of the groups that user will be added to.
484   //   $user_name = username, which is login name.
485   //   $first_name = first name
486   //   $middle_name = middle name
487   //   $last_name = last name
488   //
489 function set_user_aro($arr_group_titles, $user_name, $first_name, $middle_name, $last_name)
491     global $phpgacl_location, $section_aro_value;
493     if (isset($phpgacl_location)) {
494         include_once("$phpgacl_location/gacl_api.class.php");
495         $gacl = new gacl_api();
497       //see if this user is gacl protected (ie. do not allow
498       //removal from the Administrators group)
499         require_once(dirname(__FILE__).'/user.inc');
500         require_once(dirname(__FILE__).'/calendar.inc');
501         $userNametoID = getIDfromUser($user_name);
502         if (checkUserSetting("gacl_protect", "1", $userNametoID) || $user_name == "admin") {
503             $gacl_protect = true;
504         } else {
505             $gacl_protect = false;
506         }
508       //get array of all available group ID numbers
509         $parent_id = $gacl->get_root_group_id();
510         $arr_all_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
512       //Cycle through ID array to find and process each selected group
513       //Create a counter since processing of first hit is unique
514         $counter = 0;
515         foreach ($arr_all_group_ids as $value) {
516             $arr_group_data = $gacl->get_group_data($value, 'ARO');
517             if ((empty($arr_group_titles)) ||
518             (in_array($arr_group_data[3], $arr_group_titles))) {
519                 //We have a hit, so need to add group and increment counter
520                 // because processing of first hit is unique
521             //This will also deal with an empty $arr_group_titles array
522             // removing user from all groups unless 'admin'
523                 $counter = $counter + 1;
524                 //create user full name field
525                 if ($middle_name) {
526                       $full_name = $first_name . " " . $middle_name . " " .  $last_name;
527                 } else {
528                     if ($last_name) {
529                               $full_name = $first_name . " " . $last_name;
530                     } else {
531                           $full_name = $first_name;
532                     }
533                 }
535                 //If this is not the first group to be added, then will skip below
536                 // and will be added. If this is the first group, then need to
537                 // go thru several steps before adding the group.
538                 if ($counter == 1) {
539                       //get ID of user ARO object, if it exist
540                       $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
541                     if ($user_aro_id) {
542                         //user ARO object already exist, so will edit it
543                         $gacl->edit_object($user_aro_id, $section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
545                         //remove all current user ARO object group associations
546                         $arr_remove_group_ids = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
547                         foreach ($arr_remove_group_ids as $value2) {
548                             $gacl->del_group_object($value2, $section_aro_value, $user_name, 'ARO');
549                         }
550                     } else {
551                         //user ARO object does not exist, so will create it
552                         $gacl->add_object($section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
553                     }
554                 }
556                 //place the user ARO object in the selected group (if group(s) is selected)
557                 if (!empty($arr_group_titles)) {
558                           $gacl->add_group_object($value, $section_aro_value, $user_name, 'ARO');
559                 }
561               //
562               //Below will not allow 'admin' or gacl_protected user to be removed from 'admin' group
563               //
564                 if ($gacl_protect) {
565                     $boolean_admin=0;
566                     $admin_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
567                     $arr_admin = $gacl->get_object_groups($admin_id, 'ARO', 'NO_RECURSE');
568                     foreach ($arr_admin as $value3) {
569                         $arr_admin_data = $gacl->get_group_data($value3, 'ARO');
570                         if (strcmp($arr_admin_data[2], 'admin') == 0) {
571                             $boolean_admin=1;
572                         }
573                     }
574                     if (!$boolean_admin) {
575                         foreach ($arr_all_group_ids as $value4) {
576                             $arr_temp = $gacl->get_group_data($value4, 'ARO');
577                             if ($arr_temp[2] == 'admin') {
578                                 $gacl->add_group_object($value4, $section_aro_value, $user_name, 'ARO');
579                             }
580                         }
581                     }
582                 }
583             }
584         //if array of groups was empty, then we are done, and can break from loop
585             if (empty($arr_group_titles)) {
586                 break;
587             }
588         }
589         return true;
590     }
591     return false;
594   //
595   // Returns true if acl exist
596   // Returns false if acl doesn't exist
597   //  EITHER $title or $name is required(send FALSE in variable
598   //  not being used). If both are sent, then only $title will be
599   //  used.
600   //  $return_value is required
601   //    $title = title of acl (string)
602   //    $name = name of acl (string)
603   //    $return_value = return value of acl (string)
604   //
605 function acl_exist($title, $name, $return_value)
607     global $phpgacl_location;
608     if (isset($phpgacl_location)) {
609         include_once("$phpgacl_location/gacl_api.class.php");
610         $gacl = new gacl_api();
611         if (!$name) {
612             $acl = $gacl->search_acl(false, false, false, false, $title, false, false, false, $return_value);
613         } else if (!$title) {
614             $group_id = $gacl->get_group_id($name, null, 'ARO');
615             if ($group_id) {
616                 $group_data = $gacl->get_group_data($group_id, 'ARO');
617                 $acl = $gacl->search_acl(false, false, false, false, $group_data[3], false, false, false, $return_value);
618             } else {
619                 return false;
620             }
621         } else {
622             $acl = $gacl->search_acl(false, false, false, false, $title, false, false, false, $return_value);
623         }
624         if (!empty($acl)) {
625             return true;
626         } else {
627             return false;
628         }
629     }
632   //
633   // This will add a new acl and group(if group doesn't yet exist)
634   // with one aco in it.
635   //   $acl_title = title of acl (string)
636   //   $acl_name = name of acl (string)
637   //   $return_value = return value of acl (string)
638   //   $note = description of acl (array)
639   //
640 function acl_add($acl_title, $acl_name, $return_value, $note)
642     global $phpgacl_location;
643     if (isset($phpgacl_location)) {
644         include_once("$phpgacl_location/gacl_api.class.php");
645         $gacl = new gacl_api();
646         $group_id = $gacl->get_group_id($acl_name, $acl_title, 'ARO');
647         if ($group_id) {
648             //group already exist, so just create acl
649             $gacl->add_acl(
650                 array("placeholder"=>array("filler")),
651                 null,
652                 array($group_id),
653                 null,
654                 null,
655                 1,
656                 1,
657                 $return_value,
658                 $note
659             );
660         } else {
661             //create group, then create acl
662             $parent_id = $gacl->get_root_group_id();
663             $aro_id = $gacl->add_group($acl_name, $acl_title, $parent_id, 'ARO');
664             $gacl->add_acl(
665                 array("placeholder"=>array("filler")),
666                 null,
667                 array($aro_id),
668                 null,
669                 null,
670                 1,
671                 1,
672                 $return_value,
673                 $note
674             );
675         }
676         return;
677     }
678     return 0;
681   //
682   // This will remove acl. It will also remove group(if the group
683   // is no longer associated with any acl's).
684   //   $acl_title = title of acl (string)
685   //   $acl_name = name of acl (string)
686   //   $return_value = return value of acl (string)
687   //   $note = description of acl (array)
688   //
689 function acl_remove($acl_title, $return_value)
691     global $phpgacl_location;
692     if (isset($phpgacl_location)) {
693         include_once("$phpgacl_location/gacl_api.class.php");
694         $gacl = new gacl_api();
695       //First, delete the acl
696         $acl_id=$gacl->search_acl(false, false, false, false, $acl_title, false, false, false, $return_value);
697         $gacl->del_acl($acl_id[0]);
698       //Then, remove the group(if no more acl's are remaining)
699         $acl_search=$gacl->search_acl(false, false, false, false, $acl_title, false, false, false, false);
700         if (empty($acl_search)) {
701             $group_id=$gacl-> get_group_id(null, $acl_title, 'ARO');
702             $gacl->del_group($group_id, true, 'ARO');
703         }
704         return;
705     }
706     return 0;
709   //
710   // This will place the aco(s) into the selected acl
711   //   $acl_title = title of acl (string)
712   //   $return_value = return value of acl (string)
713   //   $aco_id = id of aco (array)
714   //
715 function acl_add_acos($acl_title, $return_value, $aco_id)
717     global $phpgacl_location;
718     if (isset($phpgacl_location)) {
719         include_once("$phpgacl_location/gacl_api.class.php");
720         $gacl = new gacl_api();
721         $acl_id = $gacl->search_acl(false, false, false, false, $acl_title, false, false, false, $return_value);
722         foreach ($aco_id as $value) {
723             $aco_data = $gacl->get_object_data($value, 'ACO');
724             $aco_section = $aco_data[0][0];
725             $aco_name = $aco_data[0][1];
726             $gacl->append_acl($acl_id[0], null, null, null, null, array($aco_section=>array($aco_name)));
727         }
728         return;
729     }
730     return 0;
733   //
734   // This will remove the aco(s) from the selected acl
735   //  Note if all aco's are removed, then will place the filler-placeholder
736   //  into the acl to avoid complete removal of the acl.
737   //   $acl_title = title of acl (string)
738   //   $return_value = return value of acl (string)
739   //   $aco_id = id of aco (array)
740   //
741 function acl_remove_acos($acl_title, $return_value, $aco_id)
743     global $phpgacl_location;
744     if (isset($phpgacl_location)) {
745         include_once("$phpgacl_location/gacl_api.class.php");
746         $gacl = new gacl_api();
747         $acl_id = $gacl->search_acl(false, false, false, false, $acl_title, false, false, false, $return_value);
749       // Check to see if removing all acos. If removing all acos then will
750       //  ensure the filler-placeholder aco in acl to avoid complete
751       //  removal of the acl.
752         if (count($aco_id) == acl_count_acos($acl_title, $return_value)) {
753             //1-get the filler-placeholder aco id
754             $filler_aco_id = $gacl->get_object_id('placeholder', 'filler', 'ACO');
755             //2-add filler-placeholder aco
756             acl_add_acos($acl_title, $return_value, array($filler_aco_id));
757             //3-ensure filler-placeholder aco is not to be deleted
758             $safeListaco = remove_element($_POST["selection"], $filler_aco_id);
759             //4-prepare to safely delete the acos
760             $aco_id = $safeListaco;
761         }
763         foreach ($aco_id as $value) {
764             $aco_data = $gacl->get_object_data($value, 'ACO');
765             $aco_section = $aco_data[0][0];
766             $aco_name = $aco_data[0][1];
767             $gacl->shift_acl($acl_id[0], null, null, null, null, array($aco_section=>array($aco_name)));
768         }
769         return;
770     }
771     return 0;
774   //
775   // This will return the number of aco objects
776   //  in a specified acl.
777   //   $acl_title = title of acl (string)
778   //   $return_value = return value of acl (string)
779   //
780 function acl_count_acos($acl_title, $return_value)
782     global $phpgacl_location;
783     if (isset($phpgacl_location)) {
784         include_once("$phpgacl_location/gacl_api.class.php");
785         $gacl = new gacl_api();
786         $acl_id = $gacl->search_acl(false, false, false, false, $acl_title, false, false, false, $return_value);
787         $acl_data = $gacl->get_acl($acl_id[0]);
788         $aco_count = 0;
789         foreach ($acl_data['aco'] as $key => $value) {
790             $aco_count = $aco_count + count($acl_data['aco'][$key]);
791         }
792         return $aco_count;
793     }
794     return 0;
797   //
798   // Function to remove an element from an array
799   //
800 function remove_element($arr, $val)
802     $arr2 = array();
803     foreach ($arr as $value) {
804         if ($value != $val) {
805             array_push($arr2, $value);
806         }
807     }
808     return $arr2;
810   /**
811   * Checks ACL
812   *
813   * Same Functionality in the Zend Module
814   * for ACL Check in Zend
815   * Path openemr/interface/modules/zend_modules/module/Application/src/Application/Model/ApplicationTable
816   * Function Name zAclCheck
817   *
818   * @param String $user_id Auth user Id
819   * $param String $section_identifier ACL Section id
820   * @return boolean
821   */
822 function zh_acl_check($user_id, $section_identifier)
824     $sql_user_acl = " SELECT
825                         COUNT(allowed) AS count
826                       FROM
827                         module_acl_user_settings AS usr_settings
828                         LEFT JOIN module_acl_sections AS acl_sections
829                             ON usr_settings.section_id = acl_sections.`section_id`
830                       WHERE
831                           acl_sections.section_identifier = ? AND usr_settings.user_id = ? AND usr_settings.allowed = ?";
832     $sql_user_group = " SELECT
833                           gagp.id AS group_id
834                         FROM
835                           gacl_aro AS garo
836                           LEFT JOIN `gacl_groups_aro_map` AS gamp
837                             ON garo.id = gamp.aro_id
838                           LEFT JOIN `gacl_aro_groups` AS gagp
839                             ON gagp.id = gamp.group_id
840                           RIGHT JOIN `users_secure` usr
841                             ON usr. username =  garo.value
842                         WHERE
843                           garo.section_value = ? AND usr. id = ?";
844     $res_groups     = sqlStatement($sql_user_group, array('users',$user_id));
846     // Prepare the group queries with the placemakers and binding array for the IN part
847     $groups_sql_param = array();
848     $groupPlacemakers = "";
849     $firstFlag = true;
850     while ($row = sqlFetchArray($res_groups)) {
851         array_push($groups_sql_param, $row['group_id']);
852         if ($firstFlag) {
853             $groupPlacemakers = "?";
854             $firstFlag = false;
855         } else {
856             $groupPlacemakers .= ",?";
857         }
858     }
859     $sql_group_acl_base  = " SELECT
860                         COUNT(allowed) AS count
861                       FROM
862                         module_acl_group_settings AS group_settings
863                         LEFT JOIN module_acl_sections AS  acl_sections
864                           ON group_settings.section_id = acl_sections.section_id
865                       WHERE
866                         group_settings.group_id IN (".$groupPlacemakers.") AND acl_sections.`section_identifier` = ? ";
868     $sql_group_acl_allowed = $sql_group_acl_base . " AND group_settings.allowed = '1'";
870     // Complete the group queries sql binding array
871     array_push($groups_sql_param, $section_identifier);
873     $count_group_allowed    = 0;
874     $count_user_allowed     = 0;
876     $res_user_allowed       = sqlQuery($sql_user_acl, array($section_identifier,$user_id,1));
877     $count_user_allowed     = $res_user_allowed['count'];
879     $res_group_allowed      = sqlQuery($sql_group_acl_allowed, $groups_sql_param);
880     $count_group_allowed    = $res_group_allowed['count'];
882     if ($count_user_allowed > 0) {
883         return true;
884     } elseif ($count_group_allowed > 0) {
885         return true;
886     } else {
887         return false;
888     }
891   // This generates an HTML options list for all ACOs.
892   // The caller inserts this between <select> and </select> tags.
893   //
894 function gen_aco_html_options($default = '')
896     $acoArray = gen_aco_array();
897     $s = '';
898     foreach ($acoArray as $section => $acos_array) {
899         $s .= "<optgroup label='" . xla($section) . "'>\n";
900         foreach ($acos_array as $aco_array) {
901             $s .= "<option value='" . attr($aco_array['value']) . "'";
902             if ($aco_array['value'] == $default) {
903                 $s .= ' selected';
904             }
905             $s .= ">" . xlt($aco_array['name']) . "</option>";
906         }
907         $s .= "</optgroup>";
908     }
909     return $s;
913   // Returns array of all ACOs
914 function gen_aco_array()
916     global $phpgacl_location;
917     require_once("$phpgacl_location/gacl_api.class.php");
918     $acoArray = array();
919     $gacl = new gacl_api();
920     // collect and sort all aco objects
921     $list_aco_objects = $gacl->get_objects(null, 0, 'ACO');
922     ksort($list_aco_objects);
923     foreach ($list_aco_objects as $seckey => $dummy) {
924         if (empty($dummy)) {
925             continue;
926         }
927         asort($list_aco_objects[$seckey]);
928         $aco_section_data = $gacl->get_section_data($seckey, 'ACO');
929         $aco_section_title = $aco_section_data[3];
930         foreach ($list_aco_objects[$seckey] as $acokey) {
931             $aco_id = $gacl->get_object_id($seckey, $acokey, 'ACO');
932             $aco_data = $gacl->get_object_data($aco_id, 'ACO');
933             $aco_title = $aco_data[0][3];
934             $optkey = "$seckey|$acokey";
935             $acoArray[$aco_section_title][$aco_id]['name'] = $aco_title;
936             $acoArray[$aco_section_title][$aco_id]['value'] = $optkey;
937         }
938     }
939     return $acoArray;
943   // Permissions check for an ACO in "section|aco" format.
944   // Note $return_value may be an array of return values.
945   //
946 function acl_check_aco_spec($aco_spec, $user = '', $return_value = '')
948     if (empty($aco_spec)) {
949         return true;
950     }
951     $tmp = explode('|', $aco_spec);
952     if (!is_array($return_value)) {
953         $return_value = array($return_value);
954     }
955     foreach ($return_value as $rv) {
956         if (acl_check($tmp[0], $tmp[1], $user, $rv)) {
957             return true;
958         }
959     }
960     return false;
963   // Permissions check for a specified encounter form type.
964   // Note $return_value may be an array of return values.
965   //
966 function acl_check_form($formdir, $user = '', $return_value = '')
968     require_once(dirname(__FILE__) . '/registry.inc');
969     $tmp = getRegistryEntryByDirectory($formdir, 'aco_spec');
970     return acl_check_aco_spec($tmp['aco_spec'], $user, $return_value);
973   // Permissions check for a specified issue type.
974   // Note $return_value may be an array of return values.
975   //
976 function acl_check_issue($type, $user = '', $return_value = '')
978     require_once(dirname(__FILE__) . '/lists.inc');
979     global $ISSUE_TYPES;
980     if (empty($ISSUE_TYPES[$type][5])) {
981         return true;
982     }
983     return acl_check_aco_spec($ISSUE_TYPES[$type][5], $user, $return_value);
986   // Permissions check for a specified document category name.
987   // Note $return_value may be an array of return values.
988   //
989 function acl_check_cat_name($catname, $user = '', $return_value = '')
991     $tmp = sqlQuery(
992         "SELECT aco_spec FROM categories WHERE name = ? ORDER BY id LIMIT 1",
993         array($catname)
994     );
995     if (empty($tmp['aco_spec'])) {
996         return true;
997     }
998     return acl_check_aco_spec($tmp['aco_spec'], $user, $return_value);
1001   //Fetches aco for given postcalendar category
1002 function fetchPostCalendarCategoryACO($pc_catid)
1004     $aco = sqlQuery(
1005         "SELECT aco_spec FROM openemr_postcalendar_categories WHERE pc_catid = ? LIMIT 1",
1006         array($pc_catid)
1007     );
1008     return $aco['aco_spec'];
1011 // check if aro group have superuser rule
1012 function is_group_include_superuser($aro_group_name)
1014     global $phpgacl_location;
1015     include_once("$phpgacl_location/gacl_api.class.php");
1016     $gacl = new gacl_api();
1017     return empty($gacl->search_acl('admin', 'super', false, false, $aro_group_name)) ? false : true;