4 * Download selected patient documents in a zip file
7 * @link https://www.open-emr.org
8 * @author Jerry Padgett <sjpadgett@gmail.com>
9 * @copyright Copyright (c) 2024 Jerry Padgett <sjpadgett@gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 require_once("../verify_session.php");
14 require_once("$srcdir/documents.php");
15 require_once($GLOBALS['fileroot'] . "/controllers/C_Document.class.php");
17 use OpenEMR\Common\Csrf\CsrfUtils
;
19 if (!CsrfUtils
::verifyCsrfToken($_POST['csrf_token_form'] ??
'')) {
20 CsrfUtils
::csrfNotVerified();
23 // Check if documents are selected
24 if (empty($_POST['documents'])) {
25 die("No documents selected.");
28 // Get the temporary folder
29 $tmp = $GLOBALS['temporary_files_dir'];
30 $documentIds = $_POST['documents'];
31 $pid = $_SESSION['pid'];
33 // Process each selected document
34 foreach ($documentIds as $documentId) {
35 $sql = "SELECT url, id, mimetype, `name`, `foreign_id` FROM `documents` WHERE `id` = ? AND `deleted` = 0";
36 $file = sqlQuery($sql, array($documentId));
37 if ($file['foreign_id'] != $pid && $file['foreign_id'] != $_SESSION['pid']) {
38 die(xlt("Invalid document selected."));
40 // Find the document category
41 $sql = "SELECT name, lft, rght FROM `categories`, `categories_to_documents`
42 WHERE `categories_to_documents`.`category_id` = `categories`.`id`
43 AND `categories_to_documents`.`document_id` = ?";
44 $cat = sqlQuery($sql, array($file['id']));
46 // Find the tree of the document's category
47 $sql = "SELECT name FROM categories WHERE lft < ? AND rght > ? ORDER BY lft ASC";
48 $pathres = sqlStatement($sql, array($cat['lft'], $cat['rght']));
50 // Create the tree of the categories
52 while ($parent = sqlFetchArray($pathres)) {
53 $path .= convert_safe_file_dir_name($parent['name']) . "/";
56 $path .= convert_safe_file_dir_name($cat['name']) . "/";
57 // Create the folder structure at the temporary dir
58 if (!is_dir($tmp . "/" . $pid . "/" . $path)) {
59 if (!mkdir($concurrentDirectory = $tmp . "/" . $pid . "/" . $path, 0777, true) && !is_dir($concurrentDirectory)) {
60 die("Error creating directory!");
65 $obj = new C_Document();
66 $document = $obj->retrieve_action("", $documentId, true, true, true);
68 $pos = strpos(substr($file['name'], -5), '.');
69 // Check if has an extension or find it from the mimetype
71 $file['name'] .= get_extension($file['mimetype']);
74 $dest = $tmp . "/" . $pid . "/" . $path . "/" . convert_safe_file_dir_name($file['name']);
75 if (file_exists($dest)) {
78 $dest = $tmp . "/" . $pid . "/" . $path . "/" . $x . "_" . convert_safe_file_dir_name($file['name']);
80 } while (file_exists($dest));
83 file_put_contents($dest, $document);
85 echo xlt("Can't find file!");
90 Zip($tmp . "/" . $pid . "/", $tmp . "/" . $pid . '.zip');
92 // Serve it to the patient
93 header('Content-type: application/zip');
94 header('Content-Disposition: attachment; filename="patient_documents.zip"');
95 readfile($tmp . "/" . $pid . '.zip');
97 // Remove the temporary folders and files
98 recursive_remove_directory($tmp . "/" . $pid);
99 unlink($tmp . "/" . $pid . '.zip');
101 function recursive_remove_directory($directory, $empty = false)
103 if (substr($directory, -1) == '/') {
104 $directory = substr($directory, 0, -1);
107 if (!file_exists($directory) ||
!is_dir($directory)) {
109 } elseif (is_readable($directory)) {
110 $handle = opendir($directory);
111 while (false !== ($item = readdir($handle))) {
112 if ($item != '.' && $item != '..') {
113 $path = $directory . '/' . $item;
115 recursive_remove_directory($path);
123 if ($empty == false) {
124 if (!rmdir($directory)) {
133 function Zip($source, $destination)
135 if (!extension_loaded('zip') ||
!file_exists($source)) {
139 $zip = new ZipArchive();
140 if (!$zip->open($destination, ZipArchive
::CREATE
)) {
144 $source = str_replace('\\', '/', realpath($source));
145 if (is_dir($source) === true) {
146 $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator
::SELF_FIRST
);
147 foreach ($files as $file) {
148 if ($file == $source . "/..") {
152 $file = str_replace('\\', '/', realpath($file));
153 if (is_dir($file) === true) {
154 $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
155 } elseif (is_file($file) === true) {
156 $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
159 } elseif (is_file($source) === true) {
160 $zip->addFromString(basename($source), file_get_contents($source));
163 return $zip->close();