5 * Functions wrapping php-GACL's functionality, to create a generic OpenEMR access control system.
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 .
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
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
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":
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
67 // Section "acct" (Accounting):
68 // bill Billing (write optional)
69 // disc Allowed to discount prices (in Fee Sheet or Checkout form)
71 // rep Financial Reporting - my encounters
72 // rep_a Financial Reporting - anything
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)
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)
102 // Section "squads" applies to sports team use only:
103 // acos in this section define the user-specified list of squads
105 // Section "sensitivities" (Sensitivities):
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)
116 // Section "placeholder" (Placeholder):
117 // filler Placeholder (Maintains empty ACLs)
119 // Section "nationnotes" (Nation Notes):
120 // nn_configure Nation Notes
122 // Section "patientportal" (Patient Portal):
123 // portal Patient Portal
125 // Section "menus" (Menus):
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
166 function acl_check($section, $value, $user = '', $return_value = '')
169 $user = $_SESSION['authUser'];
172 // Superuser always gets access to everything.
173 if (($section != 'admin' || $value != 'super') && acl_check('admin', 'super', $user)) {
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
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
185 $access=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
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']) {
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']) {
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']) {
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']) {
232 // Now decide whether user has access
233 // (Note a denial takes precedence)
234 if (!$deny && $access) {
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') {
248 if ($section == 'admin' && $value == 'super') {
251 if ($_SESSION['userauthorized']) {
255 if ($section == 'patients') {
256 if ($value == 'med') {
260 } else if ($section == 'encounters') {
261 if (strpos($value, 'coding') === 0) {
264 if (strpos($value, 'notes') === 0) {
267 if ($value == 'relaxed') {
270 } else if ($section != 'admin') {
277 // Get the ACO name/value pairs for a designated section. Each value
278 // is an array (section_value, value, order_value, name, hidden).
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');
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];
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]) {
307 return ($a[3] < $b[3]) ? -1 : 1;
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.
315 function acl_get_squads()
317 $squads = acl_get_section_acos('squads');
318 uasort($squads, "_acl_squad_compare");
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).
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.
334 function acl_get_sensitivities()
336 return acl_get_section_acos('sensitivities');
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)
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');
360 // Returns a sorted array of all available Group Titles.
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];
378 sort($arr_group_titles);
379 return $arr_group_titles;
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.
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');
397 $arr_group_id = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
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];
403 sort($arr_group_titles);
404 return $arr_group_titles;
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)
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();
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);
430 if (!in_array($group, $current_user_groups)) {
431 array_push($current_user_groups, $group);
434 $user_data = sqlFetchArray(sqlStatement("SELECT * FROM users WHERE username = ?", array($username)));
436 $current_user_groups,
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)
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);
462 foreach ($current_user_groups as $value) {
463 if ($value != $group) {
464 array_push($new_user_groups, $value);
468 $user_data = sqlFetchArray(sqlStatement("SELECT * FROM users WHERE username = ?", array($username)));
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
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;
505 $gacl_protect = false;
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
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
526 $full_name = $first_name . " " . $middle_name . " " . $last_name;
529 $full_name = $first_name . " " . $last_name;
531 $full_name = $first_name;
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.
539 //get ID of user ARO object, if it exist
540 $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
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');
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');
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');
562 //Below will not allow 'admin' or gacl_protected user to be removed from 'admin' group
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) {
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');
584 //if array of groups was empty, then we are done, and can break from loop
585 if (empty($arr_group_titles)) {
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
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)
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();
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');
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);
622 $acl = $gacl->search_acl(false, false, false, false, $title, false, false, false, $return_value);
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)
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');
648 //group already exist, so just create acl
650 array("placeholder"=>array("filler")),
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');
665 array("placeholder"=>array("filler")),
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)
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');
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)
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)));
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)
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;
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)));
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)
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]);
789 foreach ($acl_data['aco'] as $key => $value) {
790 $aco_count = $aco_count + count($acl_data['aco'][$key]);
798 // Function to remove an element from an array
800 function remove_element($arr, $val)
803 foreach ($arr as $value) {
804 if ($value != $val) {
805 array_push($arr2, $value);
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
818 * @param String $user_id Auth user Id
819 * $param String $section_identifier ACL Section id
822 function zh_acl_check($user_id, $section_identifier)
824 $sql_user_acl = " SELECT
825 COUNT(allowed) AS count
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`
831 acl_sections.section_identifier = ? AND usr_settings.user_id = ? AND usr_settings.allowed = ?";
832 $sql_user_group = " SELECT
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
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 = "";
850 while ($row = sqlFetchArray($res_groups)) {
851 array_push($groups_sql_param, $row['group_id']);
853 $groupPlacemakers = "?";
856 $groupPlacemakers .= ",?";
859 $sql_group_acl_base = " SELECT
860 COUNT(allowed) AS count
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
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) {
884 } elseif ($count_group_allowed > 0) {
891 // This generates an HTML options list for all ACOs.
892 // The caller inserts this between <select> and </select> tags.
894 function gen_aco_html_options($default = '')
896 $acoArray = gen_aco_array();
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) {
905 $s .= ">" . xlt($aco_array['name']) . "</option>";
913 // Returns array of all ACOs
914 function gen_aco_array()
916 global $phpgacl_location;
917 require_once("$phpgacl_location/gacl_api.class.php");
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) {
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;
943 // Permissions check for an ACO in "section|aco" format.
944 // Note $return_value may be an array of return values.
946 function acl_check_aco_spec($aco_spec, $user = '', $return_value = '')
948 if (empty($aco_spec)) {
951 $tmp = explode('|', $aco_spec);
952 if (!is_array($return_value)) {
953 $return_value = array($return_value);
955 foreach ($return_value as $rv) {
956 if (acl_check($tmp[0], $tmp[1], $user, $rv)) {
963 // Permissions check for a specified encounter form type.
964 // Note $return_value may be an array of return values.
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.
976 function acl_check_issue($type, $user = '', $return_value = '')
978 require_once(dirname(__FILE__) . '/lists.inc');
980 if (empty($ISSUE_TYPES[$type][5])) {
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.
989 function acl_check_cat_name($catname, $user = '', $return_value = '')
992 "SELECT aco_spec FROM categories WHERE name = ? ORDER BY id LIMIT 1",
995 if (empty($tmp['aco_spec'])) {
998 return acl_check_aco_spec($tmp['aco_spec'], $user, $return_value);
1001 //Fetches aco for given postcalendar category
1002 function fetchPostCalendarCategoryACO($pc_catid)
1005 "SELECT aco_spec FROM openemr_postcalendar_categories WHERE pc_catid = ? LIMIT 1",
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;