Converted to PSR-2

This commit is contained in:
helpfulrobot 2015-12-18 07:48:37 +13:00
parent 1aebe7e8d5
commit bd707c4ffc
23 changed files with 3335 additions and 3085 deletions

View File

@ -1,115 +1,130 @@
<?php <?php
class DMS implements DMSInterface { class DMS implements DMSInterface
{
static $dmsFolder = 'dms-assets'; //folder to store the documents in public static $dmsFolder = 'dms-assets'; //folder to store the documents in
//How many documents to store in a single folder. The square of this number is the maximum number of documents. //How many documents to store in a single folder. The square of this number is the maximum number of documents.
//The number should be a multiple of 10 //The number should be a multiple of 10
static $dmsFolderSize = 1000; public static $dmsFolderSize = 1000;
/** /**
* Factory method that returns an instance of the DMS. This could be any class that implements the DMSInterface. * Factory method that returns an instance of the DMS. This could be any class that implements the DMSInterface.
* @static * @static
* @return DMSInterface An instance of the Document Management System * @return DMSInterface An instance of the Document Management System
*/ */
static function inst() { public static function inst()
$dmsPath = self::get_dms_path(); {
$dmsPath = self::get_dms_path();
$dms = new DMS(); $dms = new DMS();
if (!is_dir($dmsPath)) { if (!is_dir($dmsPath)) {
self::create_storage_folder($dmsPath); self::create_storage_folder($dmsPath);
} }
if (!file_exists($dmsPath . DIRECTORY_SEPARATOR . '.htaccess')) { if (!file_exists($dmsPath . DIRECTORY_SEPARATOR . '.htaccess')) {
//restrict access to the storage folder //restrict access to the storage folder
copy(BASE_PATH . DIRECTORY_SEPARATOR . DMS_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . '.htaccess', $dmsPath . DIRECTORY_SEPARATOR . '.htaccess'); copy(BASE_PATH . DIRECTORY_SEPARATOR . DMS_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . '.htaccess', $dmsPath . DIRECTORY_SEPARATOR . '.htaccess');
copy(BASE_PATH . DIRECTORY_SEPARATOR . DMS_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'web.config', $dmsPath . DIRECTORY_SEPARATOR . 'web.config'); copy(BASE_PATH . DIRECTORY_SEPARATOR . DMS_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'web.config', $dmsPath . DIRECTORY_SEPARATOR . 'web.config');
} }
return $dms; return $dms;
} }
static function get_dms_path() { public static function get_dms_path()
return BASE_PATH . DIRECTORY_SEPARATOR . self::$dmsFolder; {
} return BASE_PATH . DIRECTORY_SEPARATOR . self::$dmsFolder;
}
static function transform_file_to_file_path($file) { public static function transform_file_to_file_path($file)
//confirm we have a file {
$filePath = null; //confirm we have a file
if (is_string($file)) $filePath = $file; $filePath = null;
elseif (is_object($file) && $file->is_a("File")) $filePath = $file->Filename; if (is_string($file)) {
$filePath = $file;
} elseif (is_object($file) && $file->is_a("File")) {
$filePath = $file->Filename;
}
if (!$filePath) throw new FileNotFoundException(); if (!$filePath) {
throw new FileNotFoundException();
}
return $filePath; return $filePath;
} }
/** /**
* Takes a File object or a String (path to a file) and copies it into the DMS. The original file remains unchanged. * Takes a File object or a String (path to a file) and copies it into the DMS. The original file remains unchanged.
* When storing a document, sets the fields on the File has "tag" metadata. * When storing a document, sets the fields on the File has "tag" metadata.
* @param $file File object, or String that is path to a file to store, e.g. "assets/documents/industry/supplied-v1-0.pdf" * @param $file File object, or String that is path to a file to store, e.g. "assets/documents/industry/supplied-v1-0.pdf"
*/ */
function storeDocument($file) { public function storeDocument($file)
$filePath = self::transform_file_to_file_path($file); {
$filePath = self::transform_file_to_file_path($file);
//create a new document and get its ID
$doc = new DMSDocument(); //create a new document and get its ID
$doc->write(); $doc = new DMSDocument();
$doc->storeDocument($filePath); $doc->write();
$doc->storeDocument($filePath);
return $doc; return $doc;
} }
/** /**
* *
* Returns a number of Document objects based on the a search by tags. You can search by category alone, * Returns a number of Document objects based on the a search by tags. You can search by category alone,
* by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana") * by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana")
* @param null $category The metadata category to search for * @param null $category The metadata category to search for
* @param null $value The metadata value 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 * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
* @return DocumentInterface * @return DocumentInterface
*/ */
function getByTag($category = null, $value = null, $showEmbargoed = false) { public function getByTag($category = null, $value = null, $showEmbargoed = false)
// TODO: Implement getByTag() method. {
} // 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)
* @param $searchText String to search for * @param $searchText String to search for
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
* @return DocumentInterface * @return DocumentInterface
*/ */
function getByFullTextSearch($searchText, $showEmbargoed = false) { public function getByFullTextSearch($searchText, $showEmbargoed = false)
// TODO: Implement getByFullTextSearch() method. {
} // TODO: Implement getByFullTextSearch() method.
}
/** /**
* Returns a list of Document objects associated with a Page * Returns a list of Document objects associated with a Page
* @param $page SiteTree to fetch the associated Documents from * @param $page SiteTree to fetch the associated Documents from
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
* @return DataList Document list associated with the Page * @return DataList Document list associated with the Page
*/ */
function getByPage($page, $showEmbargoed = false) { public function getByPage($page, $showEmbargoed = false)
// TODO: Implement getByPage() method. {
} // TODO: Implement getByPage() method.
}
/** /**
* Creates a storage folder for the given path * Creates a storage folder for the given path
* @param $path Path to create a folder for * @param $path Path to create a folder for
*/ */
static function create_storage_folder($path) { public static function create_storage_folder($path)
if (!is_dir($path)) { {
mkdir($path, 0777); if (!is_dir($path)) {
} mkdir($path, 0777);
} }
}
/** /**
* Calculates the storage path from a database DMSDocument ID * Calculates the storage path from a database DMSDocument ID
*/ */
static function get_storage_folder($id) { public static function get_storage_folder($id)
$folderName = intval($id / self::$dmsFolderSize); {
return $folderName; $folderName = intval($id / self::$dmsFolderSize);
} return $folderName;
} }
}

View File

@ -6,37 +6,37 @@
* *
* @package dms * @package dms
*/ */
class DMSShortcodeHandler { class DMSShortcodeHandler
{
public static function handle( public static function handle(
$arguments, $content, ShortcodeParser $parser, $tag, array $extra = array() $arguments, $content, ShortcodeParser $parser, $tag, array $extra = array()
) { ) {
if(!empty($arguments['id'])) { if (!empty($arguments['id'])) {
$document = DMSDocument::get()->byID($arguments['id']); $document = DMSDocument::get()->byID($arguments['id']);
if($document && !$document->isHidden()) { if ($document && !$document->isHidden()) {
if($content) { if ($content) {
return sprintf( return sprintf(
'<a href="%s">%s</a>', $document->Link(), $parser->parse($content) '<a href="%s">%s</a>', $document->Link(), $parser->parse($content)
); );
} else { } else {
if(isset($extra['element'])) { if (isset($extra['element'])) {
$extra['element']->setAttribute('data-ext', $document->getExtension()); $extra['element']->setAttribute('data-ext', $document->getExtension());
$extra['element']->setAttribute('data-size', $document->getFileSizeFormatted()); $extra['element']->setAttribute('data-size', $document->getFileSizeFormatted());
} }
return $document->Link(); return $document->Link();
} }
} }
} }
$error = ErrorPage::get()->filter('ErrorCode', '404')->First(); $error = ErrorPage::get()->filter('ErrorCode', '404')->First();
if($error) { if ($error) {
return $error->Link(); return $error->Link();
} }
return '';
}
return '';
}
} }

View File

@ -4,239 +4,254 @@
* @package dms * @package dms
*/ */
class DMSDocumentAddController extends LeftAndMain { class DMSDocumentAddController extends LeftAndMain
{
private static $url_segment = 'pages/adddocument'; private static $url_segment = 'pages/adddocument';
private static $url_priority = 60; private static $url_priority = 60;
private static $required_permission_codes = 'CMS_ACCESS_AssetAdmin'; private static $required_permission_codes = 'CMS_ACCESS_AssetAdmin';
private static $menu_title = 'Edit Page'; private static $menu_title = 'Edit Page';
private static $tree_class = 'SiteTree'; private static $tree_class = 'SiteTree';
private static $session_namespace = 'CMSMain'; private static $session_namespace = 'CMSMain';
static $allowed_extensions = array(); public static $allowed_extensions = array();
private static $allowed_actions = array ( private static $allowed_actions = array(
'getEditForm', 'getEditForm',
'documentautocomplete', 'documentautocomplete',
'linkdocument', 'linkdocument',
'documentlist' 'documentlist'
); );
/** /**
* Add an array of additional allowed extensions * Add an array of additional allowed extensions
* @static * @static
* @param $array * @param $array
*/ */
static function add_allowed_extensions($array = null) { public static function add_allowed_extensions($array = null)
if (empty($array)) return; {
if (is_array($array)) self::$allowed_extensions = $array; if (empty($array)) {
else self::$allowed_extensions = array($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 * Custom currentPage() method to handle opening the 'root' folder
* *
* @return * @return
*/ */
public function currentPage() { public function currentPage()
$id = $this->currentPageID(); {
$id = $this->currentPageID();
if($id && is_numeric($id) && $id > 0) { if ($id && is_numeric($id) && $id > 0) {
return Versioned::get_by_stage('SiteTree', 'Stage', sprintf( return Versioned::get_by_stage('SiteTree', 'Stage', sprintf(
'ID = %s', (int) $id 'ID = %s', (int) $id
))->first(); ))->first();
} else { } else {
// ID is either '0' or 'root' // ID is either '0' or 'root'
return singleton('SiteTree'); return singleton('SiteTree');
} }
} }
/** /**
* Return fake-ID "root" if no ID is found (needed to upload files into the root-folder) * Return fake-ID "root" if no ID is found (needed to upload files into the root-folder)
*/ */
public function currentPageID() { public function currentPageID()
return ($result = parent::currentPageID()) === null ? 0 : $result; {
} return ($result = parent::currentPageID()) === null ? 0 : $result;
}
/** /**
* @return Form * @return Form
* @todo what template is used here? AssetAdmin_UploadContent.ss doesn't seem to be used anymore * @todo what template is used here? AssetAdmin_UploadContent.ss doesn't seem to be used anymore
*/ */
public function getEditForm($id = null, $fields = null) { public function getEditForm($id = null, $fields = null)
Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js'); {
Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css'); Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js');
Requirements::css(DMS_DIR.'/css/DMSMainCMS.css'); Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css');
Requirements::css(DMS_DIR.'/css/DMSMainCMS.css');
$page = $this->currentPage(); $page = $this->currentPage();
$uploadField = DMSUploadField::create('AssetUploadField', ''); $uploadField = DMSUploadField::create('AssetUploadField', '');
$uploadField->setConfig('previewMaxWidth', 40); $uploadField->setConfig('previewMaxWidth', 40);
$uploadField->setConfig('previewMaxHeight', 30); $uploadField->setConfig('previewMaxHeight', 30);
// Required to avoid Solr reindexing (often used alongside DMS) to // Required to avoid Solr reindexing (often used alongside DMS) to
// return 503s because of too many concurrent reindex requests // return 503s because of too many concurrent reindex requests
$uploadField->setConfig('sequentialUploads', 1); $uploadField->setConfig('sequentialUploads', 1);
$uploadField->addExtraClass('ss-assetuploadfield'); $uploadField->addExtraClass('ss-assetuploadfield');
$uploadField->removeExtraClass('ss-uploadfield'); $uploadField->removeExtraClass('ss-uploadfield');
$uploadField->setTemplate('AssetUploadField'); $uploadField->setTemplate('AssetUploadField');
$uploadField->setRecord($page); $uploadField->setRecord($page);
$uploadField->getValidator()->setAllowedExtensions(array_filter(array_merge(Config::inst()->get('File', 'allowed_extensions'),self::$allowed_extensions))); $uploadField->getValidator()->setAllowedExtensions(array_filter(array_merge(Config::inst()->get('File', 'allowed_extensions'), self::$allowed_extensions)));
$exts = $uploadField->getValidator()->getAllowedExtensions(); $exts = $uploadField->getValidator()->getAllowedExtensions();
asort($exts); asort($exts);
$backlink = $this->Backlink(); $backlink = $this->Backlink();
$done = " $done = "
<a class=\"ss-ui-button ss-ui-action-constructive cms-panel-link ui-corner-all\" href=\"".$backlink."\"> <a class=\"ss-ui-button ss-ui-action-constructive cms-panel-link ui-corner-all\" href=\"".$backlink."\">
Done! Done!
</a>"; </a>";
$addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing'); $addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing');
$addExistingField->setRecord($page); $addExistingField->setRecord($page);
$form = new Form( $form = new Form(
$this, $this,
'getEditForm', 'getEditForm',
new FieldList( new FieldList(
new TabSet('Main', new TabSet('Main',
new Tab('From your computer', new Tab('From your computer',
new HiddenField('ID', false, $page->ID), new HiddenField('ID', false, $page->ID),
$uploadField, $uploadField,
new LiteralField( new LiteralField(
'AllowedExtensions', 'AllowedExtensions',
sprintf( sprintf(
'<p>%s: %s</p>', '<p>%s: %s</p>',
_t('AssetAdmin.ALLOWEDEXTS', 'Allowed extensions'), _t('AssetAdmin.ALLOWEDEXTS', 'Allowed extensions'),
implode('<em>, </em>', $exts) implode('<em>, </em>', $exts)
) )
) )
), ),
new Tab('From the CMS', new Tab('From the CMS',
$addExistingField $addExistingField
) )
) )
), ),
new FieldList( new FieldList(
new LiteralField('doneButton', $done) new LiteralField('doneButton', $done)
) )
); );
$form->addExtraClass('center cms-edit-form ' . $this->BaseCSSClasses()); $form->addExtraClass('center cms-edit-form ' . $this->BaseCSSClasses());
$form->Backlink = $backlink; $form->Backlink = $backlink;
// Don't use AssetAdmin_EditForm, as it assumes a different panel structure // Don't use AssetAdmin_EditForm, as it assumes a different panel structure
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); $form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
/*$form->Fields()->push( /*$form->Fields()->push(
new LiteralField( new LiteralField(
'BackLink', 'BackLink',
sprintf( sprintf(
'<a href="%s" class="backlink ss-ui-button cms-panel-link" data-icon="back">%s</a>', '<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), Controller::join_links(singleton('AssetAdmin')->Link('show'), $folder ? $folder->ID : 0),
_t('AssetAdmin.BackToFolder', 'Back to folder') _t('AssetAdmin.BackToFolder', 'Back to folder')
) )
) )
);*/ );*/
//$form->loadDataFrom($folder); //$form->loadDataFrom($folder);
return $form; return $form;
} }
/** /**
* @return ArrayList * @return ArrayList
*/ */
public function Breadcrumbs($unlinked = false) { public function Breadcrumbs($unlinked = false)
$items = parent::Breadcrumbs($unlinked); {
$items = parent::Breadcrumbs($unlinked);
// The root element should explicitly point to the root node. // The root element should explicitly point to the root node.
$items[0]->Link = Controller::join_links(singleton('CMSPageEditController')->Link('show'), 0); $items[0]->Link = Controller::join_links(singleton('CMSPageEditController')->Link('show'), 0);
// Enforce linkage of hierarchy to AssetAdmin // Enforce linkage of hierarchy to AssetAdmin
foreach($items as $item) { foreach ($items as $item) {
$baselink = $this->Link('show'); $baselink = $this->Link('show');
if(strpos($item->Link, $baselink) !== false) { if (strpos($item->Link, $baselink) !== false) {
$item->Link = str_replace($baselink, singleton('CMSPageEditController')->Link('show'), $item->Link); $item->Link = str_replace($baselink, singleton('CMSPageEditController')->Link('show'), $item->Link);
} }
} }
$items->push(new ArrayData(array( $items->push(new ArrayData(array(
'Title' => 'Add Document', 'Title' => 'Add Document',
'Link' => $this->Link() 'Link' => $this->Link()
))); )));
return $items; return $items;
} }
public function Backlink(){ public function Backlink()
$pageID = $this->currentPageID(); {
return singleton('CMSPagesController')->Link().'edit/show/'.$pageID; $pageID = $this->currentPageID();
} return singleton('CMSPagesController')->Link().'edit/show/'.$pageID;
}
public function documentautocomplete() { public function documentautocomplete()
$term = (isset($_GET['term'])) ? $_GET['term'] : ''; {
$term_sql = Convert::raw2sql($term); $term = (isset($_GET['term'])) ? $_GET['term'] : '';
$data = DMSDocument::get() $term_sql = Convert::raw2sql($term);
->where("(\"ID\" LIKE '%".$term_sql."%' OR \"Filename\" LIKE '%".$term_sql."%' OR \"Title\" LIKE '%".$term_sql."%')") $data = DMSDocument::get()
->sort('ID ASC') ->where("(\"ID\" LIKE '%".$term_sql."%' OR \"Filename\" LIKE '%".$term_sql."%' OR \"Title\" LIKE '%".$term_sql."%')")
->limit(20); ->sort('ID ASC')
->limit(20);
$return = array(); $return = array();
foreach($data as $doc) { foreach ($data as $doc) {
$return[] = array( $return[] = array(
'label' => $doc->ID . ' - ' . $doc->Title, 'label' => $doc->ID . ' - ' . $doc->Title,
'value' => $doc->ID 'value' => $doc->ID
); );
} }
return json_encode($return); return json_encode($return);
} }
public function linkdocument() { public function linkdocument()
$return = array('error' => _t('UploadField.FIELDNOTSET', 'Could not add document to page')); {
$return = array('error' => _t('UploadField.FIELDNOTSET', 'Could not add document to page'));
$page = $this->currentPage(); $page = $this->currentPage();
if (!empty($page)) { if (!empty($page)) {
$document = DataObject::get_by_id('DMSDocument', (int) $_GET['documentID']); $document = DataObject::get_by_id('DMSDocument', (int) $_GET['documentID']);
$document->addPage($page); $document->addPage($page);
$buttonText = '<button class="ss-uploadfield-item-edit ss-ui-button ui-corner-all" title="Edit this document" data-icon="pencil">'. $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>'; 'Edit<span class="toggle-details"><span class="toggle-details-icon"></span></span></button>';
// Collect all output data. // Collect all output data.
$return = array( $return = array(
'id' => $document->ID, 'id' => $document->ID,
'name' => $document->getTitle(), 'name' => $document->getTitle(),
'thumbnail_url' => $document->Icon($document->getExtension()), 'thumbnail_url' => $document->Icon($document->getExtension()),
'edit_url' => $this->getEditForm()->Fields()->fieldByName('Main.From your computer.AssetUploadField')->getItemHandler($document->ID)->EditLink(), 'edit_url' => $this->getEditForm()->Fields()->fieldByName('Main.From your computer.AssetUploadField')->getItemHandler($document->ID)->EditLink(),
'size' => $document->getFileSizeFormatted(), 'size' => $document->getFileSizeFormatted(),
'buttons' => $buttonText, 'buttons' => $buttonText,
'showeditform' => true 'showeditform' => true
); );
} }
return json_encode($return); return json_encode($return);
} }
public function documentlist() { public function documentlist()
if(!isset($_GET['pageID'])) { {
return $this->httpError(400); if (!isset($_GET['pageID'])) {
} return $this->httpError(400);
}
$page = SiteTree::get()->byId($_GET['pageID']); $page = SiteTree::get()->byId($_GET['pageID']);
if($page && $page->Documents()->count() > 0) { if ($page && $page->Documents()->count() > 0) {
$list = '<ul>'; $list = '<ul>';
foreach($page->Documents() as $document) { foreach ($page->Documents() as $document) {
$list .= sprintf( $list .= sprintf(
'<li><a class="add-document" data-document-id="%s">%s</a></li>', '<li><a class="add-document" data-document-id="%s">%s</a></li>',
$document->ID, $document->ID,
$document->ID . ' - '. Convert::raw2xml($document->Title) $document->ID . ' - '. Convert::raw2xml($document->Title)
); );
} }
$list .= '</ul>'; $list .= '</ul>';
return $list; return $list;
} }
return sprintf('<p>%s</p>', return sprintf('<p>%s</p>',
_t('DMSDocumentAddController.NODOCUMENTS', 'There are no documents attached to the selected page.') _t('DMSDocumentAddController.NODOCUMENTS', 'There are no documents attached to the selected page.')
); );
} }
} }

View File

@ -1,56 +1,63 @@
<?php <?php
class DMSDocumentAddExistingField extends CompositeField { class DMSDocumentAddExistingField extends CompositeField
{
public $useFieldContext = true; public $useFieldContext = true;
function __construct($name, $title = null) { public function __construct($name, $title = null)
$this->name = $name; {
$this->title = ($title === null) ? $name : $title; $this->name = $name;
$this->title = ($title === null) ? $name : $title;
parent::__construct(new TreeDropdownField('PageSelector', 'Add from another page', 'SiteTree', 'ID', 'TitleWithNumberOfDocuments')); parent::__construct(new TreeDropdownField('PageSelector', 'Add from another page', 'SiteTree', 'ID', 'TitleWithNumberOfDocuments'));
} }
/** /**
* Force a record to be used as "Parent" for uploaded Files (eg a Page with a has_one to File) * Force a record to be used as "Parent" for uploaded Files (eg a Page with a has_one to File)
* @param DataObject $record * @param DataObject $record
*/ */
public function setRecord($record) { public function setRecord($record)
$this->record = $record; {
return $this; $this->record = $record;
} return $this;
/** }
* Get the record to use as "Parent" for uploaded Files (eg a Page with a has_one to File) If none is set, it will use Form->getRecord() or Form->Controller()->data() /**
* @return DataObject * Get the record to use as "Parent" for uploaded Files (eg a Page with a has_one to File) If none is set, it will use Form->getRecord() or Form->Controller()->data()
*/ * @return DataObject
public function getRecord() { */
if (!$this->record && $this->form) { public function getRecord()
if ($this->form->getRecord() && is_a($this->form->getRecord(), 'DataObject')) { {
$this->record = $this->form->getRecord(); if (!$this->record && $this->form) {
} elseif ($this->form->Controller() && $this->form->Controller()->hasMethod('data') if ($this->form->getRecord() && is_a($this->form->getRecord(), 'DataObject')) {
&& $this->form->Controller()->data() && is_a($this->form->Controller()->data(), 'DataObject')) { $this->record = $this->form->getRecord();
$this->record = $this->form->Controller()->data(); } elseif ($this->form->Controller() && $this->form->Controller()->hasMethod('data')
} && $this->form->Controller()->data() && is_a($this->form->Controller()->data(), 'DataObject')) {
} $this->record = $this->form->Controller()->data();
return $this->record; }
} }
return $this->record;
}
public function FieldHolder($properties = array()) { public function FieldHolder($properties = array())
return $this->Field($properties); {
} return $this->Field($properties);
}
public function Field($properties = array()) { public function Field($properties = array())
Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentAddExistingField.js'); {
Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js"); Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentAddExistingField.js');
Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js");
return $this->renderWith('DMSDocumentAddExistingField'); return $this->renderWith('DMSDocumentAddExistingField');
} }
/** /**
* Sets or unsets the use of the "field" class in the template. The "field" class adds Javascript behaviour * Sets or unsets the use of the "field" class in the template. The "field" class adds Javascript behaviour
* that causes unwelcome hiding side-effects when this Field is used within the link editor pop-up * that causes unwelcome hiding side-effects when this Field is used within the link editor pop-up
*/ */
public function setUseFieldClass($use = false) { public function setUseFieldClass($use = false)
$this->useFieldContext = $use; {
} $this->useFieldContext = $use;
}
} }

