f449df4fd1ba4465aca4db96f49cd8e13dfc5c57
[openemr.git] / library / classes / Document.class.php
blobf449df4fd1ba4465aca4db96f49cd8e13dfc5c57
1 <?php
3 require_once(dirname(__FILE__) . "/ORDataObject.class.php");
4 require_once(dirname(__FILE__) . "/CouchDB.class.php");
6 /**
7 * class Document
8 * This class is the logical representation of a physical file on some system somewhere that can be referenced with a URL
9 * of some type. This URL is not necessarily a web url, it could be a file URL or reference to a BLOB in a db.
10 * It is implicit that a document can have other related tables to it at least a one document to many notes which join on a documents
11 * id and categories which do the same.
14 class Document extends ORDataObject{
17 * Database unique identifier
18 * @var id
20 var $id;
23 * DB unique identifier reference to some other table, this is not unique in the document table
24 * @var int
26 var $foreign_id;
29 * Enumerated DB field which is met information about how to use the URL
30 * @var int can also be a the properly enumerated string
32 var $type;
35 * Array mapping of possible for values for the type variable
36 * mapping is array text name to index
37 * @var array
39 var $type_array = array();
42 * Size of the document in bytes if that is available
43 * @var int
45 var $size;
48 * Date the document was first persisted
49 * @var string
51 var $date;
54 * URL which point to the document, may be a file URL, a web URL, a db BLOB URL, or others
55 * @var string
57 var $url;
60 * Mimetype of the document if available
61 * @var string
63 var $mimetype;
66 * If the document is a multi-page format like tiff and has at least 1 page this will be 1 or greater, if a non-multi-page format this should be null or empty
67 * @var int
69 var $pages;
72 * Foreign key identifier of who initially persisited the document,
73 * potentially ownership could be changed but that would be up to an external non-document object process
74 * @var int
76 var $owner;
79 * Timestamp of the last time the document was changed and persisted, auto maintained by DB, manually change at your own peril
80 * @var int
82 var $revision;
85 * Date (YYYY-MM-DD) logically associated with the document, e.g. when a picture was taken.
86 * @var string
88 var $docdate;
91 * 40-character sha1 hash key of the document from when it was uploaded.
92 * @var string
94 var $hash;
97 * DB identifier reference to the lists table (the related issue), 0 if none.
98 * @var int
100 var $list_id;
103 * Constructor sets all Document attributes to their default value
104 * @param int $id optional existing id of a specific document, if omitted a "blank" document is created
106 function Document($id = "") {
107 //call the parent constructor so we have a _db to work with
108 parent::ORDataObject();
110 //shore up the most basic ORDataObject bits
111 $this->id = $id;
112 $this->_table = "documents";
114 //load the enum type from the db using the parent helper function, this uses psuedo-class variables so it is really cheap
115 $this->type_array = $this->_load_enum("type");
117 $this->type = $this->type_array[0];
118 $this->size = 0;
119 $this->date = date("Y-m-d H:i:s");
120 $this->url = "";
121 $this->mimetype = "";
122 $this->docdate = date("Y-m-d");
123 $this->hash = "";
124 $this->list_id = 0;
126 if ($id != "") {
127 $this->populate();
132 * Convenience function to get an array of many document objects
133 * For really large numbers of documents there is a way more efficient way to do this by overwriting the populate method
134 * @param int $foreign_id optional id use to limit array on to a specific relation, otherwise every document object is returned
136 function documents_factory($foreign_id = "") {
137 $documents = array();
139 if (empty($foreign_id)) {
140 $foreign_id= "like '%'";
142 else {
143 $foreign_id= " = '" . mysql_real_escape_string(strval($foreign_id)) . "'";
146 $d = new Document();
147 $sql = "SELECT id FROM " . $d->_table . " WHERE foreign_id " .$foreign_id ;
148 $result = $d->_db->Execute($sql);
150 while ($result && !$result->EOF) {
151 $documents[] = new Document($result->fields['id']);
152 $result->MoveNext();
155 return $documents;
159 * Convenience function to get a document object from a url
160 * Checks to see if there is an existing document with that URL and if so returns that object, otherwise
161 * creates a new one, persists it and returns it
162 * @param string $url
163 * @return object new or existing document object with the specified URL
165 function document_factory_url($url) {
166 $d = new Document();
167 //strip url handler, for now we always assume file://
168 $filename = preg_replace("|^(.*)://|","",$url);
170 if (!file_exists($filename)) {
171 die("An invalid URL was specified to crete a new document, this would only be caused if files are being deleted as you are working through the queue. '$filename'\n");
174 $sql = "SELECT id FROM " . $d->_table . " WHERE url= '" . mysql_real_escape_string($url) ."'" ;
175 $result = $d->_db->Execute($sql);
177 if ($result && !$result->EOF) {
178 if (file_exists($filename)) {
179 $d = new Document($result->fields['id']);
181 else {
182 $sql = "DELETE FROM " . $d->_table . " WHERE id= '" . $result->fields['id'] ."'";
183 $result = $d->_db->Execute($sql);
184 echo("There is a database for the file but it no longer exists on the file system. Its document entry has been deleted. '$filename'\n");
187 else {
188 $file_command = $GLOBALS['oer_config']['document']['file_command_path'] ;
189 $cmd_args = "-i ".escapeshellarg($new_path.$fname);
191 $command = $file_command." ".$cmd_args;
192 $mimetype = exec($command);
193 $mime_array = split(":", $mimetype);
194 $mimetype = $mime_array[1];
195 $d->set_mimetype($mimetype);
196 $d->url = $url;
197 $d->size = filesize($filename);
198 $d->type = $d->type_array['file_url'];
199 $d->persist();
200 $d->populate();
203 return $d;
207 * Convenience function to generate string debug data about the object
209 function toString($html = false) {
210 $string .= "\n"
211 . "ID: " . $this->id."\n"
212 . "FID: " . $this->foreign_id."\n"
213 . "type: " . $this->type . "\n"
214 . "type_array: " . print_r($this->type_array,true) . "\n"
215 . "size: " . $this->size . "\n"
216 . "date: " . $this->date . "\n"
217 . "url: " . $this->url . "\n"
218 . "mimetype: " . $this->mimetype . "\n"
219 . "pages: " . $this->pages . "\n"
220 . "owner: " . $this->owner . "\n"
221 . "revision: " . $this->revision . "\n"
222 . "docdate: " . $this->docdate . "\n"
223 . "hash: " . $this->hash . "\n"
224 . "list_id: " . $this->list_id . "\n";
226 if ($html) {
227 return nl2br($string);
229 else {
230 return $string;
234 /**#@+
235 * Getter/Setter methods used by reflection to affect object in persist/poulate operations
236 * @param mixed new value for given attribute
238 function set_id($id) {
239 $this->id = $id;
241 function get_id() {
242 return $this->id;
244 function set_foreign_id($fid) {
245 $this->foreign_id = $fid;
247 function get_foreign_id() {
248 return $this->foreign_id;
250 function set_type($type) {
251 $this->type = $type;
253 function get_type() {
254 return $this->type;
256 function set_size($size) {
257 $this->size = $size;
259 function get_size() {
260 return $this->size;
262 function set_date($date) {
263 $this->date = $date;
265 function get_date() {
266 return $this->date;
268 function set_hash($hash) {
269 $this->hash = $hash;
271 function get_hash() {
272 return $this->hash;
274 function set_url($url) {
275 $this->url = $url;
277 function get_url() {
278 return $this->url;
281 * this returns the url stripped down to basename
283 function get_url_web() {
284 return basename($this->url);
287 * get the url without the protocol handler
289 function get_url_filepath() {
290 return preg_replace("|^(.*)://|","",$this->url);
293 * get the url filename only
295 function get_url_file() {
296 return basename(preg_replace("|^(.*)://|","",$this->url));
299 * get the url path only
301 function get_url_path() {
302 return dirname(preg_replace("|^(.*)://|","",$this->url)) ."/";
304 function get_path_depth() {
305 return $this->path_depth;
307 function set_path_depth($path_depth) {
308 $this->path_depth = $path_depth;
310 function set_mimetype($mimetype) {
311 $this->mimetype = $mimetype;
313 function get_mimetype() {
314 return $this->mimetype;
316 function set_pages($pages) {
317 $this->pages = $pages;
319 function get_pages() {
320 return $this->pages;
322 function set_owner($owner) {
323 $this->owner = $owner;
325 function get_owner() {
326 return $this->owner;
329 * No getter for revision because it is updated automatically by the DB.
331 function set_revision($revision) {
332 $this->revision = $revision;
334 function set_docdate($docdate) {
335 $this->docdate = $docdate;
337 function get_docdate() {
338 return $this->docdate;
340 function set_list_id($list_id) {
341 $this->list_id = $list_id;
343 function get_list_id() {
344 return $this->list_id;
346 function get_ccr_type($doc_id){
347 $type = sqlQuery("SELECT c.name FROM categories AS c LEFT JOIN categories_to_documents AS ctd ON c.id = ctd.category_id WHERE ctd.document_id = ?",array($doc_id));
348 return $type['name'];
351 * Overridden function to stor current object state in the db.
352 * current overide is to allow for a just in time foreign id, often this is needed
353 * when the object is never directly exposed and is handled as part of a larger
354 * object hierarchy.
355 * @param int $fid foreign id that should be used so that this document can be related (joined) on it later
358 function persist($fid ="") {
359 if (!empty($fid)) {
360 $this->foreign_id = $fid;
362 parent::persist();
365 function set_storagemethod($str) {
366 $this->storagemethod = $str;
369 function get_storagemethod() {
370 return $this->storagemethod;
373 function set_couch_docid($str) {
374 $this->couch_docid = $str;
377 function get_couch_docid() {
378 return $this->couch_docid;
381 function set_couch_revid($str) {
382 $this->couch_revid = $str;
385 function get_couch_revid() {
386 return $this->couch_revid;
389 function get_couch_url($pid,$encounter){
390 $couch_docid = $this->get_couch_docid();
391 $couch_url = $this->get_url();
392 $couch = new CouchDB();
393 $data = array($GLOBALS['couchdb_dbase'],$couch_docid,$pid,$encounter);
394 $resp = $couch->retrieve_doc($data);
395 $content = $resp->data;
396 $temp_url=$couch_url;
397 $temp_url = $GLOBALS['OE_SITE_DIR'] . '/documents/temp/' . $pid . '_' . $couch_url;
398 $f_CDB = fopen($temp_url,'w');
399 fwrite($f_CDB,base64_decode($content));
400 fclose($f_CDB);
401 return $temp_url;
404 // Function added by Rod to change the patient associated with a document.
405 // This just moves some code that used to be in C_Document.class.php,
406 // changing it as little as possible since I'm not set up to test it.
408 function change_patient($new_patient_id) {
409 $couch_docid = $this->get_couch_docid();
410 $couch_revid = $this->get_couch_revid();
412 // Set the new patient in CouchDB.
413 if ($couch_docid && $couch_revid) {
414 $couch = new CouchDB();
415 $db = $GLOBALS['couchdb_dbase'];
416 $data = array($db, $couch_docid);
417 $couchresp = $couch->retrieve_doc($data);
418 // CouchDB doesnot support updating a single value in a document.
419 // Have to retrieve the entire document, update the necessary value and save again
420 list ($db, $docid, $revid, $patient_id, $encounter, $type, $json) = $data;
421 $data = array($db, $couch_docid, $couch_revid, $new_patient_id, $couchresp->encounter,
422 $couchresp->mimetype, json_encode($couchresp->data));
423 $resp = $couch->update_doc($data);
424 // Sometimes the response from CouchDB is not available, still it would
425 // have saved in the DB. Hence check one more time.
426 if(!$resp->_id || !$resp->_rev){
427 $data = array($db, $couch_docid, $new_patient_id, $couchresp->encounter);
428 $resp = $couch->retrieve_doc($data);
430 if($resp->_rev == $couch_revid) {
431 return false;
433 else {
434 $this->set_couch_revid($resp->_rev);
438 // Set the new patient in mysql.
439 $this->set_foreign_id($new_patient_id);
440 $this->persist();
442 // Return true for success.
443 return true;
446 } // end of Document
449 $d = new Document(3);
450 $d->type = $d->type_array[1];
451 $d->url = "file:///tmp/test.gif";
452 $d->pages = 0;
453 $d->owner = 60;
454 $d->size = 8000;
455 $d->foreign_id = 25;
456 $d->persist();
457 $d->populate();
459 echo $d->toString(true);*/