Move Document Versions to a seperate table much more efficient and allow to reference same document using a link Note this update will delete previous document versions

This commit is contained in:
johnnyq 2025-06-17 17:58:20 -04:00
parent 84437a2732
commit 85e1515080
8 changed files with 176 additions and 104 deletions

View File

@ -10,12 +10,7 @@ $row = mysqli_fetch_array($sql);
$document_name = nullable_htmlentities($row['document_name']);
$document_description = nullable_htmlentities($row['document_description']);
$document_content = nullable_htmlentities($row['document_content']);
$document_created_by_id = intval($row['document_created_by']);
$document_created_at = nullable_htmlentities($row['document_created_at']);
$document_updated_at = nullable_htmlentities($row['document_updated_at']);
$document_archived_at = nullable_htmlentities($row['document_archived_at']);
$document_folder_id = intval($row['document_folder_id']);
$document_parent = intval($row['document_parent']);
$document_client_visible = intval($row['document_client_visible']);
$client_id = intval($row['document_client_id']);
@ -30,10 +25,8 @@ ob_start();
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="document_id" value="<?php if($document_parent == 0){ echo $document_id; } else { echo $document_parent; } ?>">
<input type="hidden" name="document_parent" value="<?php echo $document_parent; ?>">
<input type="hidden" name="document_id" value="<?php echo $document_id; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<input type="hidden" name="created_by" value="<?php echo $document_created_by_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">

View File

