diff --git a/code/DMS.php b/code/DMS.php index e58e099..9c8e14d 100644 --- a/code/DMS.php +++ b/code/DMS.php @@ -1,115 +1,130 @@ is_a("File")) $filePath = $file->Filename; + public static function transform_file_to_file_path($file) + { + //confirm we have a file + $filePath = null; + 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. - * 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" + /** + * 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. + * @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) { - $filePath = self::transform_file_to_file_path($file); - - //create a new document and get its ID - $doc = new DMSDocument(); - $doc->write(); - $doc->storeDocument($filePath); + */ + public function storeDocument($file) + { + $filePath = self::transform_file_to_file_path($file); + + //create a new document and get its ID + $doc = new DMSDocument(); + $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, - * by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana") - * @param null $category The metadata category to search for - * @param null $value The metadata value to search for - * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results - * @return DocumentInterface - */ - function getByTag($category = null, $value = null, $showEmbargoed = false) { - // TODO: Implement getByTag() method. - } + /** + * + * Returns a number of Document objects based on the a search by tags. You can search by category alone, + * by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana") + * @param null $category The metadata category to search for + * @param null $value The metadata value to search for + * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results + * @return DocumentInterface + */ + public function getByTag($category = null, $value = null, $showEmbargoed = false) + { + // TODO: Implement getByTag() method. + } - /** - * Returns a number of Document objects that match a full-text search of the Documents and their contents - * (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module) - * @param $searchText String to search for - * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results - * @return DocumentInterface - */ - function getByFullTextSearch($searchText, $showEmbargoed = false) { - // TODO: Implement getByFullTextSearch() method. - } + /** + * Returns a number of Document objects that match a full-text search of the Documents and their contents + * (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module) + * @param $searchText String to search for + * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results + * @return DocumentInterface + */ + public function getByFullTextSearch($searchText, $showEmbargoed = false) + { + // TODO: Implement getByFullTextSearch() method. + } - /** - * Returns a list of Document objects associated with a Page - * @param $page SiteTree to fetch the associated Documents from - * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results - * @return DataList Document list associated with the Page - */ - function getByPage($page, $showEmbargoed = false) { - // TODO: Implement getByPage() method. - } + /** + * Returns a list of Document objects associated with a Page + * @param $page SiteTree to fetch the associated Documents from + * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results + * @return DataList Document list associated with the Page + */ + public function getByPage($page, $showEmbargoed = false) + { + // TODO: Implement getByPage() method. + } - /** - * Creates a storage folder for the given path - * @param $path Path to create a folder for - */ - static function create_storage_folder($path) { - if (!is_dir($path)) { - mkdir($path, 0777); - } - } + /** + * Creates a storage folder for the given path + * @param $path Path to create a folder for + */ + public static function create_storage_folder($path) + { + if (!is_dir($path)) { + mkdir($path, 0777); + } + } - /** - * Calculates the storage path from a database DMSDocument ID - */ - static function get_storage_folder($id) { - $folderName = intval($id / self::$dmsFolderSize); - return $folderName; - } -} \ No newline at end of file + /** + * Calculates the storage path from a database DMSDocument ID + */ + public static function get_storage_folder($id) + { + $folderName = intval($id / self::$dmsFolderSize); + return $folderName; + } +} diff --git a/code/DMSShortcodeHandler.php b/code/DMSShortcodeHandler.php index 377aef8..c1dac54 100644 --- a/code/DMSShortcodeHandler.php +++ b/code/DMSShortcodeHandler.php @@ -6,37 +6,37 @@ * * @package dms */ -class DMSShortcodeHandler { +class DMSShortcodeHandler +{ - public static function handle( - $arguments, $content, ShortcodeParser $parser, $tag, array $extra = array() - ) { - if(!empty($arguments['id'])) { - $document = DMSDocument::get()->byID($arguments['id']); + public static function handle( + $arguments, $content, ShortcodeParser $parser, $tag, array $extra = array() + ) { + if (!empty($arguments['id'])) { + $document = DMSDocument::get()->byID($arguments['id']); - if($document && !$document->isHidden()) { - if($content) { - return sprintf( - '%s', $document->Link(), $parser->parse($content) - ); - } else { - if(isset($extra['element'])) { - $extra['element']->setAttribute('data-ext', $document->getExtension()); - $extra['element']->setAttribute('data-size', $document->getFileSizeFormatted()); - } + if ($document && !$document->isHidden()) { + if ($content) { + return sprintf( + '%s', $document->Link(), $parser->parse($content) + ); + } else { + if (isset($extra['element'])) { + $extra['element']->setAttribute('data-ext', $document->getExtension()); + $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) { - return $error->Link(); - } - - return ''; - } + if ($error) { + return $error->Link(); + } + return ''; + } } diff --git a/code/cms/DMSDocumentAddController.php b/code/cms/DMSDocumentAddController.php index 64ec7e3..428fdcf 100644 --- a/code/cms/DMSDocumentAddController.php +++ b/code/cms/DMSDocumentAddController.php @@ -4,239 +4,254 @@ * @package dms */ -class DMSDocumentAddController extends LeftAndMain { +class DMSDocumentAddController extends LeftAndMain +{ - private static $url_segment = 'pages/adddocument'; - private static $url_priority = 60; - private static $required_permission_codes = 'CMS_ACCESS_AssetAdmin'; - private static $menu_title = 'Edit Page'; - private static $tree_class = 'SiteTree'; - private static $session_namespace = 'CMSMain'; + private static $url_segment = 'pages/adddocument'; + private static $url_priority = 60; + private static $required_permission_codes = 'CMS_ACCESS_AssetAdmin'; + private static $menu_title = 'Edit Page'; + private static $tree_class = 'SiteTree'; + private static $session_namespace = 'CMSMain'; - static $allowed_extensions = array(); + public static $allowed_extensions = array(); - private static $allowed_actions = array ( - 'getEditForm', - 'documentautocomplete', - 'linkdocument', - 'documentlist' - ); + private static $allowed_actions = array( + 'getEditForm', + 'documentautocomplete', + 'linkdocument', + 'documentlist' + ); - /** - * Add an array of additional allowed extensions - * @static - * @param $array - */ - static function add_allowed_extensions($array = null) { - if (empty($array)) return; - if (is_array($array)) self::$allowed_extensions = $array; - else self::$allowed_extensions = array($array); - } + /** + * Add an array of additional allowed extensions + * @static + * @param $array + */ + public static function add_allowed_extensions($array = null) + { + if (empty($array)) { + return; + } + if (is_array($array)) { + self::$allowed_extensions = $array; + } else { + self::$allowed_extensions = array($array); + } + } - /** - * Custom currentPage() method to handle opening the 'root' folder - * - * @return - */ - public function currentPage() { - $id = $this->currentPageID(); + /** + * Custom currentPage() method to handle opening the 'root' folder + * + * @return + */ + public function currentPage() + { + $id = $this->currentPageID(); - if($id && is_numeric($id) && $id > 0) { - return Versioned::get_by_stage('SiteTree', 'Stage', sprintf( - 'ID = %s', (int) $id - ))->first(); - } else { - // ID is either '0' or 'root' - return singleton('SiteTree'); - } - } + if ($id && is_numeric($id) && $id > 0) { + return Versioned::get_by_stage('SiteTree', 'Stage', sprintf( + 'ID = %s', (int) $id + ))->first(); + } else { + // ID is either '0' or 'root' + return singleton('SiteTree'); + } + } - /** - * Return fake-ID "root" if no ID is found (needed to upload files into the root-folder) - */ - public function currentPageID() { - return ($result = parent::currentPageID()) === null ? 0 : $result; - } + /** + * Return fake-ID "root" if no ID is found (needed to upload files into the root-folder) + */ + public function currentPageID() + { + return ($result = parent::currentPageID()) === null ? 0 : $result; + } - /** - * @return Form - * @todo what template is used here? AssetAdmin_UploadContent.ss doesn't seem to be used anymore - */ - public function getEditForm($id = null, $fields = null) { - Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js'); - Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css'); - Requirements::css(DMS_DIR.'/css/DMSMainCMS.css'); + /** + * @return Form + * @todo what template is used here? AssetAdmin_UploadContent.ss doesn't seem to be used anymore + */ + public function getEditForm($id = null, $fields = null) + { + Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js'); + Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css'); + Requirements::css(DMS_DIR.'/css/DMSMainCMS.css'); - $page = $this->currentPage(); - $uploadField = DMSUploadField::create('AssetUploadField', ''); - $uploadField->setConfig('previewMaxWidth', 40); - $uploadField->setConfig('previewMaxHeight', 30); - // Required to avoid Solr reindexing (often used alongside DMS) to - // return 503s because of too many concurrent reindex requests - $uploadField->setConfig('sequentialUploads', 1); - $uploadField->addExtraClass('ss-assetuploadfield'); - $uploadField->removeExtraClass('ss-uploadfield'); - $uploadField->setTemplate('AssetUploadField'); - $uploadField->setRecord($page); + $page = $this->currentPage(); + $uploadField = DMSUploadField::create('AssetUploadField', ''); + $uploadField->setConfig('previewMaxWidth', 40); + $uploadField->setConfig('previewMaxHeight', 30); + // Required to avoid Solr reindexing (often used alongside DMS) to + // return 503s because of too many concurrent reindex requests + $uploadField->setConfig('sequentialUploads', 1); + $uploadField->addExtraClass('ss-assetuploadfield'); + $uploadField->removeExtraClass('ss-uploadfield'); + $uploadField->setTemplate('AssetUploadField'); + $uploadField->setRecord($page); - $uploadField->getValidator()->setAllowedExtensions(array_filter(array_merge(Config::inst()->get('File', 'allowed_extensions'),self::$allowed_extensions))); - $exts = $uploadField->getValidator()->getAllowedExtensions(); + $uploadField->getValidator()->setAllowedExtensions(array_filter(array_merge(Config::inst()->get('File', 'allowed_extensions'), self::$allowed_extensions))); + $exts = $uploadField->getValidator()->getAllowedExtensions(); - asort($exts); - $backlink = $this->Backlink(); - $done = " + asort($exts); + $backlink = $this->Backlink(); + $done = " Done! "; - $addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing'); - $addExistingField->setRecord($page); - $form = new Form( - $this, - 'getEditForm', - new FieldList( - new TabSet('Main', - new Tab('From your computer', - new HiddenField('ID', false, $page->ID), - $uploadField, - new LiteralField( - 'AllowedExtensions', - sprintf( - '
%s: %s
', - _t('AssetAdmin.ALLOWEDEXTS', 'Allowed extensions'), - implode(', ', $exts) - ) - ) - ), - new Tab('From the CMS', - $addExistingField - ) - ) - ), - new FieldList( - new LiteralField('doneButton', $done) - ) - ); - $form->addExtraClass('center cms-edit-form ' . $this->BaseCSSClasses()); - $form->Backlink = $backlink; - // Don't use AssetAdmin_EditForm, as it assumes a different panel structure - $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); - /*$form->Fields()->push( - new LiteralField( - 'BackLink', - sprintf( - '%s', - Controller::join_links(singleton('AssetAdmin')->Link('show'), $folder ? $folder->ID : 0), - _t('AssetAdmin.BackToFolder', 'Back to folder') - ) - ) - );*/ - //$form->loadDataFrom($folder); + $addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing'); + $addExistingField->setRecord($page); + $form = new Form( + $this, + 'getEditForm', + new FieldList( + new TabSet('Main', + new Tab('From your computer', + new HiddenField('ID', false, $page->ID), + $uploadField, + new LiteralField( + 'AllowedExtensions', + sprintf( + '%s: %s
', + _t('AssetAdmin.ALLOWEDEXTS', 'Allowed extensions'), + implode(', ', $exts) + ) + ) + ), + new Tab('From the CMS', + $addExistingField + ) + ) + ), + new FieldList( + new LiteralField('doneButton', $done) + ) + ); + $form->addExtraClass('center cms-edit-form ' . $this->BaseCSSClasses()); + $form->Backlink = $backlink; + // Don't use AssetAdmin_EditForm, as it assumes a different panel structure + $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); + /*$form->Fields()->push( + new LiteralField( + 'BackLink', + sprintf( + '%s', + Controller::join_links(singleton('AssetAdmin')->Link('show'), $folder ? $folder->ID : 0), + _t('AssetAdmin.BackToFolder', 'Back to folder') + ) + ) + );*/ + //$form->loadDataFrom($folder); - return $form; - } + return $form; + } - /** - * @return ArrayList - */ - public function Breadcrumbs($unlinked = false) { - $items = parent::Breadcrumbs($unlinked); + /** + * @return ArrayList + */ + public function Breadcrumbs($unlinked = false) + { + $items = parent::Breadcrumbs($unlinked); - // The root element should explicitly point to the root node. - $items[0]->Link = Controller::join_links(singleton('CMSPageEditController')->Link('show'), 0); + // The root element should explicitly point to the root node. + $items[0]->Link = Controller::join_links(singleton('CMSPageEditController')->Link('show'), 0); - // Enforce linkage of hierarchy to AssetAdmin - foreach($items as $item) { - $baselink = $this->Link('show'); - if(strpos($item->Link, $baselink) !== false) { - $item->Link = str_replace($baselink, singleton('CMSPageEditController')->Link('show'), $item->Link); - } - } + // Enforce linkage of hierarchy to AssetAdmin + foreach ($items as $item) { + $baselink = $this->Link('show'); + if (strpos($item->Link, $baselink) !== false) { + $item->Link = str_replace($baselink, singleton('CMSPageEditController')->Link('show'), $item->Link); + } + } - $items->push(new ArrayData(array( - 'Title' => 'Add Document', - 'Link' => $this->Link() - ))); - - return $items; - } - - public function Backlink(){ - $pageID = $this->currentPageID(); - return singleton('CMSPagesController')->Link().'edit/show/'.$pageID; - } + $items->push(new ArrayData(array( + 'Title' => 'Add Document', + 'Link' => $this->Link() + ))); + + return $items; + } + + public function Backlink() + { + $pageID = $this->currentPageID(); + return singleton('CMSPagesController')->Link().'edit/show/'.$pageID; + } - public function documentautocomplete() { - $term = (isset($_GET['term'])) ? $_GET['term'] : ''; - $term_sql = Convert::raw2sql($term); - $data = DMSDocument::get() - ->where("(\"ID\" LIKE '%".$term_sql."%' OR \"Filename\" LIKE '%".$term_sql."%' OR \"Title\" LIKE '%".$term_sql."%')") - ->sort('ID ASC') - ->limit(20); + public function documentautocomplete() + { + $term = (isset($_GET['term'])) ? $_GET['term'] : ''; + $term_sql = Convert::raw2sql($term); + $data = DMSDocument::get() + ->where("(\"ID\" LIKE '%".$term_sql."%' OR \"Filename\" LIKE '%".$term_sql."%' OR \"Title\" LIKE '%".$term_sql."%')") + ->sort('ID ASC') + ->limit(20); - $return = array(); - foreach($data as $doc) { - $return[] = array( - 'label' => $doc->ID . ' - ' . $doc->Title, - 'value' => $doc->ID - ); - } + $return = array(); + foreach ($data as $doc) { + $return[] = array( + 'label' => $doc->ID . ' - ' . $doc->Title, + 'value' => $doc->ID + ); + } - return json_encode($return); - } + return json_encode($return); + } - public function linkdocument() { - $return = array('error' => _t('UploadField.FIELDNOTSET', 'Could not add document to page')); + public function linkdocument() + { + $return = array('error' => _t('UploadField.FIELDNOTSET', 'Could not add document to page')); - $page = $this->currentPage(); - if (!empty($page)) { - $document = DataObject::get_by_id('DMSDocument', (int) $_GET['documentID']); - $document->addPage($page); + $page = $this->currentPage(); + if (!empty($page)) { + $document = DataObject::get_by_id('DMSDocument', (int) $_GET['documentID']); + $document->addPage($page); - $buttonText = ''; + $buttonText = ''; - // Collect all output data. - $return = array( - 'id' => $document->ID, - 'name' => $document->getTitle(), - 'thumbnail_url' => $document->Icon($document->getExtension()), - 'edit_url' => $this->getEditForm()->Fields()->fieldByName('Main.From your computer.AssetUploadField')->getItemHandler($document->ID)->EditLink(), - 'size' => $document->getFileSizeFormatted(), - 'buttons' => $buttonText, - 'showeditform' => true - ); - } + // Collect all output data. + $return = array( + 'id' => $document->ID, + 'name' => $document->getTitle(), + 'thumbnail_url' => $document->Icon($document->getExtension()), + 'edit_url' => $this->getEditForm()->Fields()->fieldByName('Main.From your computer.AssetUploadField')->getItemHandler($document->ID)->EditLink(), + 'size' => $document->getFileSizeFormatted(), + 'buttons' => $buttonText, + 'showeditform' => true + ); + } - return json_encode($return); - } + return json_encode($return); + } - public function documentlist() { - if(!isset($_GET['pageID'])) { - return $this->httpError(400); - } + public function documentlist() + { + 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) { - $list = '%s
', - _t('DMSDocumentAddController.NODOCUMENTS', 'There are no documents attached to the selected page.') - ); - } + return $list; + } + + return sprintf('%s
', + _t('DMSDocumentAddController.NODOCUMENTS', 'There are no documents attached to the selected page.') + ); + } } diff --git a/code/cms/DMSDocumentAddExistingField.php b/code/cms/DMSDocumentAddExistingField.php index f8e7ffb..1ed3f94 100644 --- a/code/cms/DMSDocumentAddExistingField.php +++ b/code/cms/DMSDocumentAddExistingField.php @@ -1,56 +1,63 @@ name = $name; - $this->title = ($title === null) ? $name : $title; + public function __construct($name, $title = null) + { + $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) - * @param DataObject $record - */ - public function setRecord($record) { - $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 - */ - public function getRecord() { - if (!$this->record && $this->form) { - if ($this->form->getRecord() && is_a($this->form->getRecord(), 'DataObject')) { - $this->record = $this->form->getRecord(); - } 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; - } + /** + * Force a record to be used as "Parent" for uploaded Files (eg a Page with a has_one to File) + * @param DataObject $record + */ + public function setRecord($record) + { + $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 + */ + public function getRecord() + { + if (!$this->record && $this->form) { + if ($this->form->getRecord() && is_a($this->form->getRecord(), 'DataObject')) { + $this->record = $this->form->getRecord(); + } 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; + } - public function FieldHolder($properties = array()) { - return $this->Field($properties); - } + public function FieldHolder($properties = array()) + { + return $this->Field($properties); + } - public function Field($properties = array()) { - Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentAddExistingField.js'); - Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js"); + public function Field($properties = array()) + { + 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 - * that causes unwelcome hiding side-effects when this Field is used within the link editor pop-up - */ - public function setUseFieldClass($use = false) { - $this->useFieldContext = $use; - } + /** + * 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 + */ + public function setUseFieldClass($use = false) + { + $this->useFieldContext = $use; + } } diff --git a/code/cms/DMSGridFieldDeleteAction.php b/code/cms/DMSGridFieldDeleteAction.php index 2f6b30e..00c5c68 100644 --- a/code/cms/DMSGridFieldDeleteAction.php +++ b/code/cms/DMSGridFieldDeleteAction.php @@ -13,74 +13,84 @@ * @package dms * @subpackage cms */ -class DMSGridFieldDeleteAction extends GridFieldDeleteAction implements GridField_ColumnProvider, GridField_ActionProvider { +class DMSGridFieldDeleteAction extends GridFieldDeleteAction implements GridField_ColumnProvider, GridField_ActionProvider +{ - /** - * - * @param GridField $gridField - * @param DataObject $record - * @param string $columnName - * @return string - the HTML for the column - */ - public function getColumnContent($gridField, $record, $columnName) { - if($this->removeRelation) { - $field = GridField_FormAction::create($gridField, 'UnlinkRelation'.$record->ID, false, "unlinkrelation", array('RecordID' => $record->ID)) - ->addExtraClass('gridfield-button-unlink') - ->setAttribute('title', _t('GridAction.UnlinkRelation', "Unlink")) - ->setAttribute('data-icon', 'chain--minus'); - } else { - if(!$record->canDelete()) { - return; - } - $field = GridField_FormAction::create($gridField, 'DeleteRecord'.$record->ID, false, "deleterecord", array('RecordID' => $record->ID)) - ->addExtraClass('gridfield-button-delete') - ->setAttribute('title', _t('GridAction.Delete', "Delete")) - ->setAttribute('data-icon', 'cross-circle') - ->setDescription(_t('GridAction.DELETE_DESCRIPTION','Delete')); - } + /** + * + * @param GridField $gridField + * @param DataObject $record + * @param string $columnName + * @return string - the HTML for the column + */ + public function getColumnContent($gridField, $record, $columnName) + { + if ($this->removeRelation) { + $field = GridField_FormAction::create($gridField, 'UnlinkRelation'.$record->ID, false, "unlinkrelation", array('RecordID' => $record->ID)) + ->addExtraClass('gridfield-button-unlink') + ->setAttribute('title', _t('GridAction.UnlinkRelation', "Unlink")) + ->setAttribute('data-icon', 'chain--minus'); + } else { + if (!$record->canDelete()) { + return; + } + $field = GridField_FormAction::create($gridField, 'DeleteRecord'.$record->ID, false, "deleterecord", array('RecordID' => $record->ID)) + ->addExtraClass('gridfield-button-delete') + ->setAttribute('title', _t('GridAction.Delete', "Delete")) + ->setAttribute('data-icon', 'cross-circle') + ->setDescription(_t('GridAction.DELETE_DESCRIPTION', 'Delete')); + } - //add a class to the field to if it is the last gridfield in the list - $numberOfRelations = $record->Pages()->Count(); - $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 - ->removeExtraClass('gridfield-button-delete'); //remove the base gridfield behaviour + //add a class to the field to if it is the last gridfield in the list + $numberOfRelations = $record->Pages()->Count(); + $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 + ->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 - if ($numberOfRelations > 1) $field->addExtraClass('dms-delete-link-only'); - else $field->addExtraClass('dms-delete-last-warning'); + //set a class telling JS what kind of warning to display when clicking the delete button + if ($numberOfRelations > 1) { + $field->addExtraClass('dms-delete-link-only'); + } else { + $field->addExtraClass('dms-delete-last-warning'); + } - //set a class to show if the document is hidden - if ($record->isHidden()) { - $field->addExtraClass('dms-document-hidden'); - } + //set a class to show if the document is hidden + if ($record->isHidden()) { + $field->addExtraClass('dms-document-hidden'); + } - return $field->Field(); - } + return $field->Field(); + } - /** - * Handle the actions and apply any changes to the GridField - * - * @param GridField $gridField - * @param string $actionName - * @param mixed $arguments - * @param array $data - form data - * @return void - */ - public function handleAction(GridField $gridField, $actionName, $arguments, $data) { - if($actionName == 'deleterecord' || $actionName == 'unlinkrelation') { - $item = $gridField->getList()->byID($arguments['RecordID']); - if(!$item) { - return; - } - if($actionName == 'deleterecord' && !$item->canDelete()) { - throw new ValidationException(_t('GridFieldAction_Delete.DeletePermissionsFailure',"No delete permissions"),0); - } + /** + * Handle the actions and apply any changes to the GridField + * + * @param GridField $gridField + * @param string $actionName + * @param mixed $arguments + * @param array $data - form data + * @return void + */ + public function handleAction(GridField $gridField, $actionName, $arguments, $data) + { + if ($actionName == 'deleterecord' || $actionName == 'unlinkrelation') { + $item = $gridField->getList()->byID($arguments['RecordID']); + if (!$item) { + return; + } + if ($actionName == 'deleterecord' && !$item->canDelete()) { + throw new ValidationException(_t('GridFieldAction_Delete.DeletePermissionsFailure', "No delete permissions"), 0); + } - $delete = false; - if ($item->Pages()->Count() <= 1) $delete = true; + $delete = false; + if ($item->Pages()->Count() <= 1) { + $delete = true; + } - $gridField->getList()->remove($item); //remove the relation - if ($delete) $item->delete(); //delete the DMSDocument - } - } + $gridField->getList()->remove($item); //remove the relation + if ($delete) { + $item->delete(); + } //delete the DMSDocument + } + } } diff --git a/code/cms/DMSGridFieldDetailForm.php b/code/cms/DMSGridFieldDetailForm.php index 61f36a1..95e9ddc 100644 --- a/code/cms/DMSGridFieldDetailForm.php +++ b/code/cms/DMSGridFieldDetailForm.php @@ -3,23 +3,24 @@ /** * Custom ItemRequest class the provides custom delete behaviour for the CMSFields of DMSDocument */ -class DMSGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest { - private static $allowed_actions = array('ItemEditForm'); +class DMSGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest +{ + private static $allowed_actions = array('ItemEditForm'); - function ItemEditForm() { - $form = parent::ItemEditForm(); + public function ItemEditForm() + { + $form = parent::ItemEditForm(); - //add a data attribute specifying how many pages this document is referenced on - if ($record = $this->record) { - $numberOfPageRelations = $record->Pages()->Count(); - $relations = new ShortCodeRelationFinder(); - $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 a data attribute specifying how many pages this document is referenced on + if ($record = $this->record) { + $numberOfPageRelations = $record->Pages()->Count(); + $relations = new ShortCodeRelationFinder(); + $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; + } } diff --git a/code/cms/DMSUploadField.php b/code/cms/DMSUploadField.php index 2d426c1..1b91ee1 100644 --- a/code/cms/DMSUploadField.php +++ b/code/cms/DMSUploadField.php @@ -12,195 +12,214 @@ * @author Julian Seidenberg * @package dms */ -class DMSUploadField extends UploadField { - private static $allowed_actions = array ( +class DMSUploadField extends UploadField +{ + private static $allowed_actions = array( "upload", - ); + ); - protected $folderName = 'DMSTemporaryUploads'; + protected $folderName = 'DMSTemporaryUploads'; - public function __construct($name, $title = null, SS_List $items = null) { - parent::__construct($name, $title, $items); + public function __construct($name, $title = null, SS_List $items = null) + { + parent::__construct($name, $title, $items); - //set default DMS replace template to false - $this->setConfig('useDMSReplaceTemplate', 0); - } + //set default DMS replace template to false + $this->setConfig('useDMSReplaceTemplate', 0); + } - /** - * Override the default behaviour of the UploadField and take the uploaded file (uploaded to assets) and - * add it into the DMS storage, deleting the old/uploaded file. - * @param File - */ - protected function attachFile($file) { - $dms = DMS::inst(); - $record = $this->getRecord(); + /** + * 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. + * @param File + */ + protected function attachFile($file) + { + $dms = DMS::inst(); + $record = $this->getRecord(); - if($record instanceof DMSDocument) { - // If the edited record is a document, - // assume we're replacing an existing file - $doc = $record; - $doc->ingestFile($file); - } else { - // Otherwise create it - $doc = $dms->storeDocument($file); - $file->delete(); - // Relate to the underlying page being edited. - // Not applicable when editing the document itself and replacing it. - $doc->addPage($record); - } + if ($record instanceof DMSDocument) { + // If the edited record is a document, + // assume we're replacing an existing file + $doc = $record; + $doc->ingestFile($file); + } else { + // Otherwise create it + $doc = $dms->storeDocument($file); + $file->delete(); + // Relate to the underlying page being edited. + // Not applicable when editing the document itself and replacing it. + $doc->addPage($record); + } - return $doc; - } + return $doc; + } - public function validate($validator) { - return true; - } + public function validate($validator) + { + return true; + } - public function isDisabled() { - return (parent::isDisabled() || !$this->isSaveable()); - } + public function isDisabled() + { + return (parent::isDisabled() || !$this->isSaveable()); + } - public function isSaveable() { - return (!empty($this->getRecord()->ID)); - } + public function isSaveable() + { + return (!empty($this->getRecord()->ID)); + } - /** - * Action to handle upload of a single file - * - * @param SS_HTTPRequest $request - * @return string json - */ - public function upload(SS_HTTPRequest $request) { - if($this->isDisabled() || $this->isReadonly()) return $this->httpError(403); + /** + * Action to handle upload of a single file + * + * @param SS_HTTPRequest $request + * @return string json + */ + public function upload(SS_HTTPRequest $request) + { + if ($this->isDisabled() || $this->isReadonly()) { + return $this->httpError(403); + } - // Protect against CSRF on destructive action - $token = $this->getForm()->getSecurityToken(); - if(!$token->checkRequest($request)) return $this->httpError(400); + // Protect against CSRF on destructive action + $token = $this->getForm()->getSecurityToken(); + if (!$token->checkRequest($request)) { + return $this->httpError(400); + } - $name = $this->getName(); - $tmpfile = $request->postVar($name); - $record = $this->getRecord(); - - // Check if the file has been uploaded into the temporary storage. - if (!$tmpfile) { - $return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found')); - } else { - $return = array( - 'name' => $tmpfile['name'], - 'size' => $tmpfile['size'], - 'type' => $tmpfile['type'], - 'error' => $tmpfile['error'] - ); - } + $name = $this->getName(); + $tmpfile = $request->postVar($name); + $record = $this->getRecord(); + + // Check if the file has been uploaded into the temporary storage. + if (!$tmpfile) { + $return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found')); + } else { + $return = array( + 'name' => $tmpfile['name'], + 'size' => $tmpfile['size'], + 'type' => $tmpfile['type'], + 'error' => $tmpfile['error'] + ); + } - // Check for constraints on the record to which the file will be attached. - if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) { - $tooManyFiles = false; - // Some relationships allow many files to be attached. - if ($this->getConfig('allowedMaxFileNumber') && ($record->has_many($name) || $record->many_many($name))) { - if(!$record->isInDB()) $record->write(); - $tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber'); - // has_one only allows one file at any given time. - } elseif($record->has_one($name)) { - $tooManyFiles = $record->{$name}() && $record->{$name}()->exists(); - } + // Check for constraints on the record to which the file will be attached. + if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) { + $tooManyFiles = false; + // Some relationships allow many files to be attached. + if ($this->getConfig('allowedMaxFileNumber') && ($record->has_many($name) || $record->many_many($name))) { + if (!$record->isInDB()) { + $record->write(); + } + $tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber'); + // has_one only allows one file at any given time. + } elseif ($record->has_one($name)) { + $tooManyFiles = $record->{$name}() && $record->{$name}()->exists(); + } - // Report the constraint violation. - if ($tooManyFiles) { - if(!$this->getConfig('allowedMaxFileNumber')) $this->setConfig('allowedMaxFileNumber', 1); - $return['error'] = _t( - 'UploadField.MAXNUMBEROFFILES', - 'Max number of {count} file(s) exceeded.', - array('count' => $this->getConfig('allowedMaxFileNumber')) - ); - } - } + // Report the constraint violation. + if ($tooManyFiles) { + if (!$this->getConfig('allowedMaxFileNumber')) { + $this->setConfig('allowedMaxFileNumber', 1); + } + $return['error'] = _t( + 'UploadField.MAXNUMBEROFFILES', + 'Max number of {count} file(s) exceeded.', + array('count' => $this->getConfig('allowedMaxFileNumber')) + ); + } + } - // Process the uploaded file - if (!$return['error']) { - $fileObject = null; + // Process the uploaded file + if (!$return['error']) { + $fileObject = null; - if ($this->relationAutoSetting) { - // Search for relations that can hold the uploaded files. - if ($relationClass = $this->getRelationAutosetClass()) { - // Create new object explicitly. Otherwise rely on Upload::load to choose the class. - $fileObject = Object::create($relationClass); - } - } + if ($this->relationAutoSetting) { + // Search for relations that can hold the uploaded files. + if ($relationClass = $this->getRelationAutosetClass()) { + // Create new object explicitly. Otherwise rely on Upload::load to choose the class. + $fileObject = Object::create($relationClass); + } + } - // Get the uploaded file into a new file object. - try { - $this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName); - } catch (Exception $e) { - // we shouldn't get an error here, but just in case - $return['error'] = $e->getMessage(); - } + // Get the uploaded file into a new file object. + try { + $this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName); + } catch (Exception $e) { + // we shouldn't get an error here, but just in case + $return['error'] = $e->getMessage(); + } - if (!$return['error']) { - if ($this->upload->isError()) { - $return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors()); - } else { - $file = $this->upload->getFile(); + if (!$return['error']) { + if ($this->upload->isError()) { + $return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors()); + } else { + $file = $this->upload->getFile(); - // CUSTOM Attach the file to the related record. - $document = $this->attachFile($file); - - // Collect all output data. - $return = array_merge($return, array( - 'id' => $document->ID, - 'name' => $document->getTitle(), - 'thumbnail_url' => $document->Icon($document->getExtension()), - 'edit_url' => $this->getItemHandler($document->ID)->EditLink(), - 'size' => $document->getFileSizeFormatted(), - 'buttons' => (string) $document->renderWith($this->getTemplateFileButtons()), - 'showeditform' => true - )); + // CUSTOM Attach the file to the related record. + $document = $this->attachFile($file); + + // Collect all output data. + $return = array_merge($return, array( + 'id' => $document->ID, + 'name' => $document->getTitle(), + 'thumbnail_url' => $document->Icon($document->getExtension()), + 'edit_url' => $this->getItemHandler($document->ID)->EditLink(), + 'size' => $document->getFileSizeFormatted(), + 'buttons' => (string) $document->renderWith($this->getTemplateFileButtons()), + 'showeditform' => true + )); - // CUSTOM END - } - } - } - $response = new SS_HTTPResponse(Convert::raw2json(array($return))); - $response->addHeader('Content-Type', 'text/plain'); - return $response; - } + // CUSTOM END + } + } + } + $response = new SS_HTTPResponse(Convert::raw2json(array($return))); + $response->addHeader('Content-Type', 'text/plain'); + return $response; + } - /** - * Never directly display items uploaded - * @return SS_List - */ - public function getItems() { - return new ArrayList(); - } + /** + * Never directly display items uploaded + * @return SS_List + */ + public function getItems() + { + return new ArrayList(); + } - public function Field($properties = array()) { - $fields = parent::Field($properties); + public function Field($properties = array()) + { + $fields = parent::Field($properties); - // Replace the download template with a new one only when access the upload field through a GridField. - // Needs to be enabled through setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate'); - Requirements::javascript('dms/javascript/DMSUploadField_downloadtemplate.js'); - - // In the add dialog, add the addtemplate into the set of file that load. - Requirements::javascript('dms/javascript/DMSUploadField_addtemplate.js'); + // Replace the download template with a new one only when access the upload field through a GridField. + // Needs to be enabled through setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate'); + Requirements::javascript('dms/javascript/DMSUploadField_downloadtemplate.js'); + + // In the add dialog, add the addtemplate into the set of file that load. + Requirements::javascript('dms/javascript/DMSUploadField_addtemplate.js'); - return $fields; - } + return $fields; + } - /** - * @param int $itemID - * @return UploadField_ItemHandler - */ - public function getItemHandler($itemID) { - return DMSUploadField_ItemHandler::create($this, $itemID); - } + /** + * @param int $itemID + * @return UploadField_ItemHandler + */ + public function getItemHandler($itemID) + { + return DMSUploadField_ItemHandler::create($this, $itemID); + } } -class DMSUploadField_ItemHandler extends UploadField_ItemHandler { - function getItem() { - return DataObject::get_by_id('DMSDocument', $this->itemID); - } - +class DMSUploadField_ItemHandler extends UploadField_ItemHandler +{ + public function getItem() + { + return DataObject::get_by_id('DMSDocument', $this->itemID); + } } diff --git a/code/cms/DocumentHtmlEditorFieldToolbar.php b/code/cms/DocumentHtmlEditorFieldToolbar.php index b866153..c879c4c 100644 --- a/code/cms/DocumentHtmlEditorFieldToolbar.php +++ b/code/cms/DocumentHtmlEditorFieldToolbar.php @@ -4,26 +4,30 @@ */ -class DocumentHtmlEditorFieldToolbar extends Extension { +class DocumentHtmlEditorFieldToolbar extends Extension +{ - function updateLinkForm(Form $form) { - $linkType = null; - $fieldList = null; - $fields = $form->Fields();//->fieldByName('Heading'); - foreach($fields as $field) { - $linkType = ($field->fieldByName('LinkType')); - $fieldList = $field; - if ($linkType) break; //break once we have the object - } + public function updateLinkForm(Form $form) + { + $linkType = null; + $fieldList = null; + $fields = $form->Fields();//->fieldByName('Heading'); + foreach ($fields as $field) { + $linkType = ($field->fieldByName('LinkType')); + $fieldList = $field; + if ($linkType) { + break; + } //break once we have the object + } - $source = $linkType->getSource(); - $source['document'] = 'Download a document'; - $linkType->setSource($source); + $source = $linkType->getSource(); + $source['document'] = 'Download a document'; + $linkType->setSource($source); - $addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing'); - $addExistingField->setForm($form); - $addExistingField->setUseFieldClass(false); - $fieldList->insertAfter($addExistingField,'Description'); + $addExistingField = new DMSDocumentAddExistingField('AddExisting', 'Add Existing'); + $addExistingField->setForm($form); + $addExistingField->setUseFieldClass(false); + $fieldList->insertAfter($addExistingField, 'Description'); // Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/behaviour/behaviour.js"); // Requirements::javascript(SAPPHIRE_DIR . "/javascript/tiny_mce_improvements.js"); @@ -35,6 +39,6 @@ class DocumentHtmlEditorFieldToolbar extends Extension { // $documents->setTreeBaseID($baseFolder->ID); - //return $form; - } -} \ No newline at end of file + //return $form; + } +} diff --git a/code/exceptions/FileNotFoundException.php b/code/exceptions/FileNotFoundException.php index d1573ad..b50bf65 100644 --- a/code/exceptions/FileNotFoundException.php +++ b/code/exceptions/FileNotFoundException.php @@ -3,6 +3,6 @@ * Simple exception extension so that we can tell the difference between internally * raised exceptions and those thrown by DMS. */ -class FileNotFoundException extends Exception { - +class FileNotFoundException extends Exception +{ } diff --git a/code/extensions/DMSSiteTreeExtension.php b/code/extensions/DMSSiteTreeExtension.php index cba0ab0..439adbc 100644 --- a/code/extensions/DMSSiteTreeExtension.php +++ b/code/extensions/DMSSiteTreeExtension.php @@ -3,160 +3,175 @@ /** * @package dms */ -class DMSSiteTreeExtension extends DataExtension { +class DMSSiteTreeExtension extends DataExtension +{ - private static $belongs_many_many = array( - 'Documents' => 'DMSDocument' - ); + private static $belongs_many_many = array( + '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 - * @static - * @param $mixed Array of page types to not show the Documents tab on - */ - static function no_documents_tab($array = array()) { - if (empty($array)) return; - if (is_array($array)) { - self::$noDocumentsList = $array; - } else { - self::$noDocumentsList = array($array); - } - } + /** + * Do not show the documents tab on the array of pages set here + * @static + * @param $mixed Array of page types to not show the Documents tab on + */ + public static function no_documents_tab($array = array()) + { + if (empty($array)) { + return; + } + if (is_array($array)) { + self::$noDocumentsList = $array; + } else { + self::$noDocumentsList = array($array); + } + } - /** - * Only show the documents tab on the list of pages set here. Any pages set in the no_documents_tab array will - * still not be shown. If this isn't called, or if it is called with an empty array, all pages will get Document tabs. - * @static - * @param $array Array of page types to show the Documents tab on - */ - static function show_documents_tab($array = array()) { - if (empty($array)) return; - if (is_array($array)) { - self::$showDocumentsList = $array; - } else { - self::$showDocumentsList = array($array); - } - } + /** + * Only show the documents tab on the list of pages set here. Any pages set in the no_documents_tab array will + * still not be shown. If this isn't called, or if it is called with an empty array, all pages will get Document tabs. + * @static + * @param $array Array of page types to show the Documents tab on + */ + public static function show_documents_tab($array = array()) + { + if (empty($array)) { + return; + } + if (is_array($array)) { + self::$showDocumentsList = $array; + } else { + self::$showDocumentsList = array($array); + } + } - function updateCMSFields(FieldList $fields){ - //prevent certain pages from having a Document tab in the CMS - if (in_array($this->owner->ClassName,self::$noDocumentsList)) return; - if (count(self::$showDocumentsList) > 0 && !in_array($this->owner->ClassName,self::$showDocumentsList)) return; + 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; + } + if (count(self::$showDocumentsList) > 0 && !in_array($this->owner->ClassName, self::$showDocumentsList)) { + return; + } - //javascript to customize the grid field for the DMS document (overriding entwine in FRAMEWORK_DIR.'/javascript/GridField.js' - Requirements::javascript(DMS_DIR.'/javascript/DMSGridField.js'); - Requirements::css(DMS_DIR.'/css/DMSMainCMS.css'); + //javascript to customize the grid field for the DMS document (overriding entwine in FRAMEWORK_DIR.'/javascript/GridField.js' + Requirements::javascript(DMS_DIR.'/javascript/DMSGridField.js'); + Requirements::css(DMS_DIR.'/css/DMSMainCMS.css'); - //javascript for the link editor pop-up in TinyMCE - Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js"); + //javascript for the link editor pop-up in TinyMCE + Requirements::javascript(DMS_DIR."/javascript/DocumentHtmlEditorFieldToolbar.js"); - // Document listing - $gridFieldConfig = GridFieldConfig::create()->addComponents( - new GridFieldToolbarHeader(), - new GridFieldFilterHeader(), - new GridFieldSortableHeader(), - new GridFieldOrderableRows('DocumentSort'), - new GridFieldDataColumns(), - new GridFieldEditButton(), - new DMSGridFieldDeleteAction(), //special delete dialog to handle custom behaviour of unlinking and deleting - new GridFieldDetailForm() - //GridFieldLevelup::create($folder->ID)->setLinkSpec('admin/assets/show/%d') - ); + // Document listing + $gridFieldConfig = GridFieldConfig::create()->addComponents( + new GridFieldToolbarHeader(), + new GridFieldFilterHeader(), + new GridFieldSortableHeader(), + new GridFieldOrderableRows('DocumentSort'), + new GridFieldDataColumns(), + new GridFieldEditButton(), + new DMSGridFieldDeleteAction(), //special delete dialog to handle custom behaviour of unlinking and deleting + new GridFieldDetailForm() + //GridFieldLevelup::create($folder->ID)->setLinkSpec('admin/assets/show/%d') + ); - if(class_exists('GridFieldPaginatorWithShowAll')){ - $paginatorComponent = new GridFieldPaginatorWithShowAll(15); - }else{ - $paginatorComponent = new GridFieldPaginator(15); - } - $gridFieldConfig->addComponent($paginatorComponent); + if (class_exists('GridFieldPaginatorWithShowAll')) { + $paginatorComponent = new GridFieldPaginatorWithShowAll(15); + } else { + $paginatorComponent = new GridFieldPaginator(15); + } + $gridFieldConfig->addComponent($paginatorComponent); - if(class_exists('GridFieldSortableRows')) { - $sortableComponent = new GridFieldSortableRows('DocumentSort'); - //setUsePagenation method removed from newer version of SortableGridField. - if(method_exists($sortableComponent,'setUsePagination')){ - $sortableComponent->setUsePagination(false)->setForceRedraw(true); - } - $gridFieldConfig->addComponent($sortableComponent); - } + if (class_exists('GridFieldSortableRows')) { + $sortableComponent = new GridFieldSortableRows('DocumentSort'); + //setUsePagenation method removed from newer version of SortableGridField. + if (method_exists($sortableComponent, 'setUsePagination')) { + $sortableComponent->setUsePagination(false)->setForceRedraw(true); + } + $gridFieldConfig->addComponent($sortableComponent); + } - // HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields. - singleton('DMSDocument'); - $gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields')) - ->setFieldCasting(array('LastChanged'=>"Datetime->Ago")) - ->setFieldFormatting(array('FilenameWithoutID'=>'$FilenameWithoutID')); + // HACK: Create a singleton of DMSDocument to ensure extensions are applied before we try to get display fields. + singleton('DMSDocument'); + $gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(Config::inst()->get('DMSDocument', 'display_fields')) + ->setFieldCasting(array('LastChanged'=>"Datetime->Ago")) + ->setFieldFormatting(array('FilenameWithoutID'=>'$FilenameWithoutID')); - //override delete functionality with this class - $gridFieldConfig->getComponentByType('GridFieldDetailForm')->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest'); + //override delete functionality with this class + $gridFieldConfig->getComponentByType('GridFieldDetailForm')->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest'); - $gridField = GridField::create( - 'Documents', - false, - $this->owner->Documents()->Sort('DocumentSort'), - $gridFieldConfig - ); - $gridField->addExtraClass('documents'); + $gridField = GridField::create( + 'Documents', + false, + $this->owner->Documents()->Sort('DocumentSort'), + $gridFieldConfig + ); + $gridField->addExtraClass('documents'); - $uploadBtn = new LiteralField( - 'UploadButton', - sprintf( - '%s', - Controller::join_links(singleton('DMSDocumentAddController')->Link(), '?ID=' . $this->owner->ID), - "Add Documents" - ) - ); + $uploadBtn = new LiteralField( + 'UploadButton', + sprintf( + '%s', + Controller::join_links(singleton('DMSDocumentAddController')->Link(), '?ID=' . $this->owner->ID), + "Add Documents" + ) + ); - $fields->addFieldsToTab( - 'Root.Documents (' . $this->owner->Documents()->Count() . ')', - array( - $uploadBtn, - $gridField - ) - ); - } + $fields->addFieldsToTab( + 'Root.Documents (' . $this->owner->Documents()->Count() . ')', + array( + $uploadBtn, + $gridField + ) + ); + } - /** - * Enforce sorting for frontend - */ - function PageDocuments() { - return $this->owner->getManyManyComponents('Documents')->sort('DocumentSort'); - } + /** + * Enforce sorting for frontend + */ + public function PageDocuments() + { + return $this->owner->getManyManyComponents('Documents')->sort('DocumentSort'); + } - function onBeforeDelete() { - if(Versioned::current_stage() == 'Live') { - $existsOnOtherStage = !$this->owner->getIsDeletedFromStage(); - } else { - $existsOnOtherStage = $this->owner->getExistsOnLive(); - } + public function onBeforeDelete() + { + if (Versioned::current_stage() == 'Live') { + $existsOnOtherStage = !$this->owner->getIsDeletedFromStage(); + } else { + $existsOnOtherStage = $this->owner->getExistsOnLive(); + } - // Only remove if record doesn't still exist on live stage. - if(!$existsOnOtherStage) { - $dmsDocuments = $this->owner->Documents(); - foreach($dmsDocuments as $document) { - //if the document is only associated with one page, i.e. only associated with this page - if ($document->Pages()->Count() <= 1) { - //delete the document before deleting this page - $document->delete(); - } - } - } - } + // Only remove if record doesn't still exist on live stage. + if (!$existsOnOtherStage) { + $dmsDocuments = $this->owner->Documents(); + foreach ($dmsDocuments as $document) { + //if the document is only associated with one page, i.e. only associated with this page + if ($document->Pages()->Count() <= 1) { + //delete the document before deleting this page + $document->delete(); + } + } + } + } - function onBeforePublish() { - $embargoedDocuments = $this->owner->Documents()->filter('EmbargoedUntilPublished',true); - if ($embargoedDocuments->Count() > 0) { - foreach($embargoedDocuments as $doc) { - $doc->EmbargoedUntilPublished = false; - $doc->write(); - } - } + public function onBeforePublish() + { + $embargoedDocuments = $this->owner->Documents()->filter('EmbargoedUntilPublished', true); + if ($embargoedDocuments->Count() > 0) { + foreach ($embargoedDocuments as $doc) { + $doc->EmbargoedUntilPublished = false; + $doc->write(); + } + } + } - } - - function getTitleWithNumberOfDocuments() { - return $this->owner->Title . ' (' . $this->owner->Documents()->Count() . ')'; - } + public function getTitleWithNumberOfDocuments() + { + return $this->owner->Title . ' (' . $this->owner->Documents()->Count() . ')'; + } } diff --git a/code/interface/DMSDocumentInterface.php b/code/interface/DMSDocumentInterface.php index 9cd8e24..9331b6f 100644 --- a/code/interface/DMSDocumentInterface.php +++ b/code/interface/DMSDocumentInterface.php @@ -4,212 +4,212 @@ * 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 */ -interface DMSDocumentInterface { +interface DMSDocumentInterface +{ - /** - * Deletes the DMSDocument, its underlying file, as well as any tags related to this DMSDocument. - * - * @todo Can't be applied to classes which already implement the DataObjectInterface (naming conflict) - * - * @abstract - * @return null - */ - // function delete(); + /** + * Deletes the DMSDocument, its underlying file, as well as any tags related to this DMSDocument. + * + * @todo Can't be applied to classes which already implement the DataObjectInterface (naming conflict) + * + * @abstract + * @return null + */ + // function delete(); - /** - * Associates this DMSDocument with a Page. This method does nothing if the association already exists. - * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to add a many_many relation - * @abstract - * @param $pageObject Page object to associate this DMSDocument with - * @return null - */ - function addPage($pageObject); - - /** - * Associates this DMSDocument with a set of Pages. This method loops through a set of page ids, and then associates this - * DMSDocument with the individual Page with the each page id in the set - * @abstract - * @param $pageIDs array of page ids used for the page objects associate this DMSDocument with - * @return null - */ - function addPages($pageIDs); + /** + * Associates this DMSDocument with a Page. This method does nothing if the association already exists. + * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to add a many_many relation + * @abstract + * @param $pageObject Page object to associate this DMSDocument with + * @return null + */ + public function addPage($pageObject); + + /** + * Associates this DMSDocument with a set of Pages. This method loops through a set of page ids, and then associates this + * DMSDocument with the individual Page with the each page id in the set + * @abstract + * @param $pageIDs array of page ids used for the page objects associate this DMSDocument with + * @return null + */ + public function addPages($pageIDs); - /** - * Removes the association between this DMSDocument and a Page. This method does nothing if the association does not exist. - * @abstract - * @param $pageObject Page object to remove the association to - * @return mixed - */ - function removePage($pageObject); + /** + * Removes the association between this DMSDocument and a Page. This method does nothing if the association does not exist. + * @abstract + * @param $pageObject Page object to remove the association to + * @return mixed + */ + public function removePage($pageObject); - /** - * Returns a list of the Page objects associated with this DMSDocument - * @abstract - * @return DataList - */ - function getPages(); + /** + * Returns a list of the Page objects associated with this DMSDocument + * @abstract + * @return DataList + */ + public function getPages(); - /** - * Removes all associated Pages from the DMSDocument - * @abstract - * @return null - */ - function removeAllPages(); + /** + * Removes all associated Pages from the DMSDocument + * @abstract + * @return null + */ + public function removeAllPages(); - /** - * Adds a metadata tag to the DMSDocument. The tag has a category and a value. - * Each category can have multiple values by default. So: addTag("fruit","banana") addTag("fruit", "apple") will add two items. - * However, if the third parameter $multiValue is set to 'false', then all updates to a category only ever update a single value. So: - * addTag("fruit","banana") addTag("fruit", "apple") would result in a single metadata tag: fruit->apple. - * Can could be implemented as a key/value store table (although it is more like category/value, because the - * same category can occur multiple times) - * @abstract - * @param $category String of a metadata category to add (required) - * @param $value String of a metadata value to add (required) - * @param bool $multiValue Boolean that determines if the category is multi-value or single-value (optional) - * @return null - */ - function addTag($category, $value, $multiValue = true); + /** + * Adds a metadata tag to the DMSDocument. The tag has a category and a value. + * Each category can have multiple values by default. So: addTag("fruit","banana") addTag("fruit", "apple") will add two items. + * However, if the third parameter $multiValue is set to 'false', then all updates to a category only ever update a single value. So: + * addTag("fruit","banana") addTag("fruit", "apple") would result in a single metadata tag: fruit->apple. + * Can could be implemented as a key/value store table (although it is more like category/value, because the + * same category can occur multiple times) + * @abstract + * @param $category String of a metadata category to add (required) + * @param $value String of a metadata value to add (required) + * @param bool $multiValue Boolean that determines if the category is multi-value or single-value (optional) + * @return null + */ + public function addTag($category, $value, $multiValue = true); - /** - * Fetches all tags associated with this DMSDocument within a given category. If a value is specified this method - * tries to fetch that specific tag. - * @abstract - * @param $category String of the metadata category to get - * @param null $value String of the value of the tag to get - * @return array of Strings of all the tags or null if there is no match found - */ - function getTagsList($category, $value = null); + /** + * Fetches all tags associated with this DMSDocument within a given category. If a value is specified this method + * tries to fetch that specific tag. + * @abstract + * @param $category String of the metadata category to get + * @param null $value String of the value of the tag to get + * @return array of Strings of all the tags or null if there is no match found + */ + public function getTagsList($category, $value = null); - /** - * Removes a tag from the DMSDocument. If you only set a category, then all values in that category are deleted. - * If you specify both a category and a value, then only that single category/value pair is deleted. - * Nothing happens if the category or the value do not exist. - * @abstract - * @param $category Category to remove (required) - * @param null $value Value to remove (optional) - * @return null - */ - function removeTag($category, $value = null); + /** + * Removes a tag from the DMSDocument. If you only set a category, then all values in that category are deleted. + * If you specify both a category and a value, then only that single category/value pair is deleted. + * Nothing happens if the category or the value do not exist. + * @abstract + * @param $category Category to remove (required) + * @param null $value Value to remove (optional) + * @return null + */ + public function removeTag($category, $value = null); - /** - * Deletes all tags associated with this DMSDocument. - * @abstract - * @return null - */ - function removeAllTags(); + /** + * Deletes all tags associated with this DMSDocument. + * @abstract + * @return null + */ + public function removeAllTags(); - /** - * Returns a link to download this DMSDocument from the DMS store - * @abstract - * @return String - */ - function getLink(); - - /** - * Return the extension of the file associated with the document - */ - function getExtension(); - - /** - * Returns the size of the file type in an appropriate format. - * - * @return string - */ - function getSize(); + /** + * Returns a link to download this DMSDocument from the DMS store + * @abstract + * @return String + */ + public function getLink(); + + /** + * Return the extension of the file associated with the document + */ + public function getExtension(); + + /** + * Returns the size of the file type in an appropriate format. + * + * @return string + */ + public function getSize(); - /** - * Return the size of the file associated with the document, in bytes. - * - * @return int - */ - function getAbsoluteSize(); + /** + * Return the size of the file associated with the document, in bytes. + * + * @return int + */ + 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 - * but keeping the rest of the document unchanged. - * @param $file File object, or String that is path to a file to store - * @return DMSDocumentInstance Document object that we replaced the file in - */ - function replaceDocument($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. + * @param $file File object, or String that is path to a file to store + * @return DMSDocumentInstance Document object that we replaced the file in + */ + public function replaceDocument($file); - /** - * Hides the DMSDocument, so it does not show up when getByPage($myPage) is called - * (without specifying the $showEmbargoed = true parameter). This is similar to expire, except that this method - * should be used to hide DMSDocuments that have not yet gone live. - * @abstract - * @return null - */ - function embargoIndefinitely(); + /** + * Hides the DMSDocument, so it does not show up when getByPage($myPage) is called + * (without specifying the $showEmbargoed = true parameter). This is similar to expire, except that this method + * should be used to hide DMSDocuments that have not yet gone live. + * @abstract + * @return null + */ + public function embargoIndefinitely(); - /** - * Returns if this is DMSDocument is embargoed or expired. - * @abstract - * @return bool True or False depending on whether this DMSDocument is embargoed or expired - */ - function isHidden(); + /** + * Returns if this is DMSDocument is embargoed or expired. + * @abstract + * @return bool True or False depending on whether this DMSDocument is embargoed or expired + */ + public function isHidden(); - /** - * Returns if this is DMSDocument is embargoed. - * @abstract - * @return bool True or False depending on whether this DMSDocument is embargoed - */ - function isEmbargoed(); + /** + * Returns if this is DMSDocument is embargoed. + * @abstract + * @return bool True or False depending on whether this DMSDocument is embargoed + */ + public function isEmbargoed(); - /** - * Hides the DMSDocument, so it does not show up when getByPage($myPage) is called. Automatically un-hides the - * DMSDocument at a specific date. - * @abstract - * @param $datetime String date time value when this DMSDocument should expire - * @return null - */ - function embargoUntilDate($datetime); + /** + * Hides the DMSDocument, so it does not show up when getByPage($myPage) is called. Automatically un-hides the + * DMSDocument at a specific date. + * @abstract + * @param $datetime String date time value when this DMSDocument should expire + * @return null + */ + public function embargoUntilDate($datetime); - /** - * Hides the document until any page it is linked to is published - * @return null - */ - function embargoUntilPublished(); + /** + * Hides the document until any page it is linked to is published + * @return null + */ + public function embargoUntilPublished(); - /** - * Clears any previously set embargos, so the DMSDocument always shows up in all queries. - * @abstract - * @return null - */ - function clearEmbargo(); + /** + * Clears any previously set embargos, so the DMSDocument always shows up in all queries. + * @abstract + * @return null + */ + public function clearEmbargo(); - /** - * Returns if this is DMSDocument is expired. - * @abstract - * @return bool True or False depending on whether this DMSDocument is expired - */ - function isExpired(); + /** + * Returns if this is DMSDocument is expired. + * @abstract + * @return bool True or False depending on whether this DMSDocument is expired + */ + public function isExpired(); - /** - * Hides the DMSDocument at a specific date, so it does not show up when getByPage($myPage) is called. - * @abstract - * @param $datetime String date time value when this DMSDocument should expire - * @return null - */ - function expireAtDate($datetime); + /** + * Hides the DMSDocument at a specific date, so it does not show up when getByPage($myPage) is called. + * @abstract + * @param $datetime String date time value when this DMSDocument should expire + * @return null + */ + public function expireAtDate($datetime); - /** - * Clears any previously set expiry. - * @abstract - * @return null - */ - function clearExpiry(); + /** + * Clears any previously set expiry. + * @abstract + * @return null + */ + 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 - * object to find the correct one) - * @abstract - * @return DataList List of DMSDocument objects - */ - function getVersions(); - -} \ No newline at end of file + /** + * Returns a DataList of all previous Versions of this DMSDocument (check the LastEdited date of each + * object to find the correct one) + * @abstract + * @return DataList List of DMSDocument objects + */ + public function getVersions(); +} diff --git a/code/interface/DMSInterface.php b/code/interface/DMSInterface.php index 8583655..79702fc 100644 --- a/code/interface/DMSInterface.php +++ b/code/interface/DMSInterface.php @@ -8,54 +8,55 @@ * 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. - * @static - * @abstract - * @return DMSInterface An instance of the Document Management System - */ - static function inst(); + /** + * Factory method that returns an instance of the DMS. This could be any class that implements the DMSInterface. + * @static + * @abstract + * @return DMSInterface An instance of the Document Management System + */ + 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. - * When storing a document, sets the fields on the File has "tag" metadata. - * @abstract - * @param $file File object, or String that is path to a file to store - * @return DMSDocumentInstance Document object that we just created - */ - function storeDocument($file); + /** + * 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. + * @abstract + * @param $file File object, or String that is path to a file to store + * @return DMSDocumentInstance Document object that we just created + */ + public function storeDocument($file); - /** - * - * Returns a number of Document objects based on the a search by tags. You can search by category alone, - * by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana") - * @abstract - * @param null $category The metadata category to search for - * @param null $value The metadata value to search for - * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results - * @return DMSDocumentInterface - */ - function getByTag($category = null, $value = null, $showEmbargoed = false); + /** + * + * Returns a number of Document objects based on the a search by tags. You can search by category alone, + * by tag value alone, or by both. I.e: getByTag("fruits",null); getByTag(null,"banana"); getByTag("fruits","banana") + * @abstract + * @param null $category The metadata category to search for + * @param null $value The metadata value to search for + * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results + * @return DMSDocumentInterface + */ + public function getByTag($category = null, $value = null, $showEmbargoed = false); - /** - * Returns a number of Document objects that match a full-text search of the Documents and their contents - * (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module) - * @abstract - * @param $searchText String to search for - * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results - * @return DMSDocumentInterface - */ - function getByFullTextSearch($searchText, $showEmbargoed = false); + /** + * Returns a number of Document objects that match a full-text search of the Documents and their contents + * (if contents is searchable and compatible search module is installed - e.g. FullTextSearch module) + * @abstract + * @param $searchText String to search for + * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results + * @return DMSDocumentInterface + */ + public function getByFullTextSearch($searchText, $showEmbargoed = false); - /** - * Returns a list of Document objects associated with a Page - * @abstract - * @param $page SiteTree to fetch the associated Documents from - * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results - * @return DataList Document list associated with the Page - */ - function getByPage($page, $showEmbargoed = false); -} \ No newline at end of file + /** + * Returns a list of Document objects associated with a Page + * @abstract + * @param $page SiteTree to fetch the associated Documents from + * @param bool $showEmbargoed Boolean that specifies if embargoed documents should be included in results + * @return DataList Document list associated with the Page + */ + public function getByPage($page, $showEmbargoed = false); +} diff --git a/code/model/DMSDocument.php b/code/model/DMSDocument.php index 2f5cb17..730911a 100644 --- a/code/model/DMSDocument.php +++ b/code/model/DMSDocument.php @@ -3,1260 +3,1366 @@ /** * @package dms */ -class DMSDocument extends DataObject implements DMSDocumentInterface { - - private static $db = array( - "Filename" => "Varchar(255)", // eg. 3469~2011-energysaving-report.pdf - "Folder" => "Varchar(255)", // eg. 0 - "Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp" - "Description" => 'Text', - "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)', - "EmbargoedUntilDate" => 'SS_DateTime', - "ExpireAtDate" => 'SS_DateTime' - ); - - private static $many_many = array( - 'Pages' => 'SiteTree', - 'Tags' => 'DMSTag' - ); - - private static $many_many_extraFields = array( - 'Pages' => array( - 'DocumentSort' => 'Int' - ) - ); - - private static $display_fields = array( - 'ID' => 'ID', - 'Title' => 'Title', - 'FilenameWithoutID' => 'Filename', - 'LastChanged' => 'LastChanged' - ); - - private static $singular_name = 'Document'; - - private static $plural_name = 'Documents'; - - private static $searchable_fields = array( - 'ID' => array( - 'filter' => 'ExactMatchFilter', - 'field' => 'NumericField' - ), - 'Title', - 'Filename', - 'LastChanged' - ); - - /** - * @param Member $member - * - * @return boolean - */ - public function canView($member = null) { - if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { - $member = Member::currentUser(); - } - - // extended access checks - $results = $this->extend('canView', $member); - - if($results && is_array($results)) { - if(!min($results)) return false; - } - - if($member && $member->ID){ - return true; - } - - return false; - } - - /** - * @param Member $member - * - * @return boolean - */ - public function canEdit($member = null) { - if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { - $member = Member::currentUser(); - } - - $results = $this->extend('canEdit', $member); - - if($results && is_array($results)) { - if(!min($results)) return false; - } - - return $this->canView(); - } - - /** - * @param Member $member - * - * @return boolean - */ - public function canCreate($member = null) { - if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { - $member = Member::currentUser(); - } - - $results = $this->extend('canCreate', $member); - - if($results && is_array($results)) { - if(!min($results)) return false; - } - - return $this->canView(); - } - - /** - * @param Member $member - * - * @return boolean - */ - public function canDelete($member = null) { - if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { - $member = Member::currentUser(); - } - - $results = $this->extend('canDelete', $member); - - if($results && is_array($results)) { - if(!min($results)) return false; - } - - return $this->canView(); - } - - - - - /** - * Associates this document with a Page. This method does nothing if the - * association already exists. - * - * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to - * add a many_many relation. - * - * @param SiteTree $pageObject Page object to associate this Document with - * - * @return DMSDocument - */ - public function addPage($pageObject) { - $this->Pages()->add($pageObject); - - DB::query("UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1 WHERE \"SiteTreeID\" = $pageObject->ID"); - - return $this; - } - - /** - * Associates this DMSDocument with a set of Pages. This method loops - * through a set of page ids, and then associates this DMSDocument with the - * individual Page with the each page id in the set. - * - * @param array $pageIDs - * - * @return DMSDocument - */ - public function addPages($pageIDs) { - foreach($pageIDs as $id) { - $pageObject = DataObject::get_by_id("SiteTree", $id); - - if($pageObject && $pageObject->exists()) { - $this->addPage($pageObject); - } - } - - return $this; - } - - /** - * Removes the association between this Document and a Page. This method - * does nothing if the association does not exist. - * - * @param SiteTree $pageObject Page object to remove the association to - * - * @return DMSDocument - */ - public function removePage($pageObject) { - $this->Pages()->remove($pageObject); - - return $this; - } - - /** - * @see getPages() - * - * @return DataList - */ - public function Pages() { - $pages = $this->getManyManyComponents('Pages'); - $this->extend('updatePages', $pages); - - return $pages; - } - - /** - * Returns a list of the Page objects associated with this Document. - * - * @return DataList - */ - public function getPages() { - return $this->Pages(); - } - - /** - * Removes all associated Pages from the DMSDocument - * - * @return DMSDocument - */ - public function removeAllPages() { - $this->Pages()->removeAll(); - - return $this; - } - - /** - * Increase ViewCount by 1, without update any other record fields such as - * LastEdited. - * - * @return DMSDocument - */ - public function trackView() { - if ($this->ID > 0) { - $count = $this->ViewCount + 1; - - $this->ViewCount = $count; - - DB::query("UPDATE \"DMSDocument\" SET \"ViewCount\"='$count' WHERE \"ID\"={$this->ID}"); - } - - return $this; - } - - - /** - * Adds a metadata tag to the Document. The tag has a category and a value. - * - * Each category can have multiple values by default. So: - * addTag("fruit","banana") addTag("fruit", "apple") will add two items. - * - * However, if the third parameter $multiValue is set to 'false', then all - * updates to a category only ever update a single value. So: - * addTag("fruit","banana") addTag("fruit", "apple") would result in a - * single metadata tag: fruit->apple. - * - * Can could be implemented as a key/value store table (although it is more - * like category/value, because the same category can occur multiple times) - * - * @param string $category of a metadata category to add (required) - * @param string $value of a metadata value to add (required) - * @param bool $multiValue Boolean that determines if the category is - * multi-value or single-value (optional) - * - * @return DMSDocument - */ - public function addTag($category, $value, $multiValue = true) { - if ($multiValue) { - //check for a duplicate tag, don't add the duplicate - $currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value)); - if ($currentTag->Count() == 0) { - //multi value tag - $tag = new DMSTag(); - $tag->Category = $category; - $tag->Value = $value; - $tag->MultiValue = true; - $tag->write(); - $tag->Documents()->add($this); - } else { - //add the relation between the tag and document - foreach($currentTag as $tagObj) { - $tagObj->Documents()->add($this); - } - } - } else { - //single value tag - $currentTag = $this->Tags()->filter(array('Category' => $category)); - $tag = null; - if ($currentTag->Count() == 0) { - //create the single-value tag - $tag = new DMSTag(); - $tag->Category = $category; - $tag->Value = $value; - $tag->MultiValue = false; - $tag->write(); - } else { - //update the single value tag - $tag = $currentTag->first(); - $tag->Value = $value; - $tag->MultiValue = false; - $tag->write(); - } - - // regardless of whether we created a new tag or are just updating an - // existing one, add the relation - $tag->Documents()->add($this); - } - - return $this; - } - - /** - * @param string $category - * @param string $value - * - * @return DataList - */ - protected function getTagsObjects($category, $value = null) { - $valueFilter = array("Category" => $category); - if (!empty($value)) $valueFilter['Value'] = $value; - - $tags = $this->Tags()->filter($valueFilter); - return $tags; - } - - /** - * Fetches all tags associated with this DMSDocument within a given - * category. If a value is specified this method tries to fetch that - * specific tag. - * - * @param string $category metadata category to get - * @param string $value value of the tag to get - * - * @return array Strings of all the tags or null if there is no match found - */ - public function getTagsList($category, $value = null) { - $tags = $this->getTagsObjects($category, $value); - - $returnArray = null; - - if ($tags->Count() > 0) { - $returnArray = array(); - - foreach($tags as $t) { - $returnArray[] = $t->Value; - } - } - - return $returnArray; - } - - /** - * Removes a tag from the Document. If you only set a category, then all - * values in that category are deleted. - * - * If you specify both a category and a value, then only that single - * category/value pair is deleted. - * - * Nothing happens if the category or the value do not exist. - * - * @param string $category Category to remove - * @param string $value Value to remove - * - * @return DMSDocument - */ - public function removeTag($category, $value = null) { - $tags = $this->getTagsObjects($category, $value); - - if ($tags->Count() > 0) { - foreach($tags as $t) { - $documentList = $t->Documents(); - - //remove the relation between the tag and the document - $documentList->remove($this); - - //delete the entire tag if it has no relations left - if ($documentList->Count() == 0) $t->delete(); - } - } - - return $this; - } - - /** - * Deletes all tags associated with this Document. - * - * @return DMSDocument - */ - public function removeAllTags() { - $allTags = $this->Tags(); - - foreach($allTags as $tag) { - $documentlist = $tag->Documents(); - $documentlist->remove($this); - if ($tag->Documents()->Count() == 0) $tag->delete(); - } - - return $this; - } - - /** - * Returns a link to download this document from the DMS store. - * - * @return string - */ - public function getLink() { - return Controller::join_links(Director::baseURL(),'dmsdocument/'.$this->ID); - } - - /** - * @return string - */ - public function Link() { - return $this->getLink(); - } - - /** - * Hides the document, so it does not show up when getByPage($myPage) is - * called (without specifying the $showEmbargoed = true parameter). - * - * This is similar to expire, except that this method should be used to hide - * 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. - * +class DMSDocument extends DataObject implements DMSDocumentInterface +{ + + private static $db = array( + "Filename" => "Varchar(255)", // eg. 3469~2011-energysaving-report.pdf + "Folder" => "Varchar(255)", // eg. 0 + "Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp" + "Description" => 'Text', + "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)', + "EmbargoedUntilDate" => 'SS_DateTime', + "ExpireAtDate" => 'SS_DateTime' + ); + + private static $many_many = array( + 'Pages' => 'SiteTree', + 'Tags' => 'DMSTag' + ); + + private static $many_many_extraFields = array( + 'Pages' => array( + 'DocumentSort' => 'Int' + ) + ); + + private static $display_fields = array( + 'ID' => 'ID', + 'Title' => 'Title', + 'FilenameWithoutID' => 'Filename', + 'LastChanged' => 'LastChanged' + ); + + private static $singular_name = 'Document'; + + private static $plural_name = 'Documents'; + + private static $searchable_fields = array( + 'ID' => array( + 'filter' => 'ExactMatchFilter', + 'field' => 'NumericField' + ), + 'Title', + 'Filename', + 'LastChanged' + ); + + /** + * @param Member $member + * + * @return boolean + */ + public function canView($member = null) + { + if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { + $member = Member::currentUser(); + } + + // extended access checks + $results = $this->extend('canView', $member); + + if ($results && is_array($results)) { + if (!min($results)) { + return false; + } + } + + if ($member && $member->ID) { + return true; + } + + return false; + } + + /** + * @param Member $member + * + * @return boolean + */ + public function canEdit($member = null) + { + if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { + $member = Member::currentUser(); + } + + $results = $this->extend('canEdit', $member); + + if ($results && is_array($results)) { + if (!min($results)) { + return false; + } + } + + return $this->canView(); + } + + /** + * @param Member $member + * + * @return boolean + */ + public function canCreate($member = null) + { + if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { + $member = Member::currentUser(); + } + + $results = $this->extend('canCreate', $member); + + if ($results && is_array($results)) { + if (!min($results)) { + return false; + } + } + + return $this->canView(); + } + + /** + * @param Member $member + * + * @return boolean + */ + public function canDelete($member = null) + { + if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { + $member = Member::currentUser(); + } + + $results = $this->extend('canDelete', $member); + + if ($results && is_array($results)) { + if (!min($results)) { + return false; + } + } + + return $this->canView(); + } + + + + + /** + * Associates this document with a Page. This method does nothing if the + * association already exists. + * + * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to + * add a many_many relation. + * + * @param SiteTree $pageObject Page object to associate this Document with + * + * @return DMSDocument + */ + public function addPage($pageObject) + { + $this->Pages()->add($pageObject); + + DB::query("UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1 WHERE \"SiteTreeID\" = $pageObject->ID"); + + return $this; + } + + /** + * Associates this DMSDocument with a set of Pages. This method loops + * through a set of page ids, and then associates this DMSDocument with the + * individual Page with the each page id in the set. + * + * @param array $pageIDs + * + * @return DMSDocument + */ + public function addPages($pageIDs) + { + foreach ($pageIDs as $id) { + $pageObject = DataObject::get_by_id("SiteTree", $id); + + if ($pageObject && $pageObject->exists()) { + $this->addPage($pageObject); + } + } + + return $this; + } + + /** + * Removes the association between this Document and a Page. This method + * does nothing if the association does not exist. + * + * @param SiteTree $pageObject Page object to remove the association to + * + * @return DMSDocument + */ + public function removePage($pageObject) + { + $this->Pages()->remove($pageObject); + + return $this; + } + + /** + * @see getPages() + * + * @return DataList + */ + public function Pages() + { + $pages = $this->getManyManyComponents('Pages'); + $this->extend('updatePages', $pages); + + return $pages; + } + + /** + * Returns a list of the Page objects associated with this Document. + * + * @return DataList + */ + public function getPages() + { + return $this->Pages(); + } + + /** + * Removes all associated Pages from the DMSDocument + * + * @return DMSDocument + */ + public function removeAllPages() + { + $this->Pages()->removeAll(); + + return $this; + } + + /** + * Increase ViewCount by 1, without update any other record fields such as + * LastEdited. + * + * @return DMSDocument + */ + public function trackView() + { + if ($this->ID > 0) { + $count = $this->ViewCount + 1; + + $this->ViewCount = $count; + + DB::query("UPDATE \"DMSDocument\" SET \"ViewCount\"='$count' WHERE \"ID\"={$this->ID}"); + } + + return $this; + } + + + /** + * Adds a metadata tag to the Document. The tag has a category and a value. + * + * Each category can have multiple values by default. So: + * addTag("fruit","banana") addTag("fruit", "apple") will add two items. + * + * However, if the third parameter $multiValue is set to 'false', then all + * updates to a category only ever update a single value. So: + * addTag("fruit","banana") addTag("fruit", "apple") would result in a + * single metadata tag: fruit->apple. + * + * Can could be implemented as a key/value store table (although it is more + * like category/value, because the same category can occur multiple times) + * + * @param string $category of a metadata category to add (required) + * @param string $value of a metadata value to add (required) + * @param bool $multiValue Boolean that determines if the category is + * multi-value or single-value (optional) + * + * @return DMSDocument + */ + public function addTag($category, $value, $multiValue = true) + { + if ($multiValue) { + //check for a duplicate tag, don't add the duplicate + $currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value)); + if ($currentTag->Count() == 0) { + //multi value tag + $tag = new DMSTag(); + $tag->Category = $category; + $tag->Value = $value; + $tag->MultiValue = true; + $tag->write(); + $tag->Documents()->add($this); + } else { + //add the relation between the tag and document + foreach ($currentTag as $tagObj) { + $tagObj->Documents()->add($this); + } + } + } else { + //single value tag + $currentTag = $this->Tags()->filter(array('Category' => $category)); + $tag = null; + if ($currentTag->Count() == 0) { + //create the single-value tag + $tag = new DMSTag(); + $tag->Category = $category; + $tag->Value = $value; + $tag->MultiValue = false; + $tag->write(); + } else { + //update the single value tag + $tag = $currentTag->first(); + $tag->Value = $value; + $tag->MultiValue = false; + $tag->write(); + } + + // regardless of whether we created a new tag or are just updating an + // existing one, add the relation + $tag->Documents()->add($this); + } + + return $this; + } + + /** + * @param string $category + * @param string $value + * + * @return DataList + */ + protected function getTagsObjects($category, $value = null) + { + $valueFilter = array("Category" => $category); + if (!empty($value)) { + $valueFilter['Value'] = $value; + } + + $tags = $this->Tags()->filter($valueFilter); + return $tags; + } + + /** + * Fetches all tags associated with this DMSDocument within a given + * category. If a value is specified this method tries to fetch that + * specific tag. + * + * @param string $category metadata category to get + * @param string $value value of the tag to get + * + * @return array Strings of all the tags or null if there is no match found + */ + public function getTagsList($category, $value = null) + { + $tags = $this->getTagsObjects($category, $value); + + $returnArray = null; + + if ($tags->Count() > 0) { + $returnArray = array(); + + foreach ($tags as $t) { + $returnArray[] = $t->Value; + } + } + + return $returnArray; + } + + /** + * Removes a tag from the Document. If you only set a category, then all + * values in that category are deleted. + * + * If you specify both a category and a value, then only that single + * category/value pair is deleted. + * + * Nothing happens if the category or the value do not exist. + * + * @param string $category Category to remove + * @param string $value Value to remove + * + * @return DMSDocument + */ + public function removeTag($category, $value = null) + { + $tags = $this->getTagsObjects($category, $value); + + if ($tags->Count() > 0) { + foreach ($tags as $t) { + $documentList = $t->Documents(); + + //remove the relation between the tag and the document + $documentList->remove($this); + + //delete the entire tag if it has no relations left + if ($documentList->Count() == 0) { + $t->delete(); + } + } + } + + return $this; + } + + /** + * Deletes all tags associated with this Document. + * + * @return DMSDocument + */ + public function removeAllTags() + { + $allTags = $this->Tags(); + + foreach ($allTags as $tag) { + $documentlist = $tag->Documents(); + $documentlist->remove($this); + if ($tag->Documents()->Count() == 0) { + $tag->delete(); + } + } + + return $this; + } + + /** + * Returns a link to download this document from the DMS store. + * + * @return string + */ + public function getLink() + { + return Controller::join_links(Director::baseURL(), 'dmsdocument/'.$this->ID); + } + + /** + * @return string + */ + public function Link() + { + return $this->getLink(); + } + + /** + * Hides the document, so it does not show up when getByPage($myPage) is + * called (without specifying the $showEmbargoed = true parameter). + * + * This is similar to expire, except that this method should be used to hide + * 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 * show up in draft mode. * - * @return bool - */ - public function isHidden() { - $hidden = $this->isEmbargoed() || $this->isExpired(); - $readingMode = Versioned::get_reading_mode(); - - if ($readingMode == "Stage.Stage") { - if($this->EmbargoedUntilPublished == true) { - $hidden = false; - } - } - - return $hidden; - } - - /** - * Returns if this is Document is embargoed. - * - * @return bool - */ - public function isEmbargoed() { - if (is_object($this->EmbargoedUntilDate)) { - $this->EmbargoedUntilDate = $this->EmbargoedUntilDate->Value; - } - - $embargoed = false; - - if ($this->EmbargoedIndefinitely) { - $embargoed = true; - } else if ($this->EmbargoedUntilPublished) { - $embargoed = true; - } else if (!empty($this->EmbargoedUntilDate)) { - if(SS_Datetime::now()->Value < $this->EmbargoedUntilDate) { - $embargoed = true; - } - } - - 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. - * - * @param string $datetime date time value when this Document should expire. - * @param bool $write - * - * @return DMSDocument - */ - public function embargoUntilDate($datetime, $write = true) { - $this->EmbargoedUntilDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s'); - - if ($write) $this->write(); - - return $this; - } - - /** - * Clears any previously set embargos, so the Document always shows up in - * all queries. - * - * @param bool $write - * - * @return DMSDocument - */ - public function clearEmbargo($write = true) { - $this->EmbargoedIndefinitely = false; - $this->EmbargoedUntilPublished = false; - $this->EmbargoedUntilDate = null; - - if ($write) $this->write(); - - return $this; - } - - /** - * Returns if this is Document is expired. - * - * @return bool - */ - public function isExpired() { - if (is_object($this->ExpireAtDate)) { - $this->ExpireAtDate = $this->ExpireAtDate->Value; - } - - $expired = false; - - if (!empty($this->ExpireAtDate)) { - if(SS_Datetime::now()->Value >= $this->ExpireAtDate) { - $expired = true; - } - } - - return $expired; - } - - /** - * Hides the document at a specific date, so it does not show up when - * getByPage($myPage) is called. - * - * @param string $datetime date time value when this Document should expire - * @param bool $write - * - * @return DMSDocument - */ - public function expireAtDate($datetime, $write = true) { - $this->ExpireAtDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s'); - - if ($write) $this->write(); - - return $this; - } - - /** - * Clears any previously set expiry. - * - * @param bool $write - * - * @return DMSDocument - */ - public function clearExpiry($write = true) { - $this->ExpireAtDate = null; - - if ($write) $this->write(); - - return $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 - * Exception is thrown - * - * @throws Exception - * - * @return DataList List of Document objects - */ - public function getVersions() { - if (!DMSDocument_versions::$enable_versions) { - throw new Exception("DMSDocument versions are disabled"); - } - - return DMSDocument_versions::get_versions($this); - } - - /** - * Returns the full filename of the document stored in this object. - * - * @return string - */ - public function getFullPath() { - if($this->Filename) { - return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename; - } - - return null; - } - - /** - * Returns the filename of this asset. - * - * @return string - */ - public function getFileName() { - if($this->getField('Filename')) { - return $this->getField('Filename'); - } else { - return ASSETS_DIR . '/'; - } - } - - /** - * @return string - */ - public function getName() { - return $this->getField('Title'); - } - - - /** - * @return string - */ - public function getFilenameWithoutID() { - $filenameParts = explode('~',$this->Filename); - $filename = array_pop($filenameParts); - - return $filename; - } - - /** - * @return string - */ - public function getStorageFolder() { - return DMS::get_dms_path() . DIRECTORY_SEPARATOR . DMS::get_storage_folder($this->ID); - } - - /** - * 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 void - */ - public function delete() { - // remove tags - $this->removeAllTags(); - - // delete the file (and previous versions of files) - $filesToDelete = array(); - $storageFolder = $this->getStorageFolder(); - - if (file_exists($storageFolder)) { - if ($handle = opendir($storageFolder)) { - while (false !== ($entry = readdir($handle))) { - // only delete if filename starts the the relevant ID - if(strpos($entry,$this->ID.'~') === 0) { - $filesToDelete[] = $entry; - } - } - - closedir($handle); - - //delete all this files that have the id of this document - foreach($filesToDelete as $file) { - $filePath = $storageFolder .DIRECTORY_SEPARATOR . $file; - - if (is_file($filePath)) { - unlink($filePath); - } - } - } - } - - $this->removeAllPages(); - - // get rid of any versions have saved for this DMSDocument, too - if (DMSDocument_versions::$enable_versions) { - $versions = $this->getVersions(); - - if ($versions->Count() > 0) { - foreach($versions as $v) { - $v->delete(); - } - } - } - - parent::delete(); - } - - - - /** - * Relate an existing file on the filesystem to the document. - * - * Copies the file to the new destination, as defined in {@link get_DMS_path()}. - * - * @param string $filePath Path to file, relative to webroot. - * - * @return DMSDocument - */ - public function storeDocument($filePath) { - if (empty($this->ID)) { - user_error("Document must be written to database before it can store documents", E_USER_ERROR); - } - - // 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); - $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; - - //version the existing file (copy it to a new "very specific" filename - if (DMSDocument_versions::$enable_versions) { - DMSDocument_versions::create_version($this); - } else { //otherwise delete the old document file - $oldPath = $this->getFullPath(); - if (file_exists($oldPath)) unlink($oldPath); - } - - copy($fromPath, $toPath); //this will overwrite the existing file (if present) - - //write the filename of the stored document - $this->Filename = $toFilename; - $this->Folder = $toFolder; - - $extension = pathinfo($this->Filename, PATHINFO_EXTENSION); - - if (empty($this->Title)) { - // don't overwrite existing document titles - $this->Title = basename($filePath,'.'.$extension); - } - - $this->LastChanged = SS_Datetime::now()->Rfc2822(); - $this->write(); - - return $this; - } - - /** - * 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. - * - * @param File|string $file path to a file to store - * - * @return DMSDocument object that we replaced the file in - */ - public function replaceDocument($file) { - $filePath = DMS::transform_file_to_file_path($file); - $doc = $this->storeDocument($filePath); // replace the document - - return $doc; - } - - - /** - * Return the type of file for the given extension - * on the current file name. - * - * @param string $ext - * - * @return string - */ - public static function get_file_type($ext) { - $types = array( - 'gif' => 'GIF image - good for diagrams', - 'jpg' => 'JPEG image - good for photos', - 'jpeg' => 'JPEG image - good for photos', - 'png' => 'PNG image - good general-purpose format', - 'ico' => 'Icon image', - 'tiff' => 'Tagged image format', - 'doc' => 'Word document', - 'xls' => 'Excel spreadsheet', - 'zip' => 'ZIP compressed file', - 'gz' => 'GZIP compressed file', - 'dmg' => 'Apple disk image', - 'pdf' => 'Adobe Acrobat PDF file', - 'mp3' => 'MP3 audio file', - 'wav' => 'WAV audo file', - 'avi' => 'AVI video file', - 'mpg' => 'MPEG video file', - 'mpeg' => 'MPEG video file', - 'js' => 'Javascript file', - 'css' => 'CSS file', - 'html' => 'HTML file', - 'htm' => 'HTML file' - ); - - return isset($types[$ext]) ? $types[$ext] : $ext; - } - - - /** - * Returns the Description field with HTML