mirror of
https://github.com/silverstripe/silverstripe-dms
synced 2024-10-22 14:05:56 +02:00
211 lines
6.2 KiB
PHP
211 lines
6.2 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* DataObject to store versions of uploaded Documents. Versions are only created when replacing a document, not on every
|
||
|
* save of the DMSDocument dataobject. So, versions store the various versions of the underlying Document, not the
|
||
|
* DataObject with information about that object.
|
||
|
*/
|
||
|
class DMSDocument_versions extends DataObject {
|
||
|
|
||
|
static $enable_versions = true; //flag that turns on or off versions of documents when replacing them
|
||
|
|
||
|
static $db = array(
|
||
|
'VersionCounter' => 'Int',
|
||
|
'VersionViewCount' => 'Int'
|
||
|
); //config system call in _config creates this to mirror DMSDocument
|
||
|
|
||
|
static $has_one = array(
|
||
|
'Document' => 'DMSDocument' //ID of the original DMSDocument object this is a version of
|
||
|
);
|
||
|
|
||
|
static $defaults = array(
|
||
|
'VersionCounter' => 0
|
||
|
);
|
||
|
|
||
|
static $display_fields = array(
|
||
|
'VersionCounter' => 'VersionCounter',
|
||
|
'FilenameWithoutID' => 'Filename',
|
||
|
'LastChanged' => 'LastChanged'
|
||
|
);
|
||
|
|
||
|
static $summary_fields = array(
|
||
|
'VersionCounter',
|
||
|
'FilenameWithoutID'
|
||
|
);
|
||
|
|
||
|
static $field_labels = array(
|
||
|
'FilenameWithoutID'=>'Filename'
|
||
|
);
|
||
|
|
||
|
static $default_sort = array(
|
||
|
'LastChanged' => 'DESC'
|
||
|
);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Creates a new version of a document by moving the current file and renaming it to the versioned filename.
|
||
|
* This method assumes that the method calling this is just about to upload a new file to replace the old file.
|
||
|
* @static
|
||
|
* @param DMSDocument $doc
|
||
|
* @return bool Success or failure
|
||
|
*/
|
||
|
static function create_version(DMSDocument $doc) {
|
||
|
$success = false;
|
||
|
|
||
|
$existingPath = $doc->getFullPath();
|
||
|
if (is_file($existingPath)) {
|
||
|
$version = new DMSDocument_versions($doc); //create a copy of the current DMSDocument as a version
|
||
|
|
||
|
$previousVersionCounter = 0;
|
||
|
$newestExistingVersion = self::get_versions($doc)->sort(array('Created'=>'DESC','ID'=>'DESC'))->limit(1);
|
||
|
if ($newestExistingVersion && $newestExistingVersion->Count() > 0) {
|
||
|
$previousVersionCounter = $newestExistingVersion->first()->VersionCounter;
|
||
|
}
|
||
|
|
||
|
//change the filename field to a field containing the new soon-to-be versioned file
|
||
|
$version->VersionCounter = $previousVersionCounter + 1; //start versions at 1
|
||
|
$newFilename = $version->generateVersionedFilename($doc, $version->VersionCounter);
|
||
|
$version->Filename = $newFilename;
|
||
|
|
||
|
//add a relation back to the origin ID;
|
||
|
$version->DocumentID = $doc->ID;
|
||
|
$id = $version->write();
|
||
|
|
||
|
if (!empty($id)) {
|
||
|
rename($existingPath, $version->getFullPath());
|
||
|
$success = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $success;
|
||
|
}
|
||
|
|
||
|
public function delete() {
|
||
|
$path = $this->getFullPath();
|
||
|
if (file_exists($path)) unlink($path);
|
||
|
|
||
|
parent::delete();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a DataList of all previous Versions of a document (check the LastEdited date of each
|
||
|
* object to find the correct one)
|
||
|
* @static
|
||
|
* @param DMSDocument $doc
|
||
|
* @return DataList List of Document objects
|
||
|
*/
|
||
|
static function get_versions(DMSDocument $doc) {
|
||
|
if (!DMSDocument_versions::$enable_versions) user_error("DMSDocument versions are disabled",E_USER_WARNING);
|
||
|
return DMSDocument_versions::get()->filter(array('DocumentID' => $doc->ID));
|
||
|
}
|
||
|
|
||
|
public function __construct($record = null, $isSingleton = false, $model = null) {
|
||
|
//check what the constructor was passed
|
||
|
$dmsObject = null;
|
||
|
if ($record && is_subclass_of($record,'DMSDocumentInterface')) {
|
||
|
$dmsObject = $record;
|
||
|
$record = null; //cancel the record creation to just create an empty object
|
||
|
}
|
||
|
|
||
|
//create the object
|
||
|
parent::__construct($record, $isSingleton, $model);
|
||
|
|
||
|
//copy the DMSDocument object, if passed into the constructor
|
||
|
if ($dmsObject) {
|
||
|
foreach(array_keys(DataObject::custom_database_fields($dmsObject->ClassName)) as $key) {
|
||
|
$this->$key = $dmsObject->$key;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a link to download this document from the DMS store
|
||
|
* @return String
|
||
|
*/
|
||
|
function getLink() {
|
||
|
return Controller::join_links(Director::baseURL(),'dmsdocument/version'.$this->ID);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Document versions are always hidden from outside viewing. Only admins can download them
|
||
|
* @return bool
|
||
|
*/
|
||
|
function isHidden() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the full filename of the document stored in this object. Can optionally specify which filename to use at the end
|
||
|
* @return string
|
||
|
*/
|
||
|
function getFullPath($filename = null) {
|
||
|
if (!$filename) $filename = $this->Filename;
|
||
|
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $filename;
|
||
|
}
|
||
|
|
||
|
function getFilenameWithoutID() {
|
||
|
$filenameParts = explode('~',$this->Filename);
|
||
|
$filename = array_pop($filenameParts);
|
||
|
return $filename;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a new filename for the current Document's file when replacing the current file with a new file
|
||
|
* @param $filename The original filename to generate the versioned filename from
|
||
|
* @return String The new filename
|
||
|
*/
|
||
|
protected function generateVersionedFilename(DMSDocument $doc, $versionCounter) {
|
||
|
$filename = $doc->Filename;
|
||
|
|
||
|
do {
|
||
|
$versionPaddingString = str_pad($versionCounter, 4, '0', STR_PAD_LEFT); //add leading zeros to make sorting accurate up to 10,000 documents
|
||
|
$newVersionFilename = preg_replace('/([0-9]+~)(.*?)/','$1~'.$versionPaddingString.'~$2',$filename);
|
||
|
|
||
|
if ($newVersionFilename == $filename || empty($newVersionFilename)) { //sanity check for crazy document names
|
||
|
user_error('Cannot generate new document filename for file: '.$filename,E_USER_ERROR);
|
||
|
}
|
||
|
|
||
|
$versionCounter++; //increase the counter for the next loop run, if necessary
|
||
|
} while(file_exists($this->getFullPath($newVersionFilename)));
|
||
|
|
||
|
return $newVersionFilename;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the extension of the file associated with the document
|
||
|
*/
|
||
|
function getExtension() {
|
||
|
return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION));
|
||
|
}
|
||
|
|
||
|
function getSize() {
|
||
|
$size = $this->getAbsoluteSize();
|
||
|
return ($size) ? File::format_size($size) : false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the size of the file associated with the document
|
||
|
*/
|
||
|
function getAbsoluteSize() {
|
||
|
return filesize($this->getFullPath());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* An alias to DMSDocument::getSize()
|
||
|
*/
|
||
|
function getFileSizeFormatted(){
|
||
|
return $this->getSize();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
|
||
|
*/
|
||
|
function trackView(){
|
||
|
if ($this->ID > 0) {
|
||
|
$count = $this->VersionViewCount + 1;
|
||
|
DB::query("UPDATE \"DMSDocument_versions\" SET \"VersionViewCount\"='$count' WHERE \"ID\"={$this->ID}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
?>
|