View File

@ -13,74 +13,84 @@
* @package dms * @package dms
* @subpackage cms * @subpackage cms
*/ */
class DMSGridFieldDeleteAction extends GridFieldDeleteAction implements GridField_ColumnProvider, GridField_ActionProvider { class DMSGridFieldDeleteAction extends GridFieldDeleteAction implements GridField_ColumnProvider, GridField_ActionProvider
{
/** /**
* *
* @param GridField $gridField * @param GridField $gridField
* @param DataObject $record * @param DataObject $record
* @param string $columnName * @param string $columnName
* @return string - the HTML for the column * @return string - the HTML for the column
*/ */
public function getColumnContent($gridField, $record, $columnName) { public function getColumnContent($gridField, $record, $columnName)
if($this->removeRelation) { {
$field = GridField_FormAction::create($gridField, 'UnlinkRelation'.$record->ID, false, "unlinkrelation", array('RecordID' => $record->ID)) if ($this->removeRelation) {
->addExtraClass('gridfield-button-unlink') $field = GridField_FormAction::create($gridField, 'UnlinkRelation'.$record->ID, false, "unlinkrelation", array('RecordID' => $record->ID))
->setAttribute('title', _t('GridAction.UnlinkRelation', "Unlink")) ->addExtraClass('gridfield-button-unlink')
->setAttribute('data-icon', 'chain--minus'); ->setAttribute('title', _t('GridAction.UnlinkRelation', "Unlink"))
} else { ->setAttribute('data-icon', 'chain--minus');
if(!$record->canDelete()) { } else {
return; if (!$record->canDelete()) {
} return;
$field = GridField_FormAction::create($gridField, 'DeleteRecord'.$record->ID, false, "deleterecord", array('RecordID' => $record->ID)) }
->addExtraClass('gridfield-button-delete') $field = GridField_FormAction::create($gridField, 'DeleteRecord'.$record->ID, false, "deleterecord", array('RecordID' => $record->ID))
->setAttribute('title', _t('GridAction.Delete', "Delete")) ->addExtraClass('gridfield-button-delete')
->setAttribute('data-icon', 'cross-circle') ->setAttribute('title', _t('GridAction.Delete', "Delete"))
->setDescription(_t('GridAction.DELETE_DESCRIPTION','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 //add a class to the field to if it is the last gridfield in the list
$numberOfRelations = $record->Pages()->Count(); $numberOfRelations = $record->Pages()->Count();
$field->addExtraClass('dms-delete') //add a new class for custom JS to handle the delete action $field->addExtraClass('dms-delete') //add a new class for custom JS to handle the delete action
->setAttribute('data-pages-count', $numberOfRelations) //add the number of pages attached to this field as a data-attribute ->setAttribute('data-pages-count', $numberOfRelations) //add the number of pages attached to this field as a data-attribute
->removeExtraClass('gridfield-button-delete'); //remove the base gridfield behaviour ->removeExtraClass('gridfield-button-delete'); //remove the base gridfield behaviour
//set a class telling JS what kind of warning to display when clicking the delete button //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'); if ($numberOfRelations > 1) {
else $field->addExtraClass('dms-delete-last-warning'); $field->addExtraClass('dms-delete-link-only');
} else {
$field->addExtraClass('dms-delete-last-warning');
}
//set a class to show if the document is hidden //set a class to show if the document is hidden
if ($record->isHidden()) { if ($record->isHidden()) {
$field->addExtraClass('dms-document-hidden'); $field->addExtraClass('dms-document-hidden');
} }
return $field->Field(); return $field->Field();
} }
/** /**
* Handle the actions and apply any changes to the GridField * Handle the actions and apply any changes to the GridField
* *
* @param GridField $gridField * @param GridField $gridField
* @param string $actionName * @param string $actionName
* @param mixed $arguments * @param mixed $arguments
* @param array $data - form data * @param array $data - form data
* @return void * @return void
*/ */
public function handleAction(GridField $gridField, $actionName, $arguments, $data) { public function handleAction(GridField $gridField, $actionName, $arguments, $data)
if($actionName == 'deleterecord' || $actionName == 'unlinkrelation') { {
$item = $gridField->getList()->byID($arguments['RecordID']); if ($actionName == 'deleterecord' || $actionName == 'unlinkrelation') {
if(!$item) { $item = $gridField->getList()->byID($arguments['RecordID']);
return; if (!$item) {
} return;
if($actionName == 'deleterecord' && !$item->canDelete()) { }
throw new ValidationException(_t('GridFieldAction_Delete.DeletePermissionsFailure',"No delete permissions"),0); if ($actionName == 'deleterecord' && !$item->canDelete()) {
} throw new ValidationException(_t('GridFieldAction_Delete.DeletePermissionsFailure', "No delete permissions"), 0);
}
$delete = false; $delete = false;
if ($item->Pages()->Count() <= 1) $delete = true; if ($item->Pages()->Count() <= 1) {
$delete = true;
}
$gridField->getList()->remove($item); //remove the relation $gridField->getList()->remove($item); //remove the relation
if ($delete) $item->delete(); //delete the DMSDocument if ($delete) {
} $item->delete();
} } //delete the DMSDocument
}
}
} }

View File

@ -3,23 +3,24 @@
/** /**
* Custom ItemRequest class the provides custom delete behaviour for the CMSFields of DMSDocument * Custom ItemRequest class the provides custom delete behaviour for the CMSFields of DMSDocument
*/ */
class DMSGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest { class DMSGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest
private static $allowed_actions = array('ItemEditForm'); {
private static $allowed_actions = array('ItemEditForm');
function ItemEditForm() { public function ItemEditForm()
$form = parent::ItemEditForm(); {
$form = parent::ItemEditForm();
//add a data attribute specifying how many pages this document is referenced on //add a data attribute specifying how many pages this document is referenced on
if ($record = $this->record) { if ($record = $this->record) {
$numberOfPageRelations = $record->Pages()->Count(); $numberOfPageRelations = $record->Pages()->Count();
$relations = new ShortCodeRelationFinder(); $relations = new ShortCodeRelationFinder();
$numberOfInlineRelations = $relations->findPageCount($record->ID); $numberOfInlineRelations = $relations->findPageCount($record->ID);
//add the number of pages attached to this field as a data-attribute
$form->setAttribute('data-pages-count', $numberOfPageRelations);
$form->setAttribute('data-relation-count', $numberOfInlineRelations);
}
return $form;
}
//add the number of pages attached to this field as a data-attribute
$form->setAttribute('data-pages-count', $numberOfPageRelations);
$form->setAttribute('data-relation-count', $numberOfInlineRelations);
}
return $form;
}
} }

View File

@ -12,195 +12,214 @@
* @author Julian Seidenberg * @author Julian Seidenberg
* @package dms * @package dms
*/ */
class DMSUploadField extends UploadField { class DMSUploadField extends UploadField
private static $allowed_actions = array ( {
private static $allowed_actions = array(
"upload", "upload",
); );
protected $folderName = 'DMSTemporaryUploads'; protected $folderName = 'DMSTemporaryUploads';
public function __construct($name, $title = null, SS_List $items = null) { public function __construct($name, $title = null, SS_List $items = null)
parent::__construct($name, $title, $items); {
parent::__construct($name, $title, $items);
//set default DMS replace template to false //set default DMS replace template to false
$this->setConfig('useDMSReplaceTemplate', 0); $this->setConfig('useDMSReplaceTemplate', 0);
} }
/** /**
* Override the default behaviour of the UploadField and take the uploaded file (uploaded to assets) and * 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. * add it into the DMS storage, deleting the old/uploaded file.
* @param File * @param File
*/ */
protected function attachFile($file) { protected function attachFile($file)
$dms = DMS::inst(); {
$record = $this->getRecord(); $dms = DMS::inst();
$record = $this->getRecord();
if($record instanceof DMSDocument) { if ($record instanceof DMSDocument) {
// If the edited record is a document, // If the edited record is a document,
// assume we're replacing an existing file // assume we're replacing an existing file
$doc = $record; $doc = $record;
$doc->ingestFile($file); $doc->ingestFile($file);
} else { } else {
// Otherwise create it // Otherwise create it
$doc = $dms->storeDocument($file); $doc = $dms->storeDocument($file);
$file->delete(); $file->delete();
// Relate to the underlying page being edited. // Relate to the underlying page being edited.
// Not applicable when editing the document itself and replacing it. // Not applicable when editing the document itself and replacing it.
$doc->addPage($record); $doc->addPage($record);
} }
return $doc; return $doc;
} }
public function validate($validator) { public function validate($validator)
return true; {
} return true;
}
public function isDisabled() { public function isDisabled()
return (parent::isDisabled() || !$this->isSaveable()); {
} return (parent::isDisabled() || !$this->isSaveable());
}
public function isSaveable() { public function isSaveable()
return (!empty($this->getRecord()->ID)); {
} return (!empty($this->getRecord()->ID));
}
/** /**
* Action to handle upload of a single file * Action to handle upload of a single file
* *
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
* @return string json * @return string json
*/ */
public function upload(SS_HTTPRequest $request) { public function upload(SS_HTTPRequest $request)
if($this->isDisabled() || $this->isReadonly()) return $this->httpError(403); {
if ($this->isDisabled() || $this->isReadonly()) {
return $this->httpError(403);
}
// Protect against CSRF on destructive action // Protect against CSRF on destructive action
$token = $this->getForm()->getSecurityToken(); $token = $this->getForm()->getSecurityToken();
if(!$token->checkRequest($request)) return $this->httpError(400); if (!$token->checkRequest($request)) {
return $this->httpError(400);
}
$name = $this->getName(); $name = $this->getName();
$tmpfile = $request->postVar($name); $tmpfile = $request->postVar($name);
$record = $this->getRecord(); $record = $this->getRecord();
// Check if the file has been uploaded into the temporary storage. // Check if the file has been uploaded into the temporary storage.
if (!$tmpfile) { if (!$tmpfile) {
$return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found')); $return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found'));
} else { } else {
$return = array( $return = array(
'name' => $tmpfile['name'], 'name' => $tmpfile['name'],
'size' => $tmpfile['size'], 'size' => $tmpfile['size'],
'type' => $tmpfile['type'], 'type' => $tmpfile['type'],
'error' => $tmpfile['error'] 'error' => $tmpfile['error']
); );
} }
// Check for constraints on the record to which the file will be attached. // Check for constraints on the record to which the file will be attached.
if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) { if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) {
$tooManyFiles = false; $tooManyFiles = false;
// Some relationships allow many files to be attached. // 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->has_many($name) || $record->many_many($name))) {
if(!$record->isInDB()) $record->write(); if (!$record->isInDB()) {
$tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber'); $record->write();
// has_one only allows one file at any given time. }
} elseif($record->has_one($name)) { $tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber');
$tooManyFiles = $record->{$name}() && $record->{$name}()->exists(); // has_one only allows one file at any given time.
} } elseif ($record->has_one($name)) {
$tooManyFiles = $record->{$name}() && $record->{$name}()->exists();
}
// Report the constraint violation. // Report the constraint violation.
if ($tooManyFiles) { if ($tooManyFiles) {
if(!$this->getConfig('allowedMaxFileNumber')) $this->setConfig('allowedMaxFileNumber', 1); if (!$this->getConfig('allowedMaxFileNumber')) {
$return['error'] = _t( $this->setConfig('allowedMaxFileNumber', 1);
'UploadField.MAXNUMBEROFFILES', }
'Max number of {count} file(s) exceeded.', $return['error'] = _t(
array('count' => $this->getConfig('allowedMaxFileNumber')) 'UploadField.MAXNUMBEROFFILES',
); 'Max number of {count} file(s) exceeded.',
} array('count' => $this->getConfig('allowedMaxFileNumber'))
} );
}
}
// Process the uploaded file // Process the uploaded file
if (!$return['error']) { if (!$return['error']) {
$fileObject = null; $fileObject = null;
if ($this->relationAutoSetting) { if ($this->relationAutoSetting) {
// Search for relations that can hold the uploaded files. // Search for relations that can hold the uploaded files.
if ($relationClass = $this->getRelationAutosetClass()) { if ($relationClass = $this->getRelationAutosetClass()) {
// Create new object explicitly. Otherwise rely on Upload::load to choose the class. // Create new object explicitly. Otherwise rely on Upload::load to choose the class.
$fileObject = Object::create($relationClass); $fileObject = Object::create($relationClass);
} }
} }
// Get the uploaded file into a new file object. // Get the uploaded file into a new file object.
try { try {
$this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName); $this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName);
} catch (Exception $e) { } catch (Exception $e) {
// we shouldn't get an error here, but just in case // we shouldn't get an error here, but just in case
$return['error'] = $e->getMessage(); $return['error'] = $e->getMessage();
} }
if (!$return['error']) { if (!$return['error']) {
if ($this->upload->isError()) { if ($this->upload->isError()) {
$return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors()); $return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors());
} else { } else {
$file = $this->upload->getFile(); $file = $this->upload->getFile();
// CUSTOM Attach the file to the related record. // CUSTOM Attach the file to the related record.
$document = $this->attachFile($file); $document = $this->attachFile($file);
// Collect all output data. // Collect all output data.
$return = array_merge($return, array( $return = array_merge($return, array(
'id' => $document->ID, 'id' => $document->ID,
'name' => $document->getTitle(), 'name' => $document->getTitle(),
'thumbnail_url' => $document->Icon($document->getExtension()), 'thumbnail_url' => $document->Icon($document->getExtension()),
'edit_url' => $this->getItemHandler($document->ID)->EditLink(), 'edit_url' => $this->getItemHandler($document->ID)->EditLink(),
'size' => $document->getFileSizeFormatted(), 'size' => $document->getFileSizeFormatted(),
'buttons' => (string) $document->renderWith($this->getTemplateFileButtons()), 'buttons' => (string) $document->renderWith($this->getTemplateFileButtons()),
'showeditform' => true 'showeditform' => true
)); ));
// CUSTOM END // CUSTOM END
} }
} }
} }
$response = new SS_HTTPResponse(Convert::raw2json(array($return))); $response = new SS_HTTPResponse(Convert::raw2json(array($return)));
$response->addHeader('Content-Type', 'text/plain'); $response->addHeader('Content-Type', 'text/plain');
return $response; return $response;
} }
/** /**
* Never directly display items uploaded * Never directly display items uploaded
* @return SS_List * @return SS_List
*/ */
public function getItems() { public function getItems()
return new ArrayList(); {
} return new ArrayList();
}
public function Field($properties = array()) { public function Field($properties = array())
$fields = parent::Field($properties); {
$fields = parent::Field($properties);
// Replace the download template with a new one only when access the upload field through a GridField. // 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'); // Needs to be enabled through setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate');
Requirements::javascript('dms/javascript/DMSUploadField_downloadtemplate.js'); Requirements::javascript('dms/javascript/DMSUploadField_downloadtemplate.js');
// In the add dialog, add the addtemplate into the set of file that load. // In the add dialog, add the addtemplate into the set of file that load.
Requirements::javascript('dms/javascript/DMSUploadField_addtemplate.js'); Requirements::javascript('dms/javascript/DMSUploadField_addtemplate.js');
return $fields; return $fields;
} }
/** /**
* @param int $itemID * @param int $itemID
* @return UploadField_ItemHandler * @return UploadField_ItemHandler
*/ */
public function getItemHandler($itemID) { public function getItemHandler($itemID)
return DMSUploadField_ItemHandler::create($this, $itemID); {
} return DMSUploadField_ItemHandler::create($this, $itemID);
}
} }
class DMSUploadField_ItemHandler extends UploadField_ItemHandler { class DMSUploadField_ItemHandler extends UploadField_ItemHandler
function getItem() { {
return DataObject::get_by_id('DMSDocument', $this->itemID); public function getItem()
} {
return DataObject::get_by_id('DMSDocument', $this->itemID);
}
} }

View File

@ -4,26 +4,30 @@
*/ */
class DocumentHtmlEditorFieldToolbar extends Extension { class DocumentHtmlEditorFieldToolbar extends Extension
{
function updateLinkForm(Form $form) { public function updateLinkForm(Form $form)
$linkType = null; {
$fieldList = null; $linkType = null;
$fields = $form->Fields();//->fieldByName('Heading'); $fieldList = null;
foreach($fields as $field) { $fields = $form->Fields();//->fieldByName('Heading');
$linkType = ($field->fieldByName('LinkType')); foreach ($fields as $field) {
$fieldList = $field; $linkType = ($field->fieldByName('LinkType'));
if ($linkType) break; //break once we have the object $fieldList = $field;
} if ($linkType) {
break;
} //break once we have the object
}
$source = $linkType->getSource(); $source = $linkType->getSource();
$source['document'] = 'Download a document'; $source['document'] = 'Download a document';
$linkType->setSource($source); $linkType->setSource($source);
$addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing'); $addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing');
$addExistingField->setForm($form); $addExistingField->setForm($form);
$addExistingField->setUseFieldClass(false); $addExistingField->setUseFieldClass(false);
$fieldList->insertAfter($addExistingField,'Description'); $fieldList->insertAfter($addExistingField, 'Description');
// Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/behaviour/behaviour.js"); // Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/behaviour/behaviour.js");
// Requirements::javascript(SAPPHIRE_DIR . "/javascript/tiny_mce_improvements.js"); // Requirements::javascript(SAPPHIRE_DIR . "/javascript/tiny_mce_improvements.js");
@ -35,6 +39,6 @@ class DocumentHtmlEditorFieldToolbar extends Extension {
// $documents->setTreeBaseID($baseFolder->ID); // $documents->setTreeBaseID($baseFolder->ID);
//return $form; //return $form;
} }
} }

View File

@ -3,6 +3,6 @@
* Simple exception extension so that we can tell the difference between internally * Simple exception extension so that we can tell the difference between internally
* raised exceptions and those thrown by DMS. * raised exceptions and those thrown by DMS.
*/ */
class FileNotFoundException extends Exception { class FileNotFoundException extends Exception
{
} }

View File

