bug fix (#5671)
[openemr.git] / library / pnotes.inc
blobb0bf000c5b09ecbf5eb6c00740bebe1518fb48e0
1 <?php
3 /**
4  * This file contains functions for handling notes attached to patient files.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * 2013-02-08 EMR Direct: changes to allow notes added by background-services with pid=0
12  */
14 use OpenEMR\Common\Logging\SystemLogger;
16 /**
17  * Retrieve a note, given its ID
18  *
19  * @param string $id the ID of the note to retrieve.
20  * @param string $cols A list of columns to retrieve. defaults to '*' for all.
21  */
22 function getPnoteById($id, $cols = "*")
24     return sqlQuery("SELECT "  . escape_sql_column_name(process_cols_escape($cols), array('pnotes')) . " FROM pnotes WHERE id=? " .
25     ' AND deleted != 1 ' . // exclude ALL deleted notes
26     'order by date DESC limit 0,1', array($id));
29 /**
30  * Get the patient notes for the given user.
31  *
32  * This function is used to retrieve notes assigned to the given user, or
33  * optionally notes assigned to any user.
34  *
35  * @param string $activity 0 for deleted notes, 1 (the default) for active
36  *                         notes, or 'All' for all.
37  * @param string $show_all whether to display only the selected user's
38  *                         messages, or all users' messages.
39  * @param string $user The user whom's notes you want to retrieve.
40  * @param bool $count Whether to return a count, or just return 0.
41  * @param string $sortby A field to sort results by. (options are users.lname,patient_data.lname,pnotes.title,pnotes.date,pnotes.message_status) (will default to users.lname)
42  * @param string $sortorder whether to sort ascending or descending.
43  * @param string $begin what row to start retrieving results from.
44  * @param string $listnumber number of rows to return.
45  * @return int The number of rows retrieved, or 0 if $count was true.
46  */
47 function getPnotesByUser($activity = "1", $show_all = "no", $user = '', $count = false, $sortby = '', $sortorder = '', $begin = '', $listnumber = '')
50   // Set the activity part of query
51     if ($activity == '1') {
52         $activity_query = " pnotes.message_status != 'Done' AND pnotes.activity = 1 AND ";
53     } elseif ($activity == '0') {
54         $activity_query = " (pnotes.message_status = 'Done' OR pnotes.activity = 0) AND ";
55     } else { //$activity=='all'
56         $activity_query = " ";
57     }
59   // Set whether to show chosen user or all users
60     if ($show_all == 'yes') {
61         $usrvar = '_%';
62     } else {
63         $usrvar = $user;
64     }
66   // run the query
67   // 2013-02-08 EMR Direct: minor changes to query so notes with pid=0 don't disappear
68     $sql = "SELECT pnotes.id, pnotes.user, pnotes.pid, pnotes.title, pnotes.date, pnotes.message_status, pnotes.activity,
69           IF(pnotes.pid = 0 OR pnotes.user != pnotes.pid,users.fname,patient_data.fname) as users_fname,
70           IF(pnotes.pid = 0 OR pnotes.user != pnotes.pid,users.lname,patient_data.lname) as users_lname,
71           patient_data.fname as patient_data_fname, patient_data.lname as patient_data_lname
72           FROM ((pnotes LEFT JOIN users ON pnotes.user = users.username)
73           LEFT JOIN patient_data ON pnotes.pid = patient_data.pid) WHERE $activity_query
74           pnotes.deleted != '1' AND pnotes.assigned_to LIKE ?";
75     if (!empty($sortby) || !empty($sortorder)  || !empty($begin) || !empty($listnumber)) {
76         $sql .= " order by " . escape_sql_column_name($sortby, array('users','patient_data','pnotes'), true) .
77             " " . escape_sort_order($sortorder) .
78             " limit " . escape_limit($begin) . ", " . escape_limit($listnumber);
79     }
81     $result = sqlStatement($sql, array($usrvar));
83   // return the results
84     if ($count) {
85         if (sqlNumRows($result) != 0) {
86             $total = sqlNumRows($result);
87         } else {
88             $total = 0;
89         }
91         return $total;
92     } else {
93         return $result;
94     }
97 function getPnotesByDate(
98     $date,
99     $activity = "1",
100     $cols = "*",
101     $pid = "%",
102     $limit = "all",
103     $start = 0,
104     $username = '',
105     $docid = 0,
106     $status = "",
107     $orderid = 0
108 ) {
110     $sqlParameterArray = array();
111     if ($docid) {
112         $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes', 'gprelations')) . " FROM pnotes AS p, gprelations AS r " .
113         "WHERE p.date LIKE ? AND r.type1 = 1 AND " .
114         "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid != p.user";
115         array_push($sqlParameterArray, '%' . $date . '%', $docid);
116     } elseif ($orderid) {
117         $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes', 'gprelations')) . " FROM pnotes AS p, gprelations AS r " .
118         "WHERE p.date LIKE ? AND r.type1 = 2 AND " .
119         "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid != p.user";
120         array_push($sqlParameterArray, '%' . $date . '%', $orderid);
121     } else {
122         $sql = "SELECT "  . escape_sql_column_name(process_cols_escape($cols), array('pnotes')) . " FROM pnotes AS p " .
123         "WHERE date LIKE ? AND pid LIKE ? AND p.pid != p.user";
124         array_push($sqlParameterArray, '%' . $date . '%', $pid);
125     }
127     $sql .= " AND deleted != 1"; // exclude ALL deleted notes
128     if ($activity != "all") {
129         if ($activity == '0') {
130             // only return inactive
131             $sql .= " AND (activity = '0' OR message_status = 'Done') ";
132         } else { // $activity == '1'
133             // only return active
134             $sql .= " AND activity = '1' AND message_status != 'Done' ";
135         }
136     }
138     if ($username) {
139         $sql .= " AND assigned_to LIKE ?";
140         array_push($sqlParameterArray, $username);
141     }
143     if ($status) {
144         $sql .= " AND message_status IN ('" . str_replace(",", "','", add_escape_custom($status)) . "')";
145     }
147     $sql .= " ORDER BY date DESC";
148     if ($limit != "all") {
149         $sql .= " LIMIT " . escape_limit($start) . ", " . escape_limit($limit);
150     }
152     $res = sqlStatement($sql, $sqlParameterArray);
154     $all = array();
155     for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
156         $all[$iter] = $row;
157     }
159     return $all;
162 // activity can only be 0, 1, or 'all'
163 function getSentPnotesByDate(
164     $date,
165     $activity = "1",
166     $cols = "*",
167     $pid = "%",
168     $limit = "all",
169     $start = 0,
170     $username = '',
171     $docid = 0,
172     $status = "",
173     $orderid = 0
174 ) {
176     $sqlParameterArray = array();
177     if ($docid) {
178         $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes', 'gprelations')) . " FROM pnotes AS p, gprelations AS r " .
179         "WHERE p.date LIKE ? AND r.type1 = 1 AND " .
180         "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid = p.user";
181         array_push($sqlParameterArray, '%' . $date . '%', $docid);
182     } elseif ($orderid) {
183         $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes','gprelations')) . " FROM pnotes AS p, gprelations AS r " .
184         "WHERE p.date LIKE ? AND r.type1 = 2 AND " .
185         "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid = p.user";
186         array_push($sqlParameterArray, '%' . $date . '%', $orderid);
187     } else {
188         $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes')) . " FROM pnotes AS p " .
189         "WHERE date LIKE ? AND pid LIKE ? AND p.pid = p.user";
190         array_push($sqlParameterArray, '%' . $date . '%', $pid);
191     }
193     $sql .= " AND deleted != 1"; // exclude ALL deleted notes
194     if ($activity != "all") {
195         if ($activity == '0') {
196             // only return inactive
197             $sql .= " AND (activity = '0' OR message_status = 'Done') ";
198         } else { // $activity == '1'
199             // only return active
200             $sql .= " AND activity = '1' AND message_status != 'Done' ";
201         }
202     }
204     if ($username) {
205         $sql .= " AND assigned_to LIKE ?";
206         array_push($sqlParameterArray, $username);
207     }
209     if ($status) {
210         $sql .= " AND message_status IN ('" . str_replace(",", "','", add_escape_custom($status)) . "')";
211     }
213     $sql .= " ORDER BY date DESC";
214     if ($limit != "all") {
215         $sql .= " LIMIT " . escape_limit($start) . ", " . escape_limit($limit);
216     }
218     $res = sqlStatement($sql, $sqlParameterArray);
220     $all = array();
221     for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
222         $all[$iter] = $row;
223     }
225     return $all;
228 function getPatientNotes($pid = '', $limit = '', $offset = 0, $search = '')
230     if ($limit) {
231         $limit = "LIMIT " . escape_limit($offset) . ", " . escape_limit($limit);
232     }
234     $sql = "
235     SELECT
236       p.id,
237       p.date,
238       p.user,
239       p.title,
240       REPLACE(
241         p.body,
242         '-patient-',
243         CONCAT(pd.fname, ' ', pd.lname)
244       ) AS body,
245       p.message_status,
246       'Message' as `type`,
247       p.activity
248     FROM
249       pnotes AS p
250       LEFT JOIN patient_data AS pd
251         ON pd.id = p.pid
252     WHERE assigned_to = '-patient-'
253       AND p.deleted != 1
254       AND p.pid = ?
255       $search
256     ORDER BY `date` desc
257     $limit
258   ";
259     $res = sqlStatement($sql, array($pid));
260     for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
261         $all[$iter] = $row;
262     }
264     return $all;
267 function getPatientNotifications($pid = '', $limit = '', $offset = 0, $search = '')
269     if ($limit) {
270         $limit = "LIMIT " . escape_limit($offset) . ", " . escape_limit($limit);
271     }
273     $sql = "
274     SELECT
275       pr.id,
276       date_created AS `date`,
277       'Patient Reminders' AS `user`,
278       due_status AS title,
279       CONCAT(lo.title, ':', lo2.title) AS body,
280       '' as message_status,
281       'Notification' as `type`
282     FROM
283       patient_reminders AS pr
284       LEFT JOIN list_options AS lo
285         ON lo.option_id = pr.category
286         AND lo.list_id = 'rule_action_category' AND lo.activity = 1
287       LEFT JOIN list_options AS lo2
288         ON lo2.option_id = pr.item
289         AND lo2.list_id = 'rule_action' AND lo2.activity = 1
290     WHERE pid = ?
291       AND active = 1
292       AND date_created > DATE_SUB(NOW(), INTERVAL 1 MONTH)
293       $search
294     ORDER BY `date` desc
295     $limit
296   ";
297     $res = sqlStatement($sql, array($pid));
298     for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
299         $all[$iter] = $row;
300     }
302     return $all;
305 function getPatientSentNotes($pid = '', $limit = '', $offset = 0, $search = '')
307     if ($limit) {
308         $limit = "LIMIT " . escape_limit($offset) . ", " . escape_limit($limit);
309     }
311     $sql = "
312     SELECT
313       p.id,
314       p.date,
315       p.assigned_to,
316       p.title,
317       REPLACE(
318         p.body,
319         '-patient-',
320         CONCAT(pd.lname, ' ', pd.fname)
321       ) AS body,
322       p.activity,
323       p.message_status,
324       'Message' as `type`
325     FROM
326       pnotes AS p
327       LEFT JOIN patient_data AS pd
328         ON pd.id = p.pid
329     WHERE `user` = ?
330       AND p.deleted != 1
331       AND p.pid = ?
332       AND p.message_status != 'Done'
333       $search
334     ORDER BY `date` desc
335     $limit
336   ";
337     $res = sqlStatement($sql, array($pid,$pid));
338     for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
339         $all[$iter] = $row;
340     }
342     return $all;
347 /** Add a note to a patient's medical record.
349  * @param int $pid the ID of the patient whos medical record this note is going to be attached to.
350  * @param string $newtext the note contents.
351  * @param int $authorized
352  * @param int $activity
353  * @param string $title
354  * @param string $assigned_to
355  * @param string $datetime
356  * @param string $message_status
357  * @param string $background_user if set then the pnote is created by a background-service rather than a user
358  * @return int the ID of the added note.
359  */
360 function addPnote(
361     $pid,
362     $newtext,
363     $authorized = '0',
364     $activity = '1',
365     $title = 'Unassigned',
366     $assigned_to = '',
367     $datetime = '',
368     $message_status = 'New',
369     $background_user = ""
370 ) {
372     if (empty($datetime)) {
373         $datetime = date('Y-m-d H:i:s');
374     }
376   // make inactive if set as Done
377     if ($message_status == 'Done') {
378         $activity = 0;
379     }
380     $user = ($background_user != "" ? $background_user : $_SESSION['authUser']);
381     $body = date('Y-m-d H:i') . ' (' . $user;
382     if ($assigned_to) {
383         $body .= " to $assigned_to";
384     }
386     $body = $body . ') ' . $newtext;
388     return sqlInsert(
389         'INSERT INTO pnotes (date, body, pid, user, groupname, ' .
390         'authorized, activity, title, assigned_to, message_status, update_by, update_date) VALUES ' .
391         '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())',
392         array($datetime, $body, $pid, $user, $_SESSION['authProvider'], $authorized, $activity, $title, $assigned_to, $message_status, $_SESSION['authUserID'])
393     );
396 function addMailboxPnote(
397     $pid,
398     $newtext,
399     $authorized = '0',
400     $activity = '1',
401     $title = 'Unassigned',
402     $assigned_to = '',
403     $datetime = '',
404     $message_status = "New"
405 ) {
407     if (empty($datetime)) {
408         $datetime = date('Y-m-d H:i:s');
409     }
411   // make inactive if set as Done
412     if ($message_status == "Done") {
413         $activity = 0;
414     }
416     $body = date('Y-m-d H:i') . ' (' . $pid;
417     if ($assigned_to) {
418         $body .= " to $assigned_to";
419     }
421     $body = $body . ') ' . $newtext;
423     return sqlInsert(
424         "INSERT INTO pnotes (date, body, pid, user, groupname, " .
425         "authorized, activity, title, assigned_to, message_status, update_by, update_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())",
426         array($datetime, $body, $pid, $pid, 'Default', $authorized, $activity, $title, $assigned_to, $message_status, $_SESSION['authUserID'])
427     );
430 function updatePnote($id, $newtext, $title, $assigned_to, $message_status = "", $datetime = "")
432     $row = getPnoteById($id);
433     if (! $row) {
434         die("updatePnote() did not find id '" . text($id) . "'");
435     }
437     if (empty($datetime)) {
438         $datetime = date('Y-m-d H:i:s');
439     }
441     $activity = $assigned_to ? '1' : '0';
443   // make inactive if set as Done
444     if ($message_status == "Done") {
445         $activity = 0;
446     }
448     $body = $row['body'] . "\n" . date('Y-m-d H:i') .
449     ' (' . $_SESSION['authUser'];
450     if ($assigned_to) {
451         $body .= " to $assigned_to";
452     }
454     $body = $body . ') ' . $newtext;
457     $sql = "UPDATE pnotes SET " .
458         "body = ?, activity = ?, title= ?, " .
459         "assigned_to = ?, update_by = ?, update_date = NOW()";
460     $bindingParams =  array($body, $activity, $title, $assigned_to, $_SESSION['authUserID']);
461     if ($message_status) {
462         $sql .= " ,message_status = ?";
463         $bindingParams[] = $message_status;
464     }
465     if ($GLOBALS['messages_due_date']) {
466         $sql .= " ,date = ?";
467         $bindingParams[] = $datetime;
468     }
469     $sql .= " WHERE id = ?";
470     $bindingParams[] = $id;
471     sqlStatement($sql, $bindingParams);
474 function updatePnoteMessageStatus($id, $message_status)
476     if ($message_status == "Done") {
477         sqlStatement("update pnotes set message_status = ?, activity = '0', update_by = ?, update_date = NOW() where id = ?", array($message_status, $_SESSION['authUserID'], $id));
478     } else {
479         sqlStatement("update pnotes set message_status = ?, activity = '1', update_by = ?, update_date = NOW() where id = ?", array($message_status, $_SESSION['authUserID'], $id));
480     }
484  * Set the patient id in an existing message where pid=0
485  * @param $id the id of the existing note
486  * @param $patient_id the patient id to associate with the note
487  * @author EMR Direct <http://www.emrdirect.com/>
488  */
489 function updatePnotePatient($id, $patient_id)
491     $row = getPnoteById($id);
492     if (! $row) {
493         die("updatePnotePatient() did not find id '" . text($id) . "'");
494     }
496     $activity = $assigned_to ? '1' : '0';
498     $pid = $row['pid'];
500     if ($pid != 0 || (int)$patient_id < 1) {
501         (new SystemLogger())->errorLogCaller("invalid operation", ['id' => $id, 'patient_id' => $patient_id, 'pid' => $pid]);
502         die("updatePnotePatient invalid operation");
503     }
505     $pid = (int) $patient_id;
506     $newtext = "\n" . date('Y-m-d H:i') . " (patient set by " . $_SESSION['authUser'] . ")";
507     $body = $row['body'] . $newtext;
509     sqlStatement("UPDATE pnotes SET pid = ?, body = ?, update_by = ?, update_date = NOW() WHERE id = ?", array($pid, $body, $_SESSION['authUserID'], $id));
512 function authorizePnote($id, $authorized = "1")
514     sqlQuery("UPDATE pnotes SET authorized = ? , update_by = ?, update_date = NOW() WHERE id = ?", array ($authorized, $_SESSION['authUserID'], $id));
517 function disappearPnote($id)
519     sqlStatement("UPDATE pnotes SET activity = '0', message_status = 'Done', update_by = ?, update_date = NOW()  WHERE id=?", array($_SESSION['authUserID'], $id));
520     return true;
523 function reappearPnote($id)
525     sqlStatement("UPDATE pnotes SET activity = '1', message_status = IF(message_status='Done','New',message_status), update_by = ?, update_date = NOW() WHERE id=?", array($_SESSION['authUserID'], $id));
526     return true;
529 function deletePnote($id)
531     if (
532         getAssignedToById($id) == $_SESSION['authUser']
533         || getMessageStatusById($id) == 'Done'
534     ) {
535         sqlStatement("UPDATE pnotes SET deleted = '1', update_by = ?, update_date = NOW() WHERE id=?", array($_SESSION['authUserID'], $id));
536         return true;
537     } else {
538         return false;
539     }
542 // Note that it is assumed that html escaping has happened before this function is called
543 function pnoteConvertLinks($note)
545     $noteActiveLink = preg_replace('!(https://[-a-zA-Z()0-9@:%_+.~#?&;//=]+)!i', '<a href="$1" target="_blank" rel="noopener">$1</a>', $note);
546     if (empty($noteActiveLink)) {
547         // something bad happened (preg_replace returned null) or the $note was empty
548         return $note;
549     } else {
550         return $noteActiveLink;
551     }
555  * Retrieve assigned_to field given the note ID
557  * @param string $id the ID of the note to retrieve.
558  */
559 function getAssignedToById($id)
561     $result = sqlQuery("SELECT assigned_to FROM pnotes WHERE id=?", array($id));
562     return $result['assigned_to'];
566  * Retrieve message_status field given the note ID
568  * @param string $id the ID of the note to retrieve.
569  */
570 function getMessageStatusById($id)
572     $result = sqlQuery("SELECT message_status FROM pnotes WHERE id=?", array($id));
573     return $result['message_status'];