From 6b25237ec6c85f556dd1d6aac29772a3d6288ce2 Mon Sep 17 00:00:00 2001 From: Franco Springveldt Date: Mon, 8 May 2017 23:57:52 +1200 Subject: [PATCH] NEW Query Builder functionality added This enhancement adds the ability to add documents to a document set based on a list of filters added from DMSDocument. Fixes #96 --- _config/querybuilder.yml | 16 ++ code/cms/DMSDocumentAddController.php | 4 +- code/cms/DMSUploadField.php | 2 +- code/forms/JsonField.php | 118 ++++++++++ code/model/DMSDocument.php | 83 ++++--- code/model/DMSDocumentSet.php | 232 ++++++++++++++------ code/model/DMSDocument_versions.php | 4 +- docs/en/configuration.md | 28 +++ lang/en.yml | 3 + templates/Includes/Document.ss | 10 +- templates/Includes/DocumentDetails.ss | 2 +- tests/DMSDocumentSetTest.php | 53 +++++ tests/DMSDocumentTest.php | 12 + tests/JsonFieldTest.php | 47 ++++ tests/Stub/StubDocumentSetMockExtension.php | 24 ++ tests/Stub/StubRelatedDocumentExtension.php | 5 + tests/dmstest.yml | 33 +++ 17 files changed, 572 insertions(+), 104 deletions(-) create mode 100644 _config/querybuilder.yml create mode 100644 code/forms/JsonField.php create mode 100644 tests/JsonFieldTest.php create mode 100644 tests/Stub/StubDocumentSetMockExtension.php diff --git a/_config/querybuilder.yml b/_config/querybuilder.yml new file mode 100644 index 0000000..1814ba2 --- /dev/null +++ b/_config/querybuilder.yml @@ -0,0 +1,16 @@ +DMSDocument: + searchable_fields: + Title: + title: "Document title matches ..." + Description: + title: "Document summary matches ..." + CreatedByID: + title: 'Document created by ...' + field: 'ListboxField' + filter: 'ExactMatchFilter' + LastEditedByID: + title: 'Document last changed by ...' + field: 'ListboxField' + filter: 'ExactMatchFilter' + Filename: + title: 'File name' \ No newline at end of file diff --git a/code/cms/DMSDocumentAddController.php b/code/cms/DMSDocumentAddController.php index 1258742..799e1be 100644 --- a/code/cms/DMSDocumentAddController.php +++ b/code/cms/DMSDocumentAddController.php @@ -120,8 +120,6 @@ class DMSDocumentAddController extends LeftAndMain _t('DMSDocumentAddController.MAINTAB', 'Main'), new Tab( _t('UploadField.FROMCOMPUTER', 'From your computer'), - new HiddenField('ID', false, $page->ID), - new HiddenField('DSID', false, $documentSet->ID), $uploadField, new LiteralField( 'AllowedExtensions', @@ -146,6 +144,8 @@ class DMSDocumentAddController extends LeftAndMain $form->Backlink = $backlink; // Don't use AssetAdmin_EditForm, as it assumes a different panel structure $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); + $form->Fields()->push(HiddenField::create('ID', false, $documentSet->ID)); + $form->Fields()->push(HiddenField::create('DSID', false, $documentSet->ID)); return $form; } diff --git a/code/cms/DMSUploadField.php b/code/cms/DMSUploadField.php index b926baa..89b65f1 100644 --- a/code/cms/DMSUploadField.php +++ b/code/cms/DMSUploadField.php @@ -48,7 +48,7 @@ class DMSUploadField extends UploadField // Relate to the underlying document set being edited. // Not applicable when editing the document itself and replacing it, or uploading from the ModelAdmin if ($record instanceof DMSDocumentSet) { - $record->Documents()->add($doc); + $record->Documents()->add($doc, array('BelongsToSet' => 1)); } return $doc; diff --git a/code/forms/JsonField.php b/code/forms/JsonField.php new file mode 100644 index 0000000..f1269f4 --- /dev/null +++ b/code/forms/JsonField.php @@ -0,0 +1,118 @@ +setName($name); + + if ($children instanceof FieldList || is_array($children)) { + foreach ($children as $child) { + $this->setChildName($child); + } + } else { + $children = is_array(func_get_args()) ? func_get_args() : array(); + if (!empty($children)) { + array_shift($children); + } + foreach ($children as $child) { + $this->setChildName($child); + } + } + parent::__construct($children); + } + + /** + * Sets the name of the child object + * + * @param FormField $child + */ + private function setChildName($child) + { + $child->setName("{$this->getName()}[{$child->getName()}]"); + } + + public function hasData() + { + return true; + } + + /** + * Override parent's behaviour as it's no longer required + * + * @param array $list + * @param bool $saveableOnly + */ + public function collateDataFields(&$list, $saveableOnly = false) + { + } + + /** + * Recursively removed empty key-value pairs from $haystack + * + * @param $haystack + * + * @return mixed + */ + public function arrayFilterEmptyRecursive($haystack) + { + foreach ($haystack as $key => $value) { + if (is_array($value)) { + $haystack[$key] = $this->arrayFilterEmptyRecursive($haystack[$key]); + } + if (empty($haystack[$key])) { + unset($haystack[$key]); + } + } + + return $haystack; + } + + /** + * Overrides parent behaviour to remove empty elements + * + * @return mixed|null|string + */ + public function dataValue() + { + $result = null; + if (is_array($this->value)) { + $this->value = $this->arrayFilterEmptyRecursive($this->value); + $result = (!empty($this->value)) ? Convert::array2json($this->value) : $result; + } else { + $result = parent::dataValue(); + } + + return $result; + } + + /** + * Sets + * @param mixed $value + * + * @return $this + */ + public function setValue($value) + { + $this->value = $value; + if (is_string($value) && !empty($value)) { + $value = Convert::json2array($value); + } elseif (!is_array($value)) { + $value = array($value); + } + + $pattern = "/^{$this->getName()}\[(.*)\]$/"; + foreach ($this->children as $c) { + $title = $c->getName(); + preg_match($pattern, $title, $matches); + if (!empty($matches[1]) && isset($value[$matches[1]])) { + $c->setValue($value[$matches[1]]); + } + } + + return $this; + } +} diff --git a/code/model/DMSDocument.php b/code/model/DMSDocument.php index 001ce27..958c8d4 100644 --- a/code/model/DMSDocument.php +++ b/code/model/DMSDocument.php @@ -8,7 +8,6 @@ * @property Varchar Title * @property Text Description * @property int ViewCount - * @property DateTime LastChanged * @property Boolean EmbargoedIndefinitely * @property Boolean EmbargoedUntilPublished * @property DateTime EmbargoedUntilDate @@ -22,6 +21,11 @@ * @method ManyManyList ViewerGroups * @method ManyManyList EditorGroups * + * @method Member CreatedBy + * @property Int CreatedByID + * @method Member LastEditedBy + * @property Int LastEditedByID + * */ class DMSDocument extends DataObject implements DMSDocumentInterface { @@ -31,9 +35,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface "Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp" "Description" => 'Text', "ViewCount" => 'Int', - // When this document's file was created or last replaced (small changes like updating title don't count) - "LastChanged" => 'SS_DateTime', - "EmbargoedIndefinitely" => 'Boolean(false)', "EmbargoedUntilPublished" => 'Boolean(false)', "EmbargoedUntilDate" => 'SS_DateTime', @@ -47,6 +48,12 @@ class DMSDocument extends DataObject implements DMSDocumentInterface 'Sets' => 'DMSDocumentSet' ); + private static $has_one = array( + 'CoverImage' => 'Image', + 'CreatedBy' => 'Member', + 'LastEditedBy' => 'Member', + ); + private static $many_many = array( 'RelatedDocuments' => 'DMSDocument', 'Tags' => 'DMSTag', @@ -58,23 +65,13 @@ class DMSDocument extends DataObject implements DMSDocumentInterface 'ID' => 'ID', 'Title' => 'Title', 'FilenameWithoutID' => 'Filename', - 'LastChanged' => 'LastChanged' + 'LastEdited' => 'LastEdited' ); private static $singular_name = 'Document'; private static $plural_name = 'Documents'; - private static $searchable_fields = array( - 'ID' => array( - 'filter' => 'ExactMatchFilter', - 'field' => 'NumericField' - ), - 'Title', - 'Filename', - 'LastChanged' - ); - private static $summary_fields = array( 'Filename' => 'Filename', 'Title' => 'Title', @@ -122,7 +119,12 @@ class DMSDocument extends DataObject implements DMSDocumentInterface return true; } - if ($member && Permission::checkMember($member, array('ADMIN', 'SITETREE_EDIT_ALL', 'SITETREE_VIEW_ALL'))) { + if ($member && Permission::checkMember($member, array( + 'ADMIN', + 'SITETREE_EDIT_ALL', + 'SITETREE_VIEW_ALL', + )) + ) { return true; } @@ -156,13 +158,14 @@ class DMSDocument extends DataObject implements DMSDocumentInterface } // Do early admin check - if ($member && Permission::checkMember($member, - array( + if ($member && Permission::checkMember( + $member, + array( 'ADMIN', 'SITETREE_EDIT_ALL', 'SITETREE_VIEW_ALL', ) - ) + ) ) { return true; } @@ -813,7 +816,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface $this->Title = basename($filePath, '.'.$extension); } - $this->LastChanged = SS_Datetime::now()->Rfc2822(); $this->write(); return $this; @@ -906,8 +908,14 @@ class DMSDocument extends DataObject implements DMSDocumentInterface $fieldsTop = $this->getFieldsForFile($relationList->count()); $fields->add($fieldsTop); - $fields->add(new TextField('Title', 'Title')); - $fields->add(new TextareaField('Description', 'Description')); + $fields->add(TextField::create('Title', _t('DMSDocument.TITLE', 'Title'))); + $fields->add(TextareaField::create('Description', _t('DMSDocument.DESCRIPTION', 'Description'))); + + $coverImageField = UploadField::create('CoverImage', _t('DMSDocument.COVERIMAGE', 'Cover Image')); + $coverImageField->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif')); + $coverImageField->setConfig('allowedMaxFileNumber', 1); + $fields->add($coverImageField); + $downloadBehaviorSource = array( 'open' => _t('DMSDocument.OPENINBROWSER', 'Open in browser'), @@ -984,7 +992,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface ); $versionsGridFieldConfig->getComponentByType('GridFieldDataColumns') ->setDisplayFields(Config::inst()->get('DMSDocument_versions', 'display_fields')) - ->setFieldCasting(array('LastChanged'=>"Datetime->Ago")) ->setFieldFormatting( array( 'FilenameWithoutID' => '' @@ -1112,6 +1119,19 @@ class DMSDocument extends DataObject implements DMSDocumentInterface return CompositeField::create($fields); } + /** + * Return a title to use on the frontend, preferably the "title", otherwise the filename without it's numeric ID + * + * @return string + */ + public function getTitle() + { + if ($this->getField('Title')) { + return $this->getField('Title'); + } + return $this->FilenameWithoutID; + } + public function onBeforeWrite() { parent::onBeforeWrite(); @@ -1120,7 +1140,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface //set the embargo options from the OptionSetField created in the getCMSFields method //do not write after clearing the embargo (write happens automatically) $savedDate = $this->EmbargoedUntilDate; - $this->clearEmbargo(false); //clear all previous settings and re-apply them on save + $this->clearEmbargo(false); // Clear all previous settings and re-apply them on save if ($this->Embargo == 'Published') { $this->embargoUntilPublished(false); @@ -1138,7 +1158,15 @@ class DMSDocument extends DataObject implements DMSDocumentInterface $this->expireAtDate($this->ExpireAtDate, false); } else { $this->clearExpiry(false); - } //clear all previous settings + } // Clear all previous settings + } + + // Set user fields + if ($currentUserID = Member::currentUserID()) { + if (!$this->CreatedByID) { + $this->CreatedByID = $currentUserID; + } + $this->LastEditedByID = $currentUserID; } } @@ -1266,11 +1294,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface _t('AssetTableField.LASTEDIT', 'Last changed') . ':', $this->LastEdited ), - new DateField_Disabled( - "LastChanged", - _t('AssetTableField.LASTCHANGED', 'Last replaced') . ':', - $this->LastChanged - ), new ReadonlyField("PublishedOn", "Published on". ':', $publishedOnValue), new ReadonlyField("ReferencedOn", "Referenced on". ':', $relationListCountValue), new ReadonlyField("ViewCount", "View count". ':', $this->ViewCount) diff --git a/code/model/DMSDocumentSet.php b/code/model/DMSDocumentSet.php index 77a5d6b..332d5c9 100644 --- a/code/model/DMSDocumentSet.php +++ b/code/model/DMSDocumentSet.php @@ -1,19 +1,34 @@ 'Varchar(255)' + 'Title' => 'Varchar(255)', + 'KeyValuePairs' => 'Text', + 'SortBy' => "Enum('LastEdited,Created,Title')')", + 'SortByDirection' => "Enum('DESC,ASC')')", ); private static $has_one = array( - 'Page' => 'SiteTree' + 'Page' => 'SiteTree', ); private static $many_many = array( - 'Documents' => 'DMSDocument' + 'Documents' => 'DMSDocument', + ); + + private static $many_many_extraFields = array( + 'Documents' => array( + 'BelongsToSet' => 'Boolean(1)', // Flag indicating if a document was added directly to a set - in which case it is set - or added via the query-builder. + ), ); /** @@ -28,14 +43,12 @@ class DMSDocumentSet extends DataObject * } * * - * @return DataList + * @return DataList|null */ public function getDocuments() { $documents = $this->Documents(); - $this->extend('updateDocuments', $documents); - return $documents; } @@ -49,8 +62,11 @@ class DMSDocumentSet extends DataObject { // PHP 5.3 only $self = $this; - $this->beforeUpdateCMSFields(function (FieldList $fields) use ($self) { + $fields->removeFieldsFromTab( + 'Root.Main', + array('KeyValuePairs', 'SortBy', 'SortByDirection') + ); // Don't put the GridField for documents in until the set has been created if (!$self->isInDB()) { $fields->addFieldToTab( @@ -64,70 +80,67 @@ class DMSDocumentSet extends DataObject ), 'Title' ); - return; - } - - // Document listing - $gridFieldConfig = GridFieldConfig::create() - ->addComponents( - new GridFieldToolbarHeader(), - new GridFieldFilterHeader(), - new GridFieldSortableHeader(), - // new GridFieldOrderableRows('DocumentSort'), - new GridFieldDataColumns(), - new GridFieldEditButton(), - // Special delete dialog to handle custom behaviour of unlinking and deleting - new DMSGridFieldDeleteAction(), - new GridFieldDetailForm() - ); - - if (class_exists('GridFieldPaginatorWithShowAll')) { - $paginatorComponent = new GridFieldPaginatorWithShowAll(15); } else { - $paginatorComponent = new GridFieldPaginator(15); - } - $gridFieldConfig->addComponent($paginatorComponent); + // Document listing + $gridFieldConfig = GridFieldConfig::create() + ->addComponents( + new GridFieldToolbarHeader(), + new GridFieldFilterHeader(), + new GridFieldSortableHeader(), + new GridFieldDataColumns(), + new GridFieldEditButton(), + // Special delete dialog to handle custom behaviour of unlinking and deleting + new DMSGridFieldDeleteAction(), + new GridFieldDetailForm() + ); - if (class_exists('GridFieldSortableRows')) { - $sortableComponent = new GridFieldSortableRows('DocumentSort'); - // setUsePagenation method removed from newer version of SortableGridField. - if (method_exists($sortableComponent, 'setUsePagination')) { - $sortableComponent->setUsePagination(false)->setForceRedraw(true); + if (class_exists('GridFieldPaginatorWithShowAll')) { + $paginatorComponent = new GridFieldPaginatorWithShowAll(15); + } else { + $paginatorComponent = new GridFieldPaginator(15); } - $gridFieldConfig->addComponent($sortableComponent); - } + $gridFieldConfig->addComponent($paginatorComponent); - // HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields. - singleton('DMSDocument'); - $gridFieldConfig->getComponentByType('GridFieldDataColumns') - ->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields')) - ->setFieldCasting(array('LastChanged' => 'Datetime->Ago')) - ->setFieldFormatting( - array( - 'FilenameWithoutID' => '$FilenameWithoutID' - ) + if (class_exists('GridFieldSortableRows')) { + $sortableComponent = new GridFieldSortableRows('DocumentSort'); + // setUsePagination method removed from newer version of SortableGridField. + if (method_exists($sortableComponent, 'setUsePagination')) { + $sortableComponent->setUsePagination(false)->setForceRedraw(true); + } + $gridFieldConfig->addComponent($sortableComponent); + } + + $gridFieldConfig->getComponentByType('GridFieldDataColumns') + ->setDisplayFields(DMSDocument::create()->config()->get('display_fields')) + ->setFieldCasting(array('LastEdited' => 'Datetime->Ago')) + ->setFieldFormatting( + array( + 'FilenameWithoutID' => '$FilenameWithoutID', + ) + ); + + // Override delete functionality with this class + $gridFieldConfig->getComponentByType('GridFieldDetailForm') + ->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest'); + $gridField = GridField::create( + 'Documents', + false, + $self->Documents(), + $gridFieldConfig ); + $gridField->setModelClass('DMSDocument'); + $gridField->addExtraClass('documents'); - // Override delete functionality with this class - $gridFieldConfig->getComponentByType('GridFieldDetailForm') - ->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest'); + $gridFieldConfig->addComponent( + $addNewButton = new DMSGridFieldAddNewButton, + 'GridFieldExportButton' + ); + $addNewButton->setDocumentSetId($self->ID); - $gridField = GridField::create( - 'Documents', - false, - $self->Documents(), //->Sort('DocumentSort'), - $gridFieldConfig - ); - $gridField->addExtraClass('documents'); - - $gridFieldConfig->addComponent( - $addNewButton = new DMSGridFieldAddNewButton, - 'GridFieldExportButton' - ); - $addNewButton->setDocumentSetId($self->ID); - - $fields->removeByName('Documents'); - $fields->addFieldToTab('Root.Main', $gridField); + $fields->removeByName('Documents'); + $fields->addFieldToTab('Root.Main', $gridField); + $self->addQueryFields($fields); + } }); $this->addRequirements(); return parent::getCMSFields(); @@ -150,4 +163,95 @@ class DMSDocumentSet extends DataObject return $this; } + + /** + * Adds the query fields to build the document logic to the DMSDocumentSet. + * + * To extend use the following from within an Extension subclass: + * + * + * public function updateQueryFields($result) + * { + * // Do something here + * } + * + * + * @param FieldList $fields + */ + public function addQueryFields($fields) + { + /** @var DMSDocument $doc */ + $doc = singleton('DMSDocument'); + /** @var FormField $field */ + $dmsDocFields = $doc->scaffoldSearchFields(array('fieldClasses' => true)); + $membersMap = Member::get()->map('ID', 'Name')->toArray(); + asort($membersMap); + foreach ($dmsDocFields as $field) { + // Apply field customisations where necessary + if (in_array($field->getName(), array('CreatedByID', 'LastEditedByID', 'LastEditedByID'))) { + /** @var ListboxField $field */ + $field->setMultiple(true)->setSource($membersMap); + } + } + $keyValPairs = JsonField::create('KeyValuePairs', $dmsDocFields->toArray()); + + // Now lastly add the sort fields + $sortedBy = FieldGroup::create('SortedBy', array( + DropdownField::create('SortBy', '', array( + 'LastEdited' => 'Last changed', + 'Created' => 'Created', + 'Title' => 'Document title', + ), 'LastEdited'), + DropdownField::create('SortByDirection', '', $this->dbObject('SortByDirection')->enumValues(), 'DESC'), + )); + + $sortedBy->setTitle(_t('DMSDocumentSet.SORTED_BY', 'Sort the document set by:')); + $fields->addFieldsToTab('Root.QueryBuilder', array($keyValPairs, $sortedBy)); + $this->extend('updateQueryFields', $fields); + } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + $this->saveLinkedDocuments(); + } + + /** + * Retrieve a list of the documents in this set. An extension hook is provided before the result is returned. + * + * @return ArrayList|null + */ + public function saveLinkedDocuments() + { + // Documents that belong to just this set. + /** @var ManyManyList $originals */ + $originals = $this->Documents(); + if (!(empty($this->KeyValuePairs)) && $this->isChanged('KeyValuePairs')) { + $keyValuesPair = Convert::json2array($this->KeyValuePairs); + /** @var DMSDocument $dmsDoc */ + $dmsDoc = singleton('DMSDocument'); + $context = $dmsDoc->getDefaultSearchContext(); + + $sortBy = $this->SortBy ? $this->SortBy : 'LastEdited'; + $sortByDirection = $this->SortByDirection ? $this->SortByDirection : 'DESC'; + $sortedBy = sprintf('%s %s', $sortBy, $sortByDirection); + /** @var DataList $documents */ + $documents = $context->getResults($keyValuesPair, $sortedBy); + $now = SS_Datetime::now()->Rfc2822(); + $documents = $documents->where( + "\"EmbargoedIndefinitely\" = 0 AND ". + " \"EmbargoedUntilPublished\" = 0 AND ". + "(\"EmbargoedUntilDate\" IS NULL OR " . + "(\"EmbargoedUntilDate\" IS NOT NULL AND '{$now}' >= \"EmbargoedUntilDate\")) AND " . + "\"ExpireAtDate\" IS NULL OR (\"ExpireAtDate\" IS NOT NULL AND '{$now}' < \"ExpireAtDate\")" + ); + + // Remove all BelongsToSet as the rules have changed + $originals->removeByFilter('"BelongsToSet" = 0'); + foreach ($documents as $document) { + $originals->add($document, array('BelongsToSet' => 0)); + } + } + } } diff --git a/code/model/DMSDocument_versions.php b/code/model/DMSDocument_versions.php index 450295c..7957e8f 100644 --- a/code/model/DMSDocument_versions.php +++ b/code/model/DMSDocument_versions.php @@ -34,7 +34,7 @@ class DMSDocument_versions extends DataObject private static $display_fields = array( 'VersionCounter' => 'Version Counter', 'FilenameWithoutID' => 'Filename', - 'LastChanged' => 'Last Changed' + 'LastEdited' => 'Last Changed' ); private static $summary_fields = array( @@ -47,7 +47,7 @@ class DMSDocument_versions extends DataObject ); private static $default_sort = array( - 'LastChanged' => 'DESC' + 'LastEdited' => 'DESC' ); diff --git a/docs/en/configuration.md b/docs/en/configuration.md index 50fee04..a9a1bf8 100644 --- a/docs/en/configuration.md +++ b/docs/en/configuration.md @@ -28,3 +28,31 @@ DMSDocumentAddController: - php - php5 ``` + +## Adding fields to the Query Builder +Query builder fields are read from the DMSDocument::searchable_fields property set in [querybuilder.yml](../../_config/querybuilder.yml). Some default fields are provided and can be customised +by modifying the field and/or filter properties of a field or adding a new field entirely. + +[See here for information](https://docs.silverstripe.org/en/developer_guides/model/searchfilters/) on how to modify search filters and [see here for more information](https://docs.silverstripe.org/en/developer_guides/forms/field_types/common_subclasses/) +on the field types available. + +The default searchable filters available to query builder is as follows: + +```yaml +DMSDocument: + searchable_fields: + Title: + title: "Document title matches ..." + Description: + title: "Document summary matches ..." + CreatedByID: + title: 'Document created by ...' + field: 'ListboxField' + filter: 'ExactMatchFilter' + LastEditedByID: + title: 'Document last changed by ...' + field: 'ListboxField' + filter: 'ExactMatchFilter' + Filename: + title: 'File name' +``` \ No newline at end of file diff --git a/lang/en.yml b/lang/en.yml index 18d5e8e..78d9f4f 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -9,6 +9,8 @@ en: TYPE: 'File type' URL: URL DMSDocument: + COVERIMAGE: Cover Image + DESCRIPTION: Description EDIT: Edit EDITDOCUMENT: Edit this document PLURALNAME: Documents @@ -18,6 +20,7 @@ en: Versions: Versions DOWNLOAD: "Download {title}" LASTCHANGED: "Last changed: {date}" + TITLE: Title DMSDocumentSet: ADDDOCUMENTBUTTON: Add Document ADDDOCUMENTSBUTTON: Add Documents diff --git a/templates/Includes/Document.ss b/templates/Includes/Document.ss index 2428804..a3fe7cf 100644 --- a/templates/Includes/Document.ss +++ b/templates/Includes/Document.ss @@ -1,9 +1,11 @@ <% if not $isHidden %>
- <% if $Title %> -

