mirror of
https://github.com/silverstripe/silverstripe-dms
synced 2024-10-22 14:05:56 +02:00
API Add document sets, remove *Page methods from DMSDocument
* Add 2.0.0 changelog * Update DMSInterface and DMSDocumentInterface removing *page and adding getDocumentSetsByPage to DMSInterface * Update use documentation and update unit tests This commit changes the relationship from Pages has_many Documents to Pages has_many DocumentSets which are many_many to Documents. The upload field has been upated to attach documents to a set instead of a page, the tests updated and the DMSInterface and DMSDocumentInterface updated to be less relevant to pages and more relevant to document sets.
This commit is contained in:
parent
9c5693dab0
commit
e4bc553521
5
CONTRIBUTING.md
Normal file
5
CONTRIBUTING.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Contributing
|
||||
|
||||
Any open source product is only as good as the community behind it. You can participate by sharing code, ideas, or simply helping others. No matter what your skill level is, every contribution counts.
|
||||
|
||||
See our [high level overview](http://silverstripe.org/contributing-to-silverstripe) on silverstripe.org on how you can help out.
|
@ -2,14 +2,10 @@
|
||||
|
||||
$config = Config::inst();
|
||||
|
||||
DMSSiteTreeExtension::show_documents_tab(); //show the Documents tab on all pages
|
||||
DMSSiteTreeExtension::no_documents_tab(); //and don't exclude it from any pages
|
||||
DMSDocumentAddController::add_allowed_extensions(); //add an array of additional allowed extensions
|
||||
|
||||
define('DMS_DIR', 'dms');
|
||||
define('DMS_DIR', basename(__DIR__));
|
||||
|
||||
if (!file_exists(BASE_PATH . DIRECTORY_SEPARATOR . DMS_DIR)) {
|
||||
user_error("DMS directory named incorrectly. Please install the DMS module into a folder named: ".DMS_DIR);
|
||||
user_error('DMS directory named incorrectly. Please install the DMS module into a folder named: ' . DMS_DIR);
|
||||
}
|
||||
|
||||
CMSMenu::remove_menu_item('DMSDocumentAddController');
|
||||
|
@ -5,11 +5,16 @@ After: framework/routes#coreroutes
|
||||
Director:
|
||||
rules:
|
||||
'dmsdocument/$ID' : 'DMSDocument_Controller'
|
||||
|
||||
SiteTree:
|
||||
extensions:
|
||||
- DMSSiteTreeExtension
|
||||
# Whether to show the document sets tab in the CMS for the page type this extension is applied to
|
||||
documents_enabled: true
|
||||
|
||||
HtmlEditorField_Toolbar:
|
||||
extensions:
|
||||
- DocumentHtmlEditorFieldToolbar
|
||||
|
||||
DMSDocument_versions:
|
||||
enable_versions: true
|
||||
|
26
code/DMS.php
26
code/DMS.php
@ -126,15 +126,25 @@ class DMS implements DMSInterface
|
||||
// TODO: Implement getByFullTextSearch() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Document objects associated with a Page
|
||||
* @param $page SiteTree to fetch the associated Documents from
|
||||
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
|
||||
* @return DataList Document list associated with the Page
|
||||
*/
|
||||
public function getByPage($page, $showEmbargoed = false)
|
||||
public function getByPage(SiteTree $page, $showEmbargoed = false)
|
||||
{
|
||||
// TODO: Implement getByPage() method.
|
||||
/** @var ArrayList $documents */
|
||||
$documents = $page->getAllDocuments();
|
||||
|
||||
if (!$showEmbargoed) {
|
||||
foreach ($documents as $document) {
|
||||
if ($document->isEmbargoed()) {
|
||||
$documents->remove($document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
public function getDocumentSetsByPage(SiteTree $page)
|
||||
{
|
||||
return $page->getDocumentSets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
class DMSDocumentAddController extends LeftAndMain
|
||||
{
|
||||
|
||||
private static $url_segment = 'pages/adddocument';
|
||||
private static $url_priority = 60;
|
||||
private static $required_permission_codes = 'CMS_ACCESS_AssetAdmin';
|
||||
@ -13,7 +12,13 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
private static $tree_class = 'SiteTree';
|
||||
private static $session_namespace = 'CMSMain';
|
||||
|
||||
public static $allowed_extensions = array();
|
||||
/**
|
||||
* Allowed file upload extensions, will be merged with `$allowed_extensions` from {@link File}
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_extensions = array();
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'getEditForm',
|
||||
@ -22,27 +27,10 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
'documentlist'
|
||||
);
|
||||
|
||||
/**
|
||||
* Add an array of additional allowed extensions
|
||||
* @static
|
||||
* @param $array
|
||||
*/
|
||||
public static function add_allowed_extensions($array = null)
|
||||
{
|
||||
if (empty($array)) {
|
||||
return;
|
||||
}
|
||||
if (is_array($array)) {
|
||||
self::$allowed_extensions = $array;
|
||||
} else {
|
||||
self::$allowed_extensions = array($array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom currentPage() method to handle opening the 'root' folder
|
||||
*
|
||||
* @return
|
||||
* @return SiteTree
|
||||
*/
|
||||
public function currentPage()
|
||||
{
|
||||
@ -61,12 +49,27 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
|
||||
/**
|
||||
* Return fake-ID "root" if no ID is found (needed to upload files into the root-folder)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function currentPageID()
|
||||
{
|
||||
return ($result = parent::currentPageID()) === null ? 0 : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current document set, if a document set ID was provided
|
||||
*
|
||||
* @return DMSDocumentSet
|
||||
*/
|
||||
public function getCurrentDocumentSet()
|
||||
{
|
||||
if ($id = $this->getRequest()->getVar('dsid')) {
|
||||
return DMSDocumentSet::get()->byid($id);
|
||||
}
|
||||
return singleton('DMSDocumentSet');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Form
|
||||
* @todo what template is used here? AssetAdmin_UploadContent.ss doesn't seem to be used anymore
|
||||
@ -75,9 +78,13 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
{
|
||||
Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js');
|
||||
Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css');
|
||||
Requirements::css(DMS_DIR.'/css/DMSMainCMS.css');
|
||||
Requirements::css(DMS_DIR . '/css/DMSMainCMS.css');
|
||||
|
||||
/** @var SiteTree $page */
|
||||
$page = $this->currentPage();
|
||||
/** @var DMSDocumentSet $documentSet */
|
||||
$documentSet = $this->getCurrentDocumentSet();
|
||||
|
||||
$uploadField = DMSUploadField::create('AssetUploadField', '');
|
||||
$uploadField->setConfig('previewMaxWidth', 40);
|
||||
$uploadField->setConfig('previewMaxHeight', 30);
|
||||
@ -87,31 +94,34 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
$uploadField->addExtraClass('ss-assetuploadfield');
|
||||
$uploadField->removeExtraClass('ss-uploadfield');
|
||||
$uploadField->setTemplate('AssetUploadField');
|
||||
$uploadField->setRecord($page);
|
||||
$uploadField->setRecord($documentSet);
|
||||
|
||||
$uploadField->getValidator()->setAllowedExtensions(
|
||||
array_filter(array_merge(Config::inst()->get('File', 'allowed_extensions'), self::$allowed_extensions))
|
||||
);
|
||||
$uploadField->getValidator()->setAllowedExtensions($this->getAllowedExtensions());
|
||||
$exts = $uploadField->getValidator()->getAllowedExtensions();
|
||||
|
||||
asort($exts);
|
||||
$backlink = $this->Backlink();
|
||||
$done = "
|
||||
<a class=\"ss-ui-button ss-ui-action-constructive cms-panel-link ui-corner-all\" href=\"".$backlink."\">
|
||||
Done!
|
||||
<a class=\"ss-ui-button ss-ui-action-constructive cms-panel-link ui-corner-all\" href=\"" . $backlink . "\">
|
||||
" . _t('UploadField.DONE', 'DONE') . "
|
||||
</a>";
|
||||
|
||||
$addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing');
|
||||
$addExistingField->setRecord($page);
|
||||
$addExistingField = new DMSDocumentAddExistingField(
|
||||
'AddExisting',
|
||||
_t('DMSDocumentAddExistingField.ADDEXISTING', 'Add Existing')
|
||||
);
|
||||
$addExistingField->setRecord($documentSet);
|
||||
|
||||
$form = new Form(
|
||||
$this,
|
||||
'getEditForm',
|
||||
new FieldList(
|
||||
new TabSet(
|
||||
'Main',
|
||||
_t('DMSDocumentAddController.MAINTAB', 'Main'),
|
||||
new Tab(
|
||||
'From your computer',
|
||||
_t('UploadField.FROMCOMPUTER', 'From your computer'),
|
||||
new HiddenField('ID', false, $page->ID),
|
||||
new HiddenField('DSID', false, $documentSet->ID),
|
||||
$uploadField,
|
||||
new LiteralField(
|
||||
'AllowedExtensions',
|
||||
@ -123,7 +133,7 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
)
|
||||
),
|
||||
new Tab(
|
||||
'From the CMS',
|
||||
_t('UploadField.FROMCMS', 'From the CMS'),
|
||||
$addExistingField
|
||||
)
|
||||
)
|
||||
@ -136,17 +146,6 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
$form->Backlink = $backlink;
|
||||
// Don't use AssetAdmin_EditForm, as it assumes a different panel structure
|
||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||
/*$form->Fields()->push(
|
||||
new LiteralField(
|
||||
'BackLink',
|
||||
sprintf(
|
||||
'<a href="%s" class="backlink ss-ui-button cms-panel-link" data-icon="back">%s</a>',
|
||||
Controller::join_links(singleton('AssetAdmin')->Link('show'), $folder ? $folder->ID : 0),
|
||||
_t('AssetAdmin.BackToFolder', 'Back to folder')
|
||||
)
|
||||
)
|
||||
);*/
|
||||
//$form->loadDataFrom($folder);
|
||||
|
||||
return $form;
|
||||
}
|
||||
@ -170,29 +169,43 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
}
|
||||
|
||||
$items->push(new ArrayData(array(
|
||||
'Title' => 'Add Document',
|
||||
'Title' => _t('DMSDocumentSet.ADDDOCUMENTBUTTON', 'Add Document'),
|
||||
'Link' => $this->Link()
|
||||
)));
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the link to be used to return the user after uploading a document. If a document set ID (dsid) is present
|
||||
* then it will be redirected back to the page that owns the document set. @todo redirect back to the document set
|
||||
*
|
||||
* If no document set ID is present then we assume that it has been added from the model admin, so redirect back to
|
||||
* that instead.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function Backlink()
|
||||
{
|
||||
$pageID = $this->currentPageID();
|
||||
return Controller::join_links(singleton('CMSPagesController')->Link(), 'edit/show', $pageID);
|
||||
if (!$this->getRequest()->getVar('dsid')) {
|
||||
$modelAdmin = new DMSDocumentAdmin;
|
||||
$modelAdmin->init();
|
||||
return $modelAdmin->Link();
|
||||
}
|
||||
return Controller::join_links(singleton('CMSPagesController')->Link(), 'edit/show', $this->currentPageID());
|
||||
}
|
||||
|
||||
public function documentautocomplete()
|
||||
{
|
||||
$term = (isset($_GET['term'])) ? $_GET['term'] : '';
|
||||
$term_sql = Convert::raw2sql($term);
|
||||
$term = (string) $this->getRequest()->getVar('term');
|
||||
$termSql = Convert::raw2sql($term);
|
||||
$data = DMSDocument::get()
|
||||
->where(
|
||||
"(\"ID\" LIKE '%".$term_sql."%' OR \"Filename\" LIKE '%".$term_sql."%' OR \"Title\" LIKE '%".$term_sql."%')"
|
||||
)
|
||||
->sort('ID ASC')
|
||||
->limit(20);
|
||||
->where(
|
||||
'("ID" LIKE \'%' . $termSql . '%\' OR "Filename" LIKE \'%' . $termSql . '%\''
|
||||
. ' OR "Title" LIKE \'%' . $termSql . '%\')'
|
||||
)
|
||||
->sort('ID ASC')
|
||||
->limit(20);
|
||||
|
||||
$return = array();
|
||||
foreach ($data as $doc) {
|
||||
@ -202,22 +215,24 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return json_encode($return);
|
||||
return Convert::raw2json($return);
|
||||
}
|
||||
|
||||
public function linkdocument()
|
||||
{
|
||||
$return = array('error' => _t('UploadField.FIELDNOTSET', 'Could not add document to page'));
|
||||
|
||||
$return = array('error' => 'testing');
|
||||
return Convert::raw2json($return);
|
||||
$page = $this->currentPage();
|
||||
if (!empty($page)) {
|
||||
$document = DataObject::get_by_id('DMSDocument', (int) $_GET['documentID']);
|
||||
$document = DMSDocument::get()->byId($this->getRequest()->getVar('documentID'));
|
||||
// @todo add sets
|
||||
$document->addPage($page);
|
||||
|
||||
$buttonText = '<button class="ss-uploadfield-item-edit ss-ui-button ui-corner-all"'
|
||||
. ' title="Edit this document" data-icon="pencil">'
|
||||
. 'Edit<span class="toggle-details"><span class="toggle-details-icon"></span></span></button>';
|
||||
. ' title="' . _t('DMSDocument.EDITDOCUMENT', 'Edit this document') . '" data-icon="pencil">'
|
||||
. _t('DMSDocument.EDIT', 'Edit') . '<span class="toggle-details">'
|
||||
. '<span class="toggle-details-icon"></span></span></button>';
|
||||
|
||||
// Collect all output data.
|
||||
$return = array(
|
||||
@ -232,21 +247,27 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
);
|
||||
}
|
||||
|
||||
return json_encode($return);
|
||||
return Convert::raw2json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML representing a list of documents that are associated with the given page ID, across all document
|
||||
* sets.
|
||||
*
|
||||
* @return string HTML
|
||||
*/
|
||||
public function documentlist()
|
||||
{
|
||||
if (!isset($_GET['pageID'])) {
|
||||
if (!$this->getRequest()->getVar('pageID')) {
|
||||
return $this->httpError(400);
|
||||
}
|
||||
|
||||
$page = SiteTree::get()->byId($_GET['pageID']);
|
||||
$page = SiteTree::get()->byId($this->getRequest()->getVar('pageID'));
|
||||
|
||||
if ($page && $page->Documents()->count() > 0) {
|
||||
if ($page && $page->getAllDocuments()->count() > 0) {
|
||||
$list = '<ul>';
|
||||
|
||||
foreach ($page->Documents() as $document) {
|
||||
foreach ($page->getAllDocuments() as $document) {
|
||||
$list .= sprintf(
|
||||
'<li><a class="add-document" data-document-id="%s">%s</a></li>',
|
||||
$document->ID,
|
||||
@ -264,4 +285,20 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
_t('DMSDocumentAddController.NODOCUMENTS', 'There are no documents attached to the selected page.')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of allowed file upload extensions, merged with {@link File} and extra configuration from this
|
||||
* class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllowedExtensions()
|
||||
{
|
||||
return array_filter(
|
||||
array_merge(
|
||||
(array) Config::inst()->get('File', 'allowed_extensions'),
|
||||
(array) $this->config()->get('allowed_extensions')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,11 @@
|
||||
class DMSGridFieldAddNewButton extends GridFieldAddNewButton implements GridField_HTMLProvider
|
||||
{
|
||||
/**
|
||||
* The page ID that the document should be attached to. Used in the GridField for Documents in a Page.
|
||||
* The document set ID that the document should be attached to
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $pageId;
|
||||
protected $documentSetId;
|
||||
|
||||
/**
|
||||
* Overriding the parent method to change the template that the DMS add button will be rendered with
|
||||
@ -30,8 +30,8 @@ class DMSGridFieldAddNewButton extends GridFieldAddNewButton implements GridFiel
|
||||
}
|
||||
|
||||
$link = singleton('DMSDocumentAddController')->Link();
|
||||
if ($this->getPageId()) {
|
||||
$link = Controller::join_links($link, '?ID=' . $this->getPageId());
|
||||
if ($this->getDocumentSetId()) {
|
||||
$link = Controller::join_links($link, '?dsid=' . $this->getDocumentSetId());
|
||||
}
|
||||
|
||||
$data = new ArrayData(array(
|
||||
@ -45,24 +45,24 @@ class DMSGridFieldAddNewButton extends GridFieldAddNewButton implements GridFiel
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page ID that this document should be attached to
|
||||
* Set the document set ID that this document should be attached to
|
||||
*
|
||||
* @param int $id
|
||||
* @return $this
|
||||
*/
|
||||
public function setPageId($id)
|
||||
public function setDocumentSetId($id)
|
||||
{
|
||||
$this->pageId = $id;
|
||||
$this->documentSetId = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page ID that this document should be attached to
|
||||
* Get the document set ID that this document should be attached to
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPageId()
|
||||
public function getDocumentSetId()
|
||||
{
|
||||
return $this->pageId;
|
||||
return $this->documentSetId;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class DMSGridFieldDeleteAction extends GridFieldDeleteAction implements
|
||||
}
|
||||
|
||||
// Add a class to the field to if it is the last gridfield in the list
|
||||
$numberOfRelations = $record->Pages()->Count();
|
||||
$numberOfRelations = $record->getRelatedPages()->count();
|
||||
$field
|
||||
// Add a new class for custom JS to handle the delete action
|
||||
->addExtraClass('dms-delete')
|
||||
|
@ -13,7 +13,7 @@ class DMSGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest
|
||||
|
||||
//add a data attribute specifying how many pages this document is referenced on
|
||||
if ($record = $this->record) {
|
||||
$numberOfPageRelations = $record->Pages()->Count();
|
||||
$numberOfPageRelations = $record->getRelatedPages()->Count();
|
||||
$relations = new ShortCodeRelationFinder();
|
||||
$numberOfInlineRelations = $relations->findPageCount($record->ID);
|
||||
|
||||
|
@ -18,17 +18,12 @@ class DMSUploadField extends UploadField
|
||||
"upload",
|
||||
);
|
||||
|
||||
/**
|
||||
* The temporary folder name to store files in during upload
|
||||
* @var string
|
||||
*/
|
||||
protected $folderName = 'DMSTemporaryUploads';
|
||||
|
||||
public function __construct($name, $title = null, SS_List $items = null)
|
||||
{
|
||||
parent::__construct($name, $title, $items);
|
||||
|
||||
//set default DMS replace template to false
|
||||
$this->setConfig('useDMSReplaceTemplate', 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override the default behaviour of the UploadField and take the uploaded file (uploaded to assets) and
|
||||
* add it into the DMS storage, deleting the old/uploaded file.
|
||||
@ -48,9 +43,12 @@ class DMSUploadField extends UploadField
|
||||
// Otherwise create it
|
||||
$doc = $dms->storeDocument($file);
|
||||
$file->delete();
|
||||
// Relate to the underlying page being edited.
|
||||
// Not applicable when editing the document itself and replacing it.
|
||||
$doc->addPage($record);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
return $doc;
|
||||
@ -61,17 +59,6 @@ class DMSUploadField extends UploadField
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function isDisabled()
|
||||
{
|
||||
return (parent::isDisabled() || !$this->isSaveable());
|
||||
}
|
||||
|
||||
public function isSaveable()
|
||||
{
|
||||
return (!empty($this->getRecord()->ID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to handle upload of a single file
|
||||
*
|
||||
@ -80,6 +67,10 @@ class DMSUploadField extends UploadField
|
||||
*/
|
||||
public function upload(SS_HTTPRequest $request)
|
||||
{
|
||||
if ($recordId = $request->postVar('ID')) {
|
||||
$this->setRecord(DMSDocumentSet::get()->byId($recordId));
|
||||
}
|
||||
|
||||
if ($this->isDisabled() || $this->isReadonly()) {
|
||||
return $this->httpError(403);
|
||||
}
|
||||
@ -110,13 +101,13 @@ class DMSUploadField extends UploadField
|
||||
if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) {
|
||||
$tooManyFiles = false;
|
||||
// Some relationships allow many files to be attached.
|
||||
if ($this->getConfig('allowedMaxFileNumber') && ($record->has_many($name) || $record->many_many($name))) {
|
||||
if ($this->getConfig('allowedMaxFileNumber') && ($record->hasMany($name) || $record->manyMany($name))) {
|
||||
if (!$record->isInDB()) {
|
||||
$record->write();
|
||||
}
|
||||
$tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber');
|
||||
// has_one only allows one file at any given time.
|
||||
} elseif ($record->has_one($name)) {
|
||||
} elseif ($record->hasOne($name)) {
|
||||
$tooManyFiles = $record->{$name}() && $record->{$name}()->exists();
|
||||
}
|
||||
|
||||
@ -147,7 +138,7 @@ class DMSUploadField extends UploadField
|
||||
|
||||
// Get the uploaded file into a new file object.
|
||||
try {
|
||||
$this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName);
|
||||
$this->upload->loadIntoFile($tmpfile, $fileObject, $this->getFolderName());
|
||||
} catch (Exception $e) {
|
||||
// we shouldn't get an error here, but just in case
|
||||
$return['error'] = $e->getMessage();
|
||||
@ -155,7 +146,7 @@ class DMSUploadField extends UploadField
|
||||
|
||||
if (!$return['error']) {
|
||||
if ($this->upload->isError()) {
|
||||
$return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors());
|
||||
$return['error'] = implode(' ' . PHP_EOL, $this->upload->getErrors());
|
||||
} else {
|
||||
$file = $this->upload->getFile();
|
||||
|
||||
@ -198,10 +189,10 @@ class DMSUploadField extends UploadField
|
||||
|
||||
// Replace the download template with a new one only when access the upload field through a GridField.
|
||||
// Needs to be enabled through setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate');
|
||||
Requirements::javascript('dms/javascript/DMSUploadField_downloadtemplate.js');
|
||||
Requirements::javascript(DMS_DIR . '/javascript/DMSUploadField_downloadtemplate.js');
|
||||
|
||||
// In the add dialog, add the addtemplate into the set of file that load.
|
||||
Requirements::javascript('dms/javascript/DMSUploadField_addtemplate.js');
|
||||
Requirements::javascript(DMS_DIR . '/javascript/DMSUploadField_addtemplate.js');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
@ -305,4 +296,26 @@ class DMSUploadField extends UploadField
|
||||
|
||||
user_error("Invalid value for UploadField::fileEditValidator", E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the folder name to store DMS files in
|
||||
*
|
||||
* @param string $folderName
|
||||
* @return $this
|
||||
*/
|
||||
public function setFolderName($folderName)
|
||||
{
|
||||
$this->folderName = (string) $folderName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the folder name for storing the document
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFolderName()
|
||||
{
|
||||
return $this->folderName;
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,14 @@ class DMSUploadField_ItemHandler extends UploadField_ItemHandler
|
||||
'EditForm',
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets a DMS document by its ID
|
||||
*
|
||||
* @return DMSDocument
|
||||
*/
|
||||
public function getItem()
|
||||
{
|
||||
return DataObject::get_by_id('DMSDocument', $this->itemID);
|
||||
return DMSDocument::get()->byId($this->itemID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,136 +5,56 @@
|
||||
*/
|
||||
class DMSSiteTreeExtension extends DataExtension
|
||||
{
|
||||
|
||||
private static $belongs_many_many = array(
|
||||
'Documents' => 'DMSDocument'
|
||||
private static $has_many = array(
|
||||
'DocumentSets' => 'DMSDocumentSet'
|
||||
);
|
||||
|
||||
private static $noDocumentsList = array();
|
||||
|
||||
private static $showDocumentsList = array();
|
||||
|
||||
/**
|
||||
* Do not show the documents tab on the array of pages set here
|
||||
* @static
|
||||
* @param $mixed Array of page types to not show the Documents tab on
|
||||
*/
|
||||
public static function no_documents_tab($array = array())
|
||||
{
|
||||
if (empty($array)) {
|
||||
return;
|
||||
}
|
||||
if (is_array($array)) {
|
||||
self::$noDocumentsList = $array;
|
||||
} else {
|
||||
self::$noDocumentsList = array($array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only show the documents tab on the list of pages set here. Any pages set in the no_documents_tab array will
|
||||
* still not be shown. If this isn't called, or if it is called with an empty array, all pages will get
|
||||
* Document tabs.
|
||||
* @static
|
||||
* @param $array Array of page types to show the Documents tab on
|
||||
*/
|
||||
public static function show_documents_tab($array = array())
|
||||
{
|
||||
if (empty($array)) {
|
||||
return;
|
||||
}
|
||||
if (is_array($array)) {
|
||||
self::$showDocumentsList = $array;
|
||||
} else {
|
||||
self::$showDocumentsList = array($array);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
// Prevent certain pages from having a Document tab in the CMS
|
||||
if (in_array($this->owner->ClassName, self::$noDocumentsList)) {
|
||||
// Ability to disable document sets for a Page
|
||||
if (!$this->owner->config()->get('documents_enabled')) {
|
||||
return;
|
||||
}
|
||||
if (count(self::$showDocumentsList) > 0 && !in_array($this->owner->ClassName, self::$showDocumentsList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Javascript to customize the grid field for the DMS document (overriding entwine
|
||||
// in FRAMEWORK_DIR.'/javascript/GridField.js'
|
||||
Requirements::javascript(DMS_DIR.'/javascript/DMSGridField.js');
|
||||
Requirements::css(DMS_DIR.'/css/DMSMainCMS.css');
|
||||
|
||||
// Javascript for the link editor pop-up in TinyMCE
|
||||
Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js");
|
||||
|
||||
// Document listing
|
||||
$gridFieldConfig = GridFieldConfig::create()->addComponents(
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldFilterHeader(),
|
||||
new GridFieldSortableHeader(),
|
||||
new GridFieldOrderableRows('DocumentSort'),
|
||||
new GridFieldDataColumns(),
|
||||
new GridFieldEditButton(),
|
||||
new DMSGridFieldDeleteAction(), //special delete dialog to handle custom behaviour of unlinking and deleting
|
||||
new GridFieldDetailForm()
|
||||
//GridFieldLevelup::create($folder->ID)->setLinkSpec('admin/assets/show/%d')
|
||||
);
|
||||
|
||||
if (class_exists('GridFieldPaginatorWithShowAll')) {
|
||||
$paginatorComponent = new GridFieldPaginatorWithShowAll(15);
|
||||
} else {
|
||||
$paginatorComponent = new GridFieldPaginator(15);
|
||||
}
|
||||
$gridFieldConfig->addComponent($paginatorComponent);
|
||||
|
||||
if (class_exists('GridFieldSortableRows')) {
|
||||
$sortableComponent = new GridFieldSortableRows('DocumentSort');
|
||||
//setUsePagenation method removed from newer version of SortableGridField.
|
||||
if (method_exists($sortableComponent, 'setUsePagination')) {
|
||||
$sortableComponent->setUsePagination(false)->setForceRedraw(true);
|
||||
}
|
||||
$gridFieldConfig->addComponent($sortableComponent);
|
||||
}
|
||||
|
||||
// HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields.
|
||||
singleton('DMSDocument');
|
||||
$gridFieldConfig->getComponentByType('GridFieldDataColumns')
|
||||
->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields'))
|
||||
->setFieldCasting(array('LastChanged'=>"Datetime->Ago"))
|
||||
->setFieldFormatting(
|
||||
array(
|
||||
'FilenameWithoutID'=>'<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>'
|
||||
)
|
||||
);
|
||||
|
||||
//override delete functionality with this class
|
||||
$gridFieldConfig->getComponentByType('GridFieldDetailForm')
|
||||
->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest');
|
||||
|
||||
$gridField = GridField::create(
|
||||
'Documents',
|
||||
'Document Sets',
|
||||
false,
|
||||
$this->owner->Documents()->Sort('DocumentSort'),
|
||||
$gridFieldConfig
|
||||
$this->owner->DocumentSets(), //->Sort('DocumentSort'),
|
||||
new GridFieldConfig_RelationEditor
|
||||
);
|
||||
$gridField->addExtraClass('documents');
|
||||
$gridField->addExtraClass('documentsets');
|
||||
|
||||
$gridFieldConfig->addComponent(
|
||||
$addNewButton = new DMSGridFieldAddNewButton,
|
||||
'GridFieldExportButton'
|
||||
$fields->addFieldToTab(
|
||||
'Root.Document Sets (' . $this->owner->DocumentSets()->Count() . ')',
|
||||
$gridField
|
||||
);
|
||||
$addNewButton->setPageId($this->owner->ID);
|
||||
|
||||
$fields->addFieldToTab('Root.Documents (' . $this->owner->Documents()->Count() . ')', $gridField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce sorting for frontend
|
||||
* Get a list of document sets for the owner page
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function PageDocuments()
|
||||
public function getDocumentSets()
|
||||
{
|
||||
return $this->owner->getManyManyComponents('Documents')->sort('DocumentSort');
|
||||
return $this->owner->DocumentSets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all documents from all document sets for the owner page
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function getAllDocuments()
|
||||
{
|
||||
$documents = ArrayList::create();
|
||||
|
||||
foreach ($this->getDocumentSets() as $documentSet) {
|
||||
/** @var DocumentSet $documentSet */
|
||||
$documents->merge($documentSet->getDocuments());
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
public function onBeforeDelete()
|
||||
@ -160,7 +80,7 @@ class DMSSiteTreeExtension extends DataExtension
|
||||
|
||||
public function onBeforePublish()
|
||||
{
|
||||
$embargoedDocuments = $this->owner->Documents()->filter('EmbargoedUntilPublished', true);
|
||||
$embargoedDocuments = $this->owner->getAllDocuments()->filter('EmbargoedUntilPublished', true);
|
||||
if ($embargoedDocuments->Count() > 0) {
|
||||
foreach ($embargoedDocuments as $doc) {
|
||||
$doc->EmbargoedUntilPublished = false;
|
||||
@ -169,8 +89,14 @@ class DMSSiteTreeExtension extends DataExtension
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title of the page with the total number of documents it has associated with it across
|
||||
* all document sets
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitleWithNumberOfDocuments()
|
||||
{
|
||||
return $this->owner->Title . ' (' . $this->owner->Documents()->Count() . ')';
|
||||
return $this->owner->Title . ' (' . $this->owner->getAllDocuments()->count() . ')';
|
||||
}
|
||||
}
|
||||
|
@ -6,58 +6,6 @@
|
||||
*/
|
||||
interface DMSDocumentInterface
|
||||
{
|
||||
/**
|
||||
* Deletes the DMSDocument, its underlying file, as well as any tags related to this DMSDocument.
|
||||
*
|
||||
* @todo Can't be applied to classes which already implement the DataObjectInterface (naming conflict)
|
||||
*
|
||||
* @abstract
|
||||
* @return null
|
||||
*/
|
||||
// function delete();
|
||||
|
||||
/**
|
||||
* Associates this DMSDocument with a Page. This method does nothing if the association already exists.
|
||||
* This could be a simple wrapper around $myDoc->Pages()->add($myPage) to add a many_many relation
|
||||
* @abstract
|
||||
* @param $pageObject Page object to associate this DMSDocument with
|
||||
* @return null
|
||||
*/
|
||||
public function addPage($pageObject);
|
||||
|
||||
/**
|
||||
* Associates this DMSDocument with a set of Pages. This method loops through a set of page ids, and then
|
||||
* associates this
|
||||
* DMSDocument with the individual Page with the each page id in the set
|
||||
* @abstract
|
||||
* @param $pageIDs array of page ids used for the page objects associate this DMSDocument with
|
||||
* @return null
|
||||
*/
|
||||
public function addPages($pageIDs);
|
||||
|
||||
/**
|
||||
* Removes the association between this DMSDocument and a Page. This method does nothing if the association does
|
||||
* not exist.
|
||||
* @abstract
|
||||
* @param $pageObject Page object to remove the association to
|
||||
* @return mixed
|
||||
*/
|
||||
public function removePage($pageObject);
|
||||
|
||||
/**
|
||||
* Returns a list of the Page objects associated with this DMSDocument
|
||||
* @abstract
|
||||
* @return DataList
|
||||
*/
|
||||
public function getPages();
|
||||
|
||||
/**
|
||||
* Removes all associated Pages from the DMSDocument
|
||||
* @abstract
|
||||
* @return null
|
||||
*/
|
||||
public function removeAllPages();
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -67,7 +15,6 @@ interface DMSDocumentInterface
|
||||
* 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)
|
||||
* @abstract
|
||||
* @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)
|
||||
@ -78,7 +25,6 @@ interface DMSDocumentInterface
|
||||
/**
|
||||
* Fetches all tags associated with this DMSDocument within a given category. If a value is specified this method
|
||||
* tries to fetch that specific tag.
|
||||
* @abstract
|
||||
* @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
|
||||
@ -89,7 +35,6 @@ interface DMSDocumentInterface
|
||||
* 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.
|
||||
* @abstract
|
||||
* @param $category Category to remove (required)
|
||||
* @param null $value Value to remove (optional)
|
||||
* @return null
|
||||
@ -98,14 +43,12 @@ interface DMSDocumentInterface
|
||||
|
||||
/**
|
||||
* Deletes all tags associated with this DMSDocument.
|
||||
* @abstract
|
||||
* @return null
|
||||
*/
|
||||
public function removeAllTags();
|
||||
|
||||
/**
|
||||
* Returns a link to download this DMSDocument from the DMS store
|
||||
* @abstract
|
||||
* @return String
|
||||
*/
|
||||
public function getLink();
|
||||
@ -142,14 +85,12 @@ interface DMSDocumentInterface
|
||||
* Hides the DMSDocument, so it does not show up when getByPage($myPage) is called
|
||||
* (without specifying the $showEmbargoed = true parameter). This is similar to expire, except that this method
|
||||
* should be used to hide DMSDocuments that have not yet gone live.
|
||||
* @abstract
|
||||
* @return null
|
||||
*/
|
||||
public function embargoIndefinitely();
|
||||
|
||||
/**
|
||||
* Returns if this is DMSDocument is embargoed or expired.
|
||||
* @abstract
|
||||
* @return bool True or False depending on whether this DMSDocument is embargoed or expired
|
||||
*/
|
||||
public function isHidden();
|
||||
@ -157,7 +98,6 @@ interface DMSDocumentInterface
|
||||
|
||||
/**
|
||||
* Returns if this is DMSDocument is embargoed.
|
||||
* @abstract
|
||||
* @return bool True or False depending on whether this DMSDocument is embargoed
|
||||
*/
|
||||
public function isEmbargoed();
|
||||
@ -165,7 +105,6 @@ interface DMSDocumentInterface
|
||||
/**
|
||||
* Hides the DMSDocument, so it does not show up when getByPage($myPage) is called. Automatically un-hides the
|
||||
* DMSDocument at a specific date.
|
||||
* @abstract
|
||||
* @param $datetime String date time value when this DMSDocument should expire
|
||||
* @return null
|
||||
*/
|
||||
@ -179,21 +118,18 @@ interface DMSDocumentInterface
|
||||
|
||||
/**
|
||||
* Clears any previously set embargos, so the DMSDocument always shows up in all queries.
|
||||
* @abstract
|
||||
* @return null
|
||||
*/
|
||||
public function clearEmbargo();
|
||||
|
||||
/**
|
||||
* Returns if this is DMSDocument is expired.
|
||||
* @abstract
|
||||
* @return bool True or False depending on whether this DMSDocument is expired
|
||||
*/
|
||||
public function isExpired();
|
||||
|
||||
/**
|
||||
* Hides the DMSDocument at a specific date, so it does not show up when getByPage($myPage) is called.
|
||||
* @abstract
|
||||
* @param $datetime String date time value when this DMSDocument should expire
|
||||
* @return null
|
||||
*/
|
||||
@ -201,7 +137,6 @@ interface DMSDocumentInterface
|
||||
|
||||
/**
|
||||
* Clears any previously set expiry.
|
||||
* @abstract
|
||||
* @return null
|
||||
*/
|
||||
public function clearExpiry();
|
||||
@ -211,7 +146,6 @@ interface DMSDocumentInterface
|
||||
/**
|
||||
* Returns a DataList of all previous Versions of this DMSDocument (check the LastEdited date of each
|
||||
* object to find the correct one)
|
||||
* @abstract
|
||||
* @return DataList List of DMSDocument objects
|
||||
*/
|
||||
public function getVersions();
|
||||
|
@ -57,11 +57,19 @@ interface DMSInterface
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list of Document objects associated with a Page
|
||||
* @abstract
|
||||
* @param $page SiteTree to fetch the associated Documents from
|
||||
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
|
||||
* @return DataList Document list associated with the Page
|
||||
* Returns a list of Document objects associated with a Page via intermediary document sets
|
||||
*
|
||||
* @param SiteTree $page SiteTree to fetch the associated Documents from
|
||||
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
|
||||
* @return ArrayList Document list associated with the Page
|
||||
*/
|
||||
public function getByPage($page, $showEmbargoed = false);
|
||||
public function getByPage(SiteTree $page, $showEmbargoed = false);
|
||||
|
||||
/**
|
||||
* Returns a list of Document Set objects associated with a Page
|
||||
*
|
||||
* @param SiteTree $page SiteTree to fetch the associated Document Sets from
|
||||
* @return ArrayList Document list associated with the Page
|
||||
*/
|
||||
public function getDocumentSetsByPage(SiteTree $page);
|
||||
}
|
||||
|
@ -43,20 +43,17 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
"CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')",
|
||||
);
|
||||
|
||||
private static $belongs_many_many = array(
|
||||
'Sets' => 'DMSDocumentSet'
|
||||
);
|
||||
|
||||
private static $many_many = array(
|
||||
'Pages' => 'SiteTree',
|
||||
'RelatedDocuments' => 'DMSDocument',
|
||||
'Tags' => 'DMSTag',
|
||||
'ViewerGroups' => 'Group',
|
||||
'EditorGroups' => 'Group',
|
||||
);
|
||||
|
||||
private static $many_many_extraFields = array(
|
||||
'Pages' => array(
|
||||
'DocumentSort' => 'Int'
|
||||
)
|
||||
);
|
||||
|
||||
private static $display_fields = array(
|
||||
'ID' => 'ID',
|
||||
'Title' => 'Title',
|
||||
@ -82,7 +79,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
'Filename' => 'Filename',
|
||||
'Title' => 'Title',
|
||||
'ViewCount' => 'ViewCount',
|
||||
'getPages.count' => 'Page Use'
|
||||
'getRelatedPages.count' => 'Page Use'
|
||||
);
|
||||
|
||||
/**
|
||||
@ -217,103 +214,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
return $this->canView();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Associates this document with a Page. This method does nothing if the
|
||||
* association already exists.
|
||||
*
|
||||
* This could be a simple wrapper around $myDoc->Pages()->add($myPage) to
|
||||
* add a many_many relation.
|
||||
*
|
||||
* @param SiteTree $pageObject Page object to associate this Document with
|
||||
*
|
||||
* @return DMSDocument
|
||||
*/
|
||||
public function addPage($pageObject)
|
||||
{
|
||||
$this->Pages()->add($pageObject);
|
||||
|
||||
DB::query(
|
||||
"UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1"
|
||||
. " WHERE \"SiteTreeID\" = $pageObject->ID"
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates this DMSDocument with a set of Pages. This method loops
|
||||
* through a set of page ids, and then associates this DMSDocument with the
|
||||
* individual Page with the each page id in the set.
|
||||
*
|
||||
* @param array $pageIDs
|
||||
*
|
||||
* @return DMSDocument
|
||||
*/
|
||||
public function addPages($pageIDs)
|
||||
{
|
||||
foreach ($pageIDs as $id) {
|
||||
$pageObject = DataObject::get_by_id("SiteTree", $id);
|
||||
|
||||
if ($pageObject && $pageObject->exists()) {
|
||||
$this->addPage($pageObject);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the association between this Document and a Page. This method
|
||||
* does nothing if the association does not exist.
|
||||
*
|
||||
* @param SiteTree $pageObject Page object to remove the association to
|
||||
*
|
||||
* @return DMSDocument
|
||||
*/
|
||||
public function removePage($pageObject)
|
||||
{
|
||||
$this->Pages()->remove($pageObject);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see getPages()
|
||||
*
|
||||
* @return DataList
|
||||
*/
|
||||
public function Pages()
|
||||
{
|
||||
$pages = $this->getManyManyComponents('Pages');
|
||||
$this->extend('updatePages', $pages);
|
||||
|
||||
return $pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the Page objects associated with this Document.
|
||||
*
|
||||
* @return DataList
|
||||
*/
|
||||
public function getPages()
|
||||
{
|
||||
return $this->Pages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all associated Pages from the DMSDocument
|
||||
*
|
||||
* @return DMSDocument
|
||||
*/
|
||||
public function removeAllPages()
|
||||
{
|
||||
$this->Pages()->removeAll();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase ViewCount by 1, without update any other record fields such as
|
||||
* LastEdited.
|
||||
@ -842,8 +742,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
}
|
||||
}
|
||||
|
||||
$this->removeAllPages();
|
||||
|
||||
// get rid of any versions have saved for this DMSDocument, too
|
||||
if (DMSDocument_versions::$enable_versions) {
|
||||
$versions = $this->getVersions();
|
||||
@ -855,11 +753,9 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
}
|
||||
}
|
||||
|
||||
parent::delete();
|
||||
return parent::delete();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Relate an existing file on the filesystem to the document.
|
||||
*
|
||||
@ -1060,7 +956,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
$pagesGrid = GridField::create(
|
||||
'Pages',
|
||||
_t('DMSDocument.RelatedPages', 'Related Pages'),
|
||||
$this->Pages(),
|
||||
$this->getRelatedPages(),
|
||||
$gridFieldConfig
|
||||
);
|
||||
|
||||
@ -1321,7 +1217,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
);
|
||||
|
||||
//count the number of pages this document is published on
|
||||
$publishedOnCount = $this->Pages()->Count();
|
||||
$publishedOnCount = $this->getRelatedPages()->count();
|
||||
$publishedOnValue = "$publishedOnCount pages";
|
||||
if ($publishedOnCount == 1) {
|
||||
$publishedOnValue = "$publishedOnCount page";
|
||||
@ -1419,6 +1315,26 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of related pages for this document by going through the associated document sets
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function getRelatedPages()
|
||||
{
|
||||
$pages = ArrayList::create();
|
||||
|
||||
foreach ($this->Sets() as $documentSet) {
|
||||
/** @var DocumentSet $documentSet */
|
||||
$pages->add($documentSet->Page());
|
||||
}
|
||||
$pages->removeDuplicates();
|
||||
|
||||
$this->extend('updateRelatedPages', $pages);
|
||||
|
||||
return $pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a GridField for managing related documents
|
||||
*
|
||||
|
123
code/model/DMSDocumentSet.php
Normal file
123
code/model/DMSDocumentSet.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* A document set is attached to Pages, and contains many DMSDocuments
|
||||
*/
|
||||
class DMSDocumentSet extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Title' => 'Varchar(255)'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Page' => 'SiteTree'
|
||||
);
|
||||
|
||||
private static $many_many = array(
|
||||
'Documents' => 'DMSDocument'
|
||||
);
|
||||
|
||||
/**
|
||||
* Retrieve a list of the documents in this set. An extension hook is provided before the result is returned.
|
||||
*
|
||||
* You can attach an extension to this event:
|
||||
*
|
||||
* <code>
|
||||
* public function updateDocuments($document)
|
||||
* {
|
||||
* // do something
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @return DataList
|
||||
*/
|
||||
public function getDocuments()
|
||||
{
|
||||
$documents = $this->Documents();
|
||||
|
||||
$this->extend('updateDocuments', $documents);
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the "documents" list into the main tab instead of its own tab, and replace the default "Add Document" button
|
||||
* with a customised button for DMS documents
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$this->beforeUpdateCMSFields(function (FieldList $fields) {
|
||||
// Javascript to customize the grid field for the DMS document (overriding entwine
|
||||
// in FRAMEWORK_DIR.'/javascript/GridField.js'
|
||||
Requirements::javascript(DMS_DIR . '/javascript/DMSGridField.js');
|
||||
Requirements::css(DMS_DIR . '/css/DMSMainCMS.css');
|
||||
|
||||
// Javascript for the link editor pop-up in TinyMCE
|
||||
Requirements::javascript(DMS_DIR . '/javascript/DocumentHtmlEditorFieldToolbar.js');
|
||||
|
||||
// Document listing
|
||||
$gridFieldConfig = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldFilterHeader(),
|
||||
new GridFieldSortableHeader(),
|
||||
// new GridFieldOrderableRows('DocumentSort'),
|
||||
new GridFieldDataColumns(),
|
||||
new GridFieldEditButton(),
|
||||
new DMSGridFieldDeleteAction(), //special delete dialog to handle custom behaviour of unlinking and deleting
|
||||
new GridFieldDetailForm()
|
||||
//GridFieldLevelup::create($folder->ID)->setLinkSpec('admin/assets/show/%d')
|
||||
);
|
||||
|
||||
if (class_exists('GridFieldPaginatorWithShowAll')) {
|
||||
$paginatorComponent = new GridFieldPaginatorWithShowAll(15);
|
||||
} else {
|
||||
$paginatorComponent = new GridFieldPaginator(15);
|
||||
}
|
||||
$gridFieldConfig->addComponent($paginatorComponent);
|
||||
|
||||
if (class_exists('GridFieldSortableRows')) {
|
||||
$sortableComponent = new GridFieldSortableRows('DocumentSort');
|
||||
//setUsePagenation method removed from newer version of SortableGridField.
|
||||
if (method_exists($sortableComponent, 'setUsePagination')) {
|
||||
$sortableComponent->setUsePagination(false)->setForceRedraw(true);
|
||||
}
|
||||
$gridFieldConfig->addComponent($sortableComponent);
|
||||
}
|
||||
|
||||
// HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields.
|
||||
singleton('DMSDocument');
|
||||
$gridFieldConfig->getComponentByType('GridFieldDataColumns')
|
||||
->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields'))
|
||||
->setFieldCasting(array('LastChanged'=>"Datetime->Ago"))
|
||||
->setFieldFormatting(
|
||||
array(
|
||||
'FilenameWithoutID' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>'
|
||||
)
|
||||
);
|
||||
|
||||
//override delete functionality with this class
|
||||
$gridFieldConfig->getComponentByType('GridFieldDetailForm')
|
||||
->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest');
|
||||
|
||||
$gridField = GridField::create(
|
||||
'Documents',
|
||||
false,
|
||||
$this->Documents(),//->Sort('DocumentSort'),
|
||||
$gridFieldConfig
|
||||
);
|
||||
$gridField->addExtraClass('documents');
|
||||
|
||||
$gridFieldConfig->addComponent(
|
||||
$addNewButton = new DMSGridFieldAddNewButton,
|
||||
'GridFieldExportButton'
|
||||
);
|
||||
$addNewButton->setDocumentSetId($this->ID);
|
||||
|
||||
$fields->removeByName('Documents');
|
||||
$fields->addFieldToTab('Root.Main', $gridField);
|
||||
});
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
}
|
30
docs/en/changelogs/2.0.0.md
Normal file
30
docs/en/changelogs/2.0.0.md
Normal file
@ -0,0 +1,30 @@
|
||||
# 2.0.0 (unreleased)
|
||||
|
||||
## Document sets
|
||||
|
||||
Documents now belong to "sets", which are attached to Pages. A Page can have many Document Sets, and a Set has a
|
||||
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 so support
|
||||
having a Document Set intermediary (@todo Add a build task for this).
|
||||
|
||||
## API changes
|
||||
|
||||
* `DMSSiteTreeExtension::no_documents_tab` removed, use YAML configuration `MyPage.documents_enabled: false` instead
|
||||
* `DMSSiteTreeExtension::show_documents_tab` removed, use YAML configuration `MyPage.documents_enabled: true` instead
|
||||
* `DMSSiteTreeExtension::PageDocuments` removed, use `DMSSiteTreeExtension::getDocumentSets` instead
|
||||
* `DMSSiteTreeExtension::getDocuments` removed, use `DMSSiteTreeExtension::getAllDocuments` instead
|
||||
* `DMSDocument::addPage` removed, use document sets instead
|
||||
* `DMSDocument::addPages` removed, use document sets instead
|
||||
* `DMSDocument::removePage` removed, use document sets instead
|
||||
* `DMSDocument::removeAllPages` removed, use document sets instead
|
||||
* `DMSDocument::getPages` removed, use `DMSDocument::getRelatedPages` instead
|
||||
* `DMSDocumentInterface` has had the page manipulation methods removed, as above
|
||||
* `DMSDocumentAddController::add_allowed_extensions` removed, use YAML configuration `DMSDocumentAddController::allowed_extensions` instead
|
||||
* `DMSInterface` (and `DMS`) are stricter in the `getByPage` method, enforcing a `SiteTree` type hint
|
||||
* New method `DMSInterface::getDocumentSetsByPage` (and in `DMS`)
|
||||
|
||||
## Template changes
|
||||
|
||||
The default template entry point is now `DocumentSets.ss` (previously `Documents.ss`). As well as this change,
|
||||
`Documents.ss` has been renamed to `DocumentSet.ss`.
|
@ -1,3 +1,30 @@
|
||||
# Configuration
|
||||
|
||||
The file location is set via the `DMS::$dmsFolder` static, and points to a location in the webroot.
|
||||
|
||||
## Enable/disable documents/sets for a specific page type
|
||||
|
||||
If you don't need documents/document sets for a specific page type you can disable this with YAML configuration:
|
||||
|
||||
```yaml
|
||||
MyPageType:
|
||||
documents_enabled: false
|
||||
```
|
||||
|
||||
Likewise, you could override a previously set configuration value by setting this back to `true` in a configuration
|
||||
file with a higher precedence.
|
||||
|
||||
## Allowed extensions for DMS documents
|
||||
|
||||
By default the allowed extensions for DMS documents will come from the UploadField's allowed extesions list, and will
|
||||
have a customised list of extensions for DMS merged in. The base `allowed_extensions` is a site-wide configuration
|
||||
setting. [See here for information](https://docs.silverstripe.org/en/3/developer_guides/forms/field_types/uploadfield/#limit-the-allowed-filetypes) on changing this.
|
||||
|
||||
To add extra allowed file extensions purely for DMS documents, you can update the YAML configuration property:
|
||||
|
||||
```yaml
|
||||
DMSDocumentAddController:
|
||||
allowed_extensions:
|
||||
- php
|
||||
- php5
|
||||
```
|
||||
|
@ -1,18 +1,35 @@
|
||||
# Creating documents
|
||||
|
||||
Create by relative path:
|
||||
The following examples will allow you to create a DMS document in the system without associating it to a document set.
|
||||
|
||||
## Create by relative path
|
||||
|
||||
```php
|
||||
$dms = DMS::getDMSInstance();
|
||||
$dms = DMS::inst();
|
||||
$doc = $dms->storeDocument('assets/myfile.pdf');
|
||||
```
|
||||
|
||||
Create from an existing `File` record:
|
||||
## Create from an existing `File` record
|
||||
|
||||
```php
|
||||
$dms = DMS::getDMSInstance();
|
||||
$dms = DMS::inst();
|
||||
$file = File::get()->byID(99);
|
||||
$doc = $dms->storeDocument($file);
|
||||
```
|
||||
|
||||
Note: Both operations copy the existing file.
|
||||
|
||||
## Associate to a document set
|
||||
|
||||
If you need to associate a document to a set once it has already been created, you can use the ORM relationship from
|
||||
SiteTree to access the document sets, or you can simply access the document set directly:
|
||||
|
||||
```php
|
||||
// Add document to the first set in my page
|
||||
$firstSetInPage = $myPage->DocumentSets()->first();
|
||||
$firstSetInPage->add($doc);
|
||||
|
||||
// Add document to a specific document set
|
||||
$docSet = DMSDocumentSet::get()->byId(123);
|
||||
$docSet->add($doc);
|
||||
```
|
||||
|
@ -5,7 +5,7 @@
|
||||
You can use `DMSDocument::getLink` to retrieve the secure route to download a DMS document:
|
||||
|
||||
```php
|
||||
$dms = DMS::getDMSInstance();
|
||||
$dms = DMS::inst();
|
||||
$docs = $dms->getByTag('priority', 'important')->First();
|
||||
$link = $doc->getLink();
|
||||
```
|
||||
|
@ -14,3 +14,7 @@
|
||||
## CMS user help
|
||||
|
||||
* TBC
|
||||
|
||||
### Changelogs
|
||||
|
||||
* [2.0.0 (unreleased)](changelogs/2.0.0.md)
|
||||
|
@ -1,10 +1,35 @@
|
||||
# Manage page relations
|
||||
|
||||
To find documents by a Page:
|
||||
Documents are associated to pages via "document sets". You can retrieve document sets for a page, then retrieve
|
||||
documents that belong to those sets. You can still retrieve all documents for a page if you want to.
|
||||
|
||||
## Get document sets for a page
|
||||
|
||||
```php
|
||||
$dms = DMS::getDMSInstance();
|
||||
$page = SiteTree::get()->filter('URLSegment', 'home')->first();
|
||||
/** @var DataList $docs */
|
||||
$docs = $dms->getByPage($page);
|
||||
$dms = DMS::inst();
|
||||
$sets = $dms->getDocumentSetsByPage($myPage);
|
||||
```
|
||||
|
||||
You can also request sets directly from the SiteTree instance:
|
||||
|
||||
```php
|
||||
$sets = $page->getDocumentSets();
|
||||
```
|
||||
|
||||
## Get all related documents for a page
|
||||
|
||||
`DMS::getByPage` will exclude currently embargoed documents by default. To include embargoed documents as well
|
||||
add `true` as the second argument.
|
||||
|
||||
```php
|
||||
$dms = DMS::inst();
|
||||
|
||||
$documents = $dms->getByPage($myPage);
|
||||
$documentsIncludingEmbargoed = $dms->getByPage($myPage, true);
|
||||
```
|
||||
|
||||
You can also request this directly from the SiteTree instance:
|
||||
|
||||
```php
|
||||
$documents = $myPage->getAllDocuments();
|
||||
```
|
||||
|
@ -4,7 +4,7 @@ Add a simple include to any of your `.ss` templates to display the DMSDocuments
|
||||
the current page on the front-end.
|
||||
|
||||
```
|
||||
<% include Documents %>
|
||||
<% include DocumentSets %>
|
||||
```
|
||||
|
||||
You can fine tune the HTML markup or display behaviour of any of the templates in `/dms/templates/Includes` to change
|
||||
|
25
lang/en.yml
25
lang/en.yml
@ -9,6 +9,8 @@ en:
|
||||
TYPE: 'File type'
|
||||
URL: URL
|
||||
DMSDocument:
|
||||
EDIT: Edit
|
||||
EDITDOCUMENT: Edit this document
|
||||
PLURALNAME: Documents
|
||||
RelatedPages: 'Related Pages'
|
||||
RelatedReferences: 'Related References'
|
||||
@ -16,9 +18,14 @@ en:
|
||||
Versions: Versions
|
||||
DOWNLOAD: "Download {title}"
|
||||
LASTCHANGED: "Last changed: {date}"
|
||||
DMSDocumentSet:
|
||||
ADDDOCUMENTBUTTON: Add Document
|
||||
ADDDOCUMENTSBUTTON: Add Documents
|
||||
PLURALNAME: Document Sets
|
||||
SINGULARNAME: Document Set
|
||||
DMSTag:
|
||||
PLURALNAME: 'D M S Tags'
|
||||
SINGULARNAME: 'D M S Tag'
|
||||
PLURALNAME: 'DMS Tags'
|
||||
SINGULARNAME: 'DMS Tag'
|
||||
FileIFrameField:
|
||||
ATTACHONCESAVED2: 'Files can be attached once you have saved the record for the first time.'
|
||||
GridAction:
|
||||
@ -29,8 +36,10 @@ en:
|
||||
DeletePermissionsFailure: 'No delete permissions'
|
||||
UploadField:
|
||||
ATTACHFILE: 'Attach a file'
|
||||
DONE: Done!
|
||||
DROPFILE: 'drop a file'
|
||||
FIELDNOTSET: 'File information not found'
|
||||
FROMCMS: From the CMS
|
||||
FROMCOMPUTER: 'From your computer'
|
||||
FROMCOMPUTERINFO: 'Upload from your computer'
|
||||
MAXNUMBEROFFILES: 'Max number of {count} file(s) exceeded.'
|
||||
@ -38,6 +47,14 @@ en:
|
||||
MENUTITLE: 'Edit Page'
|
||||
NODOCUMENTS: 'There are no documents attached to the selected page.'
|
||||
RELATEDDOCUMENTS: 'Related Documents'
|
||||
MAINTAB: Main
|
||||
DMSDocument_versions:
|
||||
PLURALNAME: 'D M S Document_versionss'
|
||||
SINGULARNAME: 'D M S Document_versions'
|
||||
PLURALNAME: 'DMS Document_versionss'
|
||||
SINGULARNAME: 'DMS Document_versions'
|
||||
DMSDocumentAddExistingField:
|
||||
ADDEXISTING: Add Existing
|
||||
AUTOCOMPLETE: Search by ID or filename
|
||||
CHOOSESET: Choose Document Set
|
||||
EDITDOCUMENTDETAILS: Edit Document Details
|
||||
LINKADOCUMENT: Link a Document
|
||||
SELECTED: Selected Document
|
||||
|
@ -1,64 +1,43 @@
|
||||
<div id="document" class="ss-add field treedropdown searchable">
|
||||
<div class="document-add-existing <% if useFieldContext %>field<% else %>link-editor-context<% end_if %>">
|
||||
<% if useFieldContext %>
|
||||
<h3>
|
||||
<% else %>
|
||||
<div>
|
||||
<% end_if %>
|
||||
<span class="step-label">
|
||||
<% if useFieldContext %>
|
||||
<span class="flyout">1</span><span class="arrow"></span>
|
||||
<strong class="title">Link a Document</strong>
|
||||
<% else %>
|
||||
<% end_if %>
|
||||
</span>
|
||||
<% if useFieldContext %>
|
||||
</h3>
|
||||
<% else %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
<div class="document-add-existing <% if $useFieldContext %>field<% else %>link-editor-context<% end_if %>">
|
||||
<% if $useFieldContext %><h3><% else %><div><% end_if %>
|
||||
<span class="step-label">
|
||||
<% if $useFieldContext %>
|
||||
<span class="flyout">1</span><span class="arrow"></span>
|
||||
<strong class="title"><%t DMSDocumentAddExistingField.LINKADOCUMENT "Link a Document" %></strong>
|
||||
<% end_if %>
|
||||
</span>
|
||||
<% if $useFieldContext %></h3><% else %></div><% end_if %>
|
||||
|
||||
<% if useFieldContext %>
|
||||
<% else %>
|
||||
<label>Link a Document</label>
|
||||
<div class="middleColumn">
|
||||
<% end_if %>
|
||||
|
||||
<input class="document-autocomplete text" type="text" placeholder="Search by ID or filename" />
|
||||
<!-- <span>or Add from page</span> -->
|
||||
$fieldByName(PageSelector)
|
||||
<% if not $useFieldContext %>
|
||||
<label><%t DMSDocumentAddExistingField.LINKADOCUMENT "Link a Document" %></label>
|
||||
<div class="middleColumn">
|
||||
<% end_if %>
|
||||
<input class="document-autocomplete text" type="text" placeholder="<%t DMSDocumentAddExistingField.AUTOCOMPLETE "Search by ID or filename" %>" />
|
||||
$fieldByName(PageSelector)
|
||||
<div class="document-list"></div>
|
||||
<% if not $useFieldContext %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
</div>
|
||||
|
||||
<div class="document-list"></div>
|
||||
|
||||
<% if useFieldContext %>
|
||||
<% else %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="ss-assetuploadfield <% if useFieldContext %>field<% else %>link-editor-context<% end_if %>">
|
||||
<div class="step4">
|
||||
<span class="step-label">
|
||||
<% if useFieldContext %>
|
||||
<span class="flyout">2</span><span class="arrow"></span>
|
||||
<strong class="title">Edit Document Details</strong>
|
||||
<% else %>
|
||||
<label>Selected Document</label>
|
||||
<% end_if %>
|
||||
</span>
|
||||
</div>
|
||||
<!-- <div class="fileOverview"></div> -->
|
||||
|
||||
<% if useFieldContext %>
|
||||
<% else %>
|
||||
<div class="middleColumn">
|
||||
<% end_if %>
|
||||
<ul class="files ss-uploadfield-files ss-add-files"></ul>
|
||||
<% if useFieldContext %>
|
||||
<% else %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="ss-assetuploadfield <% if useFieldContext %>field<% else %>link-editor-context<% end_if %>">
|
||||
<div class="step4">
|
||||
<span class="step-label">
|
||||
<% if useFieldContext %>
|
||||
<span class="flyout">2</span><span class="arrow"></span>
|
||||
<strong class="title"><%t DMSDocumentAddExistingField.EDITDOCUMENTDETAILS "Edit Document Details" %></strong>
|
||||
<% else %>
|
||||
<label><%t DMSDocumentAddExistingField.SELECTED "Selected Document" %></label>
|
||||
<% end_if %>
|
||||
</span>
|
||||
</div>
|
||||
<% if not $useFieldContext %>
|
||||
<div class="middleColumn">
|
||||
<% end_if %>
|
||||
<ul class="files ss-uploadfield-files ss-add-files"></ul>
|
||||
<% if not $useFieldContext %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<div class="clear"><!-- --></div>
|
||||
</label>
|
||||
<div class="ss-uploadfield-item-actions">
|
||||
<% if Top.isDisabled || Top.isReadonly %>
|
||||
<% if $Top.isDisabled || $Top.isReadonly %>
|
||||
<% else %>
|
||||
$UploadFieldFileButtons
|
||||
<% end_if %>
|
||||
@ -25,11 +25,11 @@
|
||||
<% end_loop %>
|
||||
<% end_if %>
|
||||
</ul>
|
||||
<% if isDisabled || isReadonly %>
|
||||
<% if isSaveable %>
|
||||
<% if $isDisabled || $isReadonly %>
|
||||
<% if $isSaveable %>
|
||||
<% else %>
|
||||
<div class="ss-uploadfield-item">
|
||||
<em><% _t('FileIFrameField.ATTACHONCESAVED2', 'Files can be attached once you have saved the record for the first time.') %></em>
|
||||
<em><%t FileIFrameField.ATTACHONCESAVED2 "Files can be attached once you have saved the record for the first time." %></em>
|
||||
</div>
|
||||
<% end_if %>
|
||||
<% else %>
|
||||
@ -41,8 +41,8 @@
|
||||
<label class="ss-uploadfield-item-name"><b>
|
||||
<% _t('UploadField.ATTACHFILE', 'Attach a file') %>
|
||||
</b></label>
|
||||
<label class="ss-uploadfield-fromcomputer ss-ui-button ui-corner-all" title="<% _t('UploadField.FROMCOMPUTERINFO', 'Upload from your computer') %>" data-icon="drive-upload">
|
||||
<% _t('UploadField.FROMCOMPUTER', 'From your computer') %>
|
||||
<label class="ss-uploadfield-fromcomputer ss-ui-button ui-corner-all" title="<%t UploadField.FROMCOMPUTERINFO 'Upload from your computer' %>" data-icon="drive-upload">
|
||||
<%t UploadField.FROMCOMPUTER 'From your computer' %>
|
||||
<input id="$id" name="$getName" class="$extraClass ss-uploadfield-fromcomputer-fileinput" data-config="$configString" type="file"<% if $multiple %> multiple="multiple"<% end_if %> />
|
||||
</label>
|
||||
<div class="clear"><!-- --></div>
|
||||
|
11
templates/Includes/DocumentSet.ss
Normal file
11
templates/Includes/DocumentSet.ss
Normal file
@ -0,0 +1,11 @@
|
||||
<% if $getDocuments %>
|
||||
<div class="documentsets-set">
|
||||
<% if $Title %>
|
||||
<h3>$Title</h3>
|
||||
<% end_if %>
|
||||
|
||||
<% loop $getDocuments %>
|
||||
<% include Document %>
|
||||
<% end_loop %>
|
||||
</div>
|
||||
<% end_if %>
|
7
templates/Includes/DocumentSets.ss
Normal file
7
templates/Includes/DocumentSets.ss
Normal file
@ -0,0 +1,7 @@
|
||||
<% if $getDocumentSets %>
|
||||
<div class="documentsets">
|
||||
<% loop $getDocumentSets %>
|
||||
<% include DocumentSet %>
|
||||
<% end_loop %>
|
||||
</div>
|
||||
<% end_if %>
|
@ -1,8 +0,0 @@
|
||||
<% if $PageDocuments %>
|
||||
<div class="documents">
|
||||
<h3><%t DMSDocument.PLURALNAME "Documents" %></h3>
|
||||
<% loop $PageDocuments %>
|
||||
<% include Document %>
|
||||
<% end_loop %>
|
||||
</div>
|
||||
<% end_if %>
|
35
tests/DMSDocumentSetTest.php
Normal file
35
tests/DMSDocumentSetTest.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
class DMSDocumentSetTest extends SapphireTest
|
||||
{
|
||||
protected static $fixture_file = 'dmstest.yml';
|
||||
|
||||
/**
|
||||
* Ensure that getDocuments is extensible
|
||||
*/
|
||||
public function testGetDocumentsIsExtensible()
|
||||
{
|
||||
DMSDocumentSet::add_extension('StubRelatedDocumentExtension');
|
||||
|
||||
$set = new DMSDocumentSet;
|
||||
$documents = $set->getDocuments();
|
||||
|
||||
$this->assertCount(1, $documents);
|
||||
$this->assertSame('Extended', $documents->first()->Filename);
|
||||
}
|
||||
|
||||
public function testRelations()
|
||||
{
|
||||
$s1 = $this->objFromFixture('SiteTree', 's1');
|
||||
$s2 = $this->objFromFixture('SiteTree', 's2');
|
||||
$s4 = $this->objFromFixture('SiteTree', 's4');
|
||||
|
||||
$ds1 = $this->objFromFixture('DMSDocumentSet', 'ds1');
|
||||
$ds2 = $this->objFromFixture('DMSDocumentSet', 'ds2');
|
||||
$ds3 = $this->objFromFixture('DMSDocumentSet', 'ds3');
|
||||
|
||||
$this->assertCount(0, $s4->getDocumentSets(), 'Page 4 has no document sets associated');
|
||||
$this->assertCount(2, $s1->getDocumentSets(), 'Page 1 has 2 document sets');
|
||||
$this->assertEquals(array($ds1->ID, $ds2->ID), $s1->getDocumentSets()->column('ID'));
|
||||
}
|
||||
}
|
@ -19,150 +19,6 @@ class DMSDocumentTest extends SapphireTest
|
||||
self::$is_running_test = $this->originalIsRunningTest;
|
||||
}
|
||||
|
||||
public function testPageRelations()
|
||||
{
|
||||
$s1 = $this->objFromFixture('SiteTree', 's1');
|
||||
$s2 = $this->objFromFixture('SiteTree', 's2');
|
||||
$s3 = $this->objFromFixture('SiteTree', 's3');
|
||||
$s4 = $this->objFromFixture('SiteTree', 's4');
|
||||
$s5 = $this->objFromFixture('SiteTree', 's5');
|
||||
$s6 = $this->objFromFixture('SiteTree', 's6');
|
||||
|
||||
$d1 = $this->objFromFixture('DMSDocument', 'd1');
|
||||
|
||||
$pages = $d1->Pages();
|
||||
$pagesArray = $pages->toArray();
|
||||
$this->assertEquals($pagesArray[0]->ID, $s1->ID, 'Page 1 associated correctly');
|
||||
$this->assertEquals($pagesArray[1]->ID, $s2->ID, 'Page 2 associated correctly');
|
||||
$this->assertEquals($pagesArray[2]->ID, $s3->ID, 'Page 3 associated correctly');
|
||||
$this->assertEquals($pagesArray[3]->ID, $s4->ID, 'Page 4 associated correctly');
|
||||
$this->assertEquals($pagesArray[4]->ID, $s5->ID, 'Page 5 associated correctly');
|
||||
$this->assertEquals($pagesArray[5]->ID, $s6->ID, 'Page 6 associated correctly');
|
||||
}
|
||||
|
||||
public function testAddPageRelation()
|
||||
{
|
||||
$s1 = $this->objFromFixture('SiteTree', 's1');
|
||||
$s2 = $this->objFromFixture('SiteTree', 's2');
|
||||
$s3 = $this->objFromFixture('SiteTree', 's3');
|
||||
|
||||
$doc = new DMSDocument();
|
||||
$doc->Filename = 'test file';
|
||||
$doc->Folder = '0';
|
||||
$doc->write();
|
||||
|
||||
$doc->addPage($s1);
|
||||
$doc->addPage($s2);
|
||||
$doc->addPage($s3);
|
||||
|
||||
$pages = $doc->Pages();
|
||||
$pagesArray = $pages->toArray();
|
||||
$this->assertEquals($pagesArray[0]->ID, $s1->ID, 'Page 1 associated correctly');
|
||||
$this->assertEquals($pagesArray[1]->ID, $s2->ID, 'Page 2 associated correctly');
|
||||
$this->assertEquals($pagesArray[2]->ID, $s3->ID, 'Page 3 associated correctly');
|
||||
|
||||
$doc->removePage($s1);
|
||||
$pages = $doc->Pages();
|
||||
$pagesArray = $pages->toArray(); // Page 1 is missing
|
||||
$this->assertEquals($pagesArray[0]->ID, $s2->ID, 'Page 2 still associated correctly');
|
||||
$this->assertEquals($pagesArray[1]->ID, $s3->ID, 'Page 3 still associated correctly');
|
||||
|
||||
$documents = $s2->Documents();
|
||||
$documentsArray = $documents->toArray();
|
||||
$this->assertDOSContains(
|
||||
array(
|
||||
array('Filename' => $doc->Filename)
|
||||
),
|
||||
$documentsArray,
|
||||
'Document associated with page'
|
||||
);
|
||||
|
||||
$doc->removeAllPages();
|
||||
$pages = $doc->Pages();
|
||||
$this->assertEquals($pages->Count(), 0, 'All pages removed');
|
||||
|
||||
$documents = $s2->Documents();
|
||||
$documentsArray = $documents->toArray();
|
||||
$this->assertNotContains($doc, $documentsArray, 'Document no longer associated with page');
|
||||
}
|
||||
|
||||
public function testDeletingPageWithAssociatedDocuments()
|
||||
{
|
||||
$s1 = $this->objFromFixture('SiteTree', 's1');
|
||||
$s2 = $this->objFromFixture('SiteTree', 's2');
|
||||
$s2->publish('Stage', 'Live');
|
||||
$s2ID = $s2->ID;
|
||||
|
||||
$doc = new DMSDocument();
|
||||
$doc->Filename = 'delete test file';
|
||||
$doc->Folder = '0';
|
||||
$doc->write();
|
||||
|
||||
$doc->addPage($s1);
|
||||
$doc->addPage($s2);
|
||||
|
||||
$s1->delete();
|
||||
|
||||
$documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'", false);
|
||||
$this->assertEquals(
|
||||
$documents->Count(),
|
||||
'1',
|
||||
"Deleting one of the associated page doesn't affect the single document we created"
|
||||
);
|
||||
|
||||
$s2->delete();
|
||||
$documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
|
||||
$this->assertEquals(
|
||||
$documents->Count(),
|
||||
'1',
|
||||
"Deleting a page from draft stage doesn't delete the associated docs,"
|
||||
. "even if it's the last page they're associated with"
|
||||
);
|
||||
|
||||
$s2 = Versioned::get_one_by_stage('SiteTree', 'Live', sprintf('"SiteTree"."ID" = %d', $s2ID));
|
||||
$s2->doDeleteFromLive();
|
||||
$documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
|
||||
$this->assertEquals(
|
||||
$documents->Count(),
|
||||
'0',
|
||||
'However, deleting the live version of the last page that a document is '
|
||||
. 'associated with causes that document to be deleted as well'
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnpublishPageWithAssociatedDocuments()
|
||||
{
|
||||
$s2 = $this->objFromFixture('SiteTree', 's2');
|
||||
$s2->publish('Stage', 'Live');
|
||||
$s2ID = $s2->ID;
|
||||
|
||||
$doc = new DMSDocument();
|
||||
$doc->Filename = 'delete test file';
|
||||
$doc->Folder = '0';
|
||||
$doc->write();
|
||||
|
||||
$doc->addPage($s2);
|
||||
|
||||
$s2->doDeleteFromLive();
|
||||
$documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
|
||||
$this->assertEquals(
|
||||
$documents->Count(),
|
||||
'1',
|
||||
"Deleting a page from live stage doesn't delete the associated docs,"
|
||||
. "even if it's the last page they're associated with"
|
||||
);
|
||||
|
||||
$s2 = Versioned::get_one_by_stage('SiteTree', 'Stage', sprintf('"SiteTree"."ID" = %d', $s2ID));
|
||||
$s2->delete();
|
||||
$documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
|
||||
$this->assertEquals(
|
||||
$documents->Count(),
|
||||
'0',
|
||||
'However, deleting the draft version of the last page that a document is '
|
||||
. 'associated with causes that document to be deleted as well'
|
||||
);
|
||||
}
|
||||
|
||||
public function testDefaultDownloadBehabiourCMSFields()
|
||||
{
|
||||
$document = singleton('DMSDocument');
|
||||
@ -364,4 +220,15 @@ class DMSDocumentTest extends SapphireTest
|
||||
$doc3 = $this->objFromFixture('DMSDocument', 'doc-anyone');
|
||||
$this->assertEquals('', $doc3->getPermissionDeniedReason());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that all pages that a document belongs to (via many document sets) can be retrieved in one list
|
||||
*/
|
||||
public function testGetRelatedPages()
|
||||
{
|
||||
$document = $this->objFromFixture('DMSDocument', 'd1');
|
||||
$result = $document->getRelatedPages();
|
||||
$this->assertCount(3, $result, 'Document 1 is related to 3 Pages');
|
||||
$this->assertSame(array('s1', 's2', 's3'), $result->column('URLSegment'));
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ class DMSEmbargoTest extends SapphireTest
|
||||
$doc->Folder = "0";
|
||||
$dID = $doc->write();
|
||||
|
||||
$doc->addPage($s1);
|
||||
$s1->getDocumentSets()->first()->getDocuments()->add($doc);
|
||||
|
||||
$s1->publish('Stage', 'Live');
|
||||
$s1->doPublish();
|
||||
|
@ -24,24 +24,24 @@ class DMSGridFieldAddNewButtonTest extends SapphireTest
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when no page ID is present then it is not added to the URL for "add document"
|
||||
* Test that when no document set ID is present then it is not added to the URL for "add document"
|
||||
*/
|
||||
public function testNoPageIdInAddUrlWhenNotProvided()
|
||||
{
|
||||
$fragments = $this->button->getHTMLFragments($this->gridField);
|
||||
$result = array_pop($fragments)->getValue();
|
||||
$this->assertNotContains('?ID', $result);
|
||||
$this->assertNotContains('?dsid', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when a page ID is provided, it is added onto the "add document" link
|
||||
* Test that when a document set ID is provided, it is added onto the "add document" link
|
||||
*/
|
||||
public function testPageIdAddedToLinkWhenProvided()
|
||||
{
|
||||
$this->button->setPageId(123);
|
||||
$this->button->setDocumentSetId(123);
|
||||
|
||||
$fragments = $this->button->getHTMLFragments($this->gridField);
|
||||
$result = array_pop($fragments)->getValue();
|
||||
$this->assertContains('?ID=123', $result);
|
||||
$this->assertContains('?dsid=123', $result);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
class DMSTest extends FunctionalTest
|
||||
{
|
||||
protected $usesDatabase = true;
|
||||
protected static $fixture_file = 'dmstest.yml';
|
||||
|
||||
/**
|
||||
* Stub PDF files for testing
|
||||
@ -16,6 +16,11 @@ class DMSTest extends FunctionalTest
|
||||
public static $dmsFolderOld;
|
||||
public static $dmsFolderSizeOld;
|
||||
|
||||
/**
|
||||
* @var DMS
|
||||
*/
|
||||
protected $dms;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
@ -28,6 +33,8 @@ class DMSTest extends FunctionalTest
|
||||
|
||||
//clear out the test folder (in case a broken test doesn't delete it)
|
||||
$this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-1234');
|
||||
|
||||
$this->dms = DMS::inst();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
@ -82,10 +89,8 @@ class DMSTest extends FunctionalTest
|
||||
|
||||
public function testDMSStorage()
|
||||
{
|
||||
$dms = DMS::inst();
|
||||
|
||||
$file = self::$testFile;
|
||||
$document = $dms->storeDocument($file);
|
||||
$document = $this->dms->storeDocument($file);
|
||||
|
||||
$this->assertNotNull($document, "Document object created");
|
||||
$this->assertTrue(
|
||||
@ -100,13 +105,11 @@ class DMSTest extends FunctionalTest
|
||||
public function testDMSFolderSpanning()
|
||||
{
|
||||
DMS::$dmsFolderSize = 5;
|
||||
$dms = DMS::inst();
|
||||
|
||||
$file = self::$testFile;
|
||||
|
||||
$documents = array();
|
||||
for ($i = 0; $i <= 16; $i++) {
|
||||
$document = $dms->storeDocument($file);
|
||||
$document = $this->dms->storeDocument($file);
|
||||
$this->assertNotNull($document, "Document object created on run number: $i");
|
||||
$this->assertTrue(file_exists($document->getFullPath()));
|
||||
$documents[] = $document;
|
||||
@ -131,10 +134,8 @@ class DMSTest extends FunctionalTest
|
||||
|
||||
public function testReplaceDocument()
|
||||
{
|
||||
$dms = DMS::inst();
|
||||
|
||||
// Store the first document
|
||||
$document = $dms->storeDocument(self::$testFile);
|
||||
$document = $this->dms->storeDocument(self::$testFile);
|
||||
$document->Title = "My custom title";
|
||||
$document->Description = "My custom description";
|
||||
$document->write();
|
||||
@ -158,4 +159,39 @@ class DMSTest extends FunctionalTest
|
||||
$this->assertEquals("My custom title", $document->Title, "Custom title not modified");
|
||||
$this->assertEquals("My custom description", $document->Description, "Custom description not modified");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that documents can be returned by a given page
|
||||
*/
|
||||
public function testGetByPageWithoutEmbargoes()
|
||||
{
|
||||
$pageWithEmbargoes = $this->objFromFixture('SiteTree', 's3');
|
||||
$documents = $this->dms->getByPage($pageWithEmbargoes);
|
||||
// Fixture: 3 documents in set, 1 is embargoed
|
||||
$this->assertCount(2, $documents, 'Embargoed documents are excluded by default');
|
||||
$this->assertContainsOnlyInstancesOf('DMSDocument', $documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that embargoed documents are excluded from getByPage
|
||||
*/
|
||||
public function testGetByPageWithEmbargoedDocuments()
|
||||
{
|
||||
$pageWithEmbargoes = $this->objFromFixture('SiteTree', 's3');
|
||||
$documents = $this->dms->getByPage($pageWithEmbargoes, true);
|
||||
// Fixture: 3 documents in set, 1 is embargoed
|
||||
$this->assertCount(3, $documents, 'Embargoed documents can be included');
|
||||
$this->assertContainsOnlyInstancesOf('DMSDocument', $documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that document sets can be retrieved for a given page
|
||||
*/
|
||||
public function testGetDocumentSetsByPage()
|
||||
{
|
||||
$page = $this->objFromFixture('SiteTree', 's1');
|
||||
$sets = $this->dms->getDocumentSetsByPage($page);
|
||||
$this->assertCount(2, $sets);
|
||||
$this->assertContainsOnlyInstancesOf('DMSDocumentSet', $sets);
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,38 @@
|
||||
class StubRelatedDocumentExtension extends DataExtension implements TestOnly
|
||||
{
|
||||
/**
|
||||
* Push a fixed array entry into the datalist for extensibility testing
|
||||
* For method {@link DMSDocument::getRelatedDocuments}
|
||||
*
|
||||
* @param ArrayList $relatedDocuments
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function updateRelatedDocuments(ArrayList $relatedDocuments)
|
||||
public function updateRelatedDocuments($relatedDocuments)
|
||||
{
|
||||
$relatedDocuments->push($this->getFakeDocument());
|
||||
return $relatedDocuments;
|
||||
}
|
||||
|
||||
/**
|
||||
* For method {@link DMSDocumentSet::getDocuments}
|
||||
*
|
||||
* @param ArrayList $relatedDocuments
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function updateDocuments($documents)
|
||||
{
|
||||
$documents->push($this->getFakeDocument());
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a dummy document for testing purposes
|
||||
*
|
||||
* @return DMSDocument
|
||||
*/
|
||||
protected function getFakeDocument()
|
||||
{
|
||||
$fakeDocument = new DMSDocument;
|
||||
$fakeDocument->Filename = 'Extended';
|
||||
$relatedDocuments->push($fakeDocument);
|
||||
return $relatedDocuments;
|
||||
return $fakeDocument;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
DMSDocumentSet:
|
||||
ds1:
|
||||
Title: Document Set 1
|
||||
SiteTree:
|
||||
s1:
|
||||
Title: testPage1
|
||||
URLSegment: s1
|
||||
DocumentSets: =>DMSDocumentSet.ds1
|
||||
s2:
|
||||
Title: testPage2
|
||||
URLSegment: s2
|
||||
|
@ -1,21 +1,21 @@
|
||||
SiteTree:
|
||||
s1:
|
||||
Title: testPage1
|
||||
Title: testPage1 has document sets
|
||||
URLSegment: s1
|
||||
s2:
|
||||
Title: testPage2
|
||||
Title: testPage2 has document sets
|
||||
URLSegment: s2
|
||||
s3:
|
||||
Title: testPage3
|
||||
Title: testPage3 has document sets with embargoed docs
|
||||
URLSegment: s3
|
||||
s4:
|
||||
Title: testPage4
|
||||
Title: testPage4 has no sets
|
||||
URLSegment: s4
|
||||
s5:
|
||||
Title: testPage5
|
||||
Title: testPage5 has no sets
|
||||
URLSegment: s5
|
||||
s6:
|
||||
Title: testPage6
|
||||
Title: testPage6 has no sets
|
||||
URLSegment: s6
|
||||
DMSTag:
|
||||
t1:
|
||||
@ -43,17 +43,30 @@ Group:
|
||||
cable-guy:
|
||||
Code: cable-guy
|
||||
Title: "Cable Guy"
|
||||
DMSDocumentSet:
|
||||
ds1:
|
||||
Title: Document Set 1
|
||||
Page: =>SiteTree.s1
|
||||
ds2:
|
||||
Title: Document Set 2
|
||||
Page: =>SiteTree.s1
|
||||
ds3:
|
||||
Title: Document Set 3
|
||||
Page: =>SiteTree.s2
|
||||
ds4:
|
||||
Title: Set containing embargoed documents
|
||||
Page: =>SiteTree.s3
|
||||
DMSDocument:
|
||||
d1:
|
||||
Filename: test-file-file-doesnt-exist-1
|
||||
Folder: 5
|
||||
Tags: =>DMSTag.t1, =>DMSTag.t2, =>DMSTag.t3, =>DMSTag.t4
|
||||
Pages: =>SiteTree.s1, =>SiteTree.s2, =>SiteTree.s3, =>SiteTree.s4, =>SiteTree.s5, =>SiteTree.s6
|
||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||
d2:
|
||||
Filename: test-file-file-doesnt-exist-2
|
||||
Folder: 5
|
||||
Tags: =>DMSTag.t5, =>DMSTag.t6
|
||||
Pages: =>SiteTree.s5, =>SiteTree.s6
|
||||
Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4
|
||||
document_with_relations:
|
||||
Filename: file-with-relations
|
||||
Folder: 5
|
||||
@ -80,6 +93,11 @@ DMSDocument:
|
||||
Pages: =>SiteTree.s1, =>SiteTree.s2, =>SiteTree.s3, =>SiteTree.s4, =>SiteTree.s5, =>SiteTree.s6
|
||||
ViewerGroups: =>Group.content-author
|
||||
EditorGroups: =>Group.content-author
|
||||
embargoed_document1:
|
||||
Filename: foobar
|
||||
EmbargoedIndefinitely: true
|
||||
Folder: 5
|
||||
Sets: =>DMSDocumentSet.ds4
|
||||
Member:
|
||||
editor:
|
||||
Name: editor
|
||||
|
Loading…
Reference in New Issue
Block a user