diff --git a/README.md b/README.md
index 1f930bc..40476ea 100644
--- a/README.md
+++ b/README.md
@@ -19,10 +19,10 @@ Additionally, documents are stored and managed as part of a page instead of away
* 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
* Download via SilverStripe controller (rather than filesystem URLs)
* Access control based on PHP logic, and page relations
* Replacement of existing files
+ * Tagging via the [taxonomy module](https://github.com/silverstripe/silverstripe-taxonomy) if installed
## Documentation
@@ -32,11 +32,11 @@ For information on configuring and using this module, please see [the documentat
* PHP 5.3 with the "fileinfo" module (or alternatively the "whereis" and "file" Unix commands)
* SilverStripe framework/CMS ^3.5
+ * [Taxonomy](https://github.com/silverstripe/silverstripe-taxonomy) ^1.2 (for tagging)
* (optional) [Pagination of Documents in the CMS](https://github.com/silverstripe-big-o/gridfieldpaginatorwithshowall)
* (optional) [Sorting of Documents in the CMS](https://github.com/silverstripe-big-o/SortableGridField)
* (optional) [Full text search of Documents](https://github.com/silverstripe-big-o/silverstripe-fulltextsearch)
* (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)
## Contributing
diff --git a/_config/querybuilder.yml b/_config/querybuilder.yml
index 1814ba2..be986aa 100644
--- a/_config/querybuilder.yml
+++ b/_config/querybuilder.yml
@@ -1,16 +1,16 @@
DMSDocument:
searchable_fields:
Title:
- title: "Document title matches ..."
+ title: Document title matches
Description:
- title: "Document summary matches ..."
+ title: Document summary matches
CreatedByID:
- title: 'Document created by ...'
- field: 'ListboxField'
- filter: 'ExactMatchFilter'
+ title: Document created by
+ field: ListboxField
+ filter: ExactMatchFilter
LastEditedByID:
- title: 'Document last changed by ...'
- field: 'ListboxField'
- filter: 'ExactMatchFilter'
+ title: Document last changed by
+ field: ListboxField
+ filter: ExactMatchFilter
Filename:
- title: 'File name'
\ No newline at end of file
+ title: File name
diff --git a/_config/taxonomy.yml b/_config/taxonomy.yml
new file mode 100644
index 0000000..2b45fd5
--- /dev/null
+++ b/_config/taxonomy.yml
@@ -0,0 +1,25 @@
+---
+Name: dmstaxonomy
+Only:
+ moduleexists: taxonomy
+---
+TaxonomyType:
+ extensions:
+ - DMSTaxonomyTypeExtension
+
+DMSDocument:
+ extensions:
+ - DMSDocumentTaxonomyExtension
+ # Add query builder filter for tags
+ searchable_fields:
+ Tags.ID:
+ title: Document has tags
+ field: ListboxField
+ filter: ExactMatchFilter
+
+DMSTaxonomyTypeExtension:
+ # Referenced to filter taxonomy terms for DMS Documents.
+ # To change, update the default_records array too.
+ default_record_name: Document
+ default_records:
+ - Document
diff --git a/code/DMS.php b/code/DMS.php
index 541b01d..887e877 100644
--- a/code/DMS.php
+++ b/code/DMS.php
@@ -121,27 +121,6 @@ class DMS extends Object implements DMSInterface
return $doc;
}
- /**
- *
- * Returns a number of Document objects based on the a search by tags. You can search by category alone,
- * by tag value alone, or by both. I.e:
- *
- *
- * getByTag("fruits", null);
- * getByTag(null, "banana");
- * getByTag("fruits", "banana");
- *
- *
- * @param null $category The metadata category to search for
- * @param null $value The metadata value to search for
- * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
- * @return DocumentInterface
- */
- public function getByTag($category = null, $value = null, $showEmbargoed = false)
- {
- // TODO: Implement getByTag() method.
- }
-
/**
* Returns a number of Document objects that match a full-text search of the Documents and their contents
* (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module)
diff --git a/code/cms/DMSGridFieldDeleteAction.php b/code/cms/DMSGridFieldDeleteAction.php
deleted file mode 100644
index edbba46..0000000
--- a/code/cms/DMSGridFieldDeleteAction.php
+++ /dev/null
@@ -1,121 +0,0 @@
-
- * $action = new GridFieldDeleteAction(); // delete objects permanently
- *
- *
- * @package dms
- * @subpackage cms
- */
-class DMSGridFieldDeleteAction extends GridFieldDeleteAction implements
- GridField_ColumnProvider,
- GridField_ActionProvider
-{
-
- /**
- *
- * @param GridField $gridField
- * @param DataObject $record
- * @param string $columnName
- * @return string - the HTML for the column
- */
- public function getColumnContent($gridField, $record, $columnName)
- {
- if ($this->removeRelation) {
- $field = GridField_FormAction::create(
- $gridField,
- 'UnlinkRelation' . $record->ID,
- false,
- "unlinkrelation",
- array('RecordID' => $record->ID)
- )
- ->addExtraClass('gridfield-button-unlink')
- ->setAttribute('title', _t('GridAction.UnlinkRelation', "Unlink"))
- ->setAttribute('data-icon', 'chain--minus');
- } else {
- if (!$record->canDelete()) {
- return '';
- }
-
- $field = GridField_FormAction::create(
- $gridField,
- 'DeleteRecord' . $record->ID,
- false,
- "deleterecord",
- array('RecordID' => $record->ID)
- )
- ->addExtraClass('gridfield-button-delete')
- ->setAttribute('title', _t('GridAction.Delete', "Delete"))
- ->setAttribute('data-icon', 'cross-circle')
- ->setDescription(_t('GridAction.DELETE_DESCRIPTION', 'Delete'));
- }
-
- // Add a class to the field to if it is the last gridfield in the list
- $numberOfRelations = $record->getRelatedPages()->count();
- $field
- // Add a new class for custom JS to handle the delete action
- ->addExtraClass('dms-delete')
- // Add the number of pages attached to this field as a data-attribute
- ->setAttribute('data-pages-count', $numberOfRelations)
- // Remove the base gridfield behaviour
- ->removeExtraClass('gridfield-button-delete');
-
- // Set a class telling JS what kind of warning to display when clicking the delete button
- if ($numberOfRelations > 1) {
- $field->addExtraClass('dms-delete-link-only');
- } else {
- $field->addExtraClass('dms-delete-last-warning');
- }
-
- // Set a class to show if the document is hidden
- if ($record->isHidden()) {
- $field->addExtraClass('dms-document-hidden');
- }
-
- return $field->Field();
- }
-
- /**
- * Handle the actions and apply any changes to the GridField
- *
- * @param GridField $gridField
- * @param string $actionName
- * @param mixed $arguments
- * @param array $data - form data
- * @return void
- * @throws ValidationException If the current user doesn't have permission to delete the record
- */
- public function handleAction(GridField $gridField, $actionName, $arguments, $data)
- {
- if ($actionName == 'deleterecord' || $actionName == 'unlinkrelation') {
- $item = $gridField->getList()->byID($arguments['RecordID']);
- if (!$item) {
- return;
- }
- if ($actionName == 'deleterecord' && !$item->canDelete()) {
- throw new ValidationException(
- _t('GridFieldAction_Delete.DeletePermissionsFailure', "No delete permissions"),
- 0
- );
- }
-
- $delete = false;
- if ($item->getRelatedPages()->count() <= 1) {
- $delete = true;
- }
-
- // Remove the relation
- $gridField->getList()->remove($item);
- if ($delete) {
- // Delete the document
- $item->delete();
- }
- }
- }
-}
diff --git a/code/cms/DMSUploadField.php b/code/cms/DMSUploadField.php
index 89b65f1..7f64f25 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, array('BelongsToSet' => 1));
+ $record->Documents()->add($doc, array('ManuallyAdded' => 1));
}
return $doc;
diff --git a/code/extensions/DMSDocumentTaxonomyExtension.php b/code/extensions/DMSDocumentTaxonomyExtension.php
new file mode 100644
index 0000000..2925ef9
--- /dev/null
+++ b/code/extensions/DMSDocumentTaxonomyExtension.php
@@ -0,0 +1,55 @@
+ 'TaxonomyTerm'
+ );
+
+ /**
+ * Push an autocomplete dropdown for the available tags in documents
+ *
+ * @param FieldList $fields
+ */
+ public function updateCMSFields(FieldList $fields)
+ {
+ $tags = $this->getAllTagsMap();
+ $tagField = ListboxField::create('Tags', _t('DMSDocumentTaxonomyExtension.TAGS', 'Tags'))
+ ->setMultiple(true)
+ ->setSource($tags);
+
+ if (empty($tags)) {
+ $tagField->setAttribute('data-placeholder', _t('DMSDocumentTaxonomyExtension.NOTAGS', 'No tags found'));
+ }
+
+ $fields->insertAfter('Description', $tagField);
+ }
+
+ /**
+ * Return an array of all the available tags that a document can use. Will return a list containing a taxonomy
+ * term's entire hierarchy, e.g. "Photo > Attribute > Density > High"
+ *
+ * @return array
+ */
+ public function getAllTagsMap()
+ {
+ $tags = TaxonomyTerm::get()->filter(
+ 'Type.Name:ExactMatch',
+ Config::inst()->get('DMSTaxonomyTypeExtension', 'default_record_name')
+ );
+
+ $map = array();
+ foreach ($tags as $tag) {
+ $nameParts = array($tag->Name);
+ $currentTag = $tag;
+
+ while ($currentTag->Parent() && $currentTag->Parent()->exists()) {
+ array_unshift($nameParts, $currentTag->Parent()->Name);
+ $currentTag = $currentTag->Parent();
+ }
+
+ $map[$tag->ID] = implode(' > ', $nameParts);
+ }
+ return $map;
+ }
+}
diff --git a/code/extensions/DMSTaxonomyTypeExtension.php b/code/extensions/DMSTaxonomyTypeExtension.php
new file mode 100644
index 0000000..76a03af
--- /dev/null
+++ b/code/extensions/DMSTaxonomyTypeExtension.php
@@ -0,0 +1,28 @@
+
+ * DMSTaxonomyTypeExtension:
+ * default_records:
+ * - Document
+ * - PrivateDocument
+ *
+ */
+ public function requireDefaultRecords()
+ {
+ $records = (array) Config::inst()->get(get_class($this), 'default_records');
+ foreach ($records as $name) {
+ $type = TaxonomyType::get()->filter('Name', $name)->first();
+ if (!$type) {
+ $type = TaxonomyType::create(array('Name' => $name));
+ $type->write();
+ }
+ }
+ }
+}
diff --git a/code/interface/DMSDocumentInterface.php b/code/interface/DMSDocumentInterface.php
index e46fac8..58be684 100644
--- a/code/interface/DMSDocumentInterface.php
+++ b/code/interface/DMSDocumentInterface.php
@@ -6,47 +6,6 @@
*/
interface DMSDocumentInterface
{
- /**
- * Adds a metadata tag to the DMSDocument. The tag has a category and a value.
- * Each category can have multiple values by default. So: addTag("fruit","banana") addTag("fruit", "apple") will
- * add two items.
- * However, if the third parameter $multiValue is set to 'false', then all updates to a category only ever update
- * a single value. So:
- * addTag("fruit","banana") addTag("fruit", "apple") would result in a single metadata tag: fruit->apple.
- * Can could be implemented as a key/value store table (although it is more like category/value, because the
- * same category can occur multiple times)
- * @param $category String of a metadata category to add (required)
- * @param $value String of a metadata value to add (required)
- * @param bool $multiValue Boolean that determines if the category is multi-value or single-value (optional)
- * @return null
- */
- public function addTag($category, $value, $multiValue = true);
-
- /**
- * Fetches all tags associated with this DMSDocument within a given category. If a value is specified this method
- * tries to fetch that specific tag.
- * @param $category String of the metadata category to get
- * @param null $value String of the value of the tag to get
- * @return array of Strings of all the tags or null if there is no match found
- */
- public function getTagsList($category, $value = null);
-
- /**
- * Removes a tag from the DMSDocument. If you only set a category, then all values in that category are deleted.
- * If you specify both a category and a value, then only that single category/value pair is deleted.
- * Nothing happens if the category or the value do not exist.
- * @param $category Category to remove (required)
- * @param null $value Value to remove (optional)
- * @return null
- */
- public function removeTag($category, $value = null);
-
- /**
- * Deletes all tags associated with this DMSDocument.
- * @return null
- */
- public function removeAllTags();
-
/**
* Returns a link to download this DMSDocument from the DMS store
* @return String
diff --git a/code/interface/DMSInterface.php b/code/interface/DMSInterface.php
index 1909dda..09be427 100644
--- a/code/interface/DMSInterface.php
+++ b/code/interface/DMSInterface.php
@@ -27,24 +27,6 @@ interface DMSInterface
*/
public function storeDocument($file);
- /**
- *
- * Returns a number of Document objects based on the a search by tags. You can search by category alone,
- * by tag value alone, or by both. I.e:
- *
- *
- * getByTag("fruits", null);
- * getByTag(null, "banana");
- * getByTag("fruits", "banana");
- *
- * @abstract
- * @param null $category The metadata category to search for
- * @param null $value The metadata value to search for
- * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
- * @return DMSDocumentInterface
- */
- public function getByTag($category = null, $value = null, $showEmbargoed = false);
-
/**
* Returns a number of Document objects that match a full-text search of the Documents and their contents
* (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module)
diff --git a/code/model/DMSDocument.php b/code/model/DMSDocument.php
index bd76322..523bc92 100644
--- a/code/model/DMSDocument.php
+++ b/code/model/DMSDocument.php
@@ -17,7 +17,6 @@
* @property Enum CanEditType Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')
*
* @method ManyManyList RelatedDocuments
- * @method ManyManyList Tags
* @method ManyManyList ViewerGroups
* @method ManyManyList EditorGroups
*
@@ -56,7 +55,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
private static $many_many = array(
'RelatedDocuments' => 'DMSDocument',
- 'Tags' => 'DMSTag',
'ViewerGroups' => 'Group',
'EditorGroups' => 'Group',
);
@@ -65,7 +63,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
'ID' => 'ID',
'Title' => 'Title',
'FilenameWithoutID' => 'Filename',
- 'LastEdited' => 'LastEdited'
+ 'LastEdited' => 'Last Edited'
);
private static $singular_name = 'Document';
@@ -244,173 +242,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
return $this;
}
-
- /**
- * Adds a metadata tag to the Document. The tag has a category and a value.
- *
- * Each category can have multiple values by default. So:
- * addTag("fruit","banana") addTag("fruit", "apple") will add two items.
- *
- * However, if the third parameter $multiValue is set to 'false', then all
- * updates to a category only ever update a single value. So:
- * addTag("fruit","banana") addTag("fruit", "apple") would result in a
- * single metadata tag: fruit->apple.
- *
- * Can could be implemented as a key/value store table (although it is more
- * like category/value, because the same category can occur multiple times)
- *
- * @param string $category of a metadata category to add (required)
- * @param string $value of a metadata value to add (required)
- * @param bool $multiValue Boolean that determines if the category is
- * multi-value or single-value (optional)
- *
- * @return DMSDocument
- */
- public function addTag($category, $value, $multiValue = true)
- {
- if ($multiValue) {
- //check for a duplicate tag, don't add the duplicate
- $currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value));
- if ($currentTag->Count() == 0) {
- //multi value tag
- $tag = new DMSTag();
- $tag->Category = $category;
- $tag->Value = $value;
- $tag->MultiValue = true;
- $tag->write();
- $tag->Documents()->add($this);
- } else {
- //add the relation between the tag and document
- foreach ($currentTag as $tagObj) {
- $tagObj->Documents()->add($this);
- }
- }
- } else {
- //single value tag
- $currentTag = $this->Tags()->filter(array('Category' => $category));
- $tag = null;
- if ($currentTag->Count() == 0) {
- //create the single-value tag
- $tag = new DMSTag();
- $tag->Category = $category;
- $tag->Value = $value;
- $tag->MultiValue = false;
- $tag->write();
- } else {
- //update the single value tag
- $tag = $currentTag->first();
- $tag->Value = $value;
- $tag->MultiValue = false;
- $tag->write();
- }
-
- // regardless of whether we created a new tag or are just updating an
- // existing one, add the relation
- $tag->Documents()->add($this);
- }
-
- return $this;
- }
-
- /**
- * @param string $category
- * @param string $value
- *
- * @return DataList
- */
- protected function getTagsObjects($category, $value = null)
- {
- $valueFilter = array("Category" => $category);
- if (!empty($value)) {
- $valueFilter['Value'] = $value;
- }
-
- $tags = $this->Tags()->filter($valueFilter);
- return $tags;
- }
-
- /**
- * Fetches all tags associated with this DMSDocument within a given
- * category. If a value is specified this method tries to fetch that
- * specific tag.
- *
- * @param string $category metadata category to get
- * @param string $value value of the tag to get
- *
- * @return array Strings of all the tags or null if there is no match found
- */
- public function getTagsList($category, $value = null)
- {
- $tags = $this->getTagsObjects($category, $value);
-
- $returnArray = null;
-
- if ($tags->Count() > 0) {
- $returnArray = array();
-
- foreach ($tags as $t) {
- $returnArray[] = $t->Value;
- }
- }
-
- return $returnArray;
- }
-
- /**
- * Removes a tag from the Document. If you only set a category, then all
- * values in that category are deleted.
- *
- * If you specify both a category and a value, then only that single
- * category/value pair is deleted.
- *
- * Nothing happens if the category or the value do not exist.
- *
- * @param string $category Category to remove
- * @param string $value Value to remove
- *
- * @return DMSDocument
- */
- public function removeTag($category, $value = null)
- {
- $tags = $this->getTagsObjects($category, $value);
-
- if ($tags->Count() > 0) {
- foreach ($tags as $t) {
- $documentList = $t->Documents();
-
- //remove the relation between the tag and the document
- $documentList->remove($this);
-
- //delete the entire tag if it has no relations left
- if ($documentList->Count() == 0) {
- $t->delete();
- }
- }
- }
-
- return $this;
- }
-
- /**
- * Deletes all tags associated with this Document.
- *
- * @return DMSDocument
- */
- public function removeAllTags()
- {
- $allTags = $this->Tags();
-
- foreach ($allTags as $tag) {
- $documentlist = $tag->Documents();
- $documentlist->remove($this);
- if ($tag->Documents()->Count() == 0) {
- $tag->delete();
- }
- }
-
- return $this;
- }
-
/**
* Returns a link to download this document from the DMS store.
* Alternatively a basic javascript alert will be shown should the user not have view permissions. An extension
@@ -717,17 +548,13 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
}
/**
- * Deletes the DMSDocument, its underlying file, as well as any tags related
- * to this DMSDocument. Also calls the parent DataObject's delete method in
+ * Deletes the DMSDocument and its underlying file. Also calls the parent DataObject's delete method in
* order to complete an cascade.
*
* @return void
*/
public function delete()
{
- // remove tags
- $this->removeAllTags();
-
// delete the file (and previous versions of files)
$filesToDelete = array();
$storageFolder = $this->getStorageFolder();
@@ -1383,6 +1210,9 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
// Ensure that current document doesn't get returned in the autocompleter
$addExisting->setSearchList($this->getRelatedDocumentsForAutocompleter());
+ // Restrict search fields to specific fields only
+ $addExisting->setSearchFields(array('Title', 'Filename'));
+
$this->extend('updateRelatedDocumentsGridField', $gridField);
return $gridField;
diff --git a/code/model/DMSDocumentSet.php b/code/model/DMSDocumentSet.php
index 65e53fc..e0cb159 100644
--- a/code/model/DMSDocumentSet.php
+++ b/code/model/DMSDocumentSet.php
@@ -26,7 +26,9 @@ class DMSDocumentSet extends DataObject
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.
+ // Flag indicating if a document was added directly to a set - in which case it is set - or added
+ // via the query-builder.
+ 'ManuallyAdded' => 'Boolean(1)',
),
);
@@ -89,7 +91,7 @@ class DMSDocumentSet extends DataObject
new GridFieldDataColumns(),
new GridFieldEditButton(),
// Special delete dialog to handle custom behaviour of unlinking and deleting
- new DMSGridFieldDeleteAction(),
+ new GridFieldDeleteAction(true),
new GridFieldDetailForm()
);
@@ -115,7 +117,7 @@ class DMSDocumentSet extends DataObject
->setFieldFormatting(
array(
'FilenameWithoutID' => '$FilenameWithoutID',
- 'BelongsToSet' => function ($value) {
+ 'ManuallyAdded' => function ($value) {
if ($value) {
return _t('DMSDocumentSet.MANUAL', 'Manually');
}
@@ -197,24 +199,24 @@ class DMSDocumentSet extends DataObject
$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);
+ if ($field instanceof ListboxField) {
+ $map = ($field->getName() === 'Tags__ID') ? $doc->getAllTagsMap() : $membersMap;
+ $field->setMultiple(true)->setSource($map);
}
}
$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'),
- ));
+ 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));
@@ -230,40 +232,65 @@ class DMSDocumentSet extends DataObject
/**
* 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));
- }
+ if (empty($this->KeyValuePairs) || !$this->isChanged('KeyValuePairs')) {
+ return;
}
+
+ $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);
+ $documents = $this->addEmbargoConditions($documents);
+ $documents = $this->addQueryBuilderSearchResults($documents);
+ }
+
+ /**
+ * Add embargo date conditions to a search query
+ *
+ * @param DataList $documents
+ * @return DataList
+ */
+ protected function addEmbargoConditions(DataList $documents)
+ {
+ $now = SS_Datetime::now()->Rfc2822();
+
+ return $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 ManuallyAdded = 0 original results and add in the new documents returned by the search context
+ *
+ * @param DataList $documents
+ * @return DataList
+ */
+ protected function addQueryBuilderSearchResults(DataList $documents)
+ {
+ /** @var ManyManyList $originals Documents that belong to just this set. */
+ $originals = $this->Documents();
+ $originals->removeByFilter('"ManuallyAdded" = 0');
+
+ foreach ($documents as $document) {
+ $originals->add($document, array('ManuallyAdded' => 0));
+ }
+
+ return $originals;
}
/**
@@ -275,7 +302,7 @@ class DMSDocumentSet extends DataObject
{
return array_merge(
(array) DMSDocument::create()->config()->get('display_fields'),
- array('BelongsToSet' => _t('DMSDocumentSet.ADDEDMETHOD', 'Added'))
+ array('ManuallyAdded' => _t('DMSDocumentSet.ADDEDMETHOD', 'Added'))
);
}
}
diff --git a/code/model/DMSTag.php b/code/model/DMSTag.php
deleted file mode 100644
index a403dbf..0000000
--- a/code/model/DMSTag.php
+++ /dev/null
@@ -1,18 +0,0 @@
- 'Varchar(1024)',
- 'Value' => 'Varchar(1024)',
- 'MultiValue' => 'Boolean(1)'
- );
-
- private static $belongs_many_many = array(
- 'Documents' => 'DMSDocument'
- );
-}
diff --git a/composer.json b/composer.json
index d751f94..4d61c7d 100644
--- a/composer.json
+++ b/composer.json
@@ -11,7 +11,8 @@
"require": {
"silverstripe/framework": "^3.5",
"silverstripe/cms": "^3.5",
- "silverstripe-australia/gridfieldextensions": "^1.1.0"
+ "silverstripe-australia/gridfieldextensions": "^1.1.0",
+ "silverstripe/taxonomy": "1.2.x-dev"
},
"extra": {
"branch-alias": {
diff --git a/docs/en/changelogs/2.0.0.md b/docs/en/changelogs/2.0.0.md
index d0380de..22c879b 100644
--- a/docs/en/changelogs/2.0.0.md
+++ b/docs/en/changelogs/2.0.0.md
@@ -6,7 +6,8 @@ Documents now belong to "sets", which are attached to Pages. A Page can have man
many_many relationship with Documents.
When upgrading from 1.x to 2.x you will need to migrate the relationships from your Pages to Documents to support
-having a Document Set intermediary (@todo Add a build task for this).
+having a Document Set intermediary. [See here](../migration/document-sets.md) for an example build task to help with
+this process.
## API changes
@@ -29,6 +30,9 @@ having a Document Set intermediary (@todo Add a build task for this).
* `DMS::transform_file_to_file_path` made non-static, use `DMS::inst()->transformFileToFilePath()` instead
* `DMS::create_storage_folder` made non-static, use `DMS::inst()->createStorageFolder()` instead
* `DMS::get_storage_folder` made non-static, use `DMS::inst()->getStorageFolder()` instead
+* `DMSDocument::addTag`, `::getTagsList`, `::removeTag` and `::removeAllTags` removed from the `DMSDocument` and `DMSDocumentInterface`. Please use the ORM relationship created by applying the `DMSDocumentTaxonomyExtension` extension to `DMSDocument` instead.
+* `DMSInterface::getByTag` removed from `DMSInterface` and `DMS`. Use ORM relationships from applying `DMSDocumentTaxonomyExtension` to `DMSDocument` instead.
+* `DMSGridFieldDeleteAction` removed
## Template changes
diff --git a/docs/en/index.md b/docs/en/index.md
index 0d791bc..cde3f75 100644
--- a/docs/en/index.md
+++ b/docs/en/index.md
@@ -8,7 +8,6 @@
* [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)
* [Building frontend assets](building-frontend-assets.md)
diff --git a/docs/en/manage-tags.md b/docs/en/manage-tags.md
deleted file mode 100644
index 7b9e51e..0000000
--- a/docs/en/manage-tags.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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/javascript/DMSGridField.js b/javascript/DMSGridField.js
index f7e1890..35543aa 100644
--- a/javascript/DMSGridField.js
+++ b/javascript/DMSGridField.js
@@ -1,125 +1,15 @@
(function ($) {
- "use strict";
+ "use strict";
- $.entwine('ss', function ($) {
-
- $('#SectionID ul li').entwine({
- onadd: function () {
- this.addClass('ui-button ss-ui-button ui-corner-all ui-state-default ui-widget ui-button-text-only');
- this.parents('ul').removeClass('ui-tabs-nav');
- }
- });
-
- $('#SectionID input[type=radio]').entwine({
- onadd: function () {
- // Checks to see what radio button is selected
- if (this.is(':checked')) {
- this.change();
- }
- },
- onchange: function (e) {
- // Remove selected class from radio buttons
- $('#SectionID').find('li').removeClass('selected');
- //If radio button is checked then add the selected class
- if (this.is(':checked')) {
- this.parent('li').addClass('selected');
- }
- }
- });
-
- $('.ss-gridfield .action.dms-delete').entwine({
- onclick: function (e) {
- //work out how many pages are left attached to this document
- var pagesCount = this.data('pages-count');
- var pagesCountAfterDeletion = pagesCount - 1;
- var addS = 's';
- if (pagesCountAfterDeletion === 1) {
- addS = '';
- }
-
- //display an appropriate message
- var message = '';
- if (this.hasClass('dms-delete-last-warning')) {
- message = "Permanently delete this document?\n\nWarning: this document is attached only to this page, deleting it here will delete it permanently.";
- }
- if (this.hasClass('dms-delete-link-only')) {
- message = "Unlink this document from this page?\n\nNote: it will remain attached to "+pagesCountAfterDeletion+" other page"+addS+".";
- }
-
- if (!confirm(message)) {
- e.preventDefault();
- return false;
- } else {
- //user says "okay", so go ahead and do the action
- this._super(e);
- }
- }
- });
-
- $('.ss-gridfield .dms-document-hidden').entwine({
- onadd: function () {
- this.closest('tr').addClass('dms-document-hidden-row');
- }
- });
-
- $('.cms-content-actions.south .ss-ui-action-destructive').entwine({
- confirmBeforeDelete: function () {
- var deleteButtons = $('button.dms-delete[data-pages-count=1]');
-
- //we have page with DMSDocuments on it, and we have documents that only exist on this page
- if (deleteButtons.length > 0) {
- var message = "Are you sure you want to delete this page? Deleting this page will delete "+deleteButtons.length;
- if (deleteButtons.length === 1) {
- message += " document that is associated only with this page. This document is:\n\n";
- } else {
- message += " documents that are associated only with this page. These documents are:\n\n";
- }
-
- //create a list of documents and their IDs
- deleteButtons.each(function () {
- var tr = $(this).closest('tr');
- message += tr.find('.col-ID').text() +' - '+ tr.find('.col-Title').text() +"\n";
- });
-
- if (!confirm(message)) {
- return false;
- }
- }
-
- return true;
- }
- });
-
- $('#Form_EditForm_action_deletefromlive').entwine({
- onclick: function (e) {
- if (this.confirmBeforeDelete()) {
- this._super(e);
- } else {
- return false;
- }
- }
- });
-
- $('#Form_EditForm_action_delete').entwine({
- onclick: function (e) {
- if (this.confirmBeforeDelete()) {
- this._super(e);
- } else {
- return false;
- }
- }
- });
-
- $('.ss-gridfield-item a.file-url').entwine({
- onclick: function (e) {
- //make sure the download link doesn't trigger a gridfield edit dialog
- window.open(this.attr('href'), '_blank');
-
- e.preventDefault();
- return false;
- }
- });
-
- });
+ $.entwine('ss', function ($) {
+ $('.ss-gridfield-item a.file-url').entwine({
+ onclick: function (e) {
+ //make sure the download link doesn't trigger a gridfield edit dialog
+ window.open(this.attr('href'), '_blank');
+ e.preventDefault();
+ return false;
+ }
+ });
+ });
}(jQuery));
diff --git a/lang/en.yml b/lang/en.yml
index 78d9f4f..8c3a4b3 100644
--- a/lang/en.yml
+++ b/lang/en.yml
@@ -27,9 +27,9 @@ en:
GRIDFIELD_NOTICE: Managing documents will be available once you have created this document set.
PLURALNAME: Document Sets
SINGULARNAME: Document Set
- DMSTag:
- PLURALNAME: 'DMS Tags'
- SINGULARNAME: 'DMS Tag'
+ DMSDocumentTaxonomyExtension:
+ TAGS: Tags
+ NOTAGS: No tags found
FileIFrameField:
ATTACHONCESAVED2: 'Files can be attached once you have saved the record for the first time.'
GridAction:
diff --git a/lang/es.yml b/lang/es.yml
index f68d97d..6cf33d0 100644
--- a/lang/es.yml
+++ b/lang/es.yml
@@ -13,9 +13,6 @@ es:
RelatedPages: 'Páginas relacionadas'
RelatedReferences: 'Referencias relacionadas'
SINGULARNAME: Documento
- DMSTag:
- PLURALNAME: 'Etiquetas del Sistema documental'
- SINGULARNAME: 'Etiqueta del Sistema documental'
FileIFrameField:
ATTACHONCESAVED2: 'Archivos pueden ser adjuntados una vez que guardes por primera vez.'
GridAction:
diff --git a/lang/nl.yml b/lang/nl.yml
index 78664b3..4d4328e 100644
--- a/lang/nl.yml
+++ b/lang/nl.yml
@@ -13,9 +13,6 @@ nl:
RelatedPages: 'Gerelateerde paginas'
RelatedReferences: 'Gerelateerde referenties'
SINGULARNAME: 'Document'
- DMSTag:
- PLURALNAME: 'D M S Tags'
- SINGULARNAME: 'D M S Tag'
FileIFrameField:
ATTACHONCESAVED2: 'Bestanden kunnen worden toegevoegd na het voor het eerst opslaan'
GridAction:
diff --git a/tests/DMSDocumentSetTest.php b/tests/DMSDocumentSetTest.php
index af7080c..4204db8 100644
--- a/tests/DMSDocumentSetTest.php
+++ b/tests/DMSDocumentSetTest.php
@@ -68,7 +68,6 @@ class DMSDocumentSetTest extends SapphireTest
/** @var GridFieldConfig $config */
$config = $gridField->getConfig();
- $this->assertNotNull($config->getComponentByType('DMSGridFieldDeleteAction'));
$this->assertNotNull($addNew = $config->getComponentByType('DMSGridFieldAddNewButton'));
$this->assertSame($set->ID, $addNew->getDocumentSetId());
@@ -96,14 +95,14 @@ class DMSDocumentSetTest extends SapphireTest
$displayFields = $document->getDocumentDisplayFields();
$this->assertContains('Apple', $displayFields);
$this->assertContains('Orange', $displayFields);
- $this->assertArrayHasKey('BelongsToSet', $displayFields);
+ $this->assertArrayHasKey('ManuallyAdded', $displayFields);
$this->assertContains('Added', $displayFields);
}
/**
- * Tests to ensure that the callback for formatting BelongsToSet will return a nice label for the user
+ * Tests to ensure that the callback for formatting ManuallyAdded will return a nice label for the user
*/
- public function testNiceFormattingForBelongsToSetInGridField()
+ public function testNiceFormattingForManuallyAddedInGridField()
{
$fieldFormatting = $this->objFromFixture('DMSDocumentSet', 'ds1')
->getCMSFields()
@@ -112,11 +111,11 @@ class DMSDocumentSetTest extends SapphireTest
->getComponentByType('GridFieldDataColumns')
->getFieldFormatting();
- $this->assertArrayHasKey('BelongsToSet', $fieldFormatting);
- $this->assertTrue(is_callable($fieldFormatting['BelongsToSet']));
+ $this->assertArrayHasKey('ManuallyAdded', $fieldFormatting);
+ $this->assertTrue(is_callable($fieldFormatting['ManuallyAdded']));
- $this->assertSame('Manually', $fieldFormatting['BelongsToSet'](1));
- $this->assertSame('Query Builder', $fieldFormatting['BelongsToSet'](0));
+ $this->assertSame('Manually', $fieldFormatting['ManuallyAdded'](1));
+ $this->assertSame('Query Builder', $fieldFormatting['ManuallyAdded'](0));
}
/**
diff --git a/tests/DMSDocumentTest.php b/tests/DMSDocumentTest.php
index b0278a5..6973d35 100644
--- a/tests/DMSDocumentTest.php
+++ b/tests/DMSDocumentTest.php
@@ -84,6 +84,7 @@ class DMSDocumentTest extends SapphireTest
$this->assertNotContains('test-file-file-doesnt-exist-1', $jsonResult);
$this->assertContains('test-file-file-doesnt-exist-2', $jsonResult);
+ $this->assertEquals(array('Title', 'Filename'), $autocompleter->getSearchFields());
}
/**
diff --git a/tests/DMSTagTest.php b/tests/DMSTagTest.php
deleted file mode 100644
index d8377bd..0000000
--- a/tests/DMSTagTest.php
+++ /dev/null
@@ -1,122 +0,0 @@
-delete();
- }
- $t = DataObject::get("DMSTag");
- foreach ($t as $t1) {
- $t1->delete();
- }
-
- self::$is_running_test = $this->originalIsRunningTest;
- }
-
- public function testAddingTags()
- {
- $doc = new DMSDocument();
- $doc->Filename = "test file";
- $doc->Folder = "0";
- $doc->write();
-
- $doc->addTag("fruit", "banana");
- $doc->addTag("fruit", "orange");
- $doc->addTag("fruit", "apple");
- $doc->addTag("company", "apple");
- $doc->addTag("company", "SilverStripe");
-
- $fruits = $doc->getTagsList("fruit");
- $this->assertNotNull($fruits, "Something returned for fruit tags");
- $this->assertEquals(count($fruits), 3, "3 fruit tags returned");
- $this->assertTrue(in_array("banana", $fruits), "correct fruit tags returned");
-
- //sneakily create another document and link one of the tags to that, too
- $doc2 = new DMSDocument();
- $doc2->Filename = "sneaky file";
- $doc2->Folder = "0";
- $doc2->write();
- $doc2->addTag("fruit", "banana");
-
- $fruits = $doc2->getTagsList("fruit");
- $this->assertNotNull($fruits, "Something returned for fruit tags");
- $this->assertEquals(count($fruits), 1, "Only 1 fruit tags returned");
-
- //tidy up by deleting all tags from doc 1 (But the banana fruit tag should remain)
- $doc->removeAllTags();
-
- //banana fruit remains
- $fruits = $doc2->getTagsList("fruit");
- $this->assertNotNull($fruits, "Something returned for fruit tags");
- $this->assertEquals(count($fruits), 1, "Only 1 fruit tags returned");
-
- $tags = DataObject::get("DMSTag");
- $this->assertEquals($tags->Count(), 1, "A single DMS tag objects remain after deletion of all tags on doc1");
-
- //delete all tags off doc2 to complete the tidy up
- $doc2->removeAllTags();
-
- $tags = DataObject::get("DMSTag");
- $this->assertEquals($tags->Count(), 0, "No DMS tag objects remain after deletion");
- }
-
- public function testRemovingTags()
- {
- $doc = new DMSDocument();
- $doc->Filename = "test file";
- $doc->Folder = "0";
- $doc->write();
-
- $doc->addTag("fruit", "banana");
- $doc->addTag("fruit", "orange");
- $doc->addTag("fruit", "apple");
- $doc->addTag("company", "apple");
- $doc->addTag("company", "SilverStripe");
-
- $companies = $doc->getTagsList("company");
- $this->assertNotNull($companies, "Companies returned before deletion");
- $this->assertEquals(count($companies), 2, "Two companies returned before deletion");
-
- //delete an entire category
- $doc->removeTag("company");
-
- $companies = $doc->getTagsList("company");
- $this->assertNull($companies, "All companies deleted");
-
- $fruit = $doc->getTagsList("fruit");
- $this->assertEquals(count($fruit), 3, "Three fruits returned before deletion");
-
- //delete a single tag
- $doc->removeTag("fruit", "apple");
-
- $fruit = $doc->getTagsList("fruit");
- $this->assertEquals(count($fruit), 2, "Two fruits returned after deleting one");
-
- //delete a single tag
- $doc->removeTag("fruit", "orange");
-
- $fruit = $doc->getTagsList("fruit");
- $this->assertEquals(count($fruit), 1, "One fruits returned after deleting two");
-
- //nothing happens when deleting tag that doesn't exist
- $doc->removeTag("fruit", "jellybean");
-
- $fruit = $doc->getTagsList("fruit");
- $this->assertEquals(count($fruit), 1, "One fruits returned after attempting to delete non-existent fruit");
-
- //delete the last fruit
- $doc->removeTag("fruit", "banana");
-
- $fruit = $doc->getTagsList("fruit");
- $this->assertNull($fruit, "All fruits deleted");
-
- $tags = DataObject::get("DMSTag");
- $this->assertEquals($tags->Count(), 0, "No DMS tag objects remain after deletion");
- }
-}
diff --git a/tests/dmstest.yml b/tests/dmstest.yml
index 1eceda6..dab68b0 100644
--- a/tests/dmstest.yml
+++ b/tests/dmstest.yml
@@ -26,25 +26,6 @@ SiteTree:
s9:
Title: testPage9
URLSegment: s9
-DMSTag:
- t1:
- Category: tag1
- Value: tag1value
- t2:
- Category: tag2
- Value: tag2value
- t3:
- Category: tag3
- Value: tag3value
- t4:
- Category: tag4
- Value: tag4value
- t5:
- Category: tag5
- Value: tag5value
- t6:
- Category: tag6
- Value: tag6value
Group:
content-author:
Code: content-author
@@ -85,13 +66,11 @@ DMSDocument:
d1:
Filename: test-file-file-doesnt-exist-1
Folder: 5
- Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
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:
Filename: file-with-relations
@@ -102,20 +81,17 @@ DMSDocument:
CanViewType: LoggedInUsers
CanEditType: LoggedInUsers
Folder: 5
- Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
doc-anyone:
FileName: doc-anyone
CanViewType: Anyone
Folder: 5
- Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
doc-only-these-users:
FileName: doc-only-these-users
CanViewType: OnlyTheseUsers
CanEditType: OnlyTheseUsers
Folder: 5
- Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
ViewerGroups: =>Group.content-author
EditorGroups: =>Group.content-author
@@ -138,19 +114,19 @@ DMSDocument:
Filename: extradoc1
Folder: 5
Sets: =>DMSDocumentSet.ds6
- BelongsToSet: 1
+ ManuallyAdded: 1
CreatedByID: 2
extraDoc2:
Filename: extradoc2
Folder: 5
CreatedByID: 2
- BelongsToSet: 0
+ ManuallyAdded: 0
extraDoc3:
Filename: extradoc3
Folder: 5
- BelongsToSet: 0
+ ManuallyAdded: 0
CreatedByID: 2
docSaveLinkedDocuments1:
Filename: saveLinkedDocument1
Folder: 5
- Sets: =>DMSDocumentSet.dsSaveLinkedDocuments
\ No newline at end of file
+ Sets: =>DMSDocumentSet.dsSaveLinkedDocuments
diff --git a/tests/extensions/DMSDocumentTaxonomyExtensionTest.php b/tests/extensions/DMSDocumentTaxonomyExtensionTest.php
new file mode 100644
index 0000000..ce71ce8
--- /dev/null
+++ b/tests/extensions/DMSDocumentTaxonomyExtensionTest.php
@@ -0,0 +1,29 @@
+markTestSkipped('This test requires silverstripe/taxonomy ^1.2 to be installed. Skipping.');
+ }
+ }
+
+ /**
+ * Ensure that appropriate tags by taxonomy type are returned, and that their hierarchy is displayd in the title
+ */
+ public function testGetAllTagsMap()
+ {
+ $extension = new DMSDocumentTaxonomyExtension;
+ $result = $extension->getAllTagsMap();
+
+ $this->assertContains('Subject > Mathematics', $result);
+ $this->assertContains('Subject', $result);
+ $this->assertContains('Subject > Science > Chemistry', $result);
+ $this->assertNotContains('Physical Education', $result);
+ }
+}
diff --git a/tests/extensions/DMSDocumentTaxonomyExtensionTest.yml b/tests/extensions/DMSDocumentTaxonomyExtensionTest.yml
new file mode 100644
index 0000000..92d3384
--- /dev/null
+++ b/tests/extensions/DMSDocumentTaxonomyExtensionTest.yml
@@ -0,0 +1,30 @@
+TaxonomyType:
+ document:
+ Name: Document
+ not_a_document:
+ Name: Not A Document
+
+TaxonomyTerm:
+ subject:
+ Name: Subject
+ Type: =>TaxonomyType.document
+ maths:
+ Name: Mathematics
+ Parent: =>TaxonomyTerm.subject
+ Type: =>TaxonomyType.document
+ science:
+ Name: Science
+ Parent: =>TaxonomyTerm.subject
+ Type: =>TaxonomyType.document
+ chemistry:
+ Name: Chemistry
+ Parent: =>TaxonomyTerm.science
+ Type: =>TaxonomyType.document
+ chemistry_level_1:
+ Name: Level 1
+ Parent: =>TaxonomyTerm.chemistry
+ Type: =>TaxonomyType.document
+ # Not applicable to DMS documents, but here for testing edge cases
+ physed:
+ Name: Physical Education
+ Type: =>TaxonomyType.not_a_document
diff --git a/tests/extensions/DMSTaxonomyTypeExtensionTest.php b/tests/extensions/DMSTaxonomyTypeExtensionTest.php
new file mode 100644
index 0000000..722c554
--- /dev/null
+++ b/tests/extensions/DMSTaxonomyTypeExtensionTest.php
@@ -0,0 +1,29 @@
+ array('DMSTaxonomyTypeExtension')
+ );
+
+ /**
+ * Ensure that the configurable list of default records are created
+ */
+ public function testDefaultRecordsAreCreated()
+ {
+ Config::inst()->update('DMSTaxonomyTypeExtension', 'default_records', array('Food', 'Beverage', 'Books'));
+
+ TaxonomyType::create()->requireDefaultRecords();
+
+ $this->assertDOSContains(
+ array(
+ array('Name' => 'Food'),
+ array('Name' => 'Beverage'),
+ array('Name' => 'Books'),
+ ),
+ TaxonomyType::get()
+ );
+ }
+}