fix: Update patient_tracker.php (#6595)
[openemr.git] / library / ajax / graphs.php
blob61ff32208acdcfec7403e1e2a7f00eb8359308e3
1 <?php
3 /**
4 * Flexible script for graphing entities in OpenEMR.
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2011 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2010-2018 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 require_once(dirname(__FILE__) . "/../../interface/globals.php");
17 use OpenEMR\Common\Acl\AclMain;
18 use OpenEMR\Common\Csrf\CsrfUtils;
20 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
21 CsrfUtils::csrfNotVerified();
24 // Collect passed variable(s)
25 // $table is the sql table (or form name if LBF)
26 // $name identifies the desired data item
27 // $title is used as the title of the graph
28 $table = trim($_POST['table']);
29 $name = trim($_POST['name']);
30 $title = trim($_POST['title']);
32 $is_lbf = substr($table, 0, 3) === 'LBF';
34 // acl checks here
35 // For now, only allow access for med aco.
36 // This can be expanded depending on which table is accessed.
37 if (!AclMain::aclCheckCore('patients', 'med')) {
38 exit;
41 // Conversion functions/constants
42 function convertFtoC($a)
44 return ($a - 32) * 0.5556;
46 function getLbstoKgMultiplier()
48 return 0.45359237;
50 function getIntoCmMultiplier()
52 return 2.54;
54 function getIdealYSteps($a)
56 if ($a > 1000) {
57 return 200;
58 } elseif ($a > 500) {
59 return 100;
60 } elseif ($a > 100) {
61 return 20;
62 } elseif ($a > 50) {
63 return 10;
64 } else {
65 return 5;
69 function graphsGetValues($name)
71 global $is_lbf, $pid, $table;
72 if ($is_lbf) {
73 // Like below, but for LBF data.
74 $values = sqlStatement(
75 "SELECT " .
76 "ld.field_value AS " . add_escape_custom($name) . ", " .
77 // If data was entered retroactively then cannot use the data entry date.
78 "IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date " .
79 "FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE " .
80 "f.pid = ? AND " .
81 "f.formdir = ? AND " .
82 "f.deleted = 0 AND " .
83 "fe.pid = f.pid AND fe.encounter = f.encounter AND " .
84 "ld.form_id = f.form_id AND " .
85 "ld.field_id = ? AND " .
86 "ld.field_value != '0' " .
87 "ORDER BY date",
88 array($pid, $table, $name)
90 } else {
91 // Collect the pertinent info and ranges
92 // (Note am skipping values of zero, this could be made to be
93 // optional in the future when using lab values)
94 $values = SqlStatement("SELECT " .
95 escape_sql_column_name($name, array($table)) . ", " .
96 "date " .
97 "FROM " . escape_table_name($table) . " " .
98 "WHERE " . escape_sql_column_name($name, array($table)) . " != 0 " .
99 "AND pid = ? ORDER BY date", array($pid));
102 return $values;
105 //Customizations (such as titles and conversions)
106 if ($is_lbf) {
107 $titleGraph = $title;
108 if ($name == 'bp_systolic' || $name == 'bp_diastolic') {
109 $titleGraph = xl("Blood Pressure") . " (" . xl("mmHg") . ")";
110 $titleGraphLine1 = xl("BP Systolic");
111 $titleGraphLine2 = xl("BP Diastolic");
113 } else {
114 switch ($name) {
115 case "weight":
116 $titleGraph = $title . " (" . xl("lbs") . ")";
117 break;
118 case "weight_metric":
119 $titleGraph = $title . " (" . xl("kg") . ")";
120 $multiplier = getLbstoKgMultiplier();
121 $name = "weight";
122 break;
123 case "height":
124 $titleGraph = $title . " (" . xl("in") . ")";
125 break;
126 case "height_metric":
127 $titleGraph = $title . " (" . xl("cm") . ")";
128 $multiplier = getIntoCmMultiplier();
129 $name = "height";
130 break;
131 case "bps":
132 $titleGraph = xl("Blood Pressure") . " (" . xl("mmHg") . ")";
133 $titleGraphLine1 = xl("BP Systolic");
134 $titleGraphLine2 = xl("BP Diastolic");
135 break;
136 case "bpd":
137 $titleGraph = xl("Blood Pressure") . " (" . xl("mmHg") . ")";
138 $titleGraphLine1 = xl("BP Diastolic");
139 $titleGraphLine2 = xl("BP Systolic");
140 break;
141 case "pulse":
142 $titleGraph = $title . " (" . xl("per min") . ")";
143 break;
144 case "respiration":
145 $titleGraph = $title . " (" . xl("per min") . ")";
146 break;
147 case "temperature":
148 $titleGraph = $title . " (" . xl("F") . ")";
149 break;
150 case "temperature_metric":
151 $titleGraph = $title . " (" . xl("C") . ")";
152 $isConvertFtoC = 1;
153 $name = "temperature";
154 break;
155 case "oxygen_saturation":
156 $titleGraph = $title . " (" . xl("%") . ")";
157 break;
158 case "head_circ":
159 $titleGraph = $title . " (" . xl("in") . ")";
160 break;
161 case "head_circ_metric":
162 $titleGraph = $title . " (" . xl("cm") . ")";
163 $multiplier = getIntoCmMultiplier();
164 $name = "head_circ";
165 break;
166 case "waist_circ":
167 $titleGraph = $title . " (" . xl("in") . ")";
168 break;
169 case "waist_circ_metric":
170 $titleGraph = $title . " (" . xl("cm") . ")";
171 $multiplier = getIntoCmMultiplier();
172 $name = "waist_circ";
173 break;
174 case "BMI":
175 $titleGraph = $title . " (" . xl("kg/m^2") . ")";
176 break;
177 default:
178 $titleGraph = $title;
182 // Collect info
183 if ($table) {
184 // Like below, but for LBF data.
185 $values = graphsGetValues($name);
186 } else {
187 exit;
190 // If less than 2 values, then exit
191 if (sqlNumRows($values) < 2) {
192 exit;
195 // If blood pressure, then collect the other reading to allow graphing both in same graph
196 $isBP = 0;
197 if ($is_lbf) {
198 if ($name == "bp_systolic" || $name == "bp_diastolic") {
199 // Set BP flag and collect other pressure reading
200 $isBP = 1;
201 if ($name == "bp_systolic") {
202 $name_alt = "bp_diastolic";
203 } else {
204 $name_alt = "bp_systolic";
207 // Collect the pertinent vitals and ranges.
208 $values_alt = graphsGetValues($name_alt);
210 } else {
211 if ($name == "bps" || $name == "bpd") {
212 // Set BP flag and collect other pressure reading
213 $isBP = 1;
214 if ($name == "bps") {
215 $name_alt = "bpd";
218 if ($name == "bpd") {
219 $name_alt = "bps";
222 // Collect the pertinent vitals and ranges.
223 $values_alt = graphsGetValues($name_alt);
227 // Prepare data
228 $data = array();
229 while ($row = sqlFetchArray($values)) {
230 if ($row["$name"]) {
231 $x = $row['date'];
232 if ($multiplier ?? null) {
233 // apply unit conversion multiplier
234 $y = $row["$name"] * $multiplier;
235 } elseif ($isConvertFtoC ?? null) {
236 // apply temp F to C conversion
237 $y = convertFtoC($row["$name"]);
238 } else {
239 // no conversion, so use raw value
240 $y = $row["$name"];
243 $data[$x][$name] = $y;
247 if ($isBP) {
248 //set up the other blood pressure line
249 while ($row = sqlFetchArray($values_alt)) {
250 if ($row["$name_alt"]) {
251 $x = $row['date'];
252 if ($multiplier ?? null) {
253 // apply unit conversion multiplier
254 $y = $row["$name_alt"] * $multiplier;
255 } elseif ($isConvertFtoC ?? null) {
256 // apply temp F to C conversion
257 $y = convertFtoC($row["$name_alt"]);
258 } else {
259 // no conversion, so use raw value
260 $y = $row["$name_alt"];
263 $data[$x][$name_alt] = $y;
268 // Prepare label
269 $data_final = "";
270 if ($isBP) {
271 $data_final .= xl('Date') . "\t" . $titleGraphLine1 . "\t" . $titleGraphLine2 . "\n";
272 } else {
273 $data_final .= xl('Date') . "\t" . $titleGraph . "\n";
276 // Prepare data
277 foreach ($data as $date => $value) {
278 if ($isBP) {
279 $data_final .= $date . "\t" . $value[$name] . "\t" . $value[$name_alt] . "\n";
280 } else {
281 $data_final .= $date . "\t" . $value[$name] . "\n";
285 // Build and send back the json
286 $graph_build = array();
287 $graph_build['data_final'] = $data_final;
288 $graph_build['title'] = $titleGraph;
289 // Note need to also use " when building the $data_final rather
290 // than ' , or else JSON_UNESCAPED_SLASHES doesn't work and \n and
291 // \t get escaped.
292 echo json_encode($graph_build, JSON_UNESCAPED_SLASHES);