@ -3,160 +3,175 @@
/** /**
* @package dms * @package dms
*/ */
class DMSSiteTreeExtension extends DataExtension { class DMSSiteTreeExtension extends DataExtension
{
private static $belongs_many_many = array( private static $belongs_many_many = array(
'Documents' => 'DMSDocument' 'Documents' => 'DMSDocument'
); );
private static $noDocumentsList = array(); private static $noDocumentsList = array();
private static $showDocumentsList = array(); private static $showDocumentsList = array();
/** /**
* Do not show the documents tab on the array of pages set here * Do not show the documents tab on the array of pages set here
* @static * @static
* @param $mixed Array of page types to not show the Documents tab on * @param $mixed Array of page types to not show the Documents tab on
*/ */
static function no_documents_tab($array = array()) { public static function no_documents_tab($array = array())
if (empty($array)) return; {
if (is_array($array)) { if (empty($array)) {
self::$noDocumentsList = $array; return;
} else { }
self::$noDocumentsList = array($array); 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 * 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. * 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 * @static
* @param $array Array of page types to show the Documents tab on * @param $array Array of page types to show the Documents tab on
*/ */
static function show_documents_tab($array = array()) { public static function show_documents_tab($array = array())
if (empty($array)) return; {
if (is_array($array)) { if (empty($array)) {
self::$showDocumentsList = $array; return;
} else { }
self::$showDocumentsList = array($array); if (is_array($array)) {
} self::$showDocumentsList = $array;
} } else {
self::$showDocumentsList = array($array);
}
}
function updateCMSFields(FieldList $fields){ public function updateCMSFields(FieldList $fields)
//prevent certain pages from having a Document tab in the CMS {
if (in_array($this->owner->ClassName,self::$noDocumentsList)) return; //prevent certain pages from having a Document tab in the CMS
if (count(self::$showDocumentsList) > 0 && !in_array($this->owner->ClassName,self::$showDocumentsList)) return; if (in_array($this->owner->ClassName, self::$noDocumentsList)) {
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' //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::javascript(DMS_DIR.'/javascript/DMSGridField.js');
Requirements::css(DMS_DIR.'/css/DMSMainCMS.css'); Requirements::css(DMS_DIR.'/css/DMSMainCMS.css');
//javascript for the link editor pop-up in TinyMCE //javascript for the link editor pop-up in TinyMCE
Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js"); Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js");
// Document listing // Document listing
$gridFieldConfig = GridFieldConfig::create()->addComponents( $gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(), new GridFieldToolbarHeader(),
new GridFieldFilterHeader(), new GridFieldFilterHeader(),
new GridFieldSortableHeader(), new GridFieldSortableHeader(),
new GridFieldOrderableRows('DocumentSort'), new GridFieldOrderableRows('DocumentSort'),
new GridFieldDataColumns(), new GridFieldDataColumns(),
new GridFieldEditButton(), new GridFieldEditButton(),
new DMSGridFieldDeleteAction(), //special delete dialog to handle custom behaviour of unlinking and deleting new DMSGridFieldDeleteAction(), //special delete dialog to handle custom behaviour of unlinking and deleting
new GridFieldDetailForm() new GridFieldDetailForm()
//GridFieldLevelup::create($folder->ID)->setLinkSpec('admin/assets/show/%d') //GridFieldLevelup::create($folder->ID)->setLinkSpec('admin/assets/show/%d')
); );
if(class_exists('GridFieldPaginatorWithShowAll')){ if (class_exists('GridFieldPaginatorWithShowAll')) {
$paginatorComponent = new GridFieldPaginatorWithShowAll(15); $paginatorComponent = new GridFieldPaginatorWithShowAll(15);
}else{ } else {
$paginatorComponent = new GridFieldPaginator(15); $paginatorComponent = new GridFieldPaginator(15);
} }
$gridFieldConfig->addComponent($paginatorComponent); $gridFieldConfig->addComponent($paginatorComponent);
if(class_exists('GridFieldSortableRows')) { if (class_exists('GridFieldSortableRows')) {
$sortableComponent = new GridFieldSortableRows('DocumentSort'); $sortableComponent = new GridFieldSortableRows('DocumentSort');
//setUsePagenation method removed from newer version of SortableGridField. //setUsePagenation method removed from newer version of SortableGridField.
if(method_exists($sortableComponent,'setUsePagination')){ if (method_exists($sortableComponent, 'setUsePagination')) {
$sortableComponent->setUsePagination(false)->setForceRedraw(true); $sortableComponent->setUsePagination(false)->setForceRedraw(true);
} }
$gridFieldConfig->addComponent($sortableComponent); $gridFieldConfig->addComponent($sortableComponent);
} }
// HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields. // HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields.
singleton('DMSDocument'); singleton('DMSDocument');
$gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields')) $gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields'))
->setFieldCasting(array('LastChanged'=>"Datetime->Ago")) ->setFieldCasting(array('LastChanged'=>"Datetime->Ago"))
->setFieldFormatting(array('FilenameWithoutID'=>'<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>')); ->setFieldFormatting(array('FilenameWithoutID'=>'<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>'));
//override delete functionality with this class //override delete functionality with this class
$gridFieldConfig->getComponentByType('GridFieldDetailForm')->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest'); $gridFieldConfig->getComponentByType('GridFieldDetailForm')->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest');
$gridField = GridField::create( $gridField = GridField::create(
'Documents', 'Documents',
false, false,
$this->owner->Documents()->Sort('DocumentSort'), $this->owner->Documents()->Sort('DocumentSort'),
$gridFieldConfig $gridFieldConfig
); );
$gridField->addExtraClass('documents'); $gridField->addExtraClass('documents');
$uploadBtn = new LiteralField( $uploadBtn = new LiteralField(
'UploadButton', 'UploadButton',
sprintf( sprintf(
'<a class="ss-ui-button ss-ui-action-constructive cms-panel-link" data-pjax-target="Content" data-icon="add" href="%s">%s</a>', '<a class="ss-ui-button ss-ui-action-constructive cms-panel-link" data-pjax-target="Content" data-icon="add" href="%s">%s</a>',
Controller::join_links(singleton('DMSDocumentAddController')->Link(), '?ID=' . $this->owner->ID), Controller::join_links(singleton('DMSDocumentAddController')->Link(), '?ID=' . $this->owner->ID),
"Add Documents" "Add Documents"
) )
); );
$fields->addFieldsToTab( $fields->addFieldsToTab(
'Root.Documents (' . $this->owner->Documents()->Count() . ')', 'Root.Documents (' . $this->owner->Documents()->Count() . ')',
array( array(
$uploadBtn, $uploadBtn,
$gridField $gridField
) )
); );
} }
/** /**
* Enforce sorting for frontend * Enforce sorting for frontend
*/ */
function PageDocuments() { public function PageDocuments()
return $this->owner->getManyManyComponents('Documents')->sort('DocumentSort'); {
} return $this->owner->getManyManyComponents('Documents')->sort('DocumentSort');
}
function onBeforeDelete() { public function onBeforeDelete()
if(Versioned::current_stage() == 'Live') { {
$existsOnOtherStage = !$this->owner->getIsDeletedFromStage(); if (Versioned::current_stage() == 'Live') {
} else { $existsOnOtherStage = !$this->owner->getIsDeletedFromStage();
$existsOnOtherStage = $this->owner->getExistsOnLive(); } else {
} $existsOnOtherStage = $this->owner->getExistsOnLive();
}
// Only remove if record doesn't still exist on live stage. // Only remove if record doesn't still exist on live stage.
if(!$existsOnOtherStage) { if (!$existsOnOtherStage) {
$dmsDocuments = $this->owner->Documents(); $dmsDocuments = $this->owner->Documents();
foreach($dmsDocuments as $document) { foreach ($dmsDocuments as $document) {
//if the document is only associated with one page, i.e. only associated with this page //if the document is only associated with one page, i.e. only associated with this page
if ($document->Pages()->Count() <= 1) { if ($document->Pages()->Count() <= 1) {
//delete the document before deleting this page //delete the document before deleting this page
$document->delete(); $document->delete();
} }
} }
} }
} }
function onBeforePublish() { public function onBeforePublish()
$embargoedDocuments = $this->owner->Documents()->filter('EmbargoedUntilPublished',true); {
if ($embargoedDocuments->Count() > 0) { $embargoedDocuments = $this->owner->Documents()->filter('EmbargoedUntilPublished', true);
foreach($embargoedDocuments as $doc) { if ($embargoedDocuments->Count() > 0) {
$doc->EmbargoedUntilPublished = false; foreach ($embargoedDocuments as $doc) {
$doc->write(); $doc->EmbargoedUntilPublished = false;
} $doc->write();
} }
}
}
} public function getTitleWithNumberOfDocuments()
{
function getTitleWithNumberOfDocuments() { return $this->owner->Title . ' (' . $this->owner->Documents()->Count() . ')';
return $this->owner->Title . ' (' . $this->owner->Documents()->Count() . ')'; }
}
} }

View File

@ -4,212 +4,212 @@
* instance of the DMSInterface. All write operations on the DMSDocument create a new relation, so we never need to * instance of the DMSInterface. All write operations on the DMSDocument create a new relation, so we never need to
* explicitly call the write() method on the DMSDocument DataObject * explicitly call the write() method on the DMSDocument DataObject
*/ */
interface DMSDocumentInterface { interface DMSDocumentInterface
{
/** /**
* Deletes the DMSDocument, its underlying file, as well as any tags related to this DMSDocument. * 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) * @todo Can't be applied to classes which already implement the DataObjectInterface (naming conflict)
* *
* @abstract * @abstract
* @return null * @return null
*/ */
// function delete(); // function delete();
/** /**
* Associates this DMSDocument with a Page. This method does nothing if the association already exists. * 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 * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to add a many_many relation
* @abstract * @abstract
* @param $pageObject Page object to associate this DMSDocument with * @param $pageObject Page object to associate this DMSDocument with
* @return null * @return null
*/ */
function addPage($pageObject); 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 * 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 * DMSDocument with the individual Page with the each page id in the set
* @abstract * @abstract
* @param $pageIDs array of page ids used for the page objects associate this DMSDocument with * @param $pageIDs array of page ids used for the page objects associate this DMSDocument with
* @return null * @return null
*/ */
function addPages($pageIDs); public function addPages($pageIDs);
/** /**
* Removes the association between this DMSDocument and a Page. This method does nothing if the association does not exist. * Removes the association between this DMSDocument and a Page. This method does nothing if the association does not exist.
* @abstract * @abstract
* @param $pageObject Page object to remove the association to * @param $pageObject Page object to remove the association to
* @return mixed * @return mixed
*/ */
function removePage($pageObject); public function removePage($pageObject);
/** /**
* Returns a list of the Page objects associated with this DMSDocument * Returns a list of the Page objects associated with this DMSDocument
* @abstract * @abstract
* @return DataList * @return DataList
*/ */
function getPages(); public function getPages();
/** /**
* Removes all associated Pages from the DMSDocument * Removes all associated Pages from the DMSDocument
* @abstract * @abstract
* @return null * @return null
*/ */
function removeAllPages(); public function removeAllPages();
/** /**
* Adds a metadata tag to the DMSDocument. The tag has a category and a value. * 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. * 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: * 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. * 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 * 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) * same category can occur multiple times)
* @abstract * @abstract
* @param $category String of a metadata category to add (required) * @param $category String of a metadata category to add (required)
* @param $value String of a metadata value 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) * @param bool $multiValue Boolean that determines if the category is multi-value or single-value (optional)
* @return null * @return null
*/ */
function addTag($category, $value, $multiValue = true); 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 * Fetches all tags associated with this DMSDocument within a given category. If a value is specified this method
* tries to fetch that specific tag. * tries to fetch that specific tag.
* @abstract * @abstract
* @param $category String of the metadata category to get * @param $category String of the metadata category to get
* @param null $value String of the value of the tag 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 * @return array of Strings of all the tags or null if there is no match found
*/ */
function getTagsList($category, $value = null); 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. * 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. * 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. * Nothing happens if the category or the value do not exist.
* @abstract * @abstract
* @param $category Category to remove (required) * @param $category Category to remove (required)
* @param null $value Value to remove (optional) * @param null $value Value to remove (optional)
* @return null * @return null
*/ */
function removeTag($category, $value = null); public function removeTag($category, $value = null);
/** /**
* Deletes all tags associated with this DMSDocument. * Deletes all tags associated with this DMSDocument.
* @abstract * @abstract
* @return null * @return null
*/ */
function removeAllTags(); 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
* @abstract * @abstract
* @return String * @return String
*/ */
function getLink(); public function getLink();
/** /**
* Return the extension of the file associated with the document * Return the extension of the file associated with the document
*/ */
function getExtension(); public function getExtension();
/** /**
* Returns the size of the file type in an appropriate format. * Returns the size of the file type in an appropriate format.
* *
* @return string * @return string
*/ */
function getSize(); public function getSize();
/** /**
* Return the size of the file associated with the document, in bytes. * Return the size of the file associated with the document, in bytes.
* *
* @return int * @return int
*/ */
function getAbsoluteSize(); public function getAbsoluteSize();
/** /**
* Takes a File object or a String (path to a file) and copies it into the DMS, replacing the original document file * Takes a File object or a String (path to a file) and copies it into the DMS, replacing the original document file
* but keeping the rest of the document unchanged. * but keeping the rest of the document unchanged.
* @param $file File object, or String that is path to a file to store * @param $file File object, or String that is path to a file to store
* @return DMSDocumentInstance Document object that we replaced the file in * @return DMSDocumentInstance Document object that we replaced the file in
*/ */
function replaceDocument($file); public function replaceDocument($file);
/** /**
* Hides the DMSDocument, so it does not show up when getByPage($myPage) is called * 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 * (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. * should be used to hide DMSDocuments that have not yet gone live.
* @abstract * @abstract
* @return null * @return null
*/ */
function embargoIndefinitely(); public function embargoIndefinitely();
/** /**
* Returns if this is DMSDocument is embargoed or expired. * Returns if this is DMSDocument is embargoed or expired.
* @abstract * @abstract
* @return bool True or False depending on whether this DMSDocument is embargoed or expired * @return bool True or False depending on whether this DMSDocument is embargoed or expired
*/ */
function isHidden(); public function isHidden();
/** /**
* Returns if this is DMSDocument is embargoed. * Returns if this is DMSDocument is embargoed.
* @abstract * @abstract
* @return bool True or False depending on whether this DMSDocument is embargoed * @return bool True or False depending on whether this DMSDocument is embargoed
*/ */
function isEmbargoed(); public function isEmbargoed();
/** /**
* Hides the DMSDocument, so it does not show up when getByPage($myPage) is called. Automatically un-hides the * Hides the DMSDocument, so it does not show up when getByPage($myPage) is called. Automatically un-hides the
* DMSDocument at a specific date. * DMSDocument at a specific date.
* @abstract * @abstract
* @param $datetime String date time value when this DMSDocument should expire * @param $datetime String date time value when this DMSDocument should expire
* @return null * @return null
*/ */
function embargoUntilDate($datetime); public function embargoUntilDate($datetime);
/** /**
* Hides the document until any page it is linked to is published * Hides the document until any page it is linked to is published
* @return null * @return null
*/ */
function embargoUntilPublished(); public function embargoUntilPublished();
/** /**
* Clears any previously set embargos, so the DMSDocument always shows up in all queries. * Clears any previously set embargos, so the DMSDocument always shows up in all queries.
* @abstract * @abstract
* @return null * @return null
*/ */
function clearEmbargo(); public function clearEmbargo();
/** /**
* Returns if this is DMSDocument is expired. * Returns if this is DMSDocument is expired.
* @abstract * @abstract
* @return bool True or False depending on whether this DMSDocument is expired * @return bool True or False depending on whether this DMSDocument is expired
*/ */
function isExpired(); public function isExpired();
/** /**
* Hides the DMSDocument at a specific date, so it does not show up when getByPage($myPage) is called. * Hides the DMSDocument at a specific date, so it does not show up when getByPage($myPage) is called.
* @abstract * @abstract
* @param $datetime String date time value when this DMSDocument should expire * @param $datetime String date time value when this DMSDocument should expire
* @return null * @return null
*/ */
function expireAtDate($datetime); public function expireAtDate($datetime);
/** /**
* Clears any previously set expiry. * Clears any previously set expiry.
* @abstract * @abstract
* @return null * @return null
*/ */
function clearExpiry(); public function clearExpiry();
/*---- FROM HERE ON: optional API features ----*/ /*---- FROM HERE ON: optional API features ----*/
/** /**
* Returns a DataList of all previous Versions of this DMSDocument (check the LastEdited date of each * Returns a DataList of all previous Versions of this DMSDocument (check the LastEdited date of each
* object to find the correct one) * object to find the correct one)
* @abstract * @abstract
* @return DataList List of DMSDocument objects * @return DataList List of DMSDocument objects
*/ */
function getVersions(); public function getVersions();
}
}

View File

@ -8,54 +8,55 @@
* 10000 files per folder is a good amount) * 10000 files per folder is a good amount)
* *
*/ */
interface DMSInterface { interface DMSInterface
{
/** /**
* Factory method that returns an instance of the DMS. This could be any class that implements the DMSInterface. * Factory method that returns an instance of the DMS. This could be any class that implements the DMSInterface.
* @static * @static
* @abstract * @abstract
* @return DMSInterface An instance of the Document Management System * @return DMSInterface An instance of the Document Management System
*/ */
static function inst(); public static function inst();
/** /**
* Takes a File object or a String (path to a file) and copies it into the DMS. The original file remains unchanged. * Takes a File object or a String (path to a file) and copies it into the DMS. The original file remains unchanged.
* When storing a document, sets the fields on the File has "tag" metadata. * When storing a document, sets the fields on the File has "tag" metadata.
* @abstract * @abstract
* @param $file File object, or String that is path to a file to store * @param $file File object, or String that is path to a file to store
* @return DMSDocumentInstance Document object that we just created * @return DMSDocumentInstance Document object that we just created
*/ */
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, * Returns a number of Document objects based on the a search by tags. You can search by category alone,
* by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana") * by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana")
* @abstract * @abstract
* @param null $category The metadata category to search for * @param null $category The metadata category to search for
* @param null $value The metadata value 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 * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
* @return DMSDocumentInterface * @return DMSDocumentInterface
*/ */
function getByTag($category = null, $value = null, $showEmbargoed = false); 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)
* @abstract * @abstract
* @param $searchText String to search for * @param $searchText String to search for
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
* @return DMSDocumentInterface * @return DMSDocumentInterface
*/ */
function getByFullTextSearch($searchText, $showEmbargoed = false); public function getByFullTextSearch($searchText, $showEmbargoed = false);
/** /**
* Returns a list of Document objects associated with a Page * Returns a list of Document objects associated with a Page
* @abstract * @abstract
* @param $page SiteTree to fetch the associated Documents from * @param $page SiteTree to fetch the associated Documents from
* @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results
* @return DataList Document list associated with the Page * @return DataList Document list associated with the Page
*/ */
function getByPage($page, $showEmbargoed = false); public function getByPage($page, $showEmbargoed = false);
} }

View File