">$Title

- <% else %> -

">$FilenameWithoutID

+

">$getTitle

+ + <% if $CoverImage %> +
+ $CoverImage.FitMax(100, 100) +
<% end_if %>

<% include DocumentDetails %>

diff --git a/templates/Includes/DocumentDetails.ss b/templates/Includes/DocumentDetails.ss index 25a90d7..d9fde11 100644 --- a/templates/Includes/DocumentDetails.ss +++ b/templates/Includes/DocumentDetails.ss @@ -1,4 +1,4 @@ $FilenameWithoutID | $Extension | $FileSizeFormatted -| <%t DMSDocument.LASTCHANGED "Last changed: {date}" date=$LastChanged.Nice %> \ No newline at end of file +| <%t DMSDocument.LASTCHANGED "Last changed: {date}" date=$LastEdited.Nice %> \ No newline at end of file diff --git a/tests/DMSDocumentSetTest.php b/tests/DMSDocumentSetTest.php index 7be996e..22108e5 100644 --- a/tests/DMSDocumentSetTest.php +++ b/tests/DMSDocumentSetTest.php @@ -83,4 +83,57 @@ class DMSDocumentSetTest extends SapphireTest $sortableAssertion = class_exists('GridFieldSortableRows') ? 'assertNotNull' : 'assertNull'; $this->$sortableAssertion($config->getComponentByType('GridFieldSortableRows')); } + + /** + * Test that query fields can be added to the gridfield + */ + public function testAddQueryFields() + { + + /** @var DMSDocumentSet $set */ + $set = $this->objFromFixture('DMSDocumentSet', 'ds6'); + /** @var FieldList $fields */ + $fields = new FieldList(new TabSet('Root')); + /** @var FieldList $fields */ + $set->addQueryFields($fields); + $keyValuePairs = $fields->dataFieldByName('KeyValuePairs'); + $this->assertNotNull( + $keyValuePairs, + 'addQueryFields() includes KeyValuePairs composite field' + ); + $this->assertNotNull( + $keyValuePairs->fieldByName('KeyValuePairs[Title]'), + 'addQueryFields() includes KeyValuePairs composite field' + ); + } + + public function testAddQueryFieldsIsExtensible() + { + + DMSDocumentSet::add_extension('StubDocumentSetMockExtension'); + + $fields = new FieldList(new TabSet('Root')); + $set = new DMSDocumentSet; + $set->addQueryFields($fields); + + $this->assertNotNull( + $fields->dataFieldByName('ExtendedField'), + 'addQueryFields() is extendible as it included the field from the extension' + ); + } + + /** + * Test that extra documents are added after write + */ + public function testSaveLinkedDocuments() + { + /** @var DMSDocumentSet $set */ + $set = $this->objFromFixture('DMSDocumentSet', 'dsSaveLinkedDocuments'); + // Assert initially docs + $this->assertEquals(1, $set->getDocuments()->count(), 'Set has 1 document'); + // Now apply the query and see if 2 extras were added with CreatedByID filter + $set->KeyValuePairs = '{"Filename":"extradoc3"}'; + $set->saveLinkedDocuments(); + $this->assertEquals(2, $set->getDocuments()->count(), 'Set has 2 documents'); + } } diff --git a/tests/DMSDocumentTest.php b/tests/DMSDocumentTest.php index c1a16a3..d010e3f 100644 --- a/tests/DMSDocumentTest.php +++ b/tests/DMSDocumentTest.php @@ -247,4 +247,16 @@ class DMSDocumentTest extends SapphireTest $this->assertCount(3, $result, 'Document 1 is related to 3 Pages'); $this->assertSame(array('s1', 's2', 's3'), $result->column('URLSegment')); } + + /** + * Test that the title is returned if it is set, otherwise the filename without ID + */ + public function testGetTitleOrFilenameWithoutId() + { + $d1 = $this->objFromFixture('DMSDocument', 'd1'); + $this->assertSame('test-file-file-doesnt-exist-1', $d1->getTitle()); + + $d2 = $this->objFromFixture('DMSDocument', 'd2'); + $this->assertSame('File That Doesn\'t Exist (Title)', $d2->getTitle()); + } } diff --git a/tests/JsonFieldTest.php b/tests/JsonFieldTest.php new file mode 100644 index 0000000..5fbf0ec --- /dev/null +++ b/tests/JsonFieldTest.php @@ -0,0 +1,47 @@ +assertEquals($jsonField->FieldList()->count(), 2); + $this->assertNotNull($jsonField->FieldList()->dataFieldByName('MyJsonField[FirstName]')); + + $jsonField = new JsonField('MyJsonField', array(new TextField('FirstName', 'Given name'), + new TextField('Surname', 'Last name'))); + $this->assertEquals($jsonField->FieldList()->count(), 2); + $this->assertNotNull($jsonField->FieldList()->dataFieldByName('MyJsonField[FirstName]')); + + $jsonField = new JsonField( + 'MyJsonField', + new TextField('FirstName', 'Given name'), + new TextField('Surname', 'Last name') + ); + $this->assertEquals($jsonField->FieldList()->count(), 2); + $this->assertNotNull($jsonField->FieldList()->dataFieldByName('MyJsonField[FirstName]')); + } + + public function testJsonFieldDataValueCouldDealWithArray() + { + $jsonField = new JsonField('MyJsonField', new FieldList( + new TextField('FirstName', 'Given name'), + new TextField('Surname', 'Last name') + )); + $jsonField->setValue($value = array( + 'MyJsonField'=>array( + 'FirstName' => 'Normann', + 'Surname' => 'Lou', + ), + )); + + $this->assertEquals($jsonField->dataValue(), Convert::array2json($value)); + $jsonField->setValue($value = array( + 'MyJsonField'=>array(), + )); + $this->assertNull($jsonField->dataValue()); + } +} diff --git a/tests/Stub/StubDocumentSetMockExtension.php b/tests/Stub/StubDocumentSetMockExtension.php new file mode 100644 index 0000000..78dd2e9 --- /dev/null +++ b/tests/Stub/StubDocumentSetMockExtension.php @@ -0,0 +1,24 @@ +addFieldToTab('Root.QueryBuilder', new TextField('ExtendedField')); + + return $fields; + } +} diff --git a/tests/Stub/StubRelatedDocumentExtension.php b/tests/Stub/StubRelatedDocumentExtension.php index 2af3984..38cb39c 100644 --- a/tests/Stub/StubRelatedDocumentExtension.php +++ b/tests/Stub/StubRelatedDocumentExtension.php @@ -1,5 +1,10 @@ SiteTree.s7 + ds6: + Title: Test Set 6 + Page: =>SiteTree.s8 + dsSaveLinkedDocuments: + Title: Test Set 6 + Page: =>SiteTree.s9 DMSDocument: d1: Filename: test-file-file-doesnt-exist-1 @@ -78,6 +90,7 @@ DMSDocument: d2: Filename: test-file-file-doesnt-exist-2 Folder: 5 + Title: File That Doesn't Exist (Title) Tags: =>DMSTag.t5, =>DMSTag.t6 Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4 document_with_relations: @@ -121,3 +134,23 @@ DMSDocument: EmbargoUntilPublish: true Folder: 5 Sets: =>DMSDocumentSet.ds5 + extraDoc1: + Filename: extradoc1 + Folder: 5 + Sets: =>DMSDocumentSet.ds6 + BelongsToSet: 1 + CreatedByID: 2 + extraDoc2: + Filename: extradoc2 + Folder: 5 + CreatedByID: 2 + BelongsToSet: 0 + extraDoc3: + Filename: extradoc3 + Folder: 5 + BelongsToSet: 0 + CreatedByID: 2 + docSaveLinkedDocuments1: + Filename: saveLinkedDocument1 + Folder: 5 + Sets: =>DMSDocumentSet.dsSaveLinkedDocuments \ No newline at end of file