feat: expose suffix and valedictory in user admin and esign (#6814)
[openemr.git] / library / ESign / DbRow / Signable.php
blobda78cfd90a166eacef918850b3095231a49ee21f
1 <?php
3 /**
4 * Abstract implementation of SignableIF which represents a signable row
5 * in the database.
7 * Copyright (C) 2013 OEMR 501c3 www.oemr.org
9 * LICENSE: This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 3
12 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
20 * @package OpenEMR
21 * @author Ken Chapple <ken@mi-squared.com>
22 * @author Medical Information Integration, LLC
23 * @link http://www.open-emr.org
24 **/
26 namespace ESign;
28 require_once $GLOBALS['srcdir'] . '/ESign/SignableIF.php';
29 require_once $GLOBALS['srcdir'] . '/ESign/Signature.php';
30 require_once $GLOBALS['srcdir'] . '/ESign/Utils/Verification.php';
32 abstract class DbRow_Signable implements SignableIF
34 private $_signatures = array();
35 protected $_tableId = null;
36 protected $_tableName = null;
37 private $_verification = null;
39 public function __construct($tableId, $tableName)
41 $this->_tableId = $tableId;
42 $this->_tableName = $tableName;
43 $this->_verification = new Utils_Verification();
46 public function getSignatures()
48 $this->_signatures = array();
50 $statement = "SELECT E.id, E.tid, E.table, E.uid, U.fname, U.lname, U.suffix, U.valedictory, E.datetime, E.is_lock, E.amendment, E.hash, E.signature_hash FROM esign_signatures E ";
51 $statement .= "JOIN users U ON E.uid = U.id ";
52 $statement .= "WHERE E.tid = ? AND E.table = ? ";
53 $statement .= "ORDER BY E.datetime ASC";
54 $result = sqlStatement($statement, array( $this->_tableId, $this->_tableName ));
56 while ($row = sqlFetchArray($result)) {
57 $signature = new Signature(
58 $row['id'],
59 $row['tid'],
60 $row['table'],
61 $row['is_lock'],
62 $row['uid'],
63 $row['fname'],
64 $row['lname'],
65 $row['suffix'],
66 $row['valedictory'],
67 $row['datetime'],
68 $row['hash'],
69 $row['amendment'],
70 $row['signature_hash']
72 $this->_signatures[] = $signature;
75 return $this->_signatures;
78 /**
79 * Get the hash of the last signature of type LOCK.
81 * This is used for comparison with a current hash to
82 * verify data integrity.
84 * @return sha1(or sha3-512)|empty string
86 protected function getLastLockHash()
88 $statement = "SELECT E.tid, E.table, E.hash FROM esign_signatures E ";
89 $statement .= "WHERE E.tid = ? AND E.table = ? AND E.is_lock = ? ";
90 $statement .= "ORDER BY E.datetime DESC LIMIT 1";
91 $row = sqlQuery($statement, array( $this->_tableId, $this->_tableName, SignatureIF::ESIGN_LOCK ));
92 $hash = null;
93 if ($row && isset($row['hash'])) {
94 $hash = $row['hash'];
97 return $hash;
100 public function getTableId()
102 return $this->_tableId;
105 public function renderForm()
107 include 'views/esign_signature_log.php';
110 public function isLocked()
112 $statement = "SELECT E.is_lock FROM esign_signatures E ";
113 $statement .= "WHERE E.tid = ? AND E.table = ? AND is_lock = ? ";
114 $statement .= "ORDER BY E.datetime DESC LIMIT 1 ";
115 $row = sqlQuery($statement, array( $this->_tableId, $this->_tableName, SignatureIF::ESIGN_LOCK ));
116 if ($row && $row['is_lock'] == SignatureIF::ESIGN_LOCK) {
117 return true;
120 return false;
123 public function sign($userId, $lock = false, $amendment = null)
125 $statement = "INSERT INTO `esign_signatures` ( `tid`, `table`, `uid`, `datetime`, `is_lock`, `hash`, `amendment`, `signature_hash` ) ";
126 $statement .= "VALUES ( ?, ?, ?, NOW(), ?, ?, ?, ? ) ";
128 // Make type string
129 $isLock = SignatureIF::ESIGN_NOLOCK;
130 if ($lock) {
131 $isLock = SignatureIF::ESIGN_LOCK;
134 // Create a hash of the signable object so we can verify it's integrity
135 $hash = $this->_verification->hash($this->getData());
137 // Crate a hash of the signature data itself. This is the same data as Signature::getData() method
138 $signature = array(
139 $this->_tableId,
140 $this->_tableName,
141 $userId,
142 $isLock,
143 $hash,
144 $amendment );
145 $signatureHash = $this->_verification->hash($signature);
147 // Append the hash of the signature data to the insert array before we insert
148 $signature[] = $signatureHash;
149 $id = sqlInsert($statement, $signature);
151 if ($id === false) {
152 throw new \Exception("Error occured while attempting to insert a signature into the database.");
155 return $id;
158 public function verify()
160 $valid = true;
161 // Verify the signable data integrity
162 // Check to see if this SignableIF is locked
163 if ($this->isLocked()) {
164 $signatures = $this->getSignatures();
166 // SignableIF is locked, so if it has any signatures, make sure it hasn't been edited since lock
167 if (count($signatures)) {
168 // Verify the data of the SignableIF object
169 $lastLockHash = $this->getLastLockHash();
170 $valid = $this->_verification->verify($this->getData(), $lastLockHash);
172 if ($valid === true) {
173 // If still vlaid, verify each signatures' integrity
174 foreach ($signatures as $signature) {
175 if ($signature instanceof SignatureIF) {
176 $valid = $signature->verify();
177 if ($valid === false) {
178 break;
186 return $valid;