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