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
This commit is contained in:
Franco Springveldt 2017-05-08 23:57:52 +12:00 committed by Franco Springveldt
parent 6b80f32832
commit 6b25237ec6
17 changed files with 572 additions and 104 deletions

16
_config/querybuilder.yml Normal file
View File

@ -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'

View File

@ -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;
}

View File

@ -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;

118
code/forms/JsonField.php Normal file
View File

@ -0,0 +1,118 @@
<?php
/**
* Class JsonField combines form inputs into a key-value pair
*/
class JsonField extends CompositeField
{
public function __construct($name, $children = null)
{
$this->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;
}
}

View File

@ -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' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>'
@ -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)

View File

@ -1,19 +1,34 @@
<?php
/**
* A document set is attached to Pages, and contains many DMSDocuments
*
* @property Varchar Title
* @property Text KeyValuePairs
* @property Enum SortBy
* @property Enum SortByDirection
*/
class DMSDocumentSet extends DataObject
{
private static $db = array(
'Title' => '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
* }
* </code>
*
* @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' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>'
)
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' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>',
)
);
// 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:
*
* <code>
* public function updateQueryFields($result)
* {
* // Do something here
* }
* </code>
*
* @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));
}
}
}
}

View File

@ -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'
);

View File

@ -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'
```

View File

@ -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

View File

@ -1,9 +1,11 @@
<% if not $isHidden %>
<div class="document $Extension">
<% if $Title %>
<h4><a href="$Link" title="<%t DMSDocument.DOWNLOAD "Download {title}" title=$Title %>">$Title</a></h4>
<% else %>
<h4><a href="$Link" title="<%t DMSDocument.DOWNLOAD "Download {title}" title=$FilenameWithoutID %>">$FilenameWithoutID</a></h4>
<h4><a href="$Link" title="<%t DMSDocument.DOWNLOAD "Download {title}" title=$getTitle %>">$getTitle</a></h4>
<% if $CoverImage %>
<div class="article-thumbnail">
$CoverImage.FitMax(100, 100)
</div>
<% end_if %>
<p class="details"><% include DocumentDetails %></p>

View File

@ -1,4 +1,4 @@
<strong>$FilenameWithoutID</strong>
| $Extension
| $FileSizeFormatted
| <%t DMSDocument.LASTCHANGED "Last changed: {date}" date=$LastChanged.Nice %>
| <%t DMSDocument.LASTCHANGED "Last changed: {date}" date=$LastEdited.Nice %>

View File

@ -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');
}
}

View File

@ -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());
}
}

47
tests/JsonFieldTest.php Normal file
View File

@ -0,0 +1,47 @@
<?php
class JsonFieldTest extends SapphireTest
{
public function testJsonFieldConstructorMultiWays()
{
$jsonField = new JsonField('MyJsonField', new FieldList(
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', 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());
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* Class StubDocumentSetMockExtension
*
* @package dms
*/
class StubDocumentSetMockExtension extends DataExtension implements TestOnly
{
/**
*
* For method {@link DMSDocumentSet::addQueryFields}
*
* @param FieldList $fields
*
* @return FieldList
*/
public function updateQueryFields($fields)
{
$fields->addFieldToTab('Root.QueryBuilder', new TextField('ExtendedField'));
return $fields;
}
}

View File

@ -1,5 +1,10 @@
<?php
/**
* Class StubRelatedDocumentExtension
*
* @package dms
*/
class StubRelatedDocumentExtension extends DataExtension implements TestOnly
{
/**

View File

@ -20,6 +20,12 @@ SiteTree:
s7:
Title: testPage7 has documents embargoed until publish
URLSegment: s7
s8:
Title: testPage8
URLSegment: s8
s9:
Title: testPage9
URLSegment: s9
DMSTag:
t1:
Category: tag1
@ -69,6 +75,12 @@ DMSDocumentSet:
ds5:
Title: Set containing embargoed until publish documents
Page: =>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