From 9c0ec616d151f87c0d8fa033f12e3cb36a308006 Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Mon, 1 May 2017 16:29:04 +1200 Subject: [PATCH 1/2] NEW Relate documents to other documents * Modularise templates, add missing localisations, add related documents to template * Add getRelatedDocuments as an extensible getter in DMSDocument --- code/model/DMSDocument.php | 101 +++++++++-------- lang/en.yml | 3 + templates/Includes/Document.ss | 37 +++---- templates/Includes/DocumentDetails.ss | 4 + templates/Includes/Documents.ss | 8 +- templates/Includes/RelatedDocuments.ss | 14 +++ tests/DMSDocumentTest.php | 116 +++++++++++++++----- tests/Stub/StubRelatedDocumentExtension.php | 18 +++ tests/dmstest.yml | 8 +- 9 files changed, 213 insertions(+), 96 deletions(-) create mode 100644 templates/Includes/DocumentDetails.ss create mode 100644 templates/Includes/RelatedDocuments.ss create mode 100644 tests/Stub/StubRelatedDocumentExtension.php diff --git a/code/model/DMSDocument.php b/code/model/DMSDocument.php index ead12bb..48b57f8 100644 --- a/code/model/DMSDocument.php +++ b/code/model/DMSDocument.php @@ -23,6 +23,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface private static $many_many = array( 'Pages' => 'SiteTree', + 'RelatedDocuments' => 'DMSDocument', 'Tags' => 'DMSTag' ); @@ -1012,19 +1013,19 @@ class DMSDocument extends DataObject implements DMSDocumentInterface $versionsGridFieldConfig ); $extraTasks .= '
  • Versions
  • '; - //$extraFields = $versionsGrid->addExtraClass('find-versions'); } $fields->add(new LiteralField( 'BottomTaskSelection', - '
    ' + '
    ' )); $embargoValue = 'None'; @@ -1076,27 +1077,13 @@ class DMSDocument extends DataObject implements DMSDocumentInterface // These are toggled on and off via the Actions Buttons above // exit('hit'); $actionsPanel = FieldGroup::create( - - FieldGroup::create( - $embargo, - $embargoDatetime - )->addExtraClass('embargo'), - FieldGroup::create( - $expiry, - $expiryDatetime - )->addExtraClass('expiry'), - FieldGroup::create( - $uploadField - )->addExtraClass('replace'), - FieldGroup::create( - $pagesGrid - )->addExtraClass('find-usage'), - FieldGroup::create( - $referencesGrid - )->addExtraClass('find-references'), - FieldGroup::create( - $versionsGrid - )->addExtraClass('find-versions') + FieldGroup::create($embargo, $embargoDatetime)->addExtraClass('embargo'), + FieldGroup::create($expiry, $expiryDatetime)->addExtraClass('expiry'), + FieldGroup::create($uploadField)->addExtraClass('replace'), + FieldGroup::create($pagesGrid)->addExtraClass('find-usage'), + FieldGroup::create($referencesGrid)->addExtraClass('find-references'), + FieldGroup::create($versionsGrid)->addExtraClass('find-versions'), + FieldGroup::create($this->getRelatedDocumentsGridField())->addExtraClass('find-relateddocuments') ); $actionsPanel->setName("ActionsPanel"); @@ -1104,22 +1091,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface $fields->push($actionsPanel); - // $fields->add(FieldGroup::create( - // FieldGroup::create( - // $embargo, - // $embargoDatetime - // )->addExtraClass('embargo'), - // FieldGroup::create( - // $expiry, - // $expiryDatetime - // )->addExtraClass('expiry'), - // $uploadField->addExtraClass('replace'), - // $pagesGrid->addExtraClass('find-usage'), - // $referencesGrid->addExtraClass('find-references'), - // $extraFields - // )->setName("ActionsPanel")->addExtraClass('dmsupload ss-uploadfield')); - - $this->extend('updateCMSFields', $fields); return $fields; @@ -1313,4 +1284,42 @@ class DMSDocument extends DataObject implements DMSDocumentInterface return $this; } + + /** + * Get a data list of documents related to this document + * + * @return DataList + */ + public function getRelatedDocuments() + { + $documents = $this->RelatedDocuments(); + + $this->extend('updateRelatedDocuments', $documents); + + return $documents; + } + + /** + * Get a GridField for managing related documents + * + * @return GridField + */ + protected function getRelatedDocumentsGridField() + { + $gridField = GridField::create( + 'RelatedDocuments', + _t('DMSDocument.RELATEDDOCUMENTS', 'Related Documents'), + $this->RelatedDocuments(), + new GridFieldConfig_RelationEditor + ); + + $gridField->getConfig()->removeComponentsByType('GridFieldAddNewButton'); + // Move the autocompleter to the left + $gridField->getConfig()->removeComponentsByType('GridFieldAddExistingAutocompleter'); + $gridField->getConfig()->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-left')); + + $this->extend('updateRelatedDocumentsGridField', $gridField); + + return $gridField; + } } diff --git a/lang/en.yml b/lang/en.yml index ed30a1b..23d1ffc 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -14,6 +14,8 @@ en: RelatedReferences: 'Related References' SINGULARNAME: Document Versions: Versions + DOWNLOAD: "Download {title}" + LASTCHANGED: "Last changed: {date}" DMSTag: PLURALNAME: 'D M S Tags' SINGULARNAME: 'D M S Tag' @@ -35,6 +37,7 @@ en: DMSDocumentAddController: MENUTITLE: 'Edit Page' NODOCUMENTS: 'There are no documents attached to the selected page.' + RELATEDDOCUMENTS: 'Related Documents' DMSDocument_versions: PLURALNAME: 'D M S Document_versionss' SINGULARNAME: 'D M S Document_versions' diff --git a/templates/Includes/Document.ss b/templates/Includes/Document.ss index 4514a23..9e0d6cc 100644 --- a/templates/Includes/Document.ss +++ b/templates/Includes/Document.ss @@ -1,19 +1,18 @@ -<% if isHidden != true %> -
    - <% if Title %> -

    $Title

    - <% else %> -

    $FilenameWithoutID

    - <% end_if %> - -

    - $FilenameWithoutID - | $Extension - | $FileSizeFormatted - | Last Changed: $LastChanged.Nice -

    - <% if Description %> -

    $DescriptionWithLineBreak

    - <% end_if %> -
    -<% end_if %> \ No newline at end of file +<% if $isHidden != true %> +
    + <% if $Title %> +

    ">$Title

    + <% else %> +

    ">$FilenameWithoutID

    + <% end_if %> + +

    <% include DocumentDetails %>

    + <% if $Description %> +

    $DescriptionWithLineBreak

    + <% end_if %> + + <% if $RelatedDocuments %> + <% include RelatedDocuments %> + <% end_if %> +
    +<% end_if %> diff --git a/templates/Includes/DocumentDetails.ss b/templates/Includes/DocumentDetails.ss new file mode 100644 index 0000000..25a90d7 --- /dev/null +++ b/templates/Includes/DocumentDetails.ss @@ -0,0 +1,4 @@ +$FilenameWithoutID +| $Extension +| $FileSizeFormatted +| <%t DMSDocument.LASTCHANGED "Last changed: {date}" date=$LastChanged.Nice %> \ No newline at end of file diff --git a/templates/Includes/Documents.ss b/templates/Includes/Documents.ss index 8832616..516d8f2 100644 --- a/templates/Includes/Documents.ss +++ b/templates/Includes/Documents.ss @@ -1,4 +1,8 @@ <% if PageDocuments %> -

    Documents:

    - <% loop PageDocuments %><% include Document %><% end_loop %> +
    +

    <%t DMSDocument.PLURALNAME "Documents" %>

    + <% loop PageDocuments %> + <% include Document %> + <% end_loop %> +
    <% end_if %> diff --git a/templates/Includes/RelatedDocuments.ss b/templates/Includes/RelatedDocuments.ss new file mode 100644 index 0000000..f648a54 --- /dev/null +++ b/templates/Includes/RelatedDocuments.ss @@ -0,0 +1,14 @@ +
    <%t DMSDocument.RELATED_DOCUMENTS "Related documents" %>
    + + diff --git a/tests/DMSDocumentTest.php b/tests/DMSDocumentTest.php index 0e4138a..10f3660 100644 --- a/tests/DMSDocumentTest.php +++ b/tests/DMSDocumentTest.php @@ -1,17 +1,17 @@ delete(); } - $t = DataObject::get("DMSTag"); + $t = DataObject::get('DMSTag'); foreach ($t as $t1) { $t1->delete(); } @@ -32,12 +32,12 @@ class DMSDocumentTest extends SapphireTest $pages = $d1->Pages(); $pagesArray = $pages->toArray(); - $this->assertEquals($pagesArray[0]->ID, $s1->ID, "Page 1 associated correctly"); - $this->assertEquals($pagesArray[1]->ID, $s2->ID, "Page 2 associated correctly"); - $this->assertEquals($pagesArray[2]->ID, $s3->ID, "Page 3 associated correctly"); - $this->assertEquals($pagesArray[3]->ID, $s4->ID, "Page 4 associated correctly"); - $this->assertEquals($pagesArray[4]->ID, $s5->ID, "Page 5 associated correctly"); - $this->assertEquals($pagesArray[5]->ID, $s6->ID, "Page 6 associated correctly"); + $this->assertEquals($pagesArray[0]->ID, $s1->ID, 'Page 1 associated correctly'); + $this->assertEquals($pagesArray[1]->ID, $s2->ID, 'Page 2 associated correctly'); + $this->assertEquals($pagesArray[2]->ID, $s3->ID, 'Page 3 associated correctly'); + $this->assertEquals($pagesArray[3]->ID, $s4->ID, 'Page 4 associated correctly'); + $this->assertEquals($pagesArray[4]->ID, $s5->ID, 'Page 5 associated correctly'); + $this->assertEquals($pagesArray[5]->ID, $s6->ID, 'Page 6 associated correctly'); } public function testAddPageRelation() @@ -47,8 +47,8 @@ class DMSDocumentTest extends SapphireTest $s3 = $this->objFromFixture('SiteTree', 's3'); $doc = new DMSDocument(); - $doc->Filename = "test file"; - $doc->Folder = "0"; + $doc->Filename = 'test file'; + $doc->Folder = '0'; $doc->write(); $doc->addPage($s1); @@ -57,15 +57,15 @@ class DMSDocumentTest extends SapphireTest $pages = $doc->Pages(); $pagesArray = $pages->toArray(); - $this->assertEquals($pagesArray[0]->ID, $s1->ID, "Page 1 associated correctly"); - $this->assertEquals($pagesArray[1]->ID, $s2->ID, "Page 2 associated correctly"); - $this->assertEquals($pagesArray[2]->ID, $s3->ID, "Page 3 associated correctly"); + $this->assertEquals($pagesArray[0]->ID, $s1->ID, 'Page 1 associated correctly'); + $this->assertEquals($pagesArray[1]->ID, $s2->ID, 'Page 2 associated correctly'); + $this->assertEquals($pagesArray[2]->ID, $s3->ID, 'Page 3 associated correctly'); $doc->removePage($s1); $pages = $doc->Pages(); $pagesArray = $pages->toArray(); // Page 1 is missing - $this->assertEquals($pagesArray[0]->ID, $s2->ID, "Page 2 still associated correctly"); - $this->assertEquals($pagesArray[1]->ID, $s3->ID, "Page 3 still associated correctly"); + $this->assertEquals($pagesArray[0]->ID, $s2->ID, 'Page 2 still associated correctly'); + $this->assertEquals($pagesArray[1]->ID, $s3->ID, 'Page 3 still associated correctly'); $documents = $s2->Documents(); $documentsArray = $documents->toArray(); @@ -74,16 +74,16 @@ class DMSDocumentTest extends SapphireTest array('Filename' => $doc->Filename) ), $documentsArray, - "Document associated with page" + 'Document associated with page' ); $doc->removeAllPages(); $pages = $doc->Pages(); - $this->assertEquals($pages->Count(), 0, "All pages removed"); + $this->assertEquals($pages->Count(), 0, 'All pages removed'); $documents = $s2->Documents(); $documentsArray = $documents->toArray(); - $this->assertNotContains($doc, $documentsArray, "Document no longer associated with page"); + $this->assertNotContains($doc, $documentsArray, 'Document no longer associated with page'); } public function testDeletingPageWithAssociatedDocuments() @@ -94,8 +94,8 @@ class DMSDocumentTest extends SapphireTest $s2ID = $s2->ID; $doc = new DMSDocument(); - $doc->Filename = "delete test file"; - $doc->Folder = "0"; + $doc->Filename = 'delete test file'; + $doc->Folder = '0'; $doc->write(); $doc->addPage($s1); @@ -125,8 +125,8 @@ class DMSDocumentTest extends SapphireTest $this->assertEquals( $documents->Count(), '0', - "However, deleting the live version of the last page that a document is " - ."associated with causes that document to be deleted as well" + 'However, deleting the live version of the last page that a document is ' + . 'associated with causes that document to be deleted as well' ); } @@ -137,8 +137,8 @@ class DMSDocumentTest extends SapphireTest $s2ID = $s2->ID; $doc = new DMSDocument(); - $doc->Filename = "delete test file"; - $doc->Folder = "0"; + $doc->Filename = 'delete test file'; + $doc->Folder = '0'; $doc->write(); $doc->addPage($s2); @@ -158,8 +158,8 @@ class DMSDocumentTest extends SapphireTest $this->assertEquals( $documents->Count(), '0', - "However, deleting the draft version of the last page that a document is " - ."associated with causes that document to be deleted as well" + 'However, deleting the draft version of the last page that a document is ' + . 'associated with causes that document to be deleted as well' ); } @@ -175,4 +175,66 @@ class DMSDocumentTest extends SapphireTest $cmsFields = $document->getCMSFields(); $this->assertEquals('download', $cmsFields->dataFieldByName('DownloadBehavior')->Value()); } + + /** + * Ensure that related documents can be retrieved for a given DMS document + */ + public function testRelatedDocuments() + { + $document = $this->objFromFixture('DMSDocument', 'document_with_relations'); + $this->assertGreaterThan(0, $document->RelatedDocuments()->count()); + $this->assertEquals( + array('test-file-file-doesnt-exist-1', 'test-file-file-doesnt-exist-2'), + $document->getRelatedDocuments()->column('Filename') + ); + } + + /** + * Test the extensibility of getRelatedDocuments + */ + public function testGetRelatedDocumentsIsExtensible() + { + DMSDocument::add_extension('StubRelatedDocumentExtension'); + + $emptyDocument = new DMSDocument; + $relatedDocuments = $emptyDocument->getRelatedDocuments(); + + $this->assertCount(1, $relatedDocuments); + $this->assertSame('Extended', $relatedDocuments->first()->Filename); + } + + /** + * Ensure that the DMS Document CMS actions contains a grid field for managing related documents + */ + public function testDocumentHasCmsFieldForManagingRelatedDocuments() + { + $document = $this->objFromFixture('DMSDocument', 'document_with_relations'); + + $documentFields = $document->getCMSFields(); + /** @var FieldGroup $actions */ + $actions = $documentFields->fieldByName('ActionsPanel'); + + $gridField = null; + foreach ($actions->getChildren() as $child) { + /** @var FieldGroup $child */ + if ($gridField = $child->fieldByName('RelatedDocuments')) { + break; + } + } + $this->assertInstanceOf('GridField', $gridField); + + /** @var GridFieldConfig $gridFieldConfig */ + $gridFieldConfig = $gridField->getConfig(); + + $this->assertNotNull( + 'GridFieldAddExistingAutocompleter', + $addExisting = $gridFieldConfig->getComponentByType('GridFieldAddExistingAutocompleter'), + 'Related documents GridField has an "add existing" autocompleter' + ); + + $this->assertNull( + $gridFieldConfig->getComponentByType('GridFieldAddNewButton'), + 'Related documents GridField does not have an "add new" button' + ); + } } diff --git a/tests/Stub/StubRelatedDocumentExtension.php b/tests/Stub/StubRelatedDocumentExtension.php new file mode 100644 index 0000000..0a74b33 --- /dev/null +++ b/tests/Stub/StubRelatedDocumentExtension.php @@ -0,0 +1,18 @@ +Filename = 'Extended'; + $relatedDocuments->push($fakeDocument); + return $relatedDocuments; + } +} diff --git a/tests/dmstest.yml b/tests/dmstest.yml index e727c01..3832895 100644 --- a/tests/dmstest.yml +++ b/tests/dmstest.yml @@ -38,12 +38,16 @@ DMSTag: Value: tag6value DMSDocument: d1: - Filename: test-file-file-doesnt-exist + Filename: test-file-file-doesnt-exist-1 Folder: 5 Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4 Pages: =>SiteTree.s1, =>SiteTree.s2, =>SiteTree.s3, =>SiteTree.s4, =>SiteTree.s5, =>SiteTree.s6 d2: - Filename: test-file-file-doesnt-exist + Filename: test-file-file-doesnt-exist-2 Folder: 5 Tags: =>DMSTag.t5, =>DMSTag.t6 Pages: =>SiteTree.s5, =>SiteTree.s6 + document_with_relations: + Filename: file-with-relations + Folder: 5 + RelatedDocuments: =>DMSDocument.d1, =>DMSDocument.d2 From cef27febf641f25658bb2647abce716f10d92bbd Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Tue, 2 May 2017 12:32:49 +1200 Subject: [PATCH 2/2] DOCS Split readme documentation into docs/en files, add related documents information --- .gitattributes | 1 + README.md | 113 +++---------------------- docs/en/_manifest_exclude | 0 docs/en/configuration.md | 3 + docs/en/creating-documents.md | 18 ++++ docs/en/documents-on-the-filesystem.md | 18 ++++ docs/en/download-documents.md | 28 ++++++ docs/en/index.md | 16 ++++ docs/en/manage-page-relations.md | 10 +++ docs/en/manage-related-documents.md | 50 +++++++++++ docs/en/manage-tags.md | 32 +++++++ docs/en/use-in-templates.md | 11 +++ templates/Includes/Document.ss | 2 +- templates/Includes/Documents.ss | 4 +- templates/Includes/RelatedDocuments.ss | 2 +- 15 files changed, 201 insertions(+), 107 deletions(-) create mode 100644 docs/en/_manifest_exclude create mode 100644 docs/en/configuration.md create mode 100644 docs/en/creating-documents.md create mode 100644 docs/en/documents-on-the-filesystem.md create mode 100644 docs/en/download-documents.md create mode 100644 docs/en/index.md create mode 100644 docs/en/manage-page-relations.md create mode 100644 docs/en/manage-related-documents.md create mode 100644 docs/en/manage-tags.md create mode 100644 docs/en/use-in-templates.md diff --git a/.gitattributes b/.gitattributes index 16daf97..a67f2cd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +/docs export-ignore /tests export-ignore /.gitignore export-ignore /.travis.yml export-ignore diff --git a/README.md b/README.md index aa82a91..b0a53a6 100644 --- a/README.md +++ b/README.md @@ -3,25 +3,20 @@ [![Build status](https://travis-ci.org/silverstripe/silverstripe-dms.png?branch=master)](https://travis-ci.org/silverstripe/silverstripe-dms) [![Code quality](https://scrutinizer-ci.com/g/silverstripe/silverstripe-dms/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/silverstripe/silverstripe-dms/?branch=master) [![Code coverage](https://codecov.io/gh/silverstripe/silverstripe-dms/branch/master/graph/badge.svg)](https://codecov.io/gh/silverstripe/silverstripe-dms) - +![Helpful Robot](https://img.shields.io/badge/helpfulrobot-52-yellow.svg?style=flat) ## Overview -The module adds a new `DMSDocument` model which allows management -of large amounts of files, and their relations to pages. -In contrast to the `File` model built into SilverStripe core, -it aims to wrap storage and access concerns in a generic API, -which allows more fine-grained control over how the documents are -managed and exposed through the website. +The module adds a new `DMSDocument` model which allows management of large amounts of files, and their relations to +pages. In contrast to the `File` model built into SilverStripe core, it aims to wrap storage and access concerns in +a generic API. This allows more fine-grained control over how the documents are managed and exposed through the website. -Additionally, documents are stored and managed as part of a page instead of -away in a separate assets store. +Additionally, documents are stored and managed as part of a page instead of away in a separate assets store. -Read more about the DMS module in this [blog post on silverstripe.org](http://www.silverstripe.org/document-management-system-module) - -Features: +## Features * Relation of documents to pages + * Relation of documents to other documents * Management and upload of documents within a page context in the CMS * Metadata management through the powerful `GridField` and `UploadField` core APIs * Configurable tags for documents @@ -29,30 +24,11 @@ Features: * Access control based on PHP logic, and page relations * Replacement of existing files -## Documents on the Filesystem +## Documentation -While the DMS architecture allows for remote storage of files, -the default implementation (the `DMS` class) stores them locally. -Relations to pages and tags are persisted as many-many relationships -through the SilverStripe ORM. +For information on configuring and using this module, please see [the documentation section](docs/en/index.md). -File locations in this implementation are structured into -subfolders, in order to avoid exceeding filesystem limits. -The file name is a composite based on its database ID -and the original file name. The exact location shouldn't -be relied on by custom logic, but rather retrieved through -the API (`DMSDocument->getLink()`). - -Example: - - dms-assets/ - 0/ - 1234~myfile.pdf - 1/ - 2345~myotherfile.pdf - - -### Requirements +## Requirements * PHP 5.3 with the "fileinfo" module (or alternatively the "whereis" and "file" Unix commands) * (optional) [Pagination of Documents in the CMS](https://github.com/silverstripe-big-o/gridfieldpaginatorwithshowall) @@ -61,75 +37,6 @@ Example: * (optional) [Text extraction for Document full-text search](https://github.com/silverstripe-big-o/silverstripe-textextraction) * (optional) [Tags](https://github.com/tubbs/silverstripe-dms-simple-tags) -### Configuration - -The file location is set via the `DMS::$dmsFolder` static, and points to a location in the webroot. - -### Usage - -Add a simple include to any of your .ss templates to display the DMSDocuments associated with -the current page on the front-end. - - <% include Documents %> - -#### Create Documents - -Create by relative path: - - $dms = DMS::getDMSInstance(); - $doc = $dms->storeDocument('assets/myfile.pdf'); - -Create from an existing `File` record: - - $dms = DMS::getDMSInstance(); - $file = File::get()->byID(99); - $doc = $dms->storeDocument($file); - -Note: Both operations copy the existing file. - -#### Download Documents - - $dms = DMS::getDMSInstance(); - $docs = $dms->getByTag('priority', 'important')->First(); - $link = $doc->getLink(); - - // Set default download behavior ('open' or 'download'). 'download' is the system default - // Attempt to open the file in the browser - Config::inst()->update('DMSDocument', 'default_download_behaviour', 'open'); - -Or in you config.yml: - - DMSDocument: - default_download_behaviour: open - -#### Manage Page Relations - - // Find documents by page - $dms = DMS::getDMSInstance(); - $page = SiteTree::get()->filter('URLSegment', 'home')->First(); - $docs = $dms->getByPage($page); - - // Add documents to page - -#### Manage Tags - - // Find documents by tag - $dms = DMS::getDMSInstance(); - $docs = $dms->getByTag('priority', 'important'); - - // Add tag to existing document - $doc = Document::get()->byID(99); - $doc->addTag('priority', 'low'); - - // Supports multiple values for tags - $doc->addTag('category', 'keyboard'); - $doc->addTag('category', 'input device'); - - // Removing tags is abstracted as well - $doc->removeTag('category', 'keyboard'); - $doc->removeTag('category', 'input device'); - $doc->removeAllTags(); - ## Contributing ### Translations diff --git a/docs/en/_manifest_exclude b/docs/en/_manifest_exclude new file mode 100644 index 0000000..e69de29 diff --git a/docs/en/configuration.md b/docs/en/configuration.md new file mode 100644 index 0000000..01d3199 --- /dev/null +++ b/docs/en/configuration.md @@ -0,0 +1,3 @@ +# Configuration + +The file location is set via the `DMS::$dmsFolder` static, and points to a location in the webroot. diff --git a/docs/en/creating-documents.md b/docs/en/creating-documents.md new file mode 100644 index 0000000..82b7891 --- /dev/null +++ b/docs/en/creating-documents.md @@ -0,0 +1,18 @@ +# Creating documents + +Create by relative path: + +```php +$dms = DMS::getDMSInstance(); +$doc = $dms->storeDocument('assets/myfile.pdf'); +``` + +Create from an existing `File` record: + +```php +$dms = DMS::getDMSInstance(); +$file = File::get()->byID(99); +$doc = $dms->storeDocument($file); +``` + +Note: Both operations copy the existing file. diff --git a/docs/en/documents-on-the-filesystem.md b/docs/en/documents-on-the-filesystem.md new file mode 100644 index 0000000..04f3636 --- /dev/null +++ b/docs/en/documents-on-the-filesystem.md @@ -0,0 +1,18 @@ +# Documents on the Filesystem + +While the DMS architecture allows for remote storage of files, the default implementation (the `DMS` class) +stores them locally. Relations to pages and tags are persisted as many-many relationships through the SilverStripe ORM. + +File locations in this implementation are structured into subfolders, in order to avoid exceeding filesystem limits. +The file name is a composite based on its database ID and the original file name. The exact location shouldn't be +relied on by custom logic, but rather retrieved through the API method `DMSDocument::getLink`. + +Example: + +``` +dms-assets/ + 0/ + 1234~myfile.pdf + 1/ + 2345~myotherfile.pdf +``` diff --git a/docs/en/download-documents.md b/docs/en/download-documents.md new file mode 100644 index 0000000..dcfbbf9 --- /dev/null +++ b/docs/en/download-documents.md @@ -0,0 +1,28 @@ +# Download documents + +## Get the download link + +You can use `DMSDocument::getLink` to retrieve the secure route to download a DMS document: + +```php +$dms = DMS::getDMSInstance(); +$docs = $dms->getByTag('priority', 'important')->First(); +$link = $doc->getLink(); +``` + +## Default download behaviour + +The default download behaviour is "download" which will force the browser to download the document. You +can select "open" as an option in the document's settings in the CMS individually, or you can change the global +default value with configuration: + +```php +Config::inst()->update('DMSDocument', 'default_download_behaviour', 'open'); +``` + +Or in YAML: + +```yaml +DMSDocument: + default_download_behaviour: open +``` diff --git a/docs/en/index.md b/docs/en/index.md new file mode 100644 index 0000000..eafc027 --- /dev/null +++ b/docs/en/index.md @@ -0,0 +1,16 @@ +# DMS documentation + +## Development + +* [Configuration](configuration.md) +* [Documents on the filesystem](documents-on-the-filesystem.md) +* [Use in templates](use-in-templates.md) +* [Creating documents](creating-documents.md) +* [Download documents](download-documents.md) +* [Manage page relations](manage-page-relations.md) +* [Manage tags](manage-tags.md) +* [Manage related documents](manage-related-documents.md) + +## CMS user help + +* TBC diff --git a/docs/en/manage-page-relations.md b/docs/en/manage-page-relations.md new file mode 100644 index 0000000..d91d444 --- /dev/null +++ b/docs/en/manage-page-relations.md @@ -0,0 +1,10 @@ +# Manage page relations + +To find documents by a Page: + +```php +$dms = DMS::getDMSInstance(); +$page = SiteTree::get()->filter('URLSegment', 'home')->first(); +/** @var DataList $docs */ +$docs = $dms->getByPage($page); +``` diff --git a/docs/en/manage-related-documents.md b/docs/en/manage-related-documents.md new file mode 100644 index 0000000..c53719e --- /dev/null +++ b/docs/en/manage-related-documents.md @@ -0,0 +1,50 @@ +# Manage related documents + +You can relate documents to each other using the GridField under "Related Documents" in the CMS. + +## Add related documents + +You can use the model relationship `DMSDocument::RelatedDocuments` to modify the DataList and save as required: + +```php +$parentDocument = DMSDocument::get()->byId(123); + +$relatedDocument = DMSDocument::get()->byId(234); + +$parentDocument->RelatedDocuments()->add($relatedDocument); +``` + +Using the relationship method directly will skip the extension hook available in `getRelatedDocuments` (see below). + +## Modifying the related documents list + +If you need to modify the related documents DataList returned by the ORM, use the `updateRelatedDocuments` extension +hook provided by `DMSDocument::getRelatedDocuments`: + +```php +# MyExtension is an extension applied to DMSDocument +class MyExtension extends DataExtension +{ + public function updateRelatedDocuments($relatedDocuments) + { + foreach ($relatedDocuments as $document) { + // Add square brackets around the description + $document->Description = '[' . $document->Description . ']'; + } + return $relatedDocuments; + } +} +``` + +## Retrieving related documents + +To retrieve a DataList of related documents you can either use `getRelatedDocuments` or the ORM relationship method +`RelatedDocuments` directly. The former will allow extensions to modify the list, whereas the latter will not. + +```php +$relatedDocuments = $document->getRelatedDocuments(); + +foreach ($relatedDocuments as $relatedDocument) { + // ... +} +``` diff --git a/docs/en/manage-tags.md b/docs/en/manage-tags.md new file mode 100644 index 0000000..7b9e51e --- /dev/null +++ b/docs/en/manage-tags.md @@ -0,0 +1,32 @@ +# Manage Tags + +## Find documents by tag + +```php +$dms = DMS::getDMSInstance(); +$docs = $dms->getByTag('priority', 'important'); +``` + +## Add tag to existing document + +```php +$doc = DMSDocument::get()->byID(99); +$doc->addTag('priority', 'low'); +``` + +## Supports multiple values for tags + +```php +$doc->addTag('category', 'keyboard'); +$doc->addTag('category', 'input device'); +``` + +## Removing tags + +Removing tags is abstracted as well. + +```php +$doc->removeTag('category', 'keyboard'); +$doc->removeTag('category', 'input device'); +$doc->removeAllTags(); +``` diff --git a/docs/en/use-in-templates.md b/docs/en/use-in-templates.md new file mode 100644 index 0000000..b95e337 --- /dev/null +++ b/docs/en/use-in-templates.md @@ -0,0 +1,11 @@ +# Use in templates + +Add a simple include to any of your `.ss` templates to display the DMSDocuments associated with +the current page on the front-end. + +``` +<% include Documents %> +``` + +You can fine tune the HTML markup or display behaviour of any of the templates in `/dms/templates/Includes` to change +the way documents will be displayed in your project. diff --git a/templates/Includes/Document.ss b/templates/Includes/Document.ss index 9e0d6cc..d074b01 100644 --- a/templates/Includes/Document.ss +++ b/templates/Includes/Document.ss @@ -11,7 +11,7 @@

    $DescriptionWithLineBreak

    <% end_if %> - <% if $RelatedDocuments %> + <% if $getRelatedDocuments %> <% include RelatedDocuments %> <% end_if %> diff --git a/templates/Includes/Documents.ss b/templates/Includes/Documents.ss index 516d8f2..f64ddbb 100644 --- a/templates/Includes/Documents.ss +++ b/templates/Includes/Documents.ss @@ -1,7 +1,7 @@ -<% if PageDocuments %> +<% if $PageDocuments %>

    <%t DMSDocument.PLURALNAME "Documents" %>

    - <% loop PageDocuments %> + <% loop $PageDocuments %> <% include Document %> <% end_loop %>
    diff --git a/templates/Includes/RelatedDocuments.ss b/templates/Includes/RelatedDocuments.ss index f648a54..919fb03 100644 --- a/templates/Includes/RelatedDocuments.ss +++ b/templates/Includes/RelatedDocuments.ss @@ -1,7 +1,7 @@
    <%t DMSDocument.RELATED_DOCUMENTS "Related documents" %>