Form-specific access control for standard encounter forms. (#565)
[openemr.git] / interface / main / tabs / menu / menu_updates.php
blob6ac3d8a37953c4b944238c8e39ffd2654b73c0cc
1 <?php
2 /**
3 * Copyright (C) 2016 Kevin Yeh <kevin.y@integralemr.com>
4 * Copyright (C) 2016 Brady Miller <brady.g.miller@gmail.com>
5 * Copyright (C) 2017 Rod Roark <rod@sunsetsystems.com>
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 <http://opensource.org/licenses/gpl-license.php>;.
18 * @package OpenEMR
19 * @author Kevin Yeh <kevin.y@integralemr.com>
20 * @author Brady Miller <brady.g.miller@gmail.com>
21 * @author Rod Roark <rod@sunsetsystems.com>
22 * @link http://www.open-emr.org
25 include_once("$srcdir/registry.inc");
27 $menu_update_map=array();
28 $menu_update_map["Visit Forms"]="update_visit_forms";
29 $menu_update_map["Modules"]="update_modules_menu";
30 $menu_update_map["Create Visit"] = "update_create_visit";
32 function update_modules_menu(&$menu_list)
34 $module_query = sqlStatement("select mod_directory,mod_name,mod_nick_name,mod_relative_link,type from modules where mod_active = 1 AND sql_run= 1 order by mod_ui_order asc");
35 if (sqlNumRows($module_query)) {
36 while ($modulerow = sqlFetchArray($module_query)) {
37 $acl_section = strtolower($modulerow['mod_directory']);
38 if (!zh_acl_check($_SESSION['authUserID'],$acl_section)) continue;
39 $modulePath = "";
40 $added = "";
41 if($modulerow['type'] == 0) {
42 $modulePath = $GLOBALS['customModDir'];
43 $added = "";
45 else{
46 $added = "index";
47 $modulePath = $GLOBALS['zendModDir'];
50 $relative_link ="/interface/modules/".$modulePath."/".$modulerow['mod_relative_link'].$added;
51 $mod_nick_name = $modulerow['mod_nick_name'] ? $modulerow['mod_nick_name'] : $modulerow['mod_name'];
52 $newEntry=new stdClass();
53 $newEntry->label=xlt($mod_nick_name);
54 $newEntry->url=$relative_link;
55 $newEntry->requirement=0;
56 $newEntry->target='mod';
57 array_push($menu_list->children,$newEntry);
62 // This creates menu entries for all encounter forms.
64 function update_visit_forms(&$menu_list) {
65 $baseURL = "/interface/patient_file/encounter/load_form.php?formname=";
66 $menu_list->children = array();
67 // LBF Visit forms
68 $lres = sqlStatement("SELECT * FROM list_options " .
69 "WHERE list_id = 'lbfnames' AND activity = 1 ORDER BY seq, title");
70 while ($lrow = sqlFetchArray($lres)) {
71 $option_id = $lrow['option_id']; // should start with LBF
72 $title = $lrow['title'];
73 $formURL = $baseURL . urlencode($option_id);
74 $formEntry = new stdClass();
75 $formEntry->label = xl_form_title($title);
76 $formEntry->url = $formURL;
77 $formEntry->requirement = 2;
78 $formEntry->target = 'enc';
79 // Plug in ACO attribute, if any, of this LBF.
80 $jobj = json_decode($lrow['notes'], true);
81 if (!empty($jobj['aco'])) {
82 $tmp = explode('|', $jobj['aco']);
83 if (!empty($tmp[1])) {
84 $formEntry->acl_req = array($tmp[0], $tmp[1], 'write', 'addonly');
87 array_push($menu_list->children, $formEntry);
89 // Traditional forms
90 $reg = getRegistered();
91 if (!empty($reg)) {
92 foreach ($reg as $entry) {
93 $option_id = $entry['directory'];
94 $title = trim($entry['nickname']);
95 if ($option_id == 'fee_sheet' ) continue;
96 if ($option_id == 'newpatient') continue;
97 if (empty($title)) $title = $entry['name'];
98 $formURL = $baseURL . urlencode($option_id);
99 $formEntry = new stdClass();
100 $formEntry->label = xl_form_title($title);
101 $formEntry->url = $formURL;
102 $formEntry->requirement = 2;
103 $formEntry->target = 'enc';
104 // Plug in ACO attribute, if any, of this form.
105 $tmp = explode('|', $entry['aco_spec']);
106 if (!empty($tmp[1])) {
107 $formEntry->acl_req = array($tmp[0], $tmp[1], 'write', 'addonly');
109 array_push($menu_list->children, $formEntry);
114 function update_create_visit(&$menu_list) {
115 $tmp = getRegistryEntryByDirectory('newpatient', 'aco_spec');
116 if (!empty($tmp['aco_spec'])) {
117 $tmp = explode('|', $tmp['aco_spec']);
118 $menu_list->acl_req = array($tmp[0], $tmp[1], 'write', 'addonly');
122 function menu_update_entries(&$menu_list)
124 global $menu_update_map;
125 for($idx=0;$idx<count($menu_list);$idx++)
128 $entry = $menu_list[$idx];
129 if(!isset($entry->url))
131 if(isset($menu_update_map[$entry->label]))
133 $menu_update_map[$entry->label]($entry);
136 // Translate the labels
137 $entry->label=xlt($entry->label);
138 // Recursive update of children
139 if(isset($entry->children))
141 menu_update_entries($entry->children);
146 // Permissions check for a particular acl_req array item.
147 // Elements beyond the 2nd are ACL return values, one of which should be permitted.
149 function menu_acl_check($arr) {
150 if (isset($arr[2])) {
151 for ($i = 2; isset($arr[$i]); ++$i) {
152 if (substr($arr[0], 0, 1) == '!') {
153 if (!acl_check(substr($arr[0], 1), $arr[1], '', $arr[$i])) return TRUE;
155 else {
156 if (acl_check($arr[0], $arr[1], '', $arr[$i])) return TRUE;
160 else {
161 if (substr($arr[0], 0, 1) == '!') {
162 if (!acl_check(substr($arr[0], 1), $arr[1])) return TRUE;
164 else {
165 if (acl_check($arr[0], $arr[1])) return TRUE;
168 return FALSE;
171 function menu_apply_restrictions(&$menu_list_src,&$menu_list_updated)
173 for ($idx=0; $idx<count($menu_list_src); $idx++)
175 $srcEntry = $menu_list_src[$idx];
176 $includeEntry = true;
178 // If the entry has an ACL Requirements(currently only support loose), then test
179 if (isset($srcEntry->acl_req))
181 if (is_array($srcEntry->acl_req[0]))
183 $noneSet = true;
184 for ($aclIdx=0; $aclIdx<count($srcEntry->acl_req); $aclIdx++)
186 if (menu_acl_check($srcEntry->acl_req[$aclIdx])) {
187 $noneSet = false;
190 if ($noneSet)
192 $includeEntry = false;
195 else
197 if (!menu_acl_check($srcEntry->acl_req))
199 $includeEntry = false;
204 // If the entry has loose global setting requirements, check
205 // Note that global_req is a loose check (if more than 1 global, only 1 needs to pass to show the menu item)
206 if (isset($srcEntry->global_req))
208 if (is_array($srcEntry->global_req))
210 $noneSet = true;
211 for ($globalIdx=0; $globalIdx<count($srcEntry->global_req); $globalIdx++)
213 $curSetting = $srcEntry->global_req[$globalIdx];
214 // ! at the start of the string means test the negation
215 if (substr($curSetting,0,1) === '!')
217 $curSetting = substr($curSetting,1);
218 // If the global isn't set at all, or if it is false, then show it
219 if (!isset($GLOBALS[$curSetting]) || !$GLOBALS[$curSetting])
221 $noneSet = false;
224 else
226 // If the setting is both set and true, then show it
227 if (isset($GLOBALS[$curSetting]) && $GLOBALS[$curSetting])
229 $noneSet = false;
234 if ($noneSet)
236 $includeEntry = false;
239 else
241 // ! at the start of the string means test the negation
242 if (substr($srcEntry->global_req,0,1) === '!')
244 $globalSetting=substr($srcEntry->global_req,1);
245 // If the setting is both set and true, then skip this entry
246 if (isset($GLOBALS[$globalSetting]) && $GLOBALS[$globalSetting])
248 $includeEntry = false;
251 else
253 // If the global isn't set at all, or if it is false then skip the entry
254 if (!isset($GLOBALS[$srcEntry->global_req]) || !$GLOBALS[$srcEntry->global_req])
256 $includeEntry = false;
262 // If the entry has strict global setting requirements, check
263 // Note that global_req_strict is a strict check (if more than 1 global, they all need to pass to show the menu item)
264 if (isset($srcEntry->global_req_strict))
266 if (is_array($srcEntry->global_req_strict))
268 $allSet = true;
269 for ($globalIdx=0; $globalIdx<count($srcEntry->global_req_strict); $globalIdx++)
271 $curSetting = $srcEntry->global_req_strict[$globalIdx];
272 // ! at the start of the string means test the negation
273 if (substr($curSetting,0,1) === '!')
275 $curSetting = substr($curSetting,1);
276 // If the setting is both set and true, then do not show it
277 if (isset($GLOBALS[$curSetting]) && $GLOBALS[$curSetting])
279 $allSet = false;
282 else
284 // If the global isn't set at all, or if it is false, then do not show it
285 if (!isset($GLOBALS[$curSetting]) || !$GLOBALS[$curSetting])
287 $allSet = false;
292 if (!$allSet)
294 $includeEntry = false;
297 else
299 // ! at the start of the string means test the negation
300 if (substr($srcEntry->global_req_strict,0,1) === '!')
302 $globalSetting=substr($srcEntry->global_req_strict,1);
303 // If the setting is both set and true, then skip this entry
304 if (isset($GLOBALS[$globalSetting]) && $GLOBALS[$globalSetting])
306 $includeEntry = false;
309 else
311 // If the global isn't set at all, or if it is false then skip the entry
312 if (!isset($GLOBALS[$srcEntry->global_req_strict]) || !$GLOBALS[$srcEntry->global_req_strict])
314 $includeEntry = false;
320 if(isset($srcEntry->children))
322 // Iterate through and check the child elements
323 $checked_children=array();
324 menu_apply_restrictions($srcEntry->children,$checked_children);
325 $srcEntry->children=$checked_children;
328 if(!isset($srcEntry->url))
330 // If this is a header only entry, and there are no child elements, then don't include it in the list.
331 if(count($srcEntry->children)===0)
333 $includeEntry=false;
336 if($includeEntry)
339 array_push($menu_list_updated,$srcEntry);