From 17ea520f98bb6b1ad80f81fbc3235985d3509e1a Mon Sep 17 00:00:00 2001 From: Julian Seidenberg Date: Fri, 27 Jul 2012 17:38:20 +1200 Subject: [PATCH] ENHANCEMENT: download link functionality --- _config/routes.yml | 7 +++ code/DMS.php | 7 ++- code/DMSDocument.php | 100 ++++++++++++++++++++++++++++++++++++++++--- tests/DMSTest.php | 26 +++++++++-- 4 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 _config/routes.yml diff --git a/_config/routes.yml b/_config/routes.yml new file mode 100644 index 0000000..e6b38ba --- /dev/null +++ b/_config/routes.yml @@ -0,0 +1,7 @@ +--- +Name: dmsdocument +After: framework/routes#coreroutes +--- +Director: + rules: + 'dmsdocument/$ID' : 'DMSDocument_Controller' \ No newline at end of file diff --git a/code/DMS.php b/code/DMS.php index 8949f89..7988185 100644 --- a/code/DMS.php +++ b/code/DMS.php @@ -13,6 +13,7 @@ class DMS implements DMSInterface { self::$modelClass = $className; } + /** * Factory method that returns an instance of the DMS. This could be any class that implements the DMSInterface. * @static @@ -22,10 +23,14 @@ class DMS implements DMSInterface { self::$dmsPath = BASE_PATH . DIRECTORY_SEPARATOR . self::$dmsFolder; $dms = new DMS(); - self::createStorageFolder(self::$dmsPath); + self::createStorageFolder(self::get_DMS_path()); return $dms; } + static function get_DMS_path() { + return BASE_PATH . DIRECTORY_SEPARATOR . self::$dmsFolder; + } + static function transformFileToFilePath($file) { //confirm we have a file $filePath = null; diff --git a/code/DMSDocument.php b/code/DMSDocument.php index 9bce72d..2b09dde 100644 --- a/code/DMSDocument.php +++ b/code/DMSDocument.php @@ -226,7 +226,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return String */ function downloadLink() { - // TODO: Implement downloadLink() method. + return Controller::join_links(Director::baseURL(),'dmsdocument/'.$this->ID); } /** @@ -314,7 +314,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return string */ function getFullPath() { - return DMS::$dmsPath . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename; + return DMS::get_DMS_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename; } /** @@ -326,7 +326,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { $this->removeAllTags(); //delete the file - unlink($this->getFullPath()); + if (is_file($this->getFullPath())) unlink($this->getFullPath()); $this->removeAllPages(); @@ -341,8 +341,8 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { $fromFilename = basename($filePath); $toFilename = $this->ID. '~' . $fromFilename; //add the docID to the start of the Filename $toFolder = DMS::getStorageFolder($this->ID); - $toPath = DMS::$dmsPath . DIRECTORY_SEPARATOR . $toFolder . DIRECTORY_SEPARATOR . $toFilename; - DMS::createStorageFolder(DMS::$dmsPath . DIRECTORY_SEPARATOR . $toFolder); + $toPath = DMS::get_DMS_path() . DIRECTORY_SEPARATOR . $toFolder . DIRECTORY_SEPARATOR . $toFilename; + DMS::createStorageFolder(DMS::get_DMS_path() . DIRECTORY_SEPARATOR . $toFolder); //copy the file into place $fromPath = BASE_PATH . DIRECTORY_SEPARATOR . $filePath; @@ -371,4 +371,92 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { return $doc; } -} \ No newline at end of file + function getCMSFields() { + $fields = parent::getCMSFields(); + return $fields; + } + +} + +class DMSDocument_Controller extends Controller { + static $allowed_actions = array( + 'index' + ); + + protected static function get_file_extension($filename) { + return pathinfo($filename, PATHINFO_EXTENSION); + } + + /** + * Access the file download without redirecting user, so we can block direct access to documents. + */ + function index(SS_HTTPRequest $request) { + $id = Convert::raw2sql($this->getRequest()->param('ID')); + Debug::show($id); + if (!empty($id)) $doc = DataObject::get_by_id('DMSDocument', $id); + if (!empty($doc)) { + Debug::Show($doc); + $canView = false; + + //Runs through all pages that this page links to and sets canView to true if the user can view ONE of these pages + $pages = $doc->Pages(); + if ($pages->Count() > 0) { + foreach($pages as $page) { + if ($page->CanView()) { + $canView = true; //just one canView is enough to know that we can view the file + break; + } + } + } else { + //if the document isn't on any page, then allow viewing of the document (because there is no canView() to consult) + $canView = true; + } + + // TODO: add a check for embargo + + if ($canView) { + $path = $doc->getFullPath(); + Debug::Show($path); + if ( is_file($path) ) { + $fileBin = trim(`whereis file`); + Debug::Show($fileBin); + if ( function_exists('finfo_file') ) { + // discover the mime type properly + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_file($finfo, $path); + } + else if ( is_executable($fileBin) ) { + // try to use the system tool + $mime = `$fileBin -i -b $path`; + $mime = explode(';', $mime); + $mime = trim($mime[0]); + } + else { + // make do with what we have + $ext = self::get_file_extension($path); + if ( $ext =='pdf') { + $mime = 'application/pdf'; + }elseif ($ext == 'html' || $ext =='htm') { + $mime = 'text/html'; + }else { + $mime = 'application/octet-stream'; + } + } + header('Content-Type: ' . $mime); + header('Content-Length: ' . filesize($path), null); + if (!empty($mime) && $mime != "text/html") header('Content-Disposition: attachment; filename="'.basename($path).'"'); + header('Content-transfer-encoding: 8bit'); + header('Expires: 0'); + header('Pragma: cache'); + header('Cache-Control: private'); + flush(); + readfile($path); + exit; + } + } + } + + $this->httpError(404, 'This asset does not exist.'); + } +} + diff --git a/tests/DMSTest.php b/tests/DMSTest.php index dd029fc..3454275 100644 --- a/tests/DMSTest.php +++ b/tests/DMSTest.php @@ -1,5 +1,5 @@ delete(); @@ -64,7 +68,7 @@ class DMSTest extends SapphireTest { $document = $dms->storeDocument($file); $this->assertNotNull($document, "Document object created"); - $this->assertTrue(file_exists(DMS::$dmsPath . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); + $this->assertTrue(file_exists(DMS::get_DMS_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); //$title = $document->getTag('title'); } @@ -93,7 +97,7 @@ class DMSTest extends SapphireTest { //test we created 4 folder to contain the 17 files foreach($folders as $f) { - $this->assertTrue(is_dir(DMS::$dmsPath . DIRECTORY_SEPARATOR . $f),"Document folder '$f' exists"); + $this->assertTrue(is_dir(DMS::get_DMS_path() . DIRECTORY_SEPARATOR . $f),"Document folder '$f' exists"); } } @@ -110,11 +114,25 @@ class DMSTest extends SapphireTest { $document = $document->replaceDocument(self::$testFile2); $this->assertNotNull($document, "Document object created"); - $this->assertTrue(file_exists(DMS::$dmsPath . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); + $this->assertTrue(file_exists(DMS::get_DMS_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); $this->assertContains("DMS-test-document-2",$document->Filename, "Original document filename is contain in the new filename"); $this->assertEquals("My custom title", $document->Title , "Custom title not modified"); $this->assertEquals("My custom description", $document->Description, "Custom description not modified"); } + function testDownloadDocument() { +// $dms = DMS::getDMSInstance(); +// +// //store the first document +// $document = $dms->storeDocument(self::$testFile); +// $link = $document->downloadLink(); +// +// Debug::Show($link); +// $d=new DMSDocument_Controller(); +// $response = $d->index(new SS_HTTPRequest('GET',$link,array("ID"=>$document->ID))); +// //$response = $this->get($link); +// Debug::show($response); + } + } \ No newline at end of file