@ -0,0 +1,39 @@
<?php
require_once '../includes/ajax_header.php';
// Initialize the HTML Purifier to prevent XSS
require_once "../plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
$purifier_config->set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]);
$purifier = new HTMLPurifier($purifier_config);
$document_version_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM document_versions WHERE document_version_id = $document_version_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$document_version_name = nullable_htmlentities($row['document_version_name']);
$document_version_content = $purifier->purify($row['document_version_content']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title text-white"><i class="fa fa-fw fa-file-alt mr-2"></i><?php echo $document_version_name; ?></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body bg-white prettyContent">
<?php echo $document_version_content; ?>
</div>
<script src="../js/pretty_content.js"></script>
<?php
require_once "../includes/ajax_footer.php";

View File

@ -33,5 +33,8 @@ ob_start();
<?php echo $document_content; ?>
</div>
<script src="../js/pretty_content.js"></script>
<?php
require_once "../includes/ajax_footer.php";

View File

@ -35,7 +35,6 @@ $document_created_at = nullable_htmlentities($row['document_created_at']);
$document_updated_at = nullable_htmlentities($row['document_updated_at']);
$document_archived_at = nullable_htmlentities($row['document_archived_at']);
$document_folder_id = intval($row['document_folder_id']);
$document_parent = intval($row['document_parent']);
$document_client_visible = intval($row['document_client_visible']);
// Override Tab Title // No Sanitizing needed as this var will opnly be used in the tab title
@ -115,45 +114,44 @@ $page_title = $row['document_name'];
<table class="table table-sm">
<thead class="thead-light">
<th>Revision</th>
<th>Version</th>
<th>Date</th>
<th>Name</th>
<th>Description</th>
<th>Author</th>
</thead>
<tbody>
<?php
$sql_document_revisions = mysqli_query($mysqli, "SELECT * FROM documents
LEFT JOIN users ON document_updated_by = user_id
WHERE document_parent = $document_parent
ORDER BY document_created_at ASC"
$sql_document_versions = mysqli_query($mysqli, "SELECT * FROM document_versions
LEFT JOIN users ON document_version_created_by = user_id
WHERE document_version_document_id = $document_id
ORDER BY document_version_created_at ASC"
);
$revision_count = 1; // Initialize the revision counter
$document_version_count = 1; // Initialize the document version counter
while ($row = mysqli_fetch_array($sql_document_revisions)) {
$revision_document_id = intval($row['document_id']);
$revision_document_name = nullable_htmlentities($row['document_name']);
$revision_document_description = nullable_htmlentities($row['document_description']);
if ($revision_document_description ) {
$revision_document_description_display = $revision_document_description;
while ($row = mysqli_fetch_array($sql_document_versions)) {
$document_version_id = intval($row['document_version_id']);
$document_version_name = nullable_htmlentities($row['document_version_name']);
$document_version_description = nullable_htmlentities($row['document_version_description']);
if ($document_version_description ) {
$document_version_description_display = $document_version_description;
} else {
$revision_document_description_display = "-";
$document_version_description_display = "-";
}
$revision_document_author = nullable_htmlentities($row['user_name']);
if (empty($revision_document_author)) {
$revision_document_author = $document_created_by_name;
}
$revision_document_created_date = date('Y-m-d', strtotime($row['document_created_at']));
$document_version_author = nullable_htmlentities($row['user_name']);
$document_version_created_date = date('Y-m-d', strtotime($row['document_version_created_at']));
?>
<tr>
<td><?php echo "$revision_count.0"; ?></td>
<td><?php echo $revision_document_created_date; ?></td>
<td><?php echo $revision_document_description_display; ?></td>
<td><?php echo $revision_document_author; ?></td>
<td><?php echo $document_version_count; ?></td>
<td><?php echo $document_version_created_date; ?></td>
<td><?php echo $document_version_name; ?></td>
<td><?php echo $document_version_description_display; ?></td>
<td><?php echo $document_version_author; ?></td>
</tr>
<?php
$revision_count++; // Increment the counter
$document_version_count++; // Increment the counter
}
?>
</tbody>
@ -378,29 +376,30 @@ $page_title = $row['document_name'];
<h6><i class="fas fa-history mr-2"></i>Revisions</h6>
<?php
$sql_document_revisions = mysqli_query($mysqli, "SELECT * FROM documents
LEFT JOIN users ON document_created_by = user_id
WHERE document_parent = $document_parent
ORDER BY document_created_at DESC"
$sql_document_versions = mysqli_query($mysqli, "SELECT * FROM document_versions
LEFT JOIN users ON document_version_created_by = user_id
WHERE document_version_document_id = $document_id
ORDER BY document_version_created_at DESC"
);
while ($row = mysqli_fetch_array($sql_document_revisions)) {
$revision_document_id = intval($row['document_id']);
$revision_document_name = nullable_htmlentities($row['document_name']);
$revision_document_description = nullable_htmlentities($row['document_description']);
$revision_document_created_by_name = nullable_htmlentities($row['user_name']);
$revision_document_created_date = nullable_htmlentities($row['document_created_at']);
while ($row = mysqli_fetch_array($sql_document_versions)) {
$document_version_id = intval($row['document_version_id']);
$document_version_name = nullable_htmlentities($row['document_version_name']);
$document_version_description = nullable_htmlentities($row['document_version_description']);
$document_version_author = nullable_htmlentities($row['user_name']);
$document_version_created_date = nullable_htmlentities($row['document_version_created_at']);
?>
<div class="mt-1 <?php if($document_id == $revision_document_id){ echo "text-bold"; } ?>">
<i class="fas fa-fw fa-history text-secondary mr-2"></i><a href="?client_id=<?php echo $client_id; ?>&document_id=<?php echo $revision_document_id; ?>"><?php echo " $revision_document_created_date"; ?></a><?php if($document_parent == $revision_document_id){ echo "<span class='float-right'>(Parent)</span>";
} else { ?>
<a class="confirm-link float-right" href="post.php?delete_document_version=<?php echo $revision_document_id; ?>">
<div class="mt-1 <?php if($document_id === $document_version_id){ echo "text-bold"; } ?>">
<i class="fas fa-fw fa-history text-secondary mr-2"></i>
<a href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_document_version_view.php"
data-ajax-id="<?php echo $document_version_id; ?>"><?php echo "$document_version_created_date | $document_version_author"; ?></a>
<a class="confirm-link float-right" href="post.php?delete_document_version=<?php echo $document_version_id; ?>">
<i class="fas fa-fw fa-trash-alt text-secondary"></i>
</a>
<?php
}
?>
</div>
<?php
}

View File

@ -3473,10 +3473,34 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.5'");
}
// if (CURRENT_DATABASE_VERSION == '2.1.5') {
// // Insert queries here required to update to DB version 2.1.6
if (CURRENT_DATABASE_VERSION == '2.1.5') {
mysqli_query($mysqli, "CREATE TABLE `document_versions` (
`document_version_id` INT(11) NOT NULL AUTO_INCREMENT,
`document_version_name` VARCHAR(200) NOT NULL,
`document_version_description` TEXT DEFAULT NULL,
`document_version_content` LONGTEXT NOT NULL,
`document_version_created_by` INT(11) DEFAULT 0,
`document_version_created_at` DATETIME NOT NULL,
`document_version_document_id` INT(11) NOT NULL,
PRIMARY KEY (`document_version_id`)
)");
// Delete all Current Document Versions
mysqli_query($mysqli, "
DELETE FROM `documents`
WHERE `document_parent` > 0 AND `document_parent` != `document_id`
");
mysqli_query($mysqli, "ALTER TABLE `documents` DROP `document_parent`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.6'");
}
// if (CURRENT_DATABASE_VERSION == '2.1.6') {
// // Insert queries here required to update to DB version 2.1.7
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.6'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.7'");
// }
} else {

22
db.sql
View File

@ -830,6 +830,25 @@ CREATE TABLE `document_files` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `document_versions`
--
DROP TABLE IF EXISTS `document_versions`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `document_versions` (
`document_version_id` int(11) NOT NULL AUTO_INCREMENT,
`document_version_name` varchar(200) NOT NULL,
`document_version_description` text DEFAULT NULL,
`document_version_content` longtext NOT NULL,
`document_version_created_by` int(11) DEFAULT 0,
`document_version_created_at` datetime NOT NULL,
`document_version_document_id` int(11) NOT NULL,
PRIMARY KEY (`document_version_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `documents`
--
@ -844,7 +863,6 @@ CREATE TABLE `documents` (
`document_content` longtext NOT NULL,
`document_content_raw` longtext NOT NULL,
`document_important` tinyint(1) NOT NULL DEFAULT 0,
`document_parent` int(11) NOT NULL DEFAULT 0,
`document_client_visible` int(11) NOT NULL DEFAULT 1,
`document_created_at` datetime NOT NULL DEFAULT current_timestamp(),
`document_updated_at` datetime DEFAULT NULL ON UPDATE current_timestamp(),
@ -2504,4 +2522,4 @@ CREATE TABLE `vendors` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-06-13 15:50:44
-- Dump completed on 2025-06-17 17:56:40

View File

@ -5,4 +5,4 @@
* It is used in conjunction with database_updates.php
*/
DEFINE("LATEST_DATABASE_VERSION", "2.1.5");
DEFINE("LATEST_DATABASE_VERSION", "2.1.6");

View File

@ -20,9 +20,6 @@ if (isset($_POST['add_document'])) {
$document_id = mysqli_insert_id($mysqli);
// Update field document_parent to be the same id as document ID as this is the only version of the document.
mysqli_query($mysqli,"UPDATE documents SET document_parent = $document_id WHERE document_id = $document_id");
if ($contact_id) {
mysqli_query($mysqli,"INSERT INTO contact_documents SET contact_id = $contact_id, document_id = $document_id");
}
@ -66,9 +63,6 @@ if (isset($_POST['add_document_from_template'])) {
$document_id = mysqli_insert_id($mysqli);
// Update field document_parent to be the same id as document ID as this is the only version of the document.
mysqli_query($mysqli,"UPDATE documents SET document_parent = $document_id WHERE document_id = $document_id");
// Logging
logAction("Document", "Create", "$session_name created document $name from template $document_template_name", $client_id, $document_id);
@ -84,45 +78,48 @@ if (isset($_POST['edit_document'])) {
require_once 'document_model.php';
$document_id = intval($_POST['document_id']);
$document_created_by = intval($_POST['created_by']);
$document_parent = intval($_POST['document_parent']);
// Save Original Document as a Version
$sql_original_document = mysqli_query($mysqli, "SELECT * FROM documents
WHERE document_client_id = $client_id AND document_id = $document_id"
);
$row = mysqli_fetch_array($sql_original_document);
$original_document_name = sanitizeInput($row['document_name']);
$original_document_description = sanitizeInput($row['document_description']);
$original_document_content = mysqli_escape_string($mysqli, $row['document_content']);
$original_document_created_by = intval($row['document_created_by']);
$original_document_updated_by = intval($row['document_updated_by']);
$original_document_created_at = sanitizeInput($row['document_created_at']);
$original_document_updated_at = sanitizeInput($row['document_updated_at']);
if ($original_document_updated_at) {
$document_version_created_at = $original_document_updated_at;
} else {
$document_version_created_at = $original_document_created_at;
}
if ($original_document_updated_by) {
$document_version_created_by = $original_document_updated_by;
} else {
$document_version_created_by = $original_document_created_by;
}
// Document add query
mysqli_query($mysqli,"INSERT INTO documents SET document_name = '$name', document_description = '$description', document_content = '$content', document_content_raw = '$content_raw', document_template = 0, document_folder_id = $folder, document_created_by = $document_created_by, document_updated_by = $session_user_id, document_client_id = $client_id");
mysqli_query($mysqli,"INSERT INTO document_versions SET document_version_name = '$original_document_name', document_version_description = '$original_document_description', document_version_content = '$original_document_content', document_version_created_by = $document_version_created_by, document_version_created_at = '$document_version_created_at', document_version_document_id = $document_id");
$new_document_id = mysqli_insert_id($mysqli);
$document_version_id = mysqli_insert_id($mysqli);
// Update the parent ID of the new document to match its new document ID
mysqli_query($mysqli,"UPDATE documents SET document_parent = $new_document_id WHERE document_id = $new_document_id");
// Link all exisiting links with old document with new document
mysqli_query($mysqli,"UPDATE documents SET document_parent = $new_document_id, document_archived_at = NOW() WHERE document_parent = $document_id");
// Update Links to the new parent document
// document files
mysqli_query($mysqli,"UPDATE document_files SET document_id = $new_document_id WHERE document_id = $document_id");
// contact documents
mysqli_query($mysqli,"UPDATE contact_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// asset documents
mysqli_query($mysqli,"UPDATE asset_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// software documents
mysqli_query($mysqli,"UPDATE software_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// vendor documents
mysqli_query($mysqli,"UPDATE vendor_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// Service document
mysqli_query($mysqli,"UPDATE service_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// Update Document
mysqli_query($mysqli,"UPDATE documents SET document_name = '$name', document_description = '$description', document_content = '$content', document_content_raw = '$content_raw', document_folder_id = $folder, document_updated_by = $session_user_id WHERE document_id = $document_id");
//Logging
logAction("Document", "Edit", "$session_name edited document $name, previous version kept", $client_id, $new_document_id);
logAction("Document", "Edit", "$session_name edited document $name, previous version kept", $client_id, $document_version_id);
$_SESSION['alert_message'] = "Document <strong>$name</strong> edited, previous version kept";
header("Location: client_document_details.php?client_id=$client_id&document_id=$new_document_id");
header("Location: client_document_details.php?client_id=$client_id&document_id=$document_id");
}
if (isset($_POST['move_document'])) {
@ -667,24 +664,23 @@ if (isset($_GET['delete_document_version'])) {
enforceUserPermission('module_support', 3);
$document_id = intval($_GET['delete_document_version']);
$document_version_id = intval($_GET['delete_document_version']);
// Get Document Parent ID
$sql = mysqli_query($mysqli,"SELECT document_name, document_parent, document_client_id FROM documents WHERE document_id = $document_id");
// Get Document
$sql = mysqli_query($mysqli,"SELECT document_version_name, document_client_id FROM documents, document_versions WHERE document_version_document_id = document_id AND document_version_id = $document_version_id");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['document_client_id']);
$document_parent = intval($row['document_parent']);
$document_name = sanitizeInput($row['document_name']);
$document_version_name = sanitizeInput($row['document_version_name']);
mysqli_query($mysqli,"DELETE FROM documents WHERE document_id = $document_id");
mysqli_query($mysqli,"DELETE FROM document_versions WHERE document_version_id = $document_version_id");
//Logging
logAction("Document Version", "Delete", "$session_name deleted document version $document_name", $client_id);
logAction("Document Version", "Delete", "$session_name deleted document version $document_version_name", $client_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Document $document_name version deleted";
$_SESSION['alert_message'] = "Document $document_version_name version deleted";
header("Location: client_document_details.php?client_id=$client_id&document_id=$document_parent");
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
@ -703,7 +699,7 @@ if (isset($_GET['delete_document'])) {
mysqli_query($mysqli,"DELETE FROM documents WHERE document_id = $document_id");
// Delete all versions associated with the master document
mysqli_query($mysqli,"DELETE FROM documents WHERE document_parent = $document_id");
mysqli_query($mysqli,"DELETE FROM document_versions WHERE document_version_document_id = $document_id");
//Logging
logAction("Document", "Delete", "$session_name deleted document $document_name and all versions", $client_id);
@ -738,7 +734,7 @@ if (isset($_POST['bulk_delete_documents'])) {
mysqli_query($mysqli,"DELETE FROM documents WHERE document_id = $document_id");
// Delete all versions associated with the master document
mysqli_query($mysqli,"DELETE FROM documents WHERE document_parent = $document_id");
mysqli_query($mysqli,"DELETE FROM document_versions WHERE document_version_document_id = $document_id");
//Logging
logAction("Document", "Delete", "$session_name deleted document $document_name and all versions", $client_id);