@ -3,1260 +3,1366 @@
/** /**
* @package dms * @package dms
*/ */
class DMSDocument extends DataObject implements DMSDocumentInterface { class DMSDocument extends DataObject implements DMSDocumentInterface
{
private static $db = array(
"Filename" => "Varchar(255)", // eg. 3469~2011-energysaving-report.pdf private static $db = array(
"Folder" => "Varchar(255)", // eg. 0 "Filename" => "Varchar(255)", // eg. 3469~2011-energysaving-report.pdf
"Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp" "Folder" => "Varchar(255)", // eg. 0
"Description" => 'Text', "Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp"
"ViewCount" => 'Int', "Description" => 'Text',
"LastChanged" => 'SS_DateTime', //when this document's file was created or last replaced (small changes like updating title don't count) "ViewCount" => 'Int',
"LastChanged" => 'SS_DateTime', //when this document's file was created or last replaced (small changes like updating title don't count)
"EmbargoedIndefinitely" => 'Boolean(false)',
"EmbargoedUntilPublished" => 'Boolean(false)', "EmbargoedIndefinitely" => 'Boolean(false)',
"EmbargoedUntilDate" => 'SS_DateTime', "EmbargoedUntilPublished" => 'Boolean(false)',
"ExpireAtDate" => 'SS_DateTime' "EmbargoedUntilDate" => 'SS_DateTime',
); "ExpireAtDate" => 'SS_DateTime'
);
private static $many_many = array(
'Pages' => 'SiteTree', private static $many_many = array(
'Tags' => 'DMSTag' 'Pages' => 'SiteTree',
); 'Tags' => 'DMSTag'
);
private static $many_many_extraFields = array(
'Pages' => array( private static $many_many_extraFields = array(
'DocumentSort' => 'Int' 'Pages' => array(
) 'DocumentSort' => 'Int'
); )
);
private static $display_fields = array(
'ID' => 'ID', private static $display_fields = array(
'Title' => 'Title', 'ID' => 'ID',
'FilenameWithoutID' => 'Filename', 'Title' => 'Title',
'LastChanged' => 'LastChanged' 'FilenameWithoutID' => 'Filename',
); 'LastChanged' => 'LastChanged'
);
private static $singular_name = 'Document';
private static $singular_name = 'Document';
private static $plural_name = 'Documents';
private static $plural_name = 'Documents';
private static $searchable_fields = array(
'ID' => array( private static $searchable_fields = array(
'filter' => 'ExactMatchFilter', 'ID' => array(
'field' => 'NumericField' 'filter' => 'ExactMatchFilter',
), 'field' => 'NumericField'
'Title', ),
'Filename', 'Title',
'LastChanged' 'Filename',
); 'LastChanged'
);
/**
* @param Member $member /**
* * @param Member $member
* @return boolean *
*/ * @return boolean
public function canView($member = null) { */
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { public function canView($member = null)
$member = Member::currentUser(); {
} if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
$member = Member::currentUser();
// extended access checks }
$results = $this->extend('canView', $member);
// extended access checks
if($results && is_array($results)) { $results = $this->extend('canView', $member);
if(!min($results)) return false;
} if ($results && is_array($results)) {
if (!min($results)) {
if($member && $member->ID){ return false;
return true; }
} }
return false; if ($member && $member->ID) {
} return true;
}
/**
* @param Member $member return false;
* }
* @return boolean
*/ /**
public function canEdit($member = null) { * @param Member $member
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { *
$member = Member::currentUser(); * @return boolean
} */
public function canEdit($member = null)
$results = $this->extend('canEdit', $member); {
if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
if($results && is_array($results)) { $member = Member::currentUser();
if(!min($results)) return false; }
}
$results = $this->extend('canEdit', $member);
return $this->canView();
} if ($results && is_array($results)) {
if (!min($results)) {
/** return false;
* @param Member $member }
* }
* @return boolean
*/ return $this->canView();
public function canCreate($member = null) { }
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
$member = Member::currentUser(); /**
} * @param Member $member
*
$results = $this->extend('canCreate', $member); * @return boolean
*/
if($results && is_array($results)) { public function canCreate($member = null)
if(!min($results)) return false; {
} if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
$member = Member::currentUser();
return $this->canView(); }
}
$results = $this->extend('canCreate', $member);
/**
* @param Member $member if ($results && is_array($results)) {
* if (!min($results)) {
* @return boolean return false;
*/ }
public function canDelete($member = null) { }
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
$member = Member::currentUser(); return $this->canView();
} }
$results = $this->extend('canDelete', $member); /**
* @param Member $member
if($results && is_array($results)) { *
if(!min($results)) return false; * @return boolean
} */
public function canDelete($member = null)
return $this->canView(); {
} if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
$member = Member::currentUser();
}
$results = $this->extend('canDelete', $member);
/**
* Associates this document with a Page. This method does nothing if the if ($results && is_array($results)) {
* association already exists. if (!min($results)) {
* return false;
* 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 $this->canView();
* }
* @return DMSDocument
*/
public function addPage($pageObject) {
$this->Pages()->add($pageObject);
/**
DB::query("UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1 WHERE \"SiteTreeID\" = $pageObject->ID"); * Associates this document with a Page. This method does nothing if the
* association already exists.
return $this; *
} * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to
* add a many_many relation.
/** *
* Associates this DMSDocument with a set of Pages. This method loops * @param SiteTree $pageObject Page object to associate this Document with
* through a set of page ids, and then associates this DMSDocument with the *
* individual Page with the each page id in the set. * @return DMSDocument
* */
* @param array $pageIDs public function addPage($pageObject)
* {
* @return DMSDocument $this->Pages()->add($pageObject);
*/
public function addPages($pageIDs) { DB::query("UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1 WHERE \"SiteTreeID\" = $pageObject->ID");
foreach($pageIDs as $id) {
$pageObject = DataObject::get_by_id("SiteTree", $id); return $this;
}
if($pageObject && $pageObject->exists()) {
$this->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.
return $this; *
} * @param array $pageIDs
*
/** * @return DMSDocument
* Removes the association between this Document and a Page. This method */
* does nothing if the association does not exist. public function addPages($pageIDs)
* {
* @param SiteTree $pageObject Page object to remove the association to foreach ($pageIDs as $id) {
* $pageObject = DataObject::get_by_id("SiteTree", $id);
* @return DMSDocument
*/ if ($pageObject && $pageObject->exists()) {
public function removePage($pageObject) { $this->addPage($pageObject);
$this->Pages()->remove($pageObject); }
}
return $this;
} return $this;
}
/**
* @see getPages() /**
* * Removes the association between this Document and a Page. This method
* @return DataList * does nothing if the association does not exist.
*/ *
public function Pages() { * @param SiteTree $pageObject Page object to remove the association to
$pages = $this->getManyManyComponents('Pages'); *
$this->extend('updatePages', $pages); * @return DMSDocument
*/
return $pages; public function removePage($pageObject)
} {
$this->Pages()->remove($pageObject);
/**
* Returns a list of the Page objects associated with this Document. return $this;
* }
* @return DataList
*/ /**
public function getPages() { * @see getPages()
return $this->Pages(); *
} * @return DataList
*/
/** public function Pages()
* Removes all associated Pages from the DMSDocument {
* $pages = $this->getManyManyComponents('Pages');
* @return DMSDocument $this->extend('updatePages', $pages);
*/
public function removeAllPages() { return $pages;
$this->Pages()->removeAll(); }
return $this; /**
} * Returns a list of the Page objects associated with this Document.
*
/** * @return DataList
* Increase ViewCount by 1, without update any other record fields such as */
* LastEdited. public function getPages()
* {
* @return DMSDocument return $this->Pages();
*/ }
public function trackView() {
if ($this->ID > 0) { /**
$count = $this->ViewCount + 1; * Removes all associated Pages from the DMSDocument
*
$this->ViewCount = $count; * @return DMSDocument
*/
DB::query("UPDATE \"DMSDocument\" SET \"ViewCount\"='$count' WHERE \"ID\"={$this->ID}"); public function removeAllPages()
} {
$this->Pages()->removeAll();
return $this;
} return $this;
}
/** /**
* Adds a metadata tag to the Document. The tag has a category and a value. * Increase ViewCount by 1, without update any other record fields such as
* * LastEdited.
* Each category can have multiple values by default. So: *
* addTag("fruit","banana") addTag("fruit", "apple") will add two items. * @return DMSDocument
* */
* However, if the third parameter $multiValue is set to 'false', then all public function trackView()
* updates to a category only ever update a single value. So: {
* addTag("fruit","banana") addTag("fruit", "apple") would result in a if ($this->ID > 0) {
* single metadata tag: fruit->apple. $count = $this->ViewCount + 1;
*
* Can could be implemented as a key/value store table (although it is more $this->ViewCount = $count;
* like category/value, because the same category can occur multiple times)
* DB::query("UPDATE \"DMSDocument\" SET \"ViewCount\"='$count' WHERE \"ID\"={$this->ID}");
* @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 return $this;
* multi-value or single-value (optional) }
*
* @return DMSDocument
*/ /**
public function addTag($category, $value, $multiValue = true) { * Adds a metadata tag to the Document. The tag has a category and a value.
if ($multiValue) { *
//check for a duplicate tag, don't add the duplicate * Each category can have multiple values by default. So:
$currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value)); * addTag("fruit","banana") addTag("fruit", "apple") will add two items.
if ($currentTag->Count() == 0) { *
//multi value tag * However, if the third parameter $multiValue is set to 'false', then all
$tag = new DMSTag(); * updates to a category only ever update a single value. So:
$tag->Category = $category; * addTag("fruit","banana") addTag("fruit", "apple") would result in a
$tag->Value = $value; * single metadata tag: fruit->apple.
$tag->MultiValue = true; *
$tag->write(); * Can could be implemented as a key/value store table (although it is more
$tag->Documents()->add($this); * like category/value, because the same category can occur multiple times)
} else { *
//add the relation between the tag and document * @param string $category of a metadata category to add (required)
foreach($currentTag as $tagObj) { * @param string $value of a metadata value to add (required)
$tagObj->Documents()->add($this); * @param bool $multiValue Boolean that determines if the category is
} * multi-value or single-value (optional)
} *
} else { * @return DMSDocument
//single value tag */
$currentTag = $this->Tags()->filter(array('Category' => $category)); public function addTag($category, $value, $multiValue = true)
$tag = null; {
if ($currentTag->Count() == 0) { if ($multiValue) {
//create the single-value tag //check for a duplicate tag, don't add the duplicate
$tag = new DMSTag(); $currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value));
$tag->Category = $category; if ($currentTag->Count() == 0) {
$tag->Value = $value; //multi value tag
$tag->MultiValue = false; $tag = new DMSTag();
$tag->write(); $tag->Category = $category;
} else { $tag->Value = $value;
//update the single value tag $tag->MultiValue = true;
$tag = $currentTag->first(); $tag->write();
$tag->Value = $value; $tag->Documents()->add($this);
$tag->MultiValue = false; } else {
$tag->write(); //add the relation between the tag and document
} foreach ($currentTag as $tagObj) {
$tagObj->Documents()->add($this);
// regardless of whether we created a new tag or are just updating an }
// existing one, add the relation }
$tag->Documents()->add($this); } else {
} //single value tag
$currentTag = $this->Tags()->filter(array('Category' => $category));
return $this; $tag = null;
} if ($currentTag->Count() == 0) {
//create the single-value tag
/** $tag = new DMSTag();
* @param string $category $tag->Category = $category;
* @param string $value $tag->Value = $value;
* $tag->MultiValue = false;
* @return DataList $tag->write();
*/ } else {
protected function getTagsObjects($category, $value = null) { //update the single value tag
$valueFilter = array("Category" => $category); $tag = $currentTag->first();
if (!empty($value)) $valueFilter['Value'] = $value; $tag->Value = $value;
$tag->MultiValue = false;
$tags = $this->Tags()->filter($valueFilter); $tag->write();
return $tags; }
}
// regardless of whether we created a new tag or are just updating an
/** // existing one, add the relation
* Fetches all tags associated with this DMSDocument within a given $tag->Documents()->add($this);
* category. If a value is specified this method tries to fetch that }
* specific tag.
* return $this;
* @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 * @param string $category
*/ * @param string $value
public function getTagsList($category, $value = null) { *
$tags = $this->getTagsObjects($category, $value); * @return DataList
*/
$returnArray = null; protected function getTagsObjects($category, $value = null)
{
if ($tags->Count() > 0) { $valueFilter = array("Category" => $category);
$returnArray = array(); if (!empty($value)) {
$valueFilter['Value'] = $value;
foreach($tags as $t) { }
$returnArray[] = $t->Value;
} $tags = $this->Tags()->filter($valueFilter);
} return $tags;
}
return $returnArray;
} /**
* Fetches all tags associated with this DMSDocument within a given
/** * category. If a value is specified this method tries to fetch that
* Removes a tag from the Document. If you only set a category, then all * specific tag.
* values in that category are deleted. *
* * @param string $category metadata category to get
* If you specify both a category and a value, then only that single * @param string $value value of the tag to get
* category/value pair is deleted. *
* * @return array Strings of all the tags or null if there is no match found
* Nothing happens if the category or the value do not exist. */
* public function getTagsList($category, $value = null)
* @param string $category Category to remove {
* @param string $value Value to remove $tags = $this->getTagsObjects($category, $value);
*
* @return DMSDocument $returnArray = null;
*/
public function removeTag($category, $value = null) { if ($tags->Count() > 0) {
$tags = $this->getTagsObjects($category, $value); $returnArray = array();
if ($tags->Count() > 0) { foreach ($tags as $t) {
foreach($tags as $t) { $returnArray[] = $t->Value;
$documentList = $t->Documents(); }
}
//remove the relation between the tag and the document
$documentList->remove($this); return $returnArray;
}
//delete the entire tag if it has no relations left
if ($documentList->Count() == 0) $t->delete(); /**
} * Removes a tag from the Document. If you only set a category, then all
} * values in that category are deleted.
*
return $this; * 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.
* Deletes all tags associated with this Document. *
* * @param string $category Category to remove
* @return DMSDocument * @param string $value Value to remove
*/ *
public function removeAllTags() { * @return DMSDocument
$allTags = $this->Tags(); */
public function removeTag($category, $value = null)
foreach($allTags as $tag) { {
$documentlist = $tag->Documents(); $tags = $this->getTagsObjects($category, $value);
$documentlist->remove($this);
if ($tag->Documents()->Count() == 0) $tag->delete(); if ($tags->Count() > 0) {
} foreach ($tags as $t) {
$documentList = $t->Documents();
return $this;
} //remove the relation between the tag and the document
$documentList->remove($this);
/**
* Returns a link to download this document from the DMS store. //delete the entire tag if it has no relations left
* if ($documentList->Count() == 0) {
* @return string $t->delete();
*/ }
public function getLink() { }
return Controller::join_links(Director::baseURL(),'dmsdocument/'.$this->ID); }
}
return $this;
/** }
* @return string
*/ /**
public function Link() { * Deletes all tags associated with this Document.
return $this->getLink(); *
} * @return DMSDocument
*/
/** public function removeAllTags()
* Hides the document, so it does not show up when getByPage($myPage) is {
* called (without specifying the $showEmbargoed = true parameter). $allTags = $this->Tags();
*
* This is similar to expire, except that this method should be used to hide foreach ($allTags as $tag) {
* documents that have not yet gone live. $documentlist = $tag->Documents();
* $documentlist->remove($this);
* @param bool $write Save change to the database if ($tag->Documents()->Count() == 0) {
* $tag->delete();
* @return DMSDocument }
*/ }
public function embargoIndefinitely($write = true) {
$this->EmbargoedIndefinitely = true; return $this;
}
if ($write) $this->write();
/**
return $this; * Returns a link to download this document from the DMS store.
} *
* @return string
/** */
* Hides the document until any page it is linked to is published public function getLink()
* {
* @param bool $write Save change to database return Controller::join_links(Director::baseURL(), 'dmsdocument/'.$this->ID);
* }
* @return DMSDocument
*/ /**
public function embargoUntilPublished($write = true) { * @return string
$this->EmbargoedUntilPublished = true; */
public function Link()
if ($write) $this->write(); {
return $this->getLink();
return $this; }
}
/**
/** * Hides the document, so it does not show up when getByPage($myPage) is
* Returns if this is Document is embargoed or expired. * called (without specifying the $showEmbargoed = true parameter).
* *
* Also, returns if the document should be displayed on the front-end, * This is similar to expire, except that this method should be used to hide
* respecting the current reading mode of the site and the embargo status. * documents that have not yet gone live.
* *
* @param bool $write Save change to the database
*
* @return DMSDocument
*/
public function embargoIndefinitely($write = true)
{
$this->EmbargoedIndefinitely = true;
if ($write) {
$this->write();
}
return $this;
}
/**
* Hides the document until any page it is linked to is published
*
* @param bool $write Save change to database
*
* @return DMSDocument
*/
public function embargoUntilPublished($write = true)
{
$this->EmbargoedUntilPublished = true;
if ($write) {
$this->write();
}
return $this;
}
/**
* Returns if this is Document is embargoed or expired.
*
* Also, returns if the document should be displayed on the front-end,
* respecting the current reading mode of the site and the embargo status.
*
* I.e. if a document is embargoed until published, then it should still * I.e. if a document is embargoed until published, then it should still
* show up in draft mode. * show up in draft mode.
* *
* @return bool * @return bool
*/ */
public function isHidden() { public function isHidden()
$hidden = $this->isEmbargoed() || $this->isExpired(); {
$readingMode = Versioned::get_reading_mode(); $hidden = $this->isEmbargoed() || $this->isExpired();
$readingMode = Versioned::get_reading_mode();
if ($readingMode == "Stage.Stage") {
if($this->EmbargoedUntilPublished == true) { if ($readingMode == "Stage.Stage") {
$hidden = false; if ($this->EmbargoedUntilPublished == true) {
} $hidden = false;
} }
}
return $hidden;
} return $hidden;
}
/**
* Returns if this is Document is embargoed. /**
* * Returns if this is Document is embargoed.
* @return bool *
*/ * @return bool
public function isEmbargoed() { */
if (is_object($this->EmbargoedUntilDate)) { public function isEmbargoed()
$this->EmbargoedUntilDate = $this->EmbargoedUntilDate->Value; {
} if (is_object($this->EmbargoedUntilDate)) {
$this->EmbargoedUntilDate = $this->EmbargoedUntilDate->Value;
$embargoed = false; }
if ($this->EmbargoedIndefinitely) { $embargoed = false;
$embargoed = true;
} else if ($this->EmbargoedUntilPublished) { if ($this->EmbargoedIndefinitely) {
$embargoed = true; $embargoed = true;
} else if (!empty($this->EmbargoedUntilDate)) { } elseif ($this->EmbargoedUntilPublished) {
if(SS_Datetime::now()->Value < $this->EmbargoedUntilDate) { $embargoed = true;
$embargoed = true; } elseif (!empty($this->EmbargoedUntilDate)) {
} if (SS_Datetime::now()->Value < $this->EmbargoedUntilDate) {
} $embargoed = true;
}
return $embargoed; }
}
return $embargoed;
/** }
* Hides the document, so it does not show up when getByPage($myPage) is
* called. Automatically un-hides the Document at a specific date. /**
* * Hides the document, so it does not show up when getByPage($myPage) is
* @param string $datetime date time value when this Document should expire. * called. Automatically un-hides the Document at a specific date.
* @param bool $write *
* * @param string $datetime date time value when this Document should expire.
* @return DMSDocument * @param bool $write
*/ *
public function embargoUntilDate($datetime, $write = true) { * @return DMSDocument
$this->EmbargoedUntilDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s'); */
public function embargoUntilDate($datetime, $write = true)
if ($write) $this->write(); {
$this->EmbargoedUntilDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s');
return $this;
} if ($write) {
$this->write();
/** }
* Clears any previously set embargos, so the Document always shows up in
* all queries. return $this;
* }
* @param bool $write
* /**
* @return DMSDocument * Clears any previously set embargos, so the Document always shows up in
*/ * all queries.
public function clearEmbargo($write = true) { *
$this->EmbargoedIndefinitely = false; * @param bool $write
$this->EmbargoedUntilPublished = false; *
$this->EmbargoedUntilDate = null; * @return DMSDocument
*/
if ($write) $this->write(); public function clearEmbargo($write = true)
{
return $this; $this->EmbargoedIndefinitely = false;
} $this->EmbargoedUntilPublished = false;
$this->EmbargoedUntilDate = null;
/**
* Returns if this is Document is expired. if ($write) {
* $this->write();
* @return bool }
*/
public function isExpired() { return $this;
if (is_object($this->ExpireAtDate)) { }
$this->ExpireAtDate = $this->ExpireAtDate->Value;
} /**
* Returns if this is Document is expired.
$expired = false; *
* @return bool
if (!empty($this->ExpireAtDate)) { */
if(SS_Datetime::now()->Value >= $this->ExpireAtDate) { public function isExpired()
$expired = true; {
} if (is_object($this->ExpireAtDate)) {
} $this->ExpireAtDate = $this->ExpireAtDate->Value;
}
return $expired;
} $expired = false;
/** if (!empty($this->ExpireAtDate)) {
* Hides the document at a specific date, so it does not show up when if (SS_Datetime::now()->Value >= $this->ExpireAtDate) {
* getByPage($myPage) is called. $expired = true;
* }
* @param string $datetime date time value when this Document should expire }
* @param bool $write
* return $expired;
* @return DMSDocument }
*/
public function expireAtDate($datetime, $write = true) { /**
$this->ExpireAtDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s'); * Hides the document at a specific date, so it does not show up when
* getByPage($myPage) is called.
if ($write) $this->write(); *
* @param string $datetime date time value when this Document should expire
return $this; * @param bool $write
} *
* @return DMSDocument
/** */
* Clears any previously set expiry. public function expireAtDate($datetime, $write = true)
* {
* @param bool $write $this->ExpireAtDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s');
*
* @return DMSDocument if ($write) {
*/ $this->write();
public function clearExpiry($write = true) { }
$this->ExpireAtDate = null;
return $this;
if ($write) $this->write(); }
return $this; /**
} * Clears any previously set expiry.
*
/** * @param bool $write
* Returns a DataList of all previous Versions of this document (check the *
* LastEdited date of each object to find the correct one). * @return DMSDocument
* */
* If {@link DMSDocument_versions::$enable_versions} is disabled then an public function clearExpiry($write = true)
* Exception is thrown {
* $this->ExpireAtDate = null;
* @throws Exception
* if ($write) {
* @return DataList List of Document objects $this->write();
*/ }
public function getVersions() {
if (!DMSDocument_versions::$enable_versions) { return $this;
throw new Exception("DMSDocument versions are disabled"); }
}
/**
return DMSDocument_versions::get_versions($this); * Returns a DataList of all previous Versions of this document (check the
} * LastEdited date of each object to find the correct one).
*
/** * If {@link DMSDocument_versions::$enable_versions} is disabled then an
* Returns the full filename of the document stored in this object. * Exception is thrown
* *
* @return string * @throws Exception
*/ *
public function getFullPath() { * @return DataList List of Document objects
if($this->Filename) { */
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename; public function getVersions()
} {
if (!DMSDocument_versions::$enable_versions) {
return null; throw new Exception("DMSDocument versions are disabled");
} }
/** return DMSDocument_versions::get_versions($this);
* Returns the filename of this asset. }
*
* @return string /**
*/ * Returns the full filename of the document stored in this object.
public function getFileName() { *
if($this->getField('Filename')) { * @return string
return $this->getField('Filename'); */
} else { public function getFullPath()
return ASSETS_DIR . '/'; {
} if ($this->Filename) {
} return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename;
}
/**
* @return string return null;
*/ }
public function getName() {
return $this->getField('Title'); /**
} * Returns the filename of this asset.
*
* @return string
/** */
* @return string public function getFileName()
*/ {
public function getFilenameWithoutID() { if ($this->getField('Filename')) {
$filenameParts = explode('~',$this->Filename); return $this->getField('Filename');
$filename = array_pop($filenameParts); } else {
return ASSETS_DIR . '/';
return $filename; }
} }
/** /**
* @return string * @return string
*/ */
public function getStorageFolder() { public function getName()
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . DMS::get_storage_folder($this->ID); {
} return $this->getField('Title');
}
/**
* Deletes the DMSDocument, its underlying file, as well as any tags related
* to this DMSDocument. Also calls the parent DataObject's delete method in /**
* order to complete an cascade. * @return string
* */
* @return void public function getFilenameWithoutID()
*/ {
public function delete() { $filenameParts = explode('~', $this->Filename);
// remove tags $filename = array_pop($filenameParts);
$this->removeAllTags();
return $filename;
// delete the file (and previous versions of files) }
$filesToDelete = array();
$storageFolder = $this->getStorageFolder(); /**
* @return string
if (file_exists($storageFolder)) { */
if ($handle = opendir($storageFolder)) { public function getStorageFolder()
while (false !== ($entry = readdir($handle))) { {
// only delete if filename starts the the relevant ID return DMS::get_dms_path() . DIRECTORY_SEPARATOR . DMS::get_storage_folder($this->ID);
if(strpos($entry,$this->ID.'~') === 0) { }
$filesToDelete[] = $entry;
} /**
} * Deletes the DMSDocument, its underlying file, as well as any tags related
* to this DMSDocument. Also calls the parent DataObject's delete method in
closedir($handle); * order to complete an cascade.
*
//delete all this files that have the id of this document * @return void
foreach($filesToDelete as $file) { */
$filePath = $storageFolder .DIRECTORY_SEPARATOR . $file; public function delete()
{
if (is_file($filePath)) { // remove tags
unlink($filePath); $this->removeAllTags();
}
} // delete the file (and previous versions of files)
} $filesToDelete = array();
} $storageFolder = $this->getStorageFolder();
$this->removeAllPages(); if (file_exists($storageFolder)) {
if ($handle = opendir($storageFolder)) {
// get rid of any versions have saved for this DMSDocument, too while (false !== ($entry = readdir($handle))) {
if (DMSDocument_versions::$enable_versions) { // only delete if filename starts the the relevant ID
$versions = $this->getVersions(); if (strpos($entry, $this->ID.'~') === 0) {
$filesToDelete[] = $entry;
if ($versions->Count() > 0) { }
foreach($versions as $v) { }
$v->delete();
} closedir($handle);
}
} //delete all this files that have the id of this document
foreach ($filesToDelete as $file) {
parent::delete(); $filePath = $storageFolder .DIRECTORY_SEPARATOR . $file;
}
if (is_file($filePath)) {
unlink($filePath);
}
/** }
* Relate an existing file on the filesystem to the document. }
* }
* Copies the file to the new destination, as defined in {@link get_DMS_path()}.
* $this->removeAllPages();
* @param string $filePath Path to file, relative to webroot.
* // get rid of any versions have saved for this DMSDocument, too
* @return DMSDocument if (DMSDocument_versions::$enable_versions) {
*/ $versions = $this->getVersions();
public function storeDocument($filePath) {
if (empty($this->ID)) { if ($versions->Count() > 0) {
user_error("Document must be written to database before it can store documents", E_USER_ERROR); foreach ($versions as $v) {
} $v->delete();
}
// calculate all the path to copy the file to }
$fromFilename = basename($filePath); }
$toFilename = $this->ID. '~' . $fromFilename; //add the docID to the start of the Filename
$toFolder = DMS::get_storage_folder($this->ID); parent::delete();
$toPath = DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder . DIRECTORY_SEPARATOR . $toFilename; }
DMS::create_storage_folder(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder);
//copy the file into place /**
$fromPath = BASE_PATH . DIRECTORY_SEPARATOR . $filePath; * Relate an existing file on the filesystem to the document.
*
//version the existing file (copy it to a new "very specific" filename * Copies the file to the new destination, as defined in {@link get_DMS_path()}.
if (DMSDocument_versions::$enable_versions) { *
DMSDocument_versions::create_version($this); * @param string $filePath Path to file, relative to webroot.
} else { //otherwise delete the old document file *
$oldPath = $this->getFullPath(); * @return DMSDocument
if (file_exists($oldPath)) unlink($oldPath); */
} public function storeDocument($filePath)
{
copy($fromPath, $toPath); //this will overwrite the existing file (if present) if (empty($this->ID)) {
user_error("Document must be written to database before it can store documents", E_USER_ERROR);
//write the filename of the stored document }
$this->Filename = $toFilename;
$this->Folder = $toFolder; // calculate all the path to copy the file to
$fromFilename = basename($filePath);
$extension = pathinfo($this->Filename, PATHINFO_EXTENSION); $toFilename = $this->ID. '~' . $fromFilename; //add the docID to the start of the Filename
$toFolder = DMS::get_storage_folder($this->ID);
if (empty($this->Title)) { $toPath = DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder . DIRECTORY_SEPARATOR . $toFilename;
// don't overwrite existing document titles
$this->Title = basename($filePath,'.'.$extension); DMS::create_storage_folder(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder);
}
//copy the file into place
$this->LastChanged = SS_Datetime::now()->Rfc2822(); $fromPath = BASE_PATH . DIRECTORY_SEPARATOR . $filePath;
$this->write();
//version the existing file (copy it to a new "very specific" filename
return $this; if (DMSDocument_versions::$enable_versions) {
} DMSDocument_versions::create_version($this);
} else { //otherwise delete the old document file
/** $oldPath = $this->getFullPath();
* Takes a File object or a String (path to a file) and copies it into the if (file_exists($oldPath)) {
* DMS, replacing the original document file but keeping the rest of the unlink($oldPath);
* document unchanged. }
* }
* @param File|string $file path to a file to store
* copy($fromPath, $toPath); //this will overwrite the existing file (if present)
* @return DMSDocument object that we replaced the file in
*/ //write the filename of the stored document
public function replaceDocument($file) { $this->Filename = $toFilename;
$filePath = DMS::transform_file_to_file_path($file); $this->Folder = $toFolder;
$doc = $this->storeDocument($filePath); // replace the document
$extension = pathinfo($this->Filename, PATHINFO_EXTENSION);
return $doc;
} if (empty($this->Title)) {
// don't overwrite existing document titles
$this->Title = basename($filePath, '.'.$extension);
/** }
* Return the type of file for the given extension
* on the current file name. $this->LastChanged = SS_Datetime::now()->Rfc2822();
* $this->write();
* @param string $ext
* return $this;
* @return string }
*/
public static function get_file_type($ext) { /**
$types = array( * Takes a File object or a String (path to a file) and copies it into the
'gif' => 'GIF image - good for diagrams', * DMS, replacing the original document file but keeping the rest of the
'jpg' => 'JPEG image - good for photos', * document unchanged.
'jpeg' => 'JPEG image - good for photos', *
'png' => 'PNG image - good general-purpose format', * @param File|string $file path to a file to store
'ico' => 'Icon image', *
'tiff' => 'Tagged image format', * @return DMSDocument object that we replaced the file in
'doc' => 'Word document', */
'xls' => 'Excel spreadsheet', public function replaceDocument($file)
'zip' => 'ZIP compressed file', {
'gz' => 'GZIP compressed file', $filePath = DMS::transform_file_to_file_path($file);
'dmg' => 'Apple disk image', $doc = $this->storeDocument($filePath); // replace the document
'pdf' => 'Adobe Acrobat PDF file',
'mp3' => 'MP3 audio file', return $doc;
'wav' => 'WAV audo file', }
'avi' => 'AVI video file',
'mpg' => 'MPEG video file',
'mpeg' => 'MPEG video file', /**
'js' => 'Javascript file', * Return the type of file for the given extension
'css' => 'CSS file', * on the current file name.
'html' => 'HTML file', *
'htm' => 'HTML file' * @param string $ext
); *
* @return string
return isset($types[$ext]) ? $types[$ext] : $ext; */
} public static function get_file_type($ext)
{
$types = array(
/** 'gif' => 'GIF image - good for diagrams',
* Returns the Description field with HTML <br> tags added when there is a 'jpg' => 'JPEG image - good for photos',
* line break. 'jpeg' => 'JPEG image - good for photos',
* 'png' => 'PNG image - good general-purpose format',
* @return string 'ico' => 'Icon image',
*/ 'tiff' => 'Tagged image format',
public function getDescriptionWithLineBreak() { 'doc' => 'Word document',
return nl2br($this->getField('Description')); 'xls' => 'Excel spreadsheet',
} 'zip' => 'ZIP compressed file',
'gz' => 'GZIP compressed file',
/** 'dmg' => 'Apple disk image',
* @return FieldList 'pdf' => 'Adobe Acrobat PDF file',
*/ 'mp3' => 'MP3 audio file',
public function getCMSFields() { 'wav' => 'WAV audo file',
//include JS to handling showing and hiding of bottom "action" tabs 'avi' => 'AVI video file',
Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentCMSFields.js'); 'mpg' => 'MPEG video file',
Requirements::css(DMS_DIR.'/css/DMSDocumentCMSFields.css'); 'mpeg' => 'MPEG video file',
'js' => 'Javascript file',
$fields = new FieldList(); //don't use the automatic scaffolding, it is slow and unnecessary here 'css' => 'CSS file',
'html' => 'HTML file',
$extraTasks = ''; //additional text to inject into the list of tasks at the bottom of a DMSDocument CMSfield 'htm' => 'HTML file'
$extraFields = FormField::create('Empty'); );
//get list of shortcode page relations return isset($types[$ext]) ? $types[$ext] : $ext;
$relationFinder = new ShortCodeRelationFinder(); }
$relationList = $relationFinder->getList($this->ID);
$fieldsTop = $this->getFieldsForFile($relationList->count()); /**
$fields->add($fieldsTop); * Returns the Description field with HTML <br> tags added when there is a
* line break.
$fields->add(new TextField('Title','Title')); *
$fields->add(new TextareaField('Description','Description')); * @return string
*/
//create upload field to replace document public function getDescriptionWithLineBreak()
$uploadField = new DMSUploadField('ReplaceFile', 'Replace file'); {
$uploadField->setConfig('allowedMaxFileNumber', 1); return nl2br($this->getField('Description'));
$uploadField->setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate'); }
$uploadField->setRecord($this);
/**
$gridFieldConfig = GridFieldConfig::create()->addComponents( * @return FieldList
new GridFieldToolbarHeader(), */
new GridFieldSortableHeader(), public function getCMSFields()
new GridFieldDataColumns(), {
new GridFieldPaginator(30), //include JS to handling showing and hiding of bottom "action" tabs
//new GridFieldEditButton(), Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentCMSFields.js');
new GridFieldDetailForm() Requirements::css(DMS_DIR.'/css/DMSDocumentCMSFields.css');
);
$fields = new FieldList(); //don't use the automatic scaffolding, it is slow and unnecessary here
$gridFieldConfig->getComponentByType('GridFieldDataColumns')
->setDisplayFields(array( $extraTasks = ''; //additional text to inject into the list of tasks at the bottom of a DMSDocument CMSfield
'Title'=>'Title', $extraFields = FormField::create('Empty');
'ClassName'=>'Page Type',
'ID'=>'Page ID' //get list of shortcode page relations
)) $relationFinder = new ShortCodeRelationFinder();
->setFieldFormatting(array( $relationList = $relationFinder->getList($this->ID);
'Title'=>sprintf(
'<a class=\"cms-panel-link\" href=\"%s/$ID\">$Title</a>', $fieldsTop = $this->getFieldsForFile($relationList->count());
singleton('CMSPageEditController')->Link('show') $fields->add($fieldsTop);
)
)); $fields->add(new TextField('Title', 'Title'));
$fields->add(new TextareaField('Description', 'Description'));
$pagesGrid = GridField::create(
'Pages', //create upload field to replace document
_t('DMSDocument.RelatedPages', 'Related Pages'), $uploadField = new DMSUploadField('ReplaceFile', 'Replace file');
$this->Pages(), $uploadField->setConfig('allowedMaxFileNumber', 1);
$gridFieldConfig $uploadField->setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate');
); $uploadField->setRecord($this);
$referencesGrid = GridField::create( $gridFieldConfig = GridFieldConfig::create()->addComponents(
'References', new GridFieldToolbarHeader(),
_t('DMSDocument.RelatedReferences', 'Related References'), new GridFieldSortableHeader(),
$relationList, new GridFieldDataColumns(),
$gridFieldConfig new GridFieldPaginator(30),
); //new GridFieldEditButton(),
new GridFieldDetailForm()
if (DMSDocument_versions::$enable_versions) { );
$versionsGridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(), $gridFieldConfig->getComponentByType('GridFieldDataColumns')
new GridFieldSortableHeader(), ->setDisplayFields(array(
new GridFieldDataColumns(), 'Title'=>'Title',
new GridFieldPaginator(30) 'ClassName'=>'Page Type',
); 'ID'=>'Page ID'
$versionsGridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(Config::inst()->get('DMSDocument_versions', 'display_fields')) ))
->setFieldCasting(array('LastChanged'=>"Datetime->Ago")) ->setFieldFormatting(array(
->setFieldFormatting(array('FilenameWithoutID'=>'<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>')); 'Title'=>sprintf(
'<a class=\"cms-panel-link\" href=\"%s/$ID\">$Title</a>',
$versionsGrid = GridField::create( singleton('CMSPageEditController')->Link('show')
'Versions', )
_t('DMSDocument.Versions', 'Versions'), ));
$this->getVersions(),
$versionsGridFieldConfig $pagesGrid = GridField::create(
); 'Pages',
$extraTasks .= '<li class="ss-ui-button" data-panel="find-versions">Versions</li>'; _t('DMSDocument.RelatedPages', 'Related Pages'),
//$extraFields = $versionsGrid->addExtraClass('find-versions'); $this->Pages(),
} $gridFieldConfig
);
$fields->add(new LiteralField('BottomTaskSelection',
'<div id="Actions" class="field actions"><label class="left">Actions</label><ul>'. $referencesGrid = GridField::create(
'<li class="ss-ui-button" data-panel="embargo">Embargo</li>'. 'References',
'<li class="ss-ui-button" data-panel="expiry">Expiry</li>'. _t('DMSDocument.RelatedReferences', 'Related References'),
'<li class="ss-ui-button" data-panel="replace">Replace</li>'. $relationList,
'<li class="ss-ui-button" data-panel="find-usage">Usage</li>'. $gridFieldConfig
'<li class="ss-ui-button" data-panel="find-references">References</li>'. );
$extraTasks.
'</ul></div>')); if (DMSDocument_versions::$enable_versions) {
$versionsGridFieldConfig = GridFieldConfig::create()->addComponents(
$embargoValue = 'None'; new GridFieldToolbarHeader(),
if ($this->EmbargoedIndefinitely) $embargoValue = 'Indefinitely'; new GridFieldSortableHeader(),
elseif ($this->EmbargoedUntilPublished) $embargoValue = 'Published'; new GridFieldDataColumns(),
elseif (!empty($this->EmbargoedUntilDate)) $embargoValue = 'Date'; new GridFieldPaginator(30)
$embargo = new OptionsetField('Embargo','Embargo',array('None'=>'None','Published'=>'Hide document until page is published','Indefinitely'=>'Hide document indefinitely','Date'=>'Hide until set date'),$embargoValue); );
$embargoDatetime = DatetimeField::create('EmbargoedUntilDate',''); $versionsGridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(Config::inst()->get('DMSDocument_versions', 'display_fields'))
$embargoDatetime->getDateField()->setConfig('showcalendar', true)->setConfig('dateformat', 'dd-MM-yyyy')->setConfig('datavalueformat', 'dd-MM-yyyy'); ->setFieldCasting(array('LastChanged'=>"Datetime->Ago"))
->setFieldFormatting(array('FilenameWithoutID'=>'<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>'));
$expiryValue = 'None';
if (!empty($this->ExpireAtDate)) $expiryValue = 'Date'; $versionsGrid = GridField::create(
$expiry = new OptionsetField('Expiry','Expiry',array('None'=>'None','Date'=>'Set document to expire on'),$expiryValue); 'Versions',
$expiryDatetime = DatetimeField::create('ExpireAtDate',''); _t('DMSDocument.Versions', 'Versions'),
$expiryDatetime->getDateField()->setConfig('showcalendar', true)->setConfig('dateformat', 'dd-MM-yyyy')->setConfig('datavalueformat', 'dd-MM-yyyy'); $this->getVersions(),
$versionsGridFieldConfig
// This adds all the actions details into a group. );
// Embargo, History, etc to go in here $extraTasks .= '<li class="ss-ui-button" data-panel="find-versions">Versions</li>';
// These are toggled on and off via the Actions Buttons above //$extraFields = $versionsGrid->addExtraClass('find-versions');
// exit('hit'); }
$actionsPanel = FieldGroup::create(
$fields->add(new LiteralField('BottomTaskSelection',
FieldGroup::create( '<div id="Actions" class="field actions"><label class="left">Actions</label><ul>'.
$embargo, '<li class="ss-ui-button" data-panel="embargo">Embargo</li>'.
$embargoDatetime '<li class="ss-ui-button" data-panel="expiry">Expiry</li>'.
)->addExtraClass('embargo'), '<li class="ss-ui-button" data-panel="replace">Replace</li>'.
'<li class="ss-ui-button" data-panel="find-usage">Usage</li>'.
FieldGroup::create( '<li class="ss-ui-button" data-panel="find-references">References</li>'.
$expiry, $extraTasks.
$expiryDatetime '</ul></div>'));
)->addExtraClass('expiry'),
$embargoValue = 'None';
FieldGroup::create( if ($this->EmbargoedIndefinitely) {
$uploadField $embargoValue = 'Indefinitely';
)->addExtraClass('replace'), } elseif ($this->EmbargoedUntilPublished) {
$embargoValue = 'Published';
FieldGroup::create( } elseif (!empty($this->EmbargoedUntilDate)) {
$pagesGrid $embargoValue = 'Date';
)->addExtraClass('find-usage'), }
$embargo = new OptionsetField('Embargo', 'Embargo', array('None'=>'None', 'Published'=>'Hide document until page is published', 'Indefinitely'=>'Hide document indefinitely', 'Date'=>'Hide until set date'), $embargoValue);
FieldGroup::create( $embargoDatetime = DatetimeField::create('EmbargoedUntilDate', '');
$referencesGrid $embargoDatetime->getDateField()->setConfig('showcalendar', true)->setConfig('dateformat', 'dd-MM-yyyy')->setConfig('datavalueformat', 'dd-MM-yyyy');
)->addExtraClass('find-references'),
$expiryValue = 'None';
FieldGroup::create( if (!empty($this->ExpireAtDate)) {
$versionsGrid $expiryValue = 'Date';
)->addExtraClass('find-versions') }
$expiry = new OptionsetField('Expiry', 'Expiry', array('None'=>'None', 'Date'=>'Set document to expire on'), $expiryValue);
); $expiryDatetime = DatetimeField::create('ExpireAtDate', '');
$expiryDatetime->getDateField()->setConfig('showcalendar', true)->setConfig('dateformat', 'dd-MM-yyyy')->setConfig('datavalueformat', 'dd-MM-yyyy');
$actionsPanel->setName("ActionsPanel");
$actionsPanel->addExtraClass("ActionsPanel"); // This adds all the actions details into a group.
// Embargo, History, etc to go in here
$fields->push($actionsPanel); // These are toggled on and off via the Actions Buttons above
// exit('hit');
// $fields->add(FieldGroup::create( $actionsPanel = FieldGroup::create(
// FieldGroup::create(
// $embargo, FieldGroup::create(
// $embargoDatetime $embargo,
// )->addExtraClass('embargo'), $embargoDatetime
// FieldGroup::create( )->addExtraClass('embargo'),
// $expiry,
// $expiryDatetime FieldGroup::create(
// )->addExtraClass('expiry'), $expiry,
// $uploadField->addExtraClass('replace'), $expiryDatetime
// $pagesGrid->addExtraClass('find-usage'), )->addExtraClass('expiry'),
// $referencesGrid->addExtraClass('find-references'),
// $extraFields FieldGroup::create(
// )->setName("ActionsPanel")->addExtraClass('dmsupload ss-uploadfield')); $uploadField
)->addExtraClass('replace'),
$this->extend('updateCMSFields', $fields); FieldGroup::create(
$pagesGrid
return $fields; )->addExtraClass('find-usage'),
}
FieldGroup::create(
public function onBeforeWrite() { $referencesGrid
parent::onBeforeWrite(); )->addExtraClass('find-references'),
if (isset($this->Embargo)) { FieldGroup::create(
//set the embargo options from the OptionSetField created in the getCMSFields method $versionsGrid
//do not write after clearing the embargo (write happens automatically) )->addExtraClass('find-versions')
$savedDate = $this->EmbargoedUntilDate;
$this->clearEmbargo(false); //clear all previous settings and re-apply them on save );
if ($this->Embargo == 'Published') $this->embargoUntilPublished(false); $actionsPanel->setName("ActionsPanel");
if ($this->Embargo == 'Indefinitely') $this->embargoIndefinitely(false); $actionsPanel->addExtraClass("ActionsPanel");
if ($this->Embargo == 'Date') $this->embargoUntilDate($savedDate, false);
} $fields->push($actionsPanel);
if (isset($this->Expiry)) { // $fields->add(FieldGroup::create(
if ($this->Expiry == 'Date') $this->expireAtDate($this->ExpireAtDate, false); // FieldGroup::create(
else $this->clearExpiry(false); //clear all previous settings // $embargo,
} // $embargoDatetime
} // )->addExtraClass('embargo'),
// FieldGroup::create(
/** // $expiry,
* Return the relative URL of an icon for the file type, based on the // $expiryDatetime
* {@link appCategory()} value. // )->addExtraClass('expiry'),
* // $uploadField->addExtraClass('replace'),
* Images are searched for in "dms/images/app_icons/". // $pagesGrid->addExtraClass('find-usage'),
* // $referencesGrid->addExtraClass('find-references'),
* @return string // $extraFields
*/ // )->setName("ActionsPanel")->addExtraClass('dmsupload ss-uploadfield'));
public function Icon($ext) {
if(!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) {
$ext = File::get_app_category($ext); $this->extend('updateCMSFields', $fields);
}
return $fields;
if(!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) { }
$ext = "generic";
} public function onBeforeWrite()
{
return DMS_DIR."/images/app_icons/{$ext}_32.png"; parent::onBeforeWrite();
}
if (isset($this->Embargo)) {
/** //set the embargo options from the OptionSetField created in the getCMSFields method
* Return the extension of the file associated with the document //do not write after clearing the embargo (write happens automatically)
* $savedDate = $this->EmbargoedUntilDate;
* @return string $this->clearEmbargo(false); //clear all previous settings and re-apply them on save
*/
public function getExtension() { if ($this->Embargo == 'Published') {
return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION)); $this->embargoUntilPublished(false);
} }
if ($this->Embargo == 'Indefinitely') {
/** $this->embargoIndefinitely(false);
* @return string }
*/ if ($this->Embargo == 'Date') {
public function getSize() { $this->embargoUntilDate($savedDate, false);
$size = $this->getAbsoluteSize(); }
return ($size) ? File::format_size($size) : false; }
}
if (isset($this->Expiry)) {
/** if ($this->Expiry == 'Date') {
* Return the size of the file associated with the document. $this->expireAtDate($this->ExpireAtDate, false);
* } else {
* @return string $this->clearExpiry(false);
*/ } //clear all previous settings
public function getAbsoluteSize() { }
return file_exists($this->getFullPath()) ? filesize($this->getFullPath()) : null; }
}
/**
/** * Return the relative URL of an icon for the file type, based on the
* An alias to DMSDocument::getSize() * {@link appCategory()} value.
* *
* @return string * Images are searched for in "dms/images/app_icons/".
*/ *
public function getFileSizeFormatted() { * @return string
return $this->getSize(); */
} public function Icon($ext)
{
if (!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) {
/** $ext = File::get_app_category($ext);
* @return FieldList }
*/
protected function getFieldsForFile($relationListCount) { if (!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) {
$extension = $this->getExtension(); $ext = "generic";
}
$previewField = new LiteralField("ImageFull",
"<img id='thumbnailImage' class='thumbnail-preview' src='{$this->Icon($extension)}?r=" . rand(1,100000) . "' alt='{$this->Title}' />\n" return DMS_DIR."/images/app_icons/{$ext}_32.png";
); }
//count the number of pages this document is published on /**
$publishedOnCount = $this->Pages()->Count(); * Return the extension of the file associated with the document
$publishedOnValue = "$publishedOnCount pages"; *
if ($publishedOnCount == 1) $publishedOnValue = "$publishedOnCount page"; * @return string
*/
$relationListCountValue = "$relationListCount pages"; public function getExtension()
if ($relationListCount == 1) $relationListCountValue = "$relationListCount page"; {
return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION));
$fields = new FieldGroup( }
$filePreview = CompositeField::create(
CompositeField::create( /**
$previewField * @return string
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'), */
CompositeField::create( public function getSize()
CompositeField::create( {
new ReadonlyField("ID", "ID number". ':', $this->ID), $size = $this->getAbsoluteSize();
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type') . ':', self::get_file_type($extension)), return ($size) ? File::format_size($size) : false;
new ReadonlyField("Size", _t('AssetTableField.SIZE','File size') . ':', $this->getFileSizeFormatted()), }
$urlField = new ReadonlyField('ClickableURL', _t('AssetTableField.URL','URL'),
sprintf('<a href="%s" target="_blank" class="file-url">%s</a>', $this->getLink(), $this->getLink()) /**
), * Return the size of the file associated with the document.
new ReadonlyField("FilenameWithoutIDField", "Filename". ':', $this->getFilenameWithoutID()), *
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded') . ':', $this->Created), * @return string
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed') . ':', $this->LastEdited), */
new DateField_Disabled("LastChanged", _t('AssetTableField.LASTCHANGED','Last replaced') . ':', $this->LastChanged), public function getAbsoluteSize()
new ReadonlyField("PublishedOn", "Published on". ':', $publishedOnValue), {
new ReadonlyField("ReferencedOn", "Referenced on". ':', $relationListCountValue), return file_exists($this->getFullPath()) ? filesize($this->getFullPath()) : null;
new ReadonlyField("ViewCount", "View count". ':', $this->ViewCount) }
)
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data') /**
)->setName("FilePreview")->addExtraClass('cms-file-info') * An alias to DMSDocument::getSize()
); *
* @return string
$fields->setName('FileP'); */
$urlField->dontEscape = true; public function getFileSizeFormatted()
{
return $fields; return $this->getSize();
} }
/**
* Takes a file and adds it to the DMSDocument storage, replacing the /**
* current file. * @return FieldList
* */
* @param File $file protected function getFieldsForFile($relationListCount)
* {
* @return DMSDocument $extension = $this->getExtension();
*/
public function ingestFile($file) { $previewField = new LiteralField("ImageFull",
$this->replaceDocument($file); "<img id='thumbnailImage' class='thumbnail-preview' src='{$this->Icon($extension)}?r=" . rand(1, 100000) . "' alt='{$this->Title}' />\n"
$file->delete(); );
return $this; //count the number of pages this document is published on
} $publishedOnCount = $this->Pages()->Count();
$publishedOnValue = "$publishedOnCount pages";
if ($publishedOnCount == 1) {
$publishedOnValue = "$publishedOnCount page";
}
$relationListCountValue = "$relationListCount pages";
if ($relationListCount == 1) {
$relationListCountValue = "$relationListCount page";
}
$fields = new FieldGroup(
$filePreview = CompositeField::create(
CompositeField::create(
$previewField
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'),
CompositeField::create(
CompositeField::create(
new ReadonlyField("ID", "ID number". ':', $this->ID),
new ReadonlyField("FileType", _t('AssetTableField.TYPE', 'File type') . ':', self::get_file_type($extension)),
new ReadonlyField("Size", _t('AssetTableField.SIZE', 'File size') . ':', $this->getFileSizeFormatted()),
$urlField = new ReadonlyField('ClickableURL', _t('AssetTableField.URL', 'URL'),
sprintf('<a href="%s" target="_blank" class="file-url">%s</a>', $this->getLink(), $this->getLink())
),
new ReadonlyField("FilenameWithoutIDField", "Filename". ':', $this->getFilenameWithoutID()),
new DateField_Disabled("Created", _t('AssetTableField.CREATED', 'First uploaded') . ':', $this->Created),
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT', 'Last changed') . ':', $this->LastEdited),
new DateField_Disabled("LastChanged", _t('AssetTableField.LASTCHANGED', 'Last replaced') . ':', $this->LastChanged),
new ReadonlyField("PublishedOn", "Published on". ':', $publishedOnValue),
new ReadonlyField("ReferencedOn", "Referenced on". ':', $relationListCountValue),
new ReadonlyField("ViewCount", "View count". ':', $this->ViewCount)
)
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data')
)->setName("FilePreview")->addExtraClass('cms-file-info')
);
$fields->setName('FileP');
$urlField->dontEscape = true;
return $fields;
}
/**
* Takes a file and adds it to the DMSDocument storage, replacing the
* current file.
*
* @param File $file
*
* @return DMSDocument
*/
public function ingestFile($file)
{
$this->replaceDocument($file);
$file->delete();
return $this;
}
} }
/** /**
* @package dms * @package dms
*/ */
class DMSDocument_Controller extends Controller { class DMSDocument_Controller extends Controller
{
static $testMode = false; //mode to switch for testing. Does not return document download, just document URL public static $testMode = false; //mode to switch for testing. Does not return document download, just document URL
private static $allowed_actions = array( private static $allowed_actions = array(
'index' 'index'
); );
public function init() { public function init()
Versioned::choose_site_stage(); {
parent::init(); Versioned::choose_site_stage();
} parent::init();
}
/** /**
* Returns the document object from the request object's ID parameter. * Returns the document object from the request object's ID parameter.
* Returns null, if no document found * Returns null, if no document found
*/ */
protected function getDocumentFromID($request) { protected function getDocumentFromID($request)
$doc = null; {
$doc = null;
$id = Convert::raw2sql($request->param('ID')); $id = Convert::raw2sql($request->param('ID'));
if (strpos($id, 'version') === 0) { //versioned document if (strpos($id, 'version') === 0) { //versioned document
$id = str_replace('version','',$id); $id = str_replace('version', '', $id);
$doc = DataObject::get_by_id('DMSDocument_versions', $id); $doc = DataObject::get_by_id('DMSDocument_versions', $id);
$this->extend('updateVersionFromID', $doc, $request); $this->extend('updateVersionFromID', $doc, $request);
} else { //normal document } else { //normal document
$doc = DataObject::get_by_id('DMSDocument', $id); $doc = DataObject::get_by_id('DMSDocument', $id);
$this->extend('updateDocumentFromID', $doc, $request); $this->extend('updateDocumentFromID', $doc, $request);
} }
return $doc; return $doc;
} }
/** /**
* Access the file download without redirecting user, so we can block direct * Access the file download without redirecting user, so we can block direct
* access to documents. * access to documents.
*/ */
public function index(SS_HTTPRequest $request) { public function index(SS_HTTPRequest $request)
$doc = $this->getDocumentFromID($request); {
$doc = $this->getDocumentFromID($request);
if (!empty($doc)) { if (!empty($doc)) {
$canView = false; $canView = false;
// Runs through all pages that this page links to and sets canView // Runs through all pages that this page links to and sets canView
// to true if the user can view ONE of these pages // to true if the user can view ONE of these pages
if (method_exists($doc, 'Pages')) { if (method_exists($doc, 'Pages')) {
$pages = $doc->Pages(); $pages = $doc->Pages();
if ($pages->Count() > 0) { if ($pages->Count() > 0) {
foreach($pages as $page) { foreach ($pages as $page) {
if ($page->CanView()) { if ($page->CanView()) {
// just one canView is enough to know that we can // just one canView is enough to know that we can
// view the file // view the file
$canView = true; $canView = true;
break; break;
} }
} }
} else { } else {
// if the document isn't on any page, then allow viewing of // if the document isn't on any page, then allow viewing of
// the document (because there is no canView() to consult) // the document (because there is no canView() to consult)
$canView = true; $canView = true;
} }
} }
// check for embargo or expiry // check for embargo or expiry
if ($doc->isHidden()) $canView = false; if ($doc->isHidden()) {
$canView = false;
}
//admins can always download any document, even if otherwise hidden //admins can always download any document, even if otherwise hidden
$member = Member::currentUser(); $member = Member::currentUser();
if ($member && Permission::checkMember($member, 'ADMIN')) $canView = true; if ($member && Permission::checkMember($member, 'ADMIN')) {
$canView = true;
}
if ($canView) { if ($canView) {
$path = $doc->getFullPath(); $path = $doc->getFullPath();
if ( is_file($path) ) { if (is_file($path)) {
$fileBin = trim(`whereis file`); $fileBin = trim(`whereis file`);
if ( function_exists('finfo_file') ) { if (function_exists('finfo_file')) {
// discover the mime type properly // discover the mime type properly
$finfo = finfo_open(FILEINFO_MIME_TYPE); $finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path); $mime = finfo_file($finfo, $path);
} } elseif (is_executable($fileBin)) {
else if ( is_executable($fileBin) ) { // try to use the system tool
// try to use the system tool $mime = `$fileBin -i -b $path`;
$mime = `$fileBin -i -b $path`; $mime = explode(';', $mime);
$mime = explode(';', $mime); $mime = trim($mime[0]);
$mime = trim($mime[0]); } else {
} // make do with what we have
else { $ext = $doc->getExtension();
// make do with what we have if ($ext =='pdf') {
$ext = $doc->getExtension(); $mime = 'application/pdf';
if ( $ext =='pdf') { } elseif ($ext == 'html' || $ext =='htm') {
$mime = 'application/pdf'; $mime = 'text/html';
}elseif ($ext == 'html' || $ext =='htm') { } else {
$mime = 'text/html'; $mime = 'application/octet-stream';
}else { }
$mime = 'application/octet-stream'; }
}
}
if (self::$testMode) return $path; if (self::$testMode) {
return $path;
}
//if a DMSDocument can be downloaded and all the permissions/privileges has passed, //if a DMSDocument can be downloaded and all the permissions/privileges has passed,
//its ViewCount should be increased by 1 just before the browser sending the file to front. //its ViewCount should be increased by 1 just before the browser sending the file to front.
$doc->trackView(); $doc->trackView();
header('Content-Type: ' . $mime); header('Content-Type: ' . $mime);
header('Content-Length: ' . filesize($path), null); header('Content-Length: ' . filesize($path), null);
if (!empty($mime) && $mime != "text/html") header('Content-Disposition: attachment; filename="'.$doc->getFilenameWithoutID().'"'); if (!empty($mime) && $mime != "text/html") {
header('Content-transfer-encoding: 8bit'); header('Content-Disposition: attachment; filename="'.$doc->getFilenameWithoutID().'"');
header('Expires: 0'); }
header('Pragma: cache'); header('Content-transfer-encoding: 8bit');
header('Cache-Control: private'); header('Expires: 0');
flush(); header('Pragma: cache');
readfile($path); header('Cache-Control: private');
exit; flush();
} readfile($path);
} exit;
} }
}
}
if (self::$testMode) return 'This asset does not exist.'; if (self::$testMode) {
$this->httpError(404, 'This asset does not exist.'); return 'This asset does not exist.';
} }
$this->httpError(404, 'This asset does not exist.');
}
} }

View File

@ -9,249 +9,269 @@
* *
* @package dms * @package dms
*/ */
class DMSDocument_versions extends DataObject { class DMSDocument_versions extends DataObject
{
/** /**
* @var bool $enable_versions Flag that turns on or off versions of * @var bool $enable_versions Flag that turns on or off versions of
* documents when replacing them * documents when replacing them
*/ */
public static $enable_versions = true; public static $enable_versions = true;
private static $db = array( private static $db = array(
'VersionCounter' => 'Int', 'VersionCounter' => 'Int',
'VersionViewCount' => 'Int' 'VersionViewCount' => 'Int'
); );
private static $has_one = array( private static $has_one = array(
'Document' => 'DMSDocument' 'Document' => 'DMSDocument'
); );
private static $defaults = array( private static $defaults = array(
'VersionCounter' => 0 'VersionCounter' => 0
); );
private static $display_fields = array( private static $display_fields = array(
'VersionCounter' => 'Version Counter', 'VersionCounter' => 'Version Counter',
'FilenameWithoutID' => 'Filename', 'FilenameWithoutID' => 'Filename',
'LastChanged' => 'Last Changed' 'LastChanged' => 'Last Changed'
); );
private static $summary_fields = array( private static $summary_fields = array(
'VersionCounter', 'VersionCounter',
'FilenameWithoutID' 'FilenameWithoutID'
); );
private static $field_labels = array( private static $field_labels = array(
'FilenameWithoutID'=>'Filename' 'FilenameWithoutID'=>'Filename'
); );
private static $default_sort = array( private static $default_sort = array(
'LastChanged' => 'DESC' 'LastChanged' => 'DESC'
); );
/** /**
* Creates a new version of a document by moving the current file and * Creates a new version of a document by moving the current file and
* renaming it to the versioned filename. * renaming it to the versioned filename.
* *
* This method assumes that the method calling this is just about to upload * This method assumes that the method calling this is just about to upload
* a new file to replace the old file. * a new file to replace the old file.
* *
* @static * @static
* @param DMSDocument $doc * @param DMSDocument $doc
* *
* @return bool Success or failure * @return bool Success or failure
*/ */
public static function create_version(DMSDocument $doc) { public static function create_version(DMSDocument $doc)
$success = false; {
$success = false;
$existingPath = $doc->getFullPath(); $existingPath = $doc->getFullPath();
if (is_file($existingPath)) { if (is_file($existingPath)) {
$docData = $doc->toMap(); $docData = $doc->toMap();
unset($docData['ID']); unset($docData['ID']);
$version = new DMSDocument_versions($docData); //create a copy of the current DMSDocument as a version $version = new DMSDocument_versions($docData); //create a copy of the current DMSDocument as a version
$previousVersionCounter = 0; $previousVersionCounter = 0;
$newestExistingVersion = self::get_versions($doc)->sort(array('Created'=>'DESC','ID'=>'DESC'))->limit(1); $newestExistingVersion = self::get_versions($doc)->sort(array('Created'=>'DESC', 'ID'=>'DESC'))->limit(1);
if ($newestExistingVersion && $newestExistingVersion->Count() > 0) { if ($newestExistingVersion && $newestExistingVersion->Count() > 0) {
$previousVersionCounter = $newestExistingVersion->first()->VersionCounter; $previousVersionCounter = $newestExistingVersion->first()->VersionCounter;
} }
//change the filename field to a field containing the new soon-to-be versioned file //change the filename field to a field containing the new soon-to-be versioned file
$version->VersionCounter = $previousVersionCounter + 1; //start versions at 1 $version->VersionCounter = $previousVersionCounter + 1; //start versions at 1
$newFilename = $version->generateVersionedFilename($doc, $version->VersionCounter); $newFilename = $version->generateVersionedFilename($doc, $version->VersionCounter);
$version->Filename = $newFilename; $version->Filename = $newFilename;
//add a relation back to the origin ID; //add a relation back to the origin ID;
$version->DocumentID = $doc->ID; $version->DocumentID = $doc->ID;
$id = $version->write(); $id = $version->write();
if (!empty($id)) { if (!empty($id)) {
rename($existingPath, $version->getFullPath()); rename($existingPath, $version->getFullPath());
$success = true; $success = true;
} }
} }
return $success; return $success;
} }
public function delete() { public function delete()
$path = $this->getFullPath(); {
$path = $this->getFullPath();
if (file_exists($path)) unlink($path); if (file_exists($path)) {
unlink($path);
}
parent::delete(); parent::delete();
} }
/** /**
* Returns a DataList of all previous Versions of a document (check the * Returns a DataList of all previous Versions of a document (check the
* LastEdited date of each object to find the correct one). * LastEdited date of each object to find the correct one).
* *
* @static * @static
* @param DMSDocument $doc * @param DMSDocument $doc
* *
* @return DataList List of Document objects * @return DataList List of Document objects
*/ */
static function get_versions(DMSDocument $doc) { public static function get_versions(DMSDocument $doc)
if (!DMSDocument_versions::$enable_versions) user_error("DMSDocument versions are disabled",E_USER_WARNING); {
return DMSDocument_versions::get()->filter(array('DocumentID' => $doc->ID)); if (!DMSDocument_versions::$enable_versions) {
} user_error("DMSDocument versions are disabled", E_USER_WARNING);
}
return DMSDocument_versions::get()->filter(array('DocumentID' => $doc->ID));
}
public function __construct($record = null, $isSingleton = false, $model = null) { public function __construct($record = null, $isSingleton = false, $model = null)
//check what the constructor was passed {
$dmsObject = null; //check what the constructor was passed
if ($record && is_subclass_of($record,'DMSDocumentInterface')) { $dmsObject = null;
$dmsObject = $record; if ($record && is_subclass_of($record, 'DMSDocumentInterface')) {
$record = null; //cancel the record creation to just create an empty object $dmsObject = $record;
} $record = null; //cancel the record creation to just create an empty object
}
//create the object //create the object
parent::__construct($record, $isSingleton, $model); parent::__construct($record, $isSingleton, $model);
//copy the DMSDocument object, if passed into the constructor //copy the DMSDocument object, if passed into the constructor
if ($dmsObject) { if ($dmsObject) {
foreach(array_keys(DataObject::custom_database_fields($dmsObject->ClassName)) as $key) { foreach (array_keys(DataObject::custom_database_fields($dmsObject->ClassName)) as $key) {
$this->$key = $dmsObject->$key; $this->$key = $dmsObject->$key;
} }
} }
} }
/** /**
* Returns a link to download this document from the DMS store. * Returns a link to download this document from the DMS store.
* *
* @return string * @return string
*/ */
public function getLink() { public function getLink()
return Controller::join_links(Director::baseURL(),'dmsdocument/version'.$this->ID); {
} return Controller::join_links(Director::baseURL(), 'dmsdocument/version'.$this->ID);
}
/** /**
* Document versions are always hidden from outside viewing. Only admins can * Document versions are always hidden from outside viewing. Only admins can
* download them. * download them.
* *
* @return bool * @return bool
*/ */
public function isHidden() { public function isHidden()
return true; {
} return true;
}
/** /**
* Returns the full filename of the document stored in this object. Can * Returns the full filename of the document stored in this object. Can
* optionally specify which filename to use at the end. * optionally specify which filename to use at the end.
* *
* @param string * @param string
* *
* @return string * @return string
*/ */
public function getFullPath($filename = null) { public function getFullPath($filename = null)
if (!$filename) $filename = $this->Filename; {
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $filename; if (!$filename) {
} $filename = $this->Filename;
}
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $filename;
}
/** /**
* @return string * @return string
*/ */
public function getFilenameWithoutID() { public function getFilenameWithoutID()
$filenameParts = explode('~',$this->Filename); {
$filename = array_pop($filenameParts); $filenameParts = explode('~', $this->Filename);
$filename = array_pop($filenameParts);
return $filename; return $filename;
} }
/** /**
* Creates a new filename for the current Document's file when replacing the * Creates a new filename for the current Document's file when replacing the
* current file with a new file. * current file with a new file.
* *
* @param DMSDocument $filename The original filename * @param DMSDocument $filename The original filename
* *
* @return string The new filename * @return string The new filename
*/ */
protected function generateVersionedFilename(DMSDocument $doc, $versionCounter) { protected function generateVersionedFilename(DMSDocument $doc, $versionCounter)
$filename = $doc->Filename; {
$filename = $doc->Filename;
do { do {
$versionPaddingString = str_pad($versionCounter, 4, '0', STR_PAD_LEFT); //add leading zeros to make sorting accurate up to 10,000 documents $versionPaddingString = str_pad($versionCounter, 4, '0', STR_PAD_LEFT); //add leading zeros to make sorting accurate up to 10,000 documents
$newVersionFilename = preg_replace('/([0-9]+~)(.*?)/','$1~'.$versionPaddingString.'~$2',$filename); $newVersionFilename = preg_replace('/([0-9]+~)(.*?)/', '$1~'.$versionPaddingString.'~$2', $filename);
if ($newVersionFilename == $filename || empty($newVersionFilename)) { //sanity check for crazy document names if ($newVersionFilename == $filename || empty($newVersionFilename)) { //sanity check for crazy document names
user_error('Cannot generate new document filename for file: '.$filename,E_USER_ERROR); user_error('Cannot generate new document filename for file: '.$filename, E_USER_ERROR);
} }
$versionCounter++; //increase the counter for the next loop run, if necessary $versionCounter++; //increase the counter for the next loop run, if necessary
} while(file_exists($this->getFullPath($newVersionFilename))); } while (file_exists($this->getFullPath($newVersionFilename)));
return $newVersionFilename; return $newVersionFilename;
} }
/** /**
* Return the extension of the file associated with the document. * Return the extension of the file associated with the document.
* *
* @return string * @return string
*/ */
public function getExtension() { public function getExtension()
return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION)); {
} return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION));
}
/** /**
* @return string * @return string
*/ */
public function getSize() { public function getSize()
$size = $this->getAbsoluteSize(); {
$size = $this->getAbsoluteSize();
return ($size) ? File::format_size($size) : false; return ($size) ? File::format_size($size) : false;
} }
/** /**
* Return the size of the file associated with the document. * Return the size of the file associated with the document.
* *
* @return string * @return string
*/ */
public function getAbsoluteSize() { public function getAbsoluteSize()
return filesize($this->getFullPath()); {
} return filesize($this->getFullPath());
}
/** /**
* An alias to DMSDocument::getSize() * An alias to DMSDocument::getSize()
* *
* @return string * @return string
*/ */
public function getFileSizeFormatted() { public function getFileSizeFormatted()
return $this->getSize(); {
} return $this->getSize();
}
/** /**
* @return DMSDocument_versions * @return DMSDocument_versions
*/ */
public function trackView() { public function trackView()
if ($this->ID > 0) { {
$this->VersionViewCount++; if ($this->ID > 0) {
$this->VersionViewCount++;
$count = $this->VersionViewCount; $count = $this->VersionViewCount;
DB::query("UPDATE \"DMSDocument_versions\" SET \"VersionViewCount\"='$count' WHERE \"ID\"={$this->ID}"); DB::query("UPDATE \"DMSDocument_versions\" SET \"VersionViewCount\"='$count' WHERE \"ID\"={$this->ID}");
} }
return $this; return $this;
} }
}
}

View File

@ -5,15 +5,16 @@
* *
* @package dms * @package dms
*/ */
class DMSTag extends DataObject { class DMSTag extends DataObject
{
private static $db = array( private static $db = array(
'Category' => 'Varchar(1024)', 'Category' => 'Varchar(1024)',
'Value' => 'Varchar(1024)', 'Value' => 'Varchar(1024)',
'MultiValue' => 'Boolean(1)' 'MultiValue' => 'Boolean(1)'
); );
private static $belongs_many_many = array( private static $belongs_many_many = array(
'Documents' => 'DMSDocument' 'Documents' => 'DMSDocument'
); );
} }

View File

@ -9,73 +9,85 @@
* search across dozens of columns and tables - but for a couple of hundred pages * search across dozens of columns and tables - but for a couple of hundred pages
* and occasionally use its a feasible solution. * and occasionally use its a feasible solution.
*/ */
class ShortCodeRelationFinder { class ShortCodeRelationFinder
{
/** /**
* @var String Regex matching a {@link DBField} class name which is shortcode capable. * @var String Regex matching a {@link DBField} class name which is shortcode capable.
* *
* This should really look for implementors of a ShortCodeParseable interface, * This should really look for implementors of a ShortCodeParseable interface,
* but we can't extend the core Text and HTMLText class * but we can't extend the core Text and HTMLText class
* on existing like SiteTree.Content for this. * on existing like SiteTree.Content for this.
*/ */
protected $fieldSpecRegex = '/^(HTMLText)/'; protected $fieldSpecRegex = '/^(HTMLText)/';
/** /**
* @param String Shortcode index number to find * @param String Shortcode index number to find
* @return array IDs * @return array IDs
*/ */
function findPageIDs($number) { public function findPageIDs($number)
$list = $this->getList($number); {
$found = $list->column(); $list = $this->getList($number);
return $found; $found = $list->column();
} return $found;
}
function findPageCount($number) { public function findPageCount($number)
$list = $this->getList($number); {
return $list->count(); $list = $this->getList($number);
} return $list->count();
}
/** /**
* @return DataList * @return DataList
*/ */
function getList($number) { public function getList($number)
$list = DataList::create('SiteTree'); {
$where = array(); $list = DataList::create('SiteTree');
$fields = $this->getShortCodeFields('SiteTree'); $where = array();
foreach($fields as $ancClass => $ancFields) { $fields = $this->getShortCodeFields('SiteTree');
foreach($ancFields as $ancFieldName => $ancFieldSpec) { foreach ($fields as $ancClass => $ancFields) {
if ($ancClass != "SiteTree") $list = $list->leftJoin($ancClass,'"'.$ancClass.'"."ID" = "SiteTree"."ID"'); foreach ($ancFields as $ancFieldName => $ancFieldSpec) {
$where[] = "\"$ancClass\".\"$ancFieldName\" LIKE '%[dms_document_link,id=$number]%'"; //."%s" LIKE ""', if ($ancClass != "SiteTree") {
} $list = $list->leftJoin($ancClass, '"'.$ancClass.'"."ID" = "SiteTree"."ID"');
} }
$where[] = "\"$ancClass\".\"$ancFieldName\" LIKE '%[dms_document_link,id=$number]%'"; //."%s" LIKE ""',
}
}
$list = $list->where(implode(' OR ', $where)); $list = $list->where(implode(' OR ', $where));
return $list; return $list;
} }
/** /**
* Returns a filtered list of fields which could contain shortcodes. * Returns a filtered list of fields which could contain shortcodes.
* *
* @param String * @param String
* @return Array Map of class names to an array of field names on these classes. * @return Array Map of class names to an array of field names on these classes.
*/ */
function getShortcodeFields($class) { public function getShortcodeFields($class)
$fields = array(); {
$ancestry = array_values(ClassInfo::dataClassesFor($class)); $fields = array();
$ancestry = array_values(ClassInfo::dataClassesFor($class));
foreach($ancestry as $ancestor) { foreach ($ancestry as $ancestor) {
if(ClassInfo::classImplements($ancestor, 'TestOnly')) continue; if (ClassInfo::classImplements($ancestor, 'TestOnly')) {
continue;
}
$ancFields = DataObject::custom_database_fields($ancestor); $ancFields = DataObject::custom_database_fields($ancestor);
if($ancFields) foreach($ancFields as $ancFieldName => $ancFieldSpec) { if ($ancFields) {
if(preg_match($this->fieldSpecRegex, $ancFieldSpec)) { foreach ($ancFields as $ancFieldName => $ancFieldSpec) {
if(!@$fields[$ancestor]) $fields[$ancestor] = array(); if (preg_match($this->fieldSpecRegex, $ancFieldSpec)) {
$fields[$ancestor][$ancFieldName] = $ancFieldSpec; if (!@$fields[$ancestor]) {
} $fields[$ancestor] = array();
} }
} $fields[$ancestor][$ancFieldName] = $ancFieldSpec;
}
return $fields; }
} }
}
return $fields;
}
} }

View File

@ -1,155 +1,160 @@
<?php <?php
class DMSDocumentTest extends SapphireTest { class DMSDocumentTest extends SapphireTest
{
static $fixture_file = "dms/tests/dmstest.yml"; public static $fixture_file = "dms/tests/dmstest.yml";
function tearDownOnce() { public function tearDownOnce()
self::$is_running_test = true; {
self::$is_running_test = true;
$d = DataObject::get("DMSDocument");
foreach($d as $d1) { $d = DataObject::get("DMSDocument");
$d1->delete(); foreach ($d as $d1) {
} $d1->delete();
$t = DataObject::get("DMSTag"); }
foreach($t as $t1) { $t = DataObject::get("DMSTag");
$t1->delete(); foreach ($t as $t1) {
} $t1->delete();
}
self::$is_running_test = $this->originalIsRunningTest; self::$is_running_test = $this->originalIsRunningTest;
} }
function testPageRelations() { public function testPageRelations()
$s1 = $this->objFromFixture('SiteTree','s1'); {
$s2 = $this->objFromFixture('SiteTree','s2'); $s1 = $this->objFromFixture('SiteTree', 's1');
$s3 = $this->objFromFixture('SiteTree','s3'); $s2 = $this->objFromFixture('SiteTree', 's2');
$s4 = $this->objFromFixture('SiteTree','s4'); $s3 = $this->objFromFixture('SiteTree', 's3');
$s5 = $this->objFromFixture('SiteTree','s5'); $s4 = $this->objFromFixture('SiteTree', 's4');
$s6 = $this->objFromFixture('SiteTree','s6'); $s5 = $this->objFromFixture('SiteTree', 's5');
$s6 = $this->objFromFixture('SiteTree', 's6');
$d1 = $this->objFromFixture('DMSDocument','d1'); $d1 = $this->objFromFixture('DMSDocument', 'd1');
$pages = $d1->Pages(); $pages = $d1->Pages();
$pagesArray = $pages->toArray(); $pagesArray = $pages->toArray();
$this->assertEquals($pagesArray[0]->ID, $s1->ID, "Page 1 associated correctly"); $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[1]->ID, $s2->ID, "Page 2 associated correctly");
$this->assertEquals($pagesArray[2]->ID, $s3->ID, "Page 3 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[3]->ID, $s4->ID, "Page 4 associated correctly");
$this->assertEquals($pagesArray[4]->ID, $s5->ID, "Page 5 associated correctly"); $this->assertEquals($pagesArray[4]->ID, $s5->ID, "Page 5 associated correctly");
$this->assertEquals($pagesArray[5]->ID, $s6->ID, "Page 6 associated correctly"); $this->assertEquals($pagesArray[5]->ID, $s6->ID, "Page 6 associated correctly");
} }
function testAddPageRelation() { public function testAddPageRelation()
$s1 = $this->objFromFixture('SiteTree','s1'); {
$s2 = $this->objFromFixture('SiteTree','s2'); $s1 = $this->objFromFixture('SiteTree', 's1');
$s3 = $this->objFromFixture('SiteTree','s3'); $s2 = $this->objFromFixture('SiteTree', 's2');
$s3 = $this->objFromFixture('SiteTree', 's3');
$doc = new DMSDocument(); $doc = new DMSDocument();
$doc->Filename = "test file"; $doc->Filename = "test file";
$doc->Folder = "0"; $doc->Folder = "0";
$doc->write(); $doc->write();
$doc->addPage($s1); $doc->addPage($s1);
$doc->addPage($s2); $doc->addPage($s2);
$doc->addPage($s3); $doc->addPage($s3);
$pages = $doc->Pages(); $pages = $doc->Pages();
$pagesArray = $pages->toArray(); $pagesArray = $pages->toArray();
$this->assertEquals($pagesArray[0]->ID, $s1->ID, "Page 1 associated correctly"); $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[1]->ID, $s2->ID, "Page 2 associated correctly");
$this->assertEquals($pagesArray[2]->ID, $s3->ID, "Page 3 associated correctly"); $this->assertEquals($pagesArray[2]->ID, $s3->ID, "Page 3 associated correctly");
$doc->removePage($s1); $doc->removePage($s1);
$pages = $doc->Pages(); $pages = $doc->Pages();
$pagesArray = $pages->toArray(); //page 1 is missing $pagesArray = $pages->toArray(); //page 1 is missing
$this->assertEquals($pagesArray[0]->ID, $s2->ID, "Page 2 still associated correctly"); $this->assertEquals($pagesArray[0]->ID, $s2->ID, "Page 2 still associated correctly");
$this->assertEquals($pagesArray[1]->ID, $s3->ID, "Page 3 still associated correctly"); $this->assertEquals($pagesArray[1]->ID, $s3->ID, "Page 3 still associated correctly");
$documents = $s2->Documents(); $documents = $s2->Documents();
$documentsArray = $documents->toArray(); $documentsArray = $documents->toArray();
$this->assertDOSContains(array(array('Filename'=>$doc->Filename)), $documentsArray, "Document associated with page"); $this->assertDOSContains(array(array('Filename'=>$doc->Filename)), $documentsArray, "Document associated with page");
$doc->removeAllPages(); $doc->removeAllPages();
$pages = $doc->Pages(); $pages = $doc->Pages();
$this->assertEquals($pages->Count(), 0, "All pages removed"); $this->assertEquals($pages->Count(), 0, "All pages removed");
$documents = $s2->Documents(); $documents = $s2->Documents();
$documentsArray = $documents->toArray(); $documentsArray = $documents->toArray();
$this->assertNotContains($doc, $documentsArray, "Document no longer associated with page"); $this->assertNotContains($doc, $documentsArray, "Document no longer associated with page");
} }
function testDeletingPageWithAssociatedDocuments() { public function testDeletingPageWithAssociatedDocuments()
$s1 = $this->objFromFixture('SiteTree','s1'); {
$s2 = $this->objFromFixture('SiteTree','s2'); $s1 = $this->objFromFixture('SiteTree', 's1');
$s2->publish('Stage', 'Live'); $s2 = $this->objFromFixture('SiteTree', 's2');
$s2ID = $s2->ID; $s2->publish('Stage', 'Live');
$s2ID = $s2->ID;
$doc = new DMSDocument(); $doc = new DMSDocument();
$doc->Filename = "delete test file"; $doc->Filename = "delete test file";
$doc->Folder = "0"; $doc->Folder = "0";
$doc->write(); $doc->write();
$doc->addPage($s1); $doc->addPage($s1);
$doc->addPage($s2); $doc->addPage($s2);
$s1->delete(); $s1->delete();
$documents = DataObject::get("DMSDocument","\"Filename\" = 'delete test file'", false); $documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'", false);
$this->assertEquals( $this->assertEquals(
$documents->Count(), $documents->Count(),
'1', '1',
"Deleting one of the associated page doesn't affect the single document we created" "Deleting one of the associated page doesn't affect the single document we created"
); );
$s2->delete(); $s2->delete();
$documents = DataObject::get("DMSDocument","\"Filename\" = 'delete test file'"); $documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
$this->assertEquals( $this->assertEquals(
$documents->Count(), $documents->Count(),
'1', '1',
"Deleting a page from draft stage doesn't delete the associated docs," "Deleting a page from draft stage doesn't delete the associated docs,"
. "even if it's the last page they're associated with" . "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 = Versioned::get_one_by_stage('SiteTree', 'Live', sprintf('"SiteTree"."ID" = %d', $s2ID));
$s2->doDeleteFromLive(); $s2->doDeleteFromLive();
$documents = DataObject::get("DMSDocument","\"Filename\" = 'delete test file'"); $documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
$this->assertEquals( $this->assertEquals(
$documents->Count(), $documents->Count(),
'0', '0',
"However, deleting the live version of the last page that a document is " "However, deleting the live version of the last page that a document is "
."associated with causes that document to be deleted as well" ."associated with causes that document to be deleted as well"
); );
} }
function testUnpublishPageWithAssociatedDocuments() { public function testUnpublishPageWithAssociatedDocuments()
$s2 = $this->objFromFixture('SiteTree','s2'); {
$s2->publish('Stage', 'Live'); $s2 = $this->objFromFixture('SiteTree', 's2');
$s2ID = $s2->ID; $s2->publish('Stage', 'Live');
$s2ID = $s2->ID;
$doc = new DMSDocument(); $doc = new DMSDocument();
$doc->Filename = "delete test file"; $doc->Filename = "delete test file";
$doc->Folder = "0"; $doc->Folder = "0";
$doc->write(); $doc->write();
$doc->addPage($s2); $doc->addPage($s2);
$s2->doDeleteFromLive(); $s2->doDeleteFromLive();
$documents = DataObject::get("DMSDocument","\"Filename\" = 'delete test file'"); $documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
$this->assertEquals( $this->assertEquals(
$documents->Count(), $documents->Count(),
'1', '1',
"Deleting a page from live stage doesn't delete the associated docs," "Deleting a page from live stage doesn't delete the associated docs,"
. "even if it's the last page they're associated with" . "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 = Versioned::get_one_by_stage('SiteTree', 'Stage', sprintf('"SiteTree"."ID" = %d', $s2ID));
$s2->delete(); $s2->delete();
$documents = DataObject::get("DMSDocument","\"Filename\" = 'delete test file'"); $documents = DataObject::get("DMSDocument", "\"Filename\" = 'delete test file'");
$this->assertEquals( $this->assertEquals(
$documents->Count(), $documents->Count(),
'0', '0',
"However, deleting the draft version of the last page that a document is " "However, deleting the draft version of the last page that a document is "
."associated with causes that document to be deleted as well" ."associated with causes that document to be deleted as well"
); );
} }
}
}

View File

@ -1,196 +1,203 @@
<?php <?php
class DMSEmbargoTest extends SapphireTest { class DMSEmbargoTest extends SapphireTest
{
static $fixture_file = "dms/tests/dmsembargotest.yml"; public static $fixture_file = "dms/tests/dmsembargotest.yml";
function tearDownOnce() { public function tearDownOnce()
self::$is_running_test = true; {
self::$is_running_test = true;
$d = DataObject::get("DMSDocument");
foreach($d as $d1) { $d = DataObject::get("DMSDocument");
$d1->delete(); foreach ($d as $d1) {
} $d1->delete();
$t = DataObject::get("DMSTag"); }
foreach($t as $t1) { $t = DataObject::get("DMSTag");
$t1->delete(); foreach ($t as $t1) {
} $t1->delete();
}
self::$is_running_test = $this->originalIsRunningTest; self::$is_running_test = $this->originalIsRunningTest;
} }
function createFakeHTTPRequest($id) { public function createFakeHTTPRequest($id)
$r = new SS_HTTPRequest('GET','index/'.$id); {
$r->match('index/$ID'); $r = new SS_HTTPRequest('GET', 'index/'.$id);
return $r; $r->match('index/$ID');
} return $r;
}
function testBasicEmbargo() { public function testBasicEmbargo()
$oldDMSFolder = DMS::$dmsFolder; {
DMS::$dmsFolder = DMS_DIR; //sneakily setting the DMS folder to the folder where the test file lives $oldDMSFolder = DMS::$dmsFolder;
DMS::$dmsFolder = DMS_DIR; //sneakily setting the DMS folder to the folder where the test file lives
$doc = new DMSDocument(); $doc = new DMSDocument();
$doc->Filename = "DMS-test-lorum-file.pdf"; $doc->Filename = "DMS-test-lorum-file.pdf";
$doc->Folder = "tests"; $doc->Folder = "tests";
$docID = $doc->write(); $docID = $doc->write();
//fake a request for a document //fake a request for a document
$controller = new DMSDocument_Controller(); $controller = new DMSDocument_Controller();
DMSDocument_Controller::$testMode = true; DMSDocument_Controller::$testMode = true;
$result = $controller->index($this->createFakeHTTPRequest($docID)); $result = $controller->index($this->createFakeHTTPRequest($docID));
$this->assertEquals($doc->getFullPath(),$result,"Correct underlying file returned (in test mode)"); $this->assertEquals($doc->getFullPath(), $result, "Correct underlying file returned (in test mode)");
$doc->embargoIndefinitely(); $doc->embargoIndefinitely();
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
$result = $controller->index($this->createFakeHTTPRequest($docID)); $result = $controller->index($this->createFakeHTTPRequest($docID));
$this->assertEquals($doc->getFullPath(),$result,"Admins can still download embargoed files"); $this->assertEquals($doc->getFullPath(), $result, "Admins can still download embargoed files");
$this->logInWithPermission('random-user-group'); $this->logInWithPermission('random-user-group');
$result = $controller->index($this->createFakeHTTPRequest($docID)); $result = $controller->index($this->createFakeHTTPRequest($docID));
$this->assertNotEquals($doc->getFullPath(),$result,"File no longer returned (in test mode) when switching to other user group"); $this->assertNotEquals($doc->getFullPath(), $result, "File no longer returned (in test mode) when switching to other user group");
DMS::$dmsFolder = $oldDMSFolder; DMS::$dmsFolder = $oldDMSFolder;
} }
function testEmbargoIndefinitely() { public function testEmbargoIndefinitely()
$doc = new DMSDocument(); {
$doc->Filename = "DMS-test-lorum-file.pdf"; $doc = new DMSDocument();
$doc->Folder = "tests"; $doc->Filename = "DMS-test-lorum-file.pdf";
$doc->write(); $doc->Folder = "tests";
$doc->write();
$doc->embargoIndefinitely(); $doc->embargoIndefinitely();
$this->assertTrue($doc->isHidden(),"Document is hidden"); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$this->assertFalse($doc->isExpired(),"Document is not expired"); $this->assertFalse($doc->isExpired(), "Document is not expired");
$doc->clearEmbargo(); $doc->clearEmbargo();
$this->assertFalse($doc->isHidden(),"Document is not hidden"); $this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isExpired(),"Document is not expired"); $this->assertFalse($doc->isExpired(), "Document is not expired");
}
} public function testExpireAtDate()
{
$doc = new DMSDocument();
$doc->Filename = "DMS-test-lorum-file.pdf";
$doc->Folder = "tests";
$doc->write();
function testExpireAtDate() { $doc->expireAtDate(strtotime('-1 second'));
$doc = new DMSDocument(); $this->assertTrue($doc->isHidden(), "Document is hidden");
$doc->Filename = "DMS-test-lorum-file.pdf"; $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$doc->Folder = "tests"; $this->assertTrue($doc->isExpired(), "Document is expired");
$doc->write();
$doc->expireAtDate(strtotime('-1 second')); $expireTime = "2019-04-05 11:43:13";
$this->assertTrue($doc->isHidden(),"Document is hidden"); $doc->expireAtDate($expireTime);
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertTrue($doc->isExpired(),"Document is expired"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
$expireTime = "2019-04-05 11:43:13"; SS_Datetime::set_mock_now($expireTime);
$doc->expireAtDate($expireTime); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertFalse($doc->isHidden(),"Document is not hidden"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertTrue($doc->isExpired(), "Document is expired");
$this->assertFalse($doc->isExpired(),"Document is not expired"); SS_Datetime::clear_mock_now();
SS_Datetime::set_mock_now($expireTime); $doc->expireAtDate(strtotime('-1 second'));
$this->assertTrue($doc->isHidden(),"Document is hidden"); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertTrue($doc->isExpired(),"Document is expired"); $this->assertTrue($doc->isExpired(), "Document is expired");
SS_Datetime::clear_mock_now();
$doc->expireAtDate(strtotime('-1 second')); $doc->clearExpiry();
$this->assertTrue($doc->isHidden(),"Document is hidden"); $this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertTrue($doc->isExpired(),"Document is expired"); $this->assertFalse($doc->isExpired(), "Document is not expired");
}
$doc->clearExpiry(); public function testEmbargoUntilDate()
$this->assertFalse($doc->isHidden(),"Document is not hidden"); {
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $doc = new DMSDocument();
$this->assertFalse($doc->isExpired(),"Document is not expired"); $doc->Filename = "DMS-test-lorum-file.pdf";
} $doc->Folder = "tests";
$doc->write();
function testEmbargoUntilDate() { $doc->embargoUntilDate(strtotime('+1 minute'));
$doc = new DMSDocument(); $this->assertTrue($doc->isHidden(), "Document is hidden");
$doc->Filename = "DMS-test-lorum-file.pdf"; $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$doc->Folder = "tests";
$doc->write();
$doc->embargoUntilDate(strtotime('+1 minute')); $this->assertFalse($doc->isExpired(), "Document is not expired");
$this->assertTrue($doc->isHidden(),"Document is hidden");
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed");
$this->assertFalse($doc->isExpired(),"Document is not expired"); $doc->embargoUntilDate(strtotime('-1 second'));
$this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
$doc->embargoUntilDate(strtotime('-1 second')); $embargoTime = "2019-04-05 11:43:13";
$this->assertFalse($doc->isHidden(),"Document is not hidden"); $doc->embargoUntilDate($embargoTime);
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertFalse($doc->isExpired(),"Document is not expired"); $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
$embargoTime = "2019-04-05 11:43:13"; SS_Datetime::set_mock_now($embargoTime);
$doc->embargoUntilDate($embargoTime); $this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertTrue($doc->isHidden(),"Document is hidden"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); $this->assertFalse($doc->isExpired(), "Document is not expired");
$this->assertFalse($doc->isExpired(),"Document is not expired");
SS_Datetime::set_mock_now($embargoTime); SS_Datetime::clear_mock_now();
$this->assertFalse($doc->isHidden(),"Document is not hidden");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed");
$this->assertFalse($doc->isExpired(),"Document is not expired");
SS_Datetime::clear_mock_now(); $doc->clearEmbargo();
$this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
}
$doc->clearEmbargo(); public function testEmbargoUntilPublished()
$this->assertFalse($doc->isHidden(),"Document is not hidden"); {
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $s1 = $this->objFromFixture('SiteTree', 's1');
$this->assertFalse($doc->isExpired(),"Document is not expired");
}
function testEmbargoUntilPublished() { $doc = new DMSDocument();
$s1 = $this->objFromFixture('SiteTree','s1'); $doc->Filename = "test file";
$doc->Folder = "0";
$dID = $doc->write();
$doc = new DMSDocument(); $doc->addPage($s1);
$doc->Filename = "test file";
$doc->Folder = "0";
$dID = $doc->write();
$doc->addPage($s1); $s1->publish('Stage', 'Live');
$s1->doPublish();
$this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
$s1->publish('Stage','Live'); $doc->embargoUntilPublished();
$s1->doPublish(); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertFalse($doc->isHidden(),"Document is not hidden"); $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertFalse($doc->isExpired(), "Document is not expired");
$this->assertFalse($doc->isExpired(),"Document is not expired");
$doc->embargoUntilPublished(); $s1->publish('Stage', 'Live');
$this->assertTrue($doc->isHidden(),"Document is hidden"); $s1->doPublish();
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); $doc = DataObject::get_by_id("DMSDocument", $dID);
$this->assertFalse($doc->isExpired(),"Document is not expired"); $this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
$s1->publish('Stage','Live'); $doc->embargoUntilPublished();
$s1->doPublish(); $doc = DataObject::get_by_id("DMSDocument", $dID);
$doc = DataObject::get_by_id("DMSDocument",$dID); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertFalse($doc->isHidden(),"Document is not hidden"); $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed"); $this->assertFalse($doc->isExpired(), "Document is not expired");
$this->assertFalse($doc->isExpired(),"Document is not expired");
$doc->embargoUntilPublished(); $doc->embargoIndefinitely();
$doc = DataObject::get_by_id("DMSDocument",$dID); $doc = DataObject::get_by_id("DMSDocument", $dID);
$this->assertTrue($doc->isHidden(),"Document is hidden"); $this->assertTrue($doc->isHidden(), "Document is hidden");
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$this->assertFalse($doc->isExpired(),"Document is not expired"); $this->assertFalse($doc->isExpired(), "Document is not expired");
$doc->embargoIndefinitely(); $s1->publish('Stage', 'Live');
$doc = DataObject::get_by_id("DMSDocument",$dID); $s1->doPublish();
$this->assertTrue($doc->isHidden(),"Document is hidden"); $doc = DataObject::get_by_id("DMSDocument", $dID);
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); $this->assertTrue($doc->isHidden(), "Document is still hidden because although the untilPublish flag is cleared, the indefinitely flag is still there");
$this->assertFalse($doc->isExpired(),"Document is not expired"); $this->assertTrue($doc->isEmbargoed(), "Document is embargoed");
$this->assertFalse($doc->isExpired(), "Document is not expired");
$s1->publish('Stage','Live'); $doc->clearEmbargo();
$s1->doPublish(); $doc = DataObject::get_by_id("DMSDocument", $dID);
$doc = DataObject::get_by_id("DMSDocument",$dID); $this->assertFalse($doc->isHidden(), "Document is not hidden");
$this->assertTrue($doc->isHidden(),"Document is still hidden because although the untilPublish flag is cleared, the indefinitely flag is still there"); $this->assertFalse($doc->isEmbargoed(), "Document is not embargoed");
$this->assertTrue($doc->isEmbargoed(),"Document is embargoed"); $this->assertFalse($doc->isExpired(), "Document is not expired");
$this->assertFalse($doc->isExpired(),"Document is not expired"); }
}
$doc->clearEmbargo();
$doc = DataObject::get_by_id("DMSDocument",$dID);
$this->assertFalse($doc->isHidden(),"Document is not hidden");
$this->assertFalse($doc->isEmbargoed(),"Document is not embargoed");
$this->assertFalse($doc->isExpired(),"Document is not expired");
}
}

View File

@ -5,22 +5,23 @@
* @package dms * @package dms
* @subpackage tests * @subpackage tests
*/ */
class DMSShortcodeTest extends SapphireTest { class DMSShortcodeTest extends SapphireTest
{
public function testShortcodeOperation() { public function testShortcodeOperation()
$file = 'dms/tests/DMS-test-lorum-file.pdf'; {
$document = DMS::inst()->storeDocument($file); $file = 'dms/tests/DMS-test-lorum-file.pdf';
$document = DMS::inst()->storeDocument($file);
$result = ShortcodeParser::get('default')->parse(sprintf( $result = ShortcodeParser::get('default')->parse(sprintf(
'<p><a href="[dms_document_link id=\'%d\']">Document</a></p>', $document->ID '<p><a href="[dms_document_link id=\'%d\']">Document</a></p>', $document->ID
)); ));
$value = Injector::inst()->create('HTMLValue', $result); $value = Injector::inst()->create('HTMLValue', $result);
$link = $value->query('//a')->item(0); $link = $value->query('//a')->item(0);
$this->assertStringEndsWith("/dmsdocument/$document->ID", $link->getAttribute('href'));
$this->assertEquals($document->getExtension(), $link->getAttribute('data-ext'));
$this->assertEquals($document->getFileSizeFormatted(), $link->getAttribute('data-size'));
}
$this->assertStringEndsWith("/dmsdocument/$document->ID", $link->getAttribute('href'));
$this->assertEquals($document->getExtension(), $link->getAttribute('data-ext'));
$this->assertEquals($document->getFileSizeFormatted(), $link->getAttribute('data-size'));
}
} }

View File

@ -1,118 +1,121 @@
<?php <?php
class DMSTagTest extends SapphireTest { class DMSTagTest extends SapphireTest
{
function tearDownOnce() { public function tearDownOnce()
self::$is_running_test = true; {
self::$is_running_test = true;
$d = DataObject::get("DMSDocument"); $d = DataObject::get("DMSDocument");
foreach($d as $d1) { foreach ($d as $d1) {
$d1->delete(); $d1->delete();
} }
$t = DataObject::get("DMSTag"); $t = DataObject::get("DMSTag");
foreach($t as $t1) { foreach ($t as $t1) {
$t1->delete(); $t1->delete();
} }
self::$is_running_test = $this->originalIsRunningTest; self::$is_running_test = $this->originalIsRunningTest;
} }
function testAddingTags() { public function testAddingTags()
$doc = new DMSDocument(); {
$doc->Filename = "test file"; $doc = new DMSDocument();
$doc->Folder = "0"; $doc->Filename = "test file";
$doc->write(); $doc->Folder = "0";
$doc->write();
$doc->addTag("fruit","banana"); $doc->addTag("fruit", "banana");
$doc->addTag("fruit","orange"); $doc->addTag("fruit", "orange");
$doc->addTag("fruit","apple"); $doc->addTag("fruit", "apple");
$doc->addTag("company","apple"); $doc->addTag("company", "apple");
$doc->addTag("company","SilverStripe"); $doc->addTag("company", "SilverStripe");
$fruits = $doc->getTagsList("fruit"); $fruits = $doc->getTagsList("fruit");
$this->assertNotNull($fruits,"Something returned for fruit tags"); $this->assertNotNull($fruits, "Something returned for fruit tags");
$this->assertEquals(count($fruits),3,"3 fruit tags returned"); $this->assertEquals(count($fruits), 3, "3 fruit tags returned");
$this->assertTrue(in_array("banana",$fruits),"correct 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 //sneakily create another document and link one of the tags to that, too
$doc2 = new DMSDocument(); $doc2 = new DMSDocument();
$doc2->Filename = "sneaky file"; $doc2->Filename = "sneaky file";
$doc2->Folder = "0"; $doc2->Folder = "0";
$doc2->write(); $doc2->write();
$doc2->addTag("fruit","banana"); $doc2->addTag("fruit", "banana");
$fruits = $doc2->getTagsList("fruit"); $fruits = $doc2->getTagsList("fruit");
$this->assertNotNull($fruits,"Something returned for fruit tags"); $this->assertNotNull($fruits, "Something returned for fruit tags");
$this->assertEquals(count($fruits),1,"Only 1 fruit tags returned"); $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) //tidy up by deleting all tags from doc 1 (But the banana fruit tag should remain)
$doc->removeAllTags(); $doc->removeAllTags();
//banana fruit remains //banana fruit remains
$fruits = $doc2->getTagsList("fruit"); $fruits = $doc2->getTagsList("fruit");
$this->assertNotNull($fruits,"Something returned for fruit tags"); $this->assertNotNull($fruits, "Something returned for fruit tags");
$this->assertEquals(count($fruits),1,"Only 1 fruit tags returned"); $this->assertEquals(count($fruits), 1, "Only 1 fruit tags returned");
$tags = DataObject::get("DMSTag"); $tags = DataObject::get("DMSTag");
$this->assertEquals($tags->Count(),1,"A single DMS tag objects remain after deletion of all tags on doc1"); $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 //delete all tags off doc2 to complete the tidy up
$doc2->removeAllTags(); $doc2->removeAllTags();
$tags = DataObject::get("DMSTag"); $tags = DataObject::get("DMSTag");
$this->assertEquals($tags->Count(),0,"No DMS tag objects remain after deletion"); $this->assertEquals($tags->Count(), 0, "No DMS tag objects remain after deletion");
} }
function testRemovingTags() { public function testRemovingTags()
$doc = new DMSDocument(); {
$doc->Filename = "test file"; $doc = new DMSDocument();
$doc->Folder = "0"; $doc->Filename = "test file";
$doc->write(); $doc->Folder = "0";
$doc->write();
$doc->addTag("fruit","banana"); $doc->addTag("fruit", "banana");
$doc->addTag("fruit","orange"); $doc->addTag("fruit", "orange");
$doc->addTag("fruit","apple"); $doc->addTag("fruit", "apple");
$doc->addTag("company","apple"); $doc->addTag("company", "apple");
$doc->addTag("company","SilverStripe"); $doc->addTag("company", "SilverStripe");
$companies = $doc->getTagsList("company"); $companies = $doc->getTagsList("company");
$this->assertNotNull($companies,"Companies returned before deletion"); $this->assertNotNull($companies, "Companies returned before deletion");
$this->assertEquals(count($companies),2,"Two companies returned before deletion"); $this->assertEquals(count($companies), 2, "Two companies returned before deletion");
//delete an entire category //delete an entire category
$doc->removeTag("company"); $doc->removeTag("company");
$companies = $doc->getTagsList("company"); $companies = $doc->getTagsList("company");
$this->assertNull($companies,"All companies deleted"); $this->assertNull($companies, "All companies deleted");
$fruit = $doc->getTagsList("fruit"); $fruit = $doc->getTagsList("fruit");
$this->assertEquals(count($fruit),3,"Three fruits returned before deletion"); $this->assertEquals(count($fruit), 3, "Three fruits returned before deletion");
//delete a single tag //delete a single tag
$doc->removeTag("fruit","apple"); $doc->removeTag("fruit", "apple");
$fruit = $doc->getTagsList("fruit"); $fruit = $doc->getTagsList("fruit");
$this->assertEquals(count($fruit),2,"Two fruits returned after deleting one"); $this->assertEquals(count($fruit), 2, "Two fruits returned after deleting one");
//delete a single tag //delete a single tag
$doc->removeTag("fruit","orange"); $doc->removeTag("fruit", "orange");
$fruit = $doc->getTagsList("fruit"); $fruit = $doc->getTagsList("fruit");
$this->assertEquals(count($fruit),1,"One fruits returned after deleting two"); $this->assertEquals(count($fruit), 1, "One fruits returned after deleting two");
//nothing happens when deleting tag that doesn't exist //nothing happens when deleting tag that doesn't exist
$doc->removeTag("fruit","jellybean"); $doc->removeTag("fruit", "jellybean");
$fruit = $doc->getTagsList("fruit"); $fruit = $doc->getTagsList("fruit");
$this->assertEquals(count($fruit),1,"One fruits returned after attempting to delete non-existent fruit"); $this->assertEquals(count($fruit), 1, "One fruits returned after attempting to delete non-existent fruit");
//delete the last fruit //delete the last fruit
$doc->removeTag("fruit","banana"); $doc->removeTag("fruit", "banana");
$fruit = $doc->getTagsList("fruit"); $fruit = $doc->getTagsList("fruit");
$this->assertNull($fruit,"All fruits deleted"); $this->assertNull($fruit, "All fruits deleted");
$tags = DataObject::get("DMSTag"); $tags = DataObject::get("DMSTag");
$this->assertEquals($tags->Count(),0,"No DMS tag objects remain after deletion"); $this->assertEquals($tags->Count(), 0, "No DMS tag objects remain after deletion");
} }
}
}

View File

@ -1,131 +1,139 @@
<?php <?php
class DMSTest extends FunctionalTest { class DMSTest extends FunctionalTest
{
static $testFile = 'dms/tests/DMS-test-lorum-file.pdf'; public static $testFile = 'dms/tests/DMS-test-lorum-file.pdf';
static $testFile2 = 'dms/tests/DMS-test-document-2.pdf'; public static $testFile2 = 'dms/tests/DMS-test-document-2.pdf';
//store values to reset back to after this test runs //store values to reset back to after this test runs
static $dmsFolderOld; public static $dmsFolderOld;
static $dmsFolderSizeOld; public static $dmsFolderSizeOld;
function setUp() { public function setUp()
parent::setUp(); {
parent::setUp();
self::$dmsFolderOld = DMS::$dmsFolder; self::$dmsFolderOld = DMS::$dmsFolder;
self::$dmsFolderSizeOld = DMS::$dmsFolderSize; self::$dmsFolderSizeOld = DMS::$dmsFolderSize;
//use a test DMS folder, so we don't overwrite the live one //use a test DMS folder, so we don't overwrite the live one
DMS::$dmsFolder = 'dms-assets-test-1234'; DMS::$dmsFolder = 'dms-assets-test-1234';
//clear out the test folder (in case a broken test doesn't delete it) //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->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-1234');
} }
function tearDown() { public function tearDown()
parent::tearDown(); {
parent::tearDown();
self::$is_running_test = true; self::$is_running_test = true;
$d = DataObject::get("DMSDocument"); $d = DataObject::get("DMSDocument");
foreach($d as $d1) { foreach ($d as $d1) {
$d1->delete(); $d1->delete();
} }
$t = DataObject::get("DMSTag"); $t = DataObject::get("DMSTag");
foreach($t as $t1) { foreach ($t as $t1) {
$t1->delete(); $t1->delete();
} }
//delete the test folder after the test runs //delete the test folder after the test runs
$this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-1234'); $this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-1234');
//set the old DMS folder back again //set the old DMS folder back again
DMS::$dmsFolder = self::$dmsFolderOld; DMS::$dmsFolder = self::$dmsFolderOld;
DMS::$dmsFolderSize = self::$dmsFolderSizeOld; DMS::$dmsFolderSize = self::$dmsFolderSizeOld;
self::$is_running_test = $this->originalIsRunningTest; self::$is_running_test = $this->originalIsRunningTest;
} }
public function delete($path) { public function delete($path)
if (file_exists($path) || is_dir($path)) { {
$it = new RecursiveIteratorIterator( if (file_exists($path) || is_dir($path)) {
new RecursiveDirectoryIterator($path), $it = new RecursiveIteratorIterator(
RecursiveIteratorIterator::CHILD_FIRST new RecursiveDirectoryIterator($path),
); RecursiveIteratorIterator::CHILD_FIRST
foreach ($it as $file) { );
if (in_array($file->getBasename(), array('.', '..'))) { foreach ($it as $file) {
continue; if (in_array($file->getBasename(), array('.', '..'))) {
} elseif ($file->isDir()) { continue;
rmdir($file->getPathname()); } elseif ($file->isDir()) {
} elseif ($file->isFile() || $file->isLink()) { rmdir($file->getPathname());
unlink($file->getPathname()); } elseif ($file->isFile() || $file->isLink()) {
} unlink($file->getPathname());
} }
rmdir($path); }
} rmdir($path);
} }
}
function testDMSStorage() { public function testDMSStorage()
$dms = DMS::inst(); {
$dms = DMS::inst();
$file = self::$testFile; $file = self::$testFile;
$document = $dms->storeDocument($file); $document = $dms->storeDocument($file);
$this->assertNotNull($document, "Document object created"); $this->assertNotNull($document, "Document object created");
$this->assertTrue(file_exists(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); $this->assertTrue(file_exists(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename), "Document file copied into DMS folder");
//$title = $document->getTag('title'); //$title = $document->getTag('title');
} }
function testDMSFolderSpanning() { public function testDMSFolderSpanning()
DMS::$dmsFolderSize = 5; {
$dms = DMS::inst(); DMS::$dmsFolderSize = 5;
$dms = DMS::inst();
$file = self::$testFile; $file = self::$testFile;
$documents = array(); $documents = array();
for($i = 0; $i <= 16; $i++) { for ($i = 0; $i <= 16; $i++) {
$document = $dms->storeDocument($file); $document = $dms->storeDocument($file);
$this->assertNotNull($document, "Document object created on run number: $i"); $this->assertNotNull($document, "Document object created on run number: $i");
$this->assertTrue(file_exists($document->getFullPath())); $this->assertTrue(file_exists($document->getFullPath()));
$documents[] = $document; $documents[] = $document;
} }
//test document objects have their folders set //test document objects have their folders set
$folders = array(); $folders = array();
for($i = 0; $i <= 16; $i++) { for ($i = 0; $i <= 16; $i++) {
$folderName = $documents[$i]->Folder; $folderName = $documents[$i]->Folder;
$this->assertTrue(strpos($documents[$i]->getFullPath(), DIRECTORY_SEPARATOR . $folderName . DIRECTORY_SEPARATOR) !== false, "Correct folder name for the documents. Document path contains reference to folder name '$folderName'"); $this->assertTrue(strpos($documents[$i]->getFullPath(), DIRECTORY_SEPARATOR . $folderName . DIRECTORY_SEPARATOR) !== false, "Correct folder name for the documents. Document path contains reference to folder name '$folderName'");
$folders[] = $folderName; $folders[] = $folderName;
} }
//test we created 4 folder to contain the 17 files //test we created 4 folder to contain the 17 files
foreach($folders as $f) { foreach ($folders as $f) {
$this->assertTrue(is_dir(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $f),"Document folder '$f' exists"); $this->assertTrue(is_dir(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $f), "Document folder '$f' exists");
} }
} }
function testReplaceDocument() { public function testReplaceDocument()
$dms = DMS::inst(); {
$dms = DMS::inst();
//store the first document //store the first document
$document = $dms->storeDocument(self::$testFile); $document = $dms->storeDocument(self::$testFile);
$document->Title = "My custom title"; $document->Title = "My custom title";
$document->Description = "My custom description"; $document->Description = "My custom description";
$document->write(); $document->write();
//then overwrite with a second document //then overwrite with a second document
$document = $document->replaceDocument(self::$testFile2); $document = $document->replaceDocument(self::$testFile2);
$this->assertNotNull($document, "Document object created"); $this->assertNotNull($document, "Document object created");
$this->assertTrue(file_exists(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); $this->assertTrue(file_exists(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename), "Document file copied into DMS folder");
$this->assertContains("DMS-test-document-2",$document->Filename, "Original document filename is contain in the new filename"); $this->assertContains("DMS-test-document-2", $document->Filename, "Original document filename is contain in the new filename");
$this->assertEquals("My custom title", $document->Title , "Custom title not modified"); $this->assertEquals("My custom title", $document->Title, "Custom title not modified");
$this->assertEquals("My custom description", $document->Description, "Custom description not modified"); $this->assertEquals("My custom description", $document->Description, "Custom description not modified");
} }
function testDownloadDocument() { public function testDownloadDocument()
// $dms = DMS::inst(); {
// $dms = DMS::inst();
// //
// //store the first document // //store the first document
// $document = $dms->storeDocument(self::$testFile); // $document = $dms->storeDocument(self::$testFile);
@ -136,7 +144,5 @@ class DMSTest extends FunctionalTest {
// $response = $d->index(new SS_HTTPRequest('GET',$link,array("ID"=>$document->ID))); // $response = $d->index(new SS_HTTPRequest('GET',$link,array("ID"=>$document->ID)));
// //$response = $this->get($link); // //$response = $this->get($link);
// Debug::show($response); // Debug::show($response);
} }
}
}

View File

@ -1,95 +1,96 @@
<?php <?php
class DMSVersioningTest extends SapphireTest { class DMSVersioningTest extends SapphireTest
{
static $testFile = 'dms/tests/DMS-test-lorum-file.pdf'; public static $testFile = 'dms/tests/DMS-test-lorum-file.pdf';
static $testFile2 = 'dms/tests/DMS-test-document-2.pdf'; public static $testFile2 = 'dms/tests/DMS-test-document-2.pdf';
//store values to reset back to after this test runs //store values to reset back to after this test runs
static $dmsFolderOld; public static $dmsFolderOld;
static $dmsFolderSizeOld; public static $dmsFolderSizeOld;
static $dmsEnableVersionsOld; public static $dmsEnableVersionsOld;
function setUp() { public function setUp()
parent::setUp(); {
parent::setUp();
self::$dmsFolderOld = DMS::$dmsFolder; self::$dmsFolderOld = DMS::$dmsFolder;
self::$dmsFolderSizeOld = DMS::$dmsFolderSize; self::$dmsFolderSizeOld = DMS::$dmsFolderSize;
self::$dmsEnableVersionsOld = DMSDocument_versions::$enable_versions; self::$dmsEnableVersionsOld = DMSDocument_versions::$enable_versions;
DMSDocument_versions::$enable_versions = true; DMSDocument_versions::$enable_versions = true;
//use a test DMS folder, so we don't overwrite the live one //use a test DMS folder, so we don't overwrite the live one
DMS::$dmsFolder = 'dms-assets-test-versions'; DMS::$dmsFolder = 'dms-assets-test-versions';
//clear out the test folder (in case a broken test doesn't delete it) //clear out the test folder (in case a broken test doesn't delete it)
$this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-versions'); $this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-versions');
} }
function tearDown() { public function tearDown()
$d = DataObject::get("DMSDocument"); {
foreach($d as $d1) { $d = DataObject::get("DMSDocument");
$d1->delete(); foreach ($d as $d1) {
} $d1->delete();
$t = DataObject::get("DMSTag"); }
foreach($t as $t1) { $t = DataObject::get("DMSTag");
$t1->delete(); foreach ($t as $t1) {
} $t1->delete();
}
//delete the test folder after the test runs //delete the test folder after the test runs
$this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-versions'); $this->delete(BASE_PATH . DIRECTORY_SEPARATOR . 'dms-assets-test-versions');
parent::tearDown(); parent::tearDown();
//set the old DMS folder back again //set the old DMS folder back again
DMS::$dmsFolder = self::$dmsFolderOld; DMS::$dmsFolder = self::$dmsFolderOld;
DMS::$dmsFolderSize = self::$dmsFolderSizeOld; DMS::$dmsFolderSize = self::$dmsFolderSizeOld;
DMSDocument_versions::$enable_versions = self::$dmsEnableVersionsOld; DMSDocument_versions::$enable_versions = self::$dmsEnableVersionsOld;
} }
public function delete($path) { public function delete($path)
if (file_exists($path) || is_dir($path)) { {
$it = new RecursiveIteratorIterator( if (file_exists($path) || is_dir($path)) {
new RecursiveDirectoryIterator($path), $it = new RecursiveIteratorIterator(
RecursiveIteratorIterator::CHILD_FIRST new RecursiveDirectoryIterator($path),
); RecursiveIteratorIterator::CHILD_FIRST
foreach ($it as $file) { );
if (in_array($file->getBasename(), array('.', '..'))) { foreach ($it as $file) {
continue; if (in_array($file->getBasename(), array('.', '..'))) {
} elseif ($file->isDir()) { continue;
rmdir($file->getPathname()); } elseif ($file->isDir()) {
} elseif ($file->isFile() || $file->isLink()) { rmdir($file->getPathname());
unlink($file->getPathname()); } elseif ($file->isFile() || $file->isLink()) {
} unlink($file->getPathname());
} }
rmdir($path); }
} rmdir($path);
} }
}
function testDMSVersionStorage() { public function testDMSVersionStorage()
$dms = DMS::inst(); {
$dms = DMS::inst();
$document = $dms->storeDocument(self::$testFile); $document = $dms->storeDocument(self::$testFile);
$this->assertNotNull($document, "Document object created"); $this->assertNotNull($document, "Document object created");
$this->assertTrue(file_exists(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename),"Document file copied into DMS folder"); $this->assertTrue(file_exists(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $document->Folder . DIRECTORY_SEPARATOR . $document->Filename), "Document file copied into DMS folder");
$document->replaceDocument(self::$testFile2); $document->replaceDocument(self::$testFile2);
$document->replaceDocument(self::$testFile); $document->replaceDocument(self::$testFile);
$document->replaceDocument(self::$testFile2); $document->replaceDocument(self::$testFile2);
$document->replaceDocument(self::$testFile); $document->replaceDocument(self::$testFile);
$versionsList = $document->getVersions(); $versionsList = $document->getVersions();
$this->assertEquals(4, $versionsList->Count(),"4 Versions created"); $this->assertEquals(4, $versionsList->Count(), "4 Versions created");
$versionsArray = $versionsList->toArray(); $versionsArray = $versionsList->toArray();
$this->assertEquals($versionsArray[0]->VersionCounter, 1,"Correct version count"); $this->assertEquals($versionsArray[0]->VersionCounter, 1, "Correct version count");
$this->assertEquals($versionsArray[1]->VersionCounter, 2,"Correct version count"); $this->assertEquals($versionsArray[1]->VersionCounter, 2, "Correct version count");
$this->assertEquals($versionsArray[2]->VersionCounter, 3,"Correct version count"); $this->assertEquals($versionsArray[2]->VersionCounter, 3, "Correct version count");
$this->assertEquals($versionsArray[3]->VersionCounter, 4,"Correct version count"); $this->assertEquals($versionsArray[3]->VersionCounter, 4, "Correct version count");
}
} }
}

View File

@ -1,35 +1,36 @@
<?php <?php
class ShortCodeRelationFinderTest extends SapphireTest { class ShortCodeRelationFinderTest extends SapphireTest
{
static $fixture_file = array( public static $fixture_file = array(
'dms/tests/dmstest.yml' 'dms/tests/dmstest.yml'
); );
function testFindInRate() { public function testFindInRate()
$d1 = $this->objFromFixture('DMSDocument', 'd1'); {
$d2 = $this->objFromFixture('DMSDocument', 'd2'); $d1 = $this->objFromFixture('DMSDocument', 'd1');
$d2 = $this->objFromFixture('DMSDocument', 'd2');
$page1 = new SiteTree(); $page1 = new SiteTree();
$page1->Content = 'Condition: <a title="document test 1" href="[dms_document_link,id='.$d1->ID.']">'; $page1->Content = 'Condition: <a title="document test 1" href="[dms_document_link,id='.$d1->ID.']">';
$page1ID = $page1->write(); $page1ID = $page1->write();
$page2 = new SiteTree(); $page2 = new SiteTree();
$page2->Content = 'Condition: <a title="document test 2" href="[dms_document_link,id='.$d2->ID.']">'; $page2->Content = 'Condition: <a title="document test 2" href="[dms_document_link,id='.$d2->ID.']">';
$page2ID = $page2->write(); $page2ID = $page2->write();
$page3 = new SiteTree(); $page3 = new SiteTree();
$page3->Content = 'Condition: <a title="document test 1" href="[dms_document_link,id='.$d1->ID.']">'; $page3->Content = 'Condition: <a title="document test 1" href="[dms_document_link,id='.$d1->ID.']">';
$page3ID = $page3->write(); $page3ID = $page3->write();
$finder = new ShortCodeRelationFinder(); $finder = new ShortCodeRelationFinder();
$ids = $finder->findPageIDs('UnknownShortcode'); $ids = $finder->findPageIDs('UnknownShortcode');
$this->assertEquals(0, count($ids)); $this->assertEquals(0, count($ids));
$ids = $finder->findPageIDs($d1->ID); $ids = $finder->findPageIDs($d1->ID);
$this->assertNotContains($page2ID, $ids); $this->assertNotContains($page2ID, $ids);
$this->assertContains($page1ID, $ids); $this->assertContains($page1ID, $ids);
$this->assertContains($page3ID, $ids); $this->assertContains($page3ID, $ids);
} }
}
}