mirror of
https://github.com/silverstripe/silverstripe-dms
synced 2024-10-22 14:05:56 +02:00
Merge pull request #124 from robbieaverill/feature/tagging
API Remove DMSTag, replace with extension for taxonomy module
This commit is contained in:
commit
e8d46a90a5
@ -19,10 +19,10 @@ Additionally, documents are stored and managed as part of a page instead of away
|
|||||||
* Relation of documents to other documents
|
* Relation of documents to other documents
|
||||||
* Management and upload of documents within a page context in the CMS
|
* Management and upload of documents within a page context in the CMS
|
||||||
* Metadata management through the powerful `GridField` and `UploadField` core APIs
|
* Metadata management through the powerful `GridField` and `UploadField` core APIs
|
||||||
* Configurable tags for documents
|
|
||||||
* Download via SilverStripe controller (rather than filesystem URLs)
|
* Download via SilverStripe controller (rather than filesystem URLs)
|
||||||
* Access control based on PHP logic, and page relations
|
* Access control based on PHP logic, and page relations
|
||||||
* Replacement of existing files
|
* Replacement of existing files
|
||||||
|
* Tagging via the [taxonomy module](https://github.com/silverstripe/silverstripe-taxonomy) if installed
|
||||||
|
|
||||||
## Documentation
|
## 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)
|
* PHP 5.3 with the "fileinfo" module (or alternatively the "whereis" and "file" Unix commands)
|
||||||
* SilverStripe framework/CMS ^3.5
|
* 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) [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) [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) [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) [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
|
## Contributing
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
DMSDocument:
|
DMSDocument:
|
||||||
searchable_fields:
|
searchable_fields:
|
||||||
Title:
|
Title:
|
||||||
title: "Document title matches ..."
|
title: Document title matches
|
||||||
Description:
|
Description:
|
||||||
title: "Document summary matches ..."
|
title: Document summary matches
|
||||||
CreatedByID:
|
CreatedByID:
|
||||||
title: 'Document created by ...'
|
title: Document created by
|
||||||
field: 'ListboxField'
|
field: ListboxField
|
||||||
filter: 'ExactMatchFilter'
|
filter: ExactMatchFilter
|
||||||
LastEditedByID:
|
LastEditedByID:
|
||||||
title: 'Document last changed by ...'
|
title: Document last changed by
|
||||||
field: 'ListboxField'
|
field: ListboxField
|
||||||
filter: 'ExactMatchFilter'
|
filter: ExactMatchFilter
|
||||||
Filename:
|
Filename:
|
||||||
title: 'File name'
|
title: File name
|
||||||
|
25
_config/taxonomy.yml
Normal file
25
_config/taxonomy.yml
Normal file
@ -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
|
21
code/DMS.php
21
code/DMS.php
@ -121,27 +121,6 @@ class DMS extends Object implements DMSInterface
|
|||||||
return $doc;
|
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:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* getByTag("fruits", null);
|
|
||||||
* getByTag(null, "banana");
|
|
||||||
* getByTag("fruits", "banana");
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @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
|
* 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)
|
* (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module)
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* This class is a {@link GridField} component that adds a delete a DMS document.
|
|
||||||
*
|
|
||||||
* This component also supports unlinking a relation instead of deleting the object. By default it unlinks, but if
|
|
||||||
* this is the last reference to a specific document, it warns the user that continuing with the operation will
|
|
||||||
* delete the document completely.
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* $action = new GridFieldDeleteAction(); // delete objects permanently
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -48,7 +48,7 @@ class DMSUploadField extends UploadField
|
|||||||
// Relate to the underlying document set being edited.
|
// Relate to the underlying document set being edited.
|
||||||
// Not applicable when editing the document itself and replacing it, or uploading from the ModelAdmin
|
// Not applicable when editing the document itself and replacing it, or uploading from the ModelAdmin
|
||||||
if ($record instanceof DMSDocumentSet) {
|
if ($record instanceof DMSDocumentSet) {
|
||||||
$record->Documents()->add($doc, array('BelongsToSet' => 1));
|
$record->Documents()->add($doc, array('ManuallyAdded' => 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $doc;
|
return $doc;
|
||||||
|
55
code/extensions/DMSDocumentTaxonomyExtension.php
Normal file
55
code/extensions/DMSDocumentTaxonomyExtension.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class DMSDocumentTaxonomyExtension extends DataExtension
|
||||||
|
{
|
||||||
|
private static $many_many = array(
|
||||||
|
'Tags' => '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;
|
||||||
|
}
|
||||||
|
}
|
28
code/extensions/DMSTaxonomyTypeExtension.php
Normal file
28
code/extensions/DMSTaxonomyTypeExtension.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Creates default taxonomy type records if they don't exist already
|
||||||
|
*/
|
||||||
|
class DMSTaxonomyTypeExtension extends DataExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create default taxonomy type records. Add records via YAML configuration (see taxonomy.yml):
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* DMSTaxonomyTypeExtension:
|
||||||
|
* default_records:
|
||||||
|
* - Document
|
||||||
|
* - PrivateDocument
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,47 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
interface DMSDocumentInterface
|
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
|
* Returns a link to download this DMSDocument from the DMS store
|
||||||
* @return String
|
* @return String
|
||||||
|
@ -27,24 +27,6 @@ interface DMSInterface
|
|||||||
*/
|
*/
|
||||||
public function storeDocument($file);
|
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:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* getByTag("fruits", null);
|
|
||||||
* getByTag(null, "banana");
|
|
||||||
* getByTag("fruits", "banana");
|
|
||||||
* </code>
|
|
||||||
* @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
|
* 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)
|
* (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module)
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
* @property Enum CanEditType Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')
|
* @property Enum CanEditType Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')
|
||||||
*
|
*
|
||||||
* @method ManyManyList RelatedDocuments
|
* @method ManyManyList RelatedDocuments
|
||||||
* @method ManyManyList Tags
|
|
||||||
* @method ManyManyList ViewerGroups
|
* @method ManyManyList ViewerGroups
|
||||||
* @method ManyManyList EditorGroups
|
* @method ManyManyList EditorGroups
|
||||||
*
|
*
|
||||||
@ -56,7 +55,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
|||||||
|
|
||||||
private static $many_many = array(
|
private static $many_many = array(
|
||||||
'RelatedDocuments' => 'DMSDocument',
|
'RelatedDocuments' => 'DMSDocument',
|
||||||
'Tags' => 'DMSTag',
|
|
||||||
'ViewerGroups' => 'Group',
|
'ViewerGroups' => 'Group',
|
||||||
'EditorGroups' => 'Group',
|
'EditorGroups' => 'Group',
|
||||||
);
|
);
|
||||||
@ -65,7 +63,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
|||||||
'ID' => 'ID',
|
'ID' => 'ID',
|
||||||
'Title' => 'Title',
|
'Title' => 'Title',
|
||||||
'FilenameWithoutID' => 'Filename',
|
'FilenameWithoutID' => 'Filename',
|
||||||
'LastEdited' => 'LastEdited'
|
'LastEdited' => 'Last Edited'
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $singular_name = 'Document';
|
private static $singular_name = 'Document';
|
||||||
@ -244,173 +242,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
|||||||
return $this;
|
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.
|
* 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
|
* 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
|
* Deletes the DMSDocument and its underlying file. Also calls the parent DataObject's delete method in
|
||||||
* to this DMSDocument. Also calls the parent DataObject's delete method in
|
|
||||||
* order to complete an cascade.
|
* order to complete an cascade.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
// remove tags
|
|
||||||
$this->removeAllTags();
|
|
||||||
|
|
||||||
// delete the file (and previous versions of files)
|
// delete the file (and previous versions of files)
|
||||||
$filesToDelete = array();
|
$filesToDelete = array();
|
||||||
$storageFolder = $this->getStorageFolder();
|
$storageFolder = $this->getStorageFolder();
|
||||||
@ -1383,6 +1210,9 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
|||||||
// Ensure that current document doesn't get returned in the autocompleter
|
// Ensure that current document doesn't get returned in the autocompleter
|
||||||
$addExisting->setSearchList($this->getRelatedDocumentsForAutocompleter());
|
$addExisting->setSearchList($this->getRelatedDocumentsForAutocompleter());
|
||||||
|
|
||||||
|
// Restrict search fields to specific fields only
|
||||||
|
$addExisting->setSearchFields(array('Title', 'Filename'));
|
||||||
|
|
||||||
$this->extend('updateRelatedDocumentsGridField', $gridField);
|
$this->extend('updateRelatedDocumentsGridField', $gridField);
|
||||||
|
|
||||||
return $gridField;
|
return $gridField;
|
||||||
|
@ -26,7 +26,9 @@ class DMSDocumentSet extends DataObject
|
|||||||
|
|
||||||
private static $many_many_extraFields = array(
|
private static $many_many_extraFields = array(
|
||||||
'Documents' => 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 GridFieldDataColumns(),
|
||||||
new GridFieldEditButton(),
|
new GridFieldEditButton(),
|
||||||
// Special delete dialog to handle custom behaviour of unlinking and deleting
|
// Special delete dialog to handle custom behaviour of unlinking and deleting
|
||||||
new DMSGridFieldDeleteAction(),
|
new GridFieldDeleteAction(true),
|
||||||
new GridFieldDetailForm()
|
new GridFieldDetailForm()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -115,7 +117,7 @@ class DMSDocumentSet extends DataObject
|
|||||||
->setFieldFormatting(
|
->setFieldFormatting(
|
||||||
array(
|
array(
|
||||||
'FilenameWithoutID' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>',
|
'FilenameWithoutID' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>',
|
||||||
'BelongsToSet' => function ($value) {
|
'ManuallyAdded' => function ($value) {
|
||||||
if ($value) {
|
if ($value) {
|
||||||
return _t('DMSDocumentSet.MANUAL', 'Manually');
|
return _t('DMSDocumentSet.MANUAL', 'Manually');
|
||||||
}
|
}
|
||||||
@ -197,24 +199,24 @@ class DMSDocumentSet extends DataObject
|
|||||||
$dmsDocFields = $doc->scaffoldSearchFields(array('fieldClasses' => true));
|
$dmsDocFields = $doc->scaffoldSearchFields(array('fieldClasses' => true));
|
||||||
$membersMap = Member::get()->map('ID', 'Name')->toArray();
|
$membersMap = Member::get()->map('ID', 'Name')->toArray();
|
||||||
asort($membersMap);
|
asort($membersMap);
|
||||||
|
|
||||||
foreach ($dmsDocFields as $field) {
|
foreach ($dmsDocFields as $field) {
|
||||||
// Apply field customisations where necessary
|
if ($field instanceof ListboxField) {
|
||||||
if (in_array($field->getName(), array('CreatedByID', 'LastEditedByID', 'LastEditedByID'))) {
|
$map = ($field->getName() === 'Tags__ID') ? $doc->getAllTagsMap() : $membersMap;
|
||||||
/** @var ListboxField $field */
|
$field->setMultiple(true)->setSource($map);
|
||||||
$field->setMultiple(true)->setSource($membersMap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$keyValPairs = JsonField::create('KeyValuePairs', $dmsDocFields->toArray());
|
$keyValPairs = JsonField::create('KeyValuePairs', $dmsDocFields->toArray());
|
||||||
|
|
||||||
// Now lastly add the sort fields
|
// Now lastly add the sort fields
|
||||||
$sortedBy = FieldGroup::create('SortedBy', array(
|
$sortedBy = FieldGroup::create('SortedBy', array(
|
||||||
DropdownField::create('SortBy', '', array(
|
DropdownField::create('SortBy', '', array(
|
||||||
'LastEdited' => 'Last changed',
|
'LastEdited' => 'Last changed',
|
||||||
'Created' => 'Created',
|
'Created' => 'Created',
|
||||||
'Title' => 'Document title',
|
'Title' => 'Document title',
|
||||||
), 'LastEdited'),
|
), 'LastEdited'),
|
||||||
DropdownField::create('SortByDirection', '', $this->dbObject('SortByDirection')->enumValues(), 'DESC'),
|
DropdownField::create('SortByDirection', '', $this->dbObject('SortByDirection')->enumValues(), 'DESC'),
|
||||||
));
|
));
|
||||||
|
|
||||||
$sortedBy->setTitle(_t('DMSDocumentSet.SORTED_BY', 'Sort the document set by:'));
|
$sortedBy->setTitle(_t('DMSDocumentSet.SORTED_BY', 'Sort the document set by:'));
|
||||||
$fields->addFieldsToTab('Root.QueryBuilder', array($keyValPairs, $sortedBy));
|
$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.
|
* 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()
|
public function saveLinkedDocuments()
|
||||||
{
|
{
|
||||||
// Documents that belong to just this set.
|
if (empty($this->KeyValuePairs) || !$this->isChanged('KeyValuePairs')) {
|
||||||
/** @var ManyManyList $originals */
|
return;
|
||||||
$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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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(
|
return array_merge(
|
||||||
(array) DMSDocument::create()->config()->get('display_fields'),
|
(array) DMSDocument::create()->config()->get('display_fields'),
|
||||||
array('BelongsToSet' => _t('DMSDocumentSet.ADDEDMETHOD', 'Added'))
|
array('ManuallyAdded' => _t('DMSDocumentSet.ADDEDMETHOD', 'Added'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Hold a set of metadata category/value tags associated with a DMSDocument
|
|
||||||
*
|
|
||||||
* @package dms
|
|
||||||
*/
|
|
||||||
class DMSTag extends DataObject
|
|
||||||
{
|
|
||||||
private static $db = array(
|
|
||||||
'Category' => 'Varchar(1024)',
|
|
||||||
'Value' => 'Varchar(1024)',
|
|
||||||
'MultiValue' => 'Boolean(1)'
|
|
||||||
);
|
|
||||||
|
|
||||||
private static $belongs_many_many = array(
|
|
||||||
'Documents' => 'DMSDocument'
|
|
||||||
);
|
|
||||||
}
|
|
@ -11,7 +11,8 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"silverstripe/framework": "^3.5",
|
"silverstripe/framework": "^3.5",
|
||||||
"silverstripe/cms": "^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": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
@ -6,7 +6,8 @@ Documents now belong to "sets", which are attached to Pages. A Page can have man
|
|||||||
many_many relationship with Documents.
|
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
|
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
|
## 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::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::create_storage_folder` made non-static, use `DMS::inst()->createStorageFolder()` instead
|
||||||
* `DMS::get_storage_folder` made non-static, use `DMS::inst()->getStorageFolder()` 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
|
## Template changes
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
* [Creating documents](creating-documents.md)
|
* [Creating documents](creating-documents.md)
|
||||||
* [Download documents](download-documents.md)
|
* [Download documents](download-documents.md)
|
||||||
* [Manage page relations](manage-page-relations.md)
|
* [Manage page relations](manage-page-relations.md)
|
||||||
* [Manage tags](manage-tags.md)
|
|
||||||
* [Manage related documents](manage-related-documents.md)
|
* [Manage related documents](manage-related-documents.md)
|
||||||
* [Building frontend assets](building-frontend-assets.md)
|
* [Building frontend assets](building-frontend-assets.md)
|
||||||
|
|
||||||
|
@ -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();
|
|
||||||
```
|
|
@ -1,125 +1,15 @@
|
|||||||
(function ($) {
|
(function ($) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
$.entwine('ss', function ($) {
|
$.entwine('ss', function ($) {
|
||||||
|
$('.ss-gridfield-item a.file-url').entwine({
|
||||||
$('#SectionID ul li').entwine({
|
onclick: function (e) {
|
||||||
onadd: function () {
|
//make sure the download link doesn't trigger a gridfield edit dialog
|
||||||
this.addClass('ui-button ss-ui-button ui-corner-all ui-state-default ui-widget ui-button-text-only');
|
window.open(this.attr('href'), '_blank');
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}(jQuery));
|
}(jQuery));
|
||||||
|
@ -27,9 +27,9 @@ en:
|
|||||||
GRIDFIELD_NOTICE: Managing documents will be available once you have created this document set.
|
GRIDFIELD_NOTICE: Managing documents will be available once you have created this document set.
|
||||||
PLURALNAME: Document Sets
|
PLURALNAME: Document Sets
|
||||||
SINGULARNAME: Document Set
|
SINGULARNAME: Document Set
|
||||||
DMSTag:
|
DMSDocumentTaxonomyExtension:
|
||||||
PLURALNAME: 'DMS Tags'
|
TAGS: Tags
|
||||||
SINGULARNAME: 'DMS Tag'
|
NOTAGS: No tags found
|
||||||
FileIFrameField:
|
FileIFrameField:
|
||||||
ATTACHONCESAVED2: 'Files can be attached once you have saved the record for the first time.'
|
ATTACHONCESAVED2: 'Files can be attached once you have saved the record for the first time.'
|
||||||
GridAction:
|
GridAction:
|
||||||
|
@ -13,9 +13,6 @@ es:
|
|||||||
RelatedPages: 'Páginas relacionadas'
|
RelatedPages: 'Páginas relacionadas'
|
||||||
RelatedReferences: 'Referencias relacionadas'
|
RelatedReferences: 'Referencias relacionadas'
|
||||||
SINGULARNAME: Documento
|
SINGULARNAME: Documento
|
||||||
DMSTag:
|
|
||||||
PLURALNAME: 'Etiquetas del Sistema documental'
|
|
||||||
SINGULARNAME: 'Etiqueta del Sistema documental'
|
|
||||||
FileIFrameField:
|
FileIFrameField:
|
||||||
ATTACHONCESAVED2: 'Archivos pueden ser adjuntados una vez que guardes por primera vez.'
|
ATTACHONCESAVED2: 'Archivos pueden ser adjuntados una vez que guardes por primera vez.'
|
||||||
GridAction:
|
GridAction:
|
||||||
|
@ -13,9 +13,6 @@ nl:
|
|||||||
RelatedPages: 'Gerelateerde paginas'
|
RelatedPages: 'Gerelateerde paginas'
|
||||||
RelatedReferences: 'Gerelateerde referenties'
|
RelatedReferences: 'Gerelateerde referenties'
|
||||||
SINGULARNAME: 'Document'
|
SINGULARNAME: 'Document'
|
||||||
DMSTag:
|
|
||||||
PLURALNAME: 'D M S Tags'
|
|
||||||
SINGULARNAME: 'D M S Tag'
|
|
||||||
FileIFrameField:
|
FileIFrameField:
|
||||||
ATTACHONCESAVED2: 'Bestanden kunnen worden toegevoegd na het voor het eerst opslaan'
|
ATTACHONCESAVED2: 'Bestanden kunnen worden toegevoegd na het voor het eerst opslaan'
|
||||||
GridAction:
|
GridAction:
|
||||||
|
@ -68,7 +68,6 @@ class DMSDocumentSetTest extends SapphireTest
|
|||||||
/** @var GridFieldConfig $config */
|
/** @var GridFieldConfig $config */
|
||||||
$config = $gridField->getConfig();
|
$config = $gridField->getConfig();
|
||||||
|
|
||||||
$this->assertNotNull($config->getComponentByType('DMSGridFieldDeleteAction'));
|
|
||||||
$this->assertNotNull($addNew = $config->getComponentByType('DMSGridFieldAddNewButton'));
|
$this->assertNotNull($addNew = $config->getComponentByType('DMSGridFieldAddNewButton'));
|
||||||
$this->assertSame($set->ID, $addNew->getDocumentSetId());
|
$this->assertSame($set->ID, $addNew->getDocumentSetId());
|
||||||
|
|
||||||
@ -96,14 +95,14 @@ class DMSDocumentSetTest extends SapphireTest
|
|||||||
$displayFields = $document->getDocumentDisplayFields();
|
$displayFields = $document->getDocumentDisplayFields();
|
||||||
$this->assertContains('Apple', $displayFields);
|
$this->assertContains('Apple', $displayFields);
|
||||||
$this->assertContains('Orange', $displayFields);
|
$this->assertContains('Orange', $displayFields);
|
||||||
$this->assertArrayHasKey('BelongsToSet', $displayFields);
|
$this->assertArrayHasKey('ManuallyAdded', $displayFields);
|
||||||
$this->assertContains('Added', $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')
|
$fieldFormatting = $this->objFromFixture('DMSDocumentSet', 'ds1')
|
||||||
->getCMSFields()
|
->getCMSFields()
|
||||||
@ -112,11 +111,11 @@ class DMSDocumentSetTest extends SapphireTest
|
|||||||
->getComponentByType('GridFieldDataColumns')
|
->getComponentByType('GridFieldDataColumns')
|
||||||
->getFieldFormatting();
|
->getFieldFormatting();
|
||||||
|
|
||||||
$this->assertArrayHasKey('BelongsToSet', $fieldFormatting);
|
$this->assertArrayHasKey('ManuallyAdded', $fieldFormatting);
|
||||||
$this->assertTrue(is_callable($fieldFormatting['BelongsToSet']));
|
$this->assertTrue(is_callable($fieldFormatting['ManuallyAdded']));
|
||||||
|
|
||||||
$this->assertSame('Manually', $fieldFormatting['BelongsToSet'](1));
|
$this->assertSame('Manually', $fieldFormatting['ManuallyAdded'](1));
|
||||||
$this->assertSame('Query Builder', $fieldFormatting['BelongsToSet'](0));
|
$this->assertSame('Query Builder', $fieldFormatting['ManuallyAdded'](0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,6 +84,7 @@ class DMSDocumentTest extends SapphireTest
|
|||||||
|
|
||||||
$this->assertNotContains('test-file-file-doesnt-exist-1', $jsonResult);
|
$this->assertNotContains('test-file-file-doesnt-exist-1', $jsonResult);
|
||||||
$this->assertContains('test-file-file-doesnt-exist-2', $jsonResult);
|
$this->assertContains('test-file-file-doesnt-exist-2', $jsonResult);
|
||||||
|
$this->assertEquals(array('Title', 'Filename'), $autocompleter->getSearchFields());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
class DMSTagTest extends SapphireTest
|
|
||||||
{
|
|
||||||
protected $usesDatabase = true;
|
|
||||||
|
|
||||||
public function tearDownOnce()
|
|
||||||
{
|
|
||||||
self::$is_running_test = true;
|
|
||||||
|
|
||||||
$d = DataObject::get("DMSDocument");
|
|
||||||
foreach ($d as $d1) {
|
|
||||||
$d1->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");
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,25 +26,6 @@ SiteTree:
|
|||||||
s9:
|
s9:
|
||||||
Title: testPage9
|
Title: testPage9
|
||||||
URLSegment: s9
|
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:
|
Group:
|
||||||
content-author:
|
content-author:
|
||||||
Code: content-author
|
Code: content-author
|
||||||
@ -85,13 +66,11 @@ DMSDocument:
|
|||||||
d1:
|
d1:
|
||||||
Filename: test-file-file-doesnt-exist-1
|
Filename: test-file-file-doesnt-exist-1
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
|
|
||||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||||
d2:
|
d2:
|
||||||
Filename: test-file-file-doesnt-exist-2
|
Filename: test-file-file-doesnt-exist-2
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Title: File That Doesn't Exist (Title)
|
Title: File That Doesn't Exist (Title)
|
||||||
Tags: =>DMSTag.t5, =>DMSTag.t6
|
|
||||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||||
document_with_relations:
|
document_with_relations:
|
||||||
Filename: file-with-relations
|
Filename: file-with-relations
|
||||||
@ -102,20 +81,17 @@ DMSDocument:
|
|||||||
CanViewType: LoggedInUsers
|
CanViewType: LoggedInUsers
|
||||||
CanEditType: LoggedInUsers
|
CanEditType: LoggedInUsers
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
|
|
||||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||||
doc-anyone:
|
doc-anyone:
|
||||||
FileName: doc-anyone
|
FileName: doc-anyone
|
||||||
CanViewType: Anyone
|
CanViewType: Anyone
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
|
|
||||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||||
doc-only-these-users:
|
doc-only-these-users:
|
||||||
FileName: doc-only-these-users
|
FileName: doc-only-these-users
|
||||||
CanViewType: OnlyTheseUsers
|
CanViewType: OnlyTheseUsers
|
||||||
CanEditType: OnlyTheseUsers
|
CanEditType: OnlyTheseUsers
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
|
|
||||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||||
ViewerGroups: =>Group.content-author
|
ViewerGroups: =>Group.content-author
|
||||||
EditorGroups: =>Group.content-author
|
EditorGroups: =>Group.content-author
|
||||||
@ -138,19 +114,19 @@ DMSDocument:
|
|||||||
Filename: extradoc1
|
Filename: extradoc1
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Sets: =>DMSDocumentSet.ds6
|
Sets: =>DMSDocumentSet.ds6
|
||||||
BelongsToSet: 1
|
ManuallyAdded: 1
|
||||||
CreatedByID: 2
|
CreatedByID: 2
|
||||||
extraDoc2:
|
extraDoc2:
|
||||||
Filename: extradoc2
|
Filename: extradoc2
|
||||||
Folder: 5
|
Folder: 5
|
||||||
CreatedByID: 2
|
CreatedByID: 2
|
||||||
BelongsToSet: 0
|
ManuallyAdded: 0
|
||||||
extraDoc3:
|
extraDoc3:
|
||||||
Filename: extradoc3
|
Filename: extradoc3
|
||||||
Folder: 5
|
Folder: 5
|
||||||
BelongsToSet: 0
|
ManuallyAdded: 0
|
||||||
CreatedByID: 2
|
CreatedByID: 2
|
||||||
docSaveLinkedDocuments1:
|
docSaveLinkedDocuments1:
|
||||||
Filename: saveLinkedDocument1
|
Filename: saveLinkedDocument1
|
||||||
Folder: 5
|
Folder: 5
|
||||||
Sets: =>DMSDocumentSet.dsSaveLinkedDocuments
|
Sets: =>DMSDocumentSet.dsSaveLinkedDocuments
|
||||||
|
29
tests/extensions/DMSDocumentTaxonomyExtensionTest.php
Normal file
29
tests/extensions/DMSDocumentTaxonomyExtensionTest.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class DMSDocumentTaxonomyExtensionTest extends SapphireTest
|
||||||
|
{
|
||||||
|
protected static $fixture_file = 'DMSDocumentTaxonomyExtensionTest.yml';
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
if (!class_exists('TaxonomyType')) {
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
30
tests/extensions/DMSDocumentTaxonomyExtensionTest.yml
Normal file
30
tests/extensions/DMSDocumentTaxonomyExtensionTest.yml
Normal file
@ -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
|
29
tests/extensions/DMSTaxonomyTypeExtensionTest.php
Normal file
29
tests/extensions/DMSTaxonomyTypeExtensionTest.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class DMSTaxonomyTypeExtensionTest extends SapphireTest
|
||||||
|
{
|
||||||
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
|
protected $requiredExtensions = array(
|
||||||
|
'TaxonomyType' => 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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user