diff --git a/code/DMSDocument.php b/code/DMSDocument.php index a422884..340c2de 100644 --- a/code/DMSDocument.php +++ b/code/DMSDocument.php @@ -5,7 +5,12 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { "Folder" => "Varchar(255)", // eg. 0 "Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp" "Description" => 'Text', - "LastChanged" => 'SS_DateTime' //when this document's file was created or last replaced (small changes like updating title don't count) + "LastChanged" => 'SS_DateTime', //when this document's file was created or last replaced (small changes like updating title don't count) + + "EmbargoedForever" => 'Boolean(false)', + "EmbargoedUntilPublished" => 'Boolean(false)', + "EmbargoedUntilDate" => 'SS_DateTime', + "ExpireAtDate" => 'SS_DateTime' ); static $many_many = array( @@ -235,8 +240,26 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * should be used to hide documents that have not yet gone live. * @return null */ - function embargo() { - // TODO: Implement embargo() method. + function embargoForever() { + $this->EmbargoedForever = true; + $this->write(); + } + + /** + * Hides the document until any page it is linked to is published + * @return null + */ + function embargoUntilPublished() { + $this->EmbargoedUntilPublished = true; + $this->write(); + } + + /** + * Returns if this is Document is embargoed or expired. + * @return bool True or False depending on whether this document is embargoed + */ + function isHidden() { + return $this->isEmbargoed() || $this->isExpired(); } /** @@ -244,7 +267,12 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return bool True or False depending on whether this document is embargoed */ function isEmbargoed() { - // TODO: Implement isEmbargoed() method. + $embargoed = false; + if ($this->EmbargoedForever) $embargoed = true; + elseif ($this->EmbargoedUntilPublished) $embargoed = true; + elseif (!empty($this->EmbargoedUntilDate) && SS_Datetime::now()->Value < $this->EmbargoedUntilDate->Value) $embargoed = true; + + return $embargoed; } /** @@ -254,7 +282,8 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return null */ function embargoUntilDate($datetime) { - // TODO: Implement embargoUntilDate() method. + $this->EmbargoedUntilDate = DBField::create_field('SS_Datetime', $datetime);; + $this->write(); } /** @@ -262,17 +291,10 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return null */ function clearEmbargo() { - // TODO: Implement clearEmbargo() method. - } - - /** - * Hides the document, so it does not show up when getByPage($myPage) is called. - * (without specifying the $showEmbargoed = true parameter). This is similar to embargo, except that it should be - * used to hide documents that are no longer useful. - * @return null - */ - function expire() { - // TODO: Implement expire() method. + $this->EmbargoedForever = false; + $this->EmbargoedUntilPublished = false; + $this->EmbargoedUntilDate = null; + $this->write(); } /** @@ -280,7 +302,10 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return bool True or False depending on whether this document is expired */ function isExpired() { - // TODO: Implement isExpired() method. + $expired = false; + if (!empty($this->ExpireAtDate) && SS_Datetime::now()->Value >= $this->ExpireAtDate->Value) $expired = true; + + return $expired; } /** @@ -289,7 +314,8 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return null */ function expireAtDate($datetime) { - // TODO: Implement expireAtDate() method. + $this->ExpireAtDate = DBField::create_field('SS_Datetime', $datetime); + $this->write(); } /** @@ -297,7 +323,8 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { * @return null */ function clearExpiry() { - // TODO: Implement clearExpiry() method. + $this->ExpireAtDate = null; + $this->write(); } /** @@ -328,17 +355,19 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { //delete the file (and previous versions of files) $filesToDelete = array(); $storageFolder = DMS::get_dms_path() . DIRECTORY_SEPARATOR . DMS::get_storage_folder($this->ID); - if ($handle = opendir($storageFolder)) { //Open directory - //List files in the directory - while (false !== ($entry = readdir($handle))) { - if(strpos($entry,$this->ID.'~') !== false) $filesToDelete[] = $entry; - } - closedir($handle); + if (file_exists($storageFolder)) { + if ($handle = opendir($storageFolder)) { //Open directory + //List files in the directory + while (false !== ($entry = readdir($handle))) { + if(strpos($entry,$this->ID.'~') !== false) $filesToDelete[] = $entry; + } + closedir($handle); - //delete all this files that have the id of this document - foreach($filesToDelete as $file) { - $filePath = $storageFolder .DIRECTORY_SEPARATOR . $file; - if (is_file($filePath)) unlink($filePath); + //delete all this files that have the id of this document + foreach($filesToDelete as $file) { + $filePath = $storageFolder .DIRECTORY_SEPARATOR . $file; + if (is_file($filePath)) unlink($filePath); + } } } @@ -594,6 +623,8 @@ class DMSDocument extends DataObject implements DMSDocumentInterface { class DMSDocument_Controller extends Controller { + static $testMode = false; //mode to switch for testing. Does not return document download, just document URL + static $allowed_actions = array( 'index' ); @@ -603,8 +634,10 @@ class DMSDocument_Controller extends Controller { * Returns null, if no document found */ protected function getDocumentFromID($request) { - $id = Convert::raw2sql($request->param('ID')); - return DataObject::get_by_id('DMSDocument', $id); + $doc = null; + $id = Convert::raw2sql(intval($request->param('ID'))); + $doc = DataObject::get_by_id('DMSDocument', $id); + return $doc; } /** @@ -630,7 +663,8 @@ class DMSDocument_Controller extends Controller { $canView = true; } - // TODO: add a check for embargo + // check for embargo or expiry + if ($doc->isHidden()) $canView = false; if ($canView) { $path = $doc->getFullPath(); @@ -658,6 +692,9 @@ class DMSDocument_Controller extends Controller { $mime = 'application/octet-stream'; } } + + if (self::$testMode) return $path; + header('Content-Type: ' . $mime); header('Content-Length: ' . filesize($path), null); if (!empty($mime) && $mime != "text/html") header('Content-Disposition: attachment; filename="'.$doc->getFilenameWithoutID().'"'); @@ -672,6 +709,7 @@ class DMSDocument_Controller extends Controller { } } + if (self::$testMode) return 'This asset does not exist.'; $this->httpError(404, 'This asset does not exist.'); } diff --git a/code/DMSSiteTreeExtension.php b/code/DMSSiteTreeExtension.php index fb47f0c..68982d0 100644 --- a/code/DMSSiteTreeExtension.php +++ b/code/DMSSiteTreeExtension.php @@ -65,4 +65,15 @@ class DMSSiteTreeExtension extends DataExtension { } } } + + function onBeforePublish() { + $embargoedDocuments = $this->owner->Documents()->filter('EmbargoedUntilPublished',true); + if ($embargoedDocuments->Count() > 0) { + foreach($embargoedDocuments as $doc) { + $doc->EmbargoedUntilPublished = false; + $doc->write(); + } + } + + } } \ No newline at end of file diff --git a/code/interface/DMSDocumentInterface.php b/code/interface/DMSDocumentInterface.php index 752bc00..73231b2 100644 --- a/code/interface/DMSDocumentInterface.php +++ b/code/interface/DMSDocumentInterface.php @@ -158,7 +158,15 @@ interface DMSDocumentInterface { * @abstract * @return null */ - function embargo(); + function embargoForever(); + + /** + * Returns if this is DMSDocument is embargoed or expired. + * @abstract + * @return bool True or False depending on whether this DMSDocument is embargoed or expired + */ + function isHidden(); + /** * Returns if this is DMSDocument is embargoed. @@ -176,6 +184,12 @@ interface DMSDocumentInterface { */ function embargoUntilDate($datetime); + /** + * Hides the document until any page it is linked to is published + * @return null + */ + function embargoUntilPublished(); + /** * Clears any previously set embargos, so the DMSDocument always shows up in all queries. * @abstract @@ -183,15 +197,6 @@ interface DMSDocumentInterface { */ function clearEmbargo(); - /** - * Hides the DMSDocument, so it does not show up when getByPage($myPage) is called. - * (without specifying the $showEmbargoed = true parameter). This is similar to embargo, except that it should be - * used to hide DMSDocuments that are no longer useful. - * @abstract - * @return null - */ - function expire(); - /** * Returns if this is DMSDocument is expired. * @abstract diff --git a/tests/DMSEmbargoTest.php b/tests/DMSEmbargoTest.php new file mode 100644 index 0000000..eddf988 --- /dev/null +++ b/tests/DMSEmbargoTest.php @@ -0,0 +1,187 @@ +delete(); + } + $t = DataObject::get("DMSTag"); + foreach($t as $t1) { + $t1->delete(); + } + } + + function createFakeHTTPRequest($id) { + $r = new SS_HTTPRequest('GET','index/'.$id); + $r->match('index/$ID'); + return $r; + } + + function testBasicEmbargo() { + $oldDMSFolder = DMS::$dmsFolder; + DMS::$dmsFolder = 'dms'; //sneakily setting the DMS folder to the folder where the test file lives + + $doc = new DMSDocument(); + $doc->Filename = "DMS-test-lorum-file.pdf"; + $doc->Folder = "tests"; + $docID = $doc->write(); + + //fake a request for a document + $controller = new DMSDocument_Controller(); + DMSDocument_Controller::$testMode = true; + $result = $controller->index($this->createFakeHTTPRequest($docID)); + $this->assertEquals($doc->getFullPath(),$result,"Correct underlying file returned (in test mode)"); + + $doc->embargoForever(); + + $result = $controller->index($this->createFakeHTTPRequest($docID)); + $this->assertNotEquals($doc->getFullPath(),$result,"File no longer returned (in test mode)"); + + DMS::$dmsFolder = $oldDMSFolder; + } + + function testEmbargoForever() { + $doc = new DMSDocument(); + $doc->Filename = "DMS-test-lorum-file.pdf"; + $doc->Folder = "tests"; + $doc->write(); + + $doc->embargoForever(); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $doc->clearEmbargo(); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + } + + function testExpireAtDate() { + $doc = new DMSDocument(); + $doc->Filename = "DMS-test-lorum-file.pdf"; + $doc->Folder = "tests"; + $doc->write(); + + $doc->expireAtDate(strtotime('-1 second')); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertTrue($doc->isExpired(),"Document is expired"); + + $expireTime = "2019-04-05 11:43:13"; + $doc->expireAtDate($expireTime); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + SS_Datetime::set_mock_now($expireTime); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertTrue($doc->isExpired(),"Document is expired"); + SS_Datetime::clear_mock_now(); + + $doc->expireAtDate(strtotime('-1 second')); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertTrue($doc->isExpired(),"Document is expired"); + + $doc->clearExpiry(); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + } + + function testEmbargoUntilDate() { + $doc = new DMSDocument(); + $doc->Filename = "DMS-test-lorum-file.pdf"; + $doc->Folder = "tests"; + $doc->write(); + + $doc->embargoUntilDate(strtotime('+1 minute')); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $doc->embargoUntilDate(strtotime('-1 second')); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $embargoTime = "2019-04-05 11:43:13"; + $doc->embargoUntilDate($embargoTime); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + SS_Datetime::set_mock_now($embargoTime); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + SS_Datetime::clear_mock_now(); + + $doc->clearEmbargo(); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + } + + function testEmbargoUntilPublished() { + $s1 = $this->objFromFixture('SiteTree','s1'); + + $doc = new DMSDocument(); + $doc->Filename = "test file"; + $doc->Folder = "0"; + $dID = $doc->write(); + + $doc->addPage($s1); + + $s1->publish('Stage','Live'); + $s1->doPublish(); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $doc->embargoUntilPublished(); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $s1->publish('Stage','Live'); + $s1->doPublish(); + $doc = DataObject::get_by_id("DMSDocument",$dID); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $doc->embargoUntilPublished(); + $doc = DataObject::get_by_id("DMSDocument",$dID); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $doc->embargoForever(); + $doc = DataObject::get_by_id("DMSDocument",$dID); + $this->assertTrue($doc->isHidden(),"Document is hidden"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $s1->publish('Stage','Live'); + $s1->doPublish(); + $doc = DataObject::get_by_id("DMSDocument",$dID); + $this->assertTrue($doc->isHidden(),"Document is still hidden because although the untilPublish flag is cleared, the forever flag is still there"); + $this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + + $doc->clearEmbargo(); + $doc = DataObject::get_by_id("DMSDocument",$dID); + $this->assertFalse($doc->isHidden(),"Document is not hidden"); + $this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); + $this->assertFalse($doc->isExpired(),"Document is not expired"); + } +} \ No newline at end of file diff --git a/tests/DMSTagTest.php b/tests/DMSTagTest.php index 46c955c..bd47fdb 100644 --- a/tests/DMSTagTest.php +++ b/tests/DMSTagTest.php @@ -1,8 +1,6 @@