diff --git a/.gitignore b/.gitignore index 436f77a0..176af8c8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ npm-debug.log /public /resources .phpunit.result.cache +/app diff --git a/composer.json b/composer.json index f3c84973..c062b524 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "require": { "silverstripe/cms": "^4.0 || ^5.0", "symbiote/silverstripe-gridfieldextensions": "*", + "silverstripe/asset-admin": "*", "silverstripe/taxonomy": "*" }, "suggest": { diff --git a/docs/en/configuration.md b/docs/en/configuration.md index 1857703b..d9de23f2 100644 --- a/docs/en/configuration.md +++ b/docs/en/configuration.md @@ -12,17 +12,16 @@ project root directory: ```yaml DMS: - folder_name: my-custom-folder + folder_name: my-custom-folder ``` - ## Enable/disable documents/sets for a specific page type If you don't need documents/document sets for a specific page type you can disable this with YAML configuration: ```yaml MyPageType: - documents_enabled: false + documents_enabled: false ``` Likewise, you could override a previously set configuration value by setting this back to `true` in a configuration @@ -38,12 +37,13 @@ To add extra allowed file extensions purely for DMS documents, you can update th ```yaml DMSDocumentAddController: - allowed_extensions: - - php - - php5 + allowed_extensions: + - php + - php5 ``` ## Adding fields to the Query Builder + Query builder fields are read from the DMSDocument::searchable_fields property set in [querybuilder.yml](../../_config/querybuilder.yml). Some default fields are provided and can be customised by modifying the field and/or filter properties of a field or adding a new field entirely. @@ -54,21 +54,21 @@ The default searchable filters available to query builder is as follows: ```yaml DMSDocument: - searchable_fields: - Title: - title: "Document title matches ..." - Description: - title: "Document summary matches ..." - CreatedByID: - title: 'Document created by ...' - field: 'ListboxField' - filter: 'ExactMatchFilter' - LastEditedByID: - title: 'Document last changed by ...' - field: 'ListboxField' - filter: 'ExactMatchFilter' - Filename: - title: 'File name' + searchable_fields: + Title: + title: "Document title matches ..." + Description: + title: "Document summary matches ..." + CreatedByID: + title: "Document created by ..." + field: "ListboxField" + filter: "ExactMatchFilter" + LastEditedByID: + title: "Document last changed by ..." + field: "ListboxField" + filter: "ExactMatchFilter" + Filename: + title: "File name" ``` ## Change the shortcode handler @@ -77,15 +77,18 @@ If you need to change the `dms_document_link` shortcode handler for some reason, and some PHP: ```yaml -DMS: - shortcode_handler_key: your_shortcode +Sunnysideup\DMS\DMS: + shortcode_handler_key: your_shortcode ``` And for example in `_config.php`: ```php +use Sunnysideup\DMS\DMS; +use Sunnysideup\DMS\DMSShortcodeHandler; + ShortcodeParser::get('default')->register( - Config::inst()->get('DMS', 'shortcode_handler_key'), - array('DMSShortcodeHandler', 'handle') + Config::inst()->get(DMS::class, 'shortcode_handler_key'), + [DMSShortcodeHandler::class, 'handle'] ); ``` diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6788a080..0c1df4dd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,16 @@ - - - - src/. - - - tests/ - - - - - tests - - + + + + src/. + + + tests/ + + + + + tests + + diff --git a/src/DMS.php b/src/DMS.php index ab68d075..00482eec 100644 --- a/src/DMS.php +++ b/src/DMS.php @@ -9,4 +9,6 @@ class DMS use Configurable; private static $folder_name = 'dms'; + + private static $shortcode_handler_key = 'dms'; } diff --git a/src/DMSShortcodeHandler.php b/src/DMSShortcodeHandler.php new file mode 100644 index 00000000..5b1aea49 --- /dev/null +++ b/src/DMSShortcodeHandler.php @@ -0,0 +1,35 @@ +byID($arguments['id']); + + if ($document && !$document->isHidden()) { + if ($content) { + return sprintf( + '%s', + $document->Link(), + $parser->parse($content) + ); + } + + if (isset($extra['element'])) { + $extra['element']->setAttribute('data-ext', $document->getExtension()); + $extra['element']->setAttribute('data-size', $document->getFileSizeFormatted()); + } + + return $document->Link(); + } + } + + return ''; + } +} diff --git a/src/Model/DMSDocument.php b/src/Model/DMSDocument.php index 425b11cd..91d7f4f5 100644 --- a/src/Model/DMSDocument.php +++ b/src/Model/DMSDocument.php @@ -42,6 +42,7 @@ use Sunnysideup\DMS\Admin\DMSDocumentAdmin;; use SilverStripe\Core\Injector\Injector; +use SilverStripe\Security\Security; /** * @package dms @@ -373,12 +374,12 @@ public function getPermissionsActionPanel() public function onBeforeWrite() { - // Set user fields - if ($currentUserID = Member::currentUserID()) { + if ($currentUser = Security::getCurrentUser()) { if (!$this->CreatedByID) { - $this->CreatedByID = $currentUserID; + $this->CreatedByID = $currentUser->ID; } - $this->LastEditedByID = $currentUserID; + + $this->LastEditedByID = $currentUser->ID; } if ($this->TempFileID) { diff --git a/src/Tasks/MakeDMSTablesObsolete.php b/src/Tasks/MakeDMSTablesObsolete.php deleted file mode 100644 index f38f1a6c..00000000 --- a/src/Tasks/MakeDMSTablesObsolete.php +++ /dev/null @@ -1,64 +0,0 @@ -get('Sunnysideup\\MigrateData\\Tasks\\MigrateDataTask'); - - if ($obj->tableExists('DMSDocument_versions')) { - if ( - $obj->fieldExists('DMSDocument_versions', 'Created') && - $obj->fieldExists('DMSDocument_versions', 'LastEdited') - ) { - $obj->makeTableObsolete('DMSDocument_versions'); - } - } - - if ($obj->tableExists('DMSDocument')) { - if ( - $obj->fieldExists('DMSDocument', 'Created') && - $obj->fieldExists('DMSDocument', 'LastEdited') - ) { - $obj->makeTableObsolete('DMSDocument'); - } - } - } -} diff --git a/src/Tasks/MigrateDMSToSilverstripe4.php b/src/Tasks/MigrateDMSToSilverstripe4.php deleted file mode 100644 index e113f97b..00000000 --- a/src/Tasks/MigrateDMSToSilverstripe4.php +++ /dev/null @@ -1,346 +0,0 @@ - fields that need migrating - * 'MyPageLongFormDocument' => 'DownloadFile' - * these tables also need to have a OriginalDMSDocumentID[TableName] field - *@var array - */ - private static $my_table_and_field_for_post_queries = []; - - public static function flush() - { - if (!empty($_GET['rundmsmigration'])) { - $oldFolder = ASSETS_PATH . '/_dmsassets'; - $newFolder = ASSETS_PATH . '/dmsassets'; - if (file_exists($oldFolder) && !file_exists($newFolder)) { - rename($oldFolder, $newFolder); - } elseif (file_exists($oldFolder) && file_exists($newFolder)) { - user_error($oldFolder . ' AND ' . $newFolder . ' exist! Please review ...', E_USER_NOTICE); - } - - $obj = Injector::inst()->get('Sunnysideup\\MigrateData\\Tasks\\MigrateDataTask'); - - if ($obj->tableExists('DMSDocument_versions')) { - if ( - $obj->fieldExists('DMSDocument_versions', 'Created') && - $obj->fieldExists('DMSDocument_versions', 'LastEdited') - ) { - $obj->makeTableObsolete('DMSDocument_versions'); - } - } - - if ($obj->tableExists('DMSDocument')) { - if ( - $obj->fieldExists('DMSDocument', 'Created') && - $obj->fieldExists('DMSDocument', 'LastEdited') - ) { - $obj->makeTableObsolete('DMSDocument'); - } - } - } - } - - protected $title = 'Upgrade DMS to SS4'; - - protected $description = 'Migration tool for upgrading from DMS from SS3 to SS4. CAREFUL: this removes a ton of functionality from the module.'; - - protected $enabled = true; - - - private $_folderCache = []; - - protected function performMigration() - { - - self::flush(); - - $this->runSQLQueries($this->getPreQueries(), 'PRE'); - - $this->setMainDMSFolder(); - $baseDir = Director::baseFolder(); - $baseDirWithPublic = $baseDir . '/public/'; - $baseURL = Director::absoluteBaseURL(); - self::flush(); - $rows = DB::query('SELECT * FROM "_obsolete_DMSDocument";'); - $this->flushNow('... selecting ' . DB::affected_rows() . ' rows from _obsolete_DMSDocument'); - foreach ($rows as $row) { - //new file system doesn't like using _ or 0 for folder names - $oldFolderName = '/dmsassets/' . $row['Folder'] . ''; - $folderNumber = $row['Folder'] ? $row['Folder'] : 'zero'; - $newFolderName = 'dmsassets/' . $folderNumber . ''; - if (!isset($this->_folderCache[$newFolderName])) { - $this->_folderCache[$newFolderName] = Folder::find_or_make($newFolderName); - } - if ($this->_folderCache[$newFolderName] instanceof Folder) { - $myFolder = $this->_folderCache[$newFolderName]; - $exists = File::get()->filter(['OriginalDMSDocumentIDFile' => $row['ID']])->count() ? true : false; - if ($exists) { - $this->flushNow('Skipping File with ID ' . $row['ID']); - //do nothing - } else { - $this->flushNow('Doing: ' . print_r($row, 1)); - $fullLocationFromAssets = $oldFolderName . '/' . $row['Filename']; - $fullLocationFromBase = ASSETS_PATH . $fullLocationFromAssets; - - - if (file_exists($fullLocationFromBase)) { - $newFile = File::find($fullLocationFromAssets); - if ($newFile) { - $newFile->ClassName = DMSDocument::class; - $newFile->write(); - } else { - $newFile = DMSDocument::create(); - } - - - //File Values - $newFile->Created = $row['Created']; - $newFile->LastEdited = $row['LastEdited']; - $newFile->Name = $row['Filename']; - $newFile->Title = $row['Title']; - $newFile->CanViewType = $row['CanViewType']; - $newFile->CanEditType = $row['CanEditType']; - - //DMSDocument Values - $newFile->Description = $row['Description']; - $newFile->ISBN = $row['ISBN']; - $newFile->ISSN = $row['ISSN']; - $newFile->CoverImageID = $row['CoverImageID']; - $newFile->CreatedByID = $row['CreatedByID']; - $newFile->LastEditedByID = $row['LastEditedByID']; - $newFile->write(); - - //in the obsolete one we already have a version 1. Above we write a file - //so we end up with version 1 - $sql = 'DELETE FROM "File_Versions" WHERE "RecordID" = ' . $newFile->ID . ' AND "Version" = 1;'; - $this->flushNow('... ... ... running - ' . $sql); - DB::query($sql); - - $sql = 'DELETE FROM "DMSDocument_Versions" WHERE "RecordID" = ' . $newFile->ID . ' AND "Version" = 1;'; - $this->flushNow('... ... ... running -' . $sql); - DB::query($sql); - - if (!$this->tableExists('_obsolete_DMSDocument_versions')) { - user_error('Table _obsolete_DMSDocument_versions does not exist. Error', E_USER_ERROR); - } - $versionRows = DB::query('SELECT "ID" FROM "_obsolete_DMSDocument_versions" WHERE "DocumentID" = ' . $row['ID']); - foreach ($versionRows as $versionRow) { - $this->flushNow('... adding row for DocumentID = ' . $row['ID']); - $sql = ' - INSERT - INTO "File_Versions" ( - "RecordID", "Version", "Created", "LastEdited", "Name", "Title", "CanViewType", "CanEditType", "OriginalDMSDocumentIDFile", "ClassName" - ) - SELECT - ' . $newFile->ID . ', "VersionCounter", "Created", "LastEdited", "Filename", "Title", "CanViewType", "CanEditType", ' . $row['ID'] . ' AS OriginalDMSDocumentIDFile, \'Sunnysideup\\\\DMS\\\\Model\\\\DMSDocument\' as ClassNameInsert - FROM "_obsolete_DMSDocument_versions" - WHERE "ID" = ' . $versionRow['ID'] . ';'; - echo $sql; - DB::query($sql); - $id = DB::query('SELECT LAST_INSERT_ID();')->value(); - if (!$id) { - user_error('Could not find an ID from the last insert.'); - } - $testVersionCountForDMSDocumentTable = DB::query('SELECT COUNT("ID") FROM "DMSDocument_Versions" WHERE "ID" = ' . $id); - if (!$testVersionCountForDMSDocumentTable) { - user_error('ID already exists in DMSDocument_Versions: ' . $testVersionCountForDMSDocumentTable); - } - $sql = ' - INSERT - INTO "DMSDocument_Versions" ( - "ID", "RecordID", "Version", "Description", "ISBN", "ISSN", "CoverImageID", "CreatedByID", "LastEditedByID" - ) - SELECT - ' . $id . ' AS ID, ' . $newFile->ID . ', "VersionCounter", "Description", "ISBN", "ISSN", ' . $newFile->CoverImageID . ', ' . $newFile->CreatedByID . ', "VersionAuthorID" - FROM "_obsolete_DMSDocument_versions" - WHERE "ID" = ' . $versionRow['ID'] . ';'; - DB::query($sql); - } - - //attach File - $newFile->generateFilename(); - $newFile->setFromLocalFile($fullLocationFromBase); - $newFile->ParentID = $myFolder->ID; - $id = $newFile->write(); - - $newFile->doPublish(); - //run test 1 - $testFilter1 = [ - 'Name' => $row['Filename'], - 'ParentID' => $myFolder->ID - ]; - $testCount1 = DMSDocument::get() - ->filter(['ID' => $id]) - ->count(); - if ($testCount1 !== 1) { - $this->flushNow('error in migration for row TEST 1 - could not find File Record, number of files found: ' . $testCount1, 'error'); - $this->flushNow('-----------------------------'); - $this->flushNow('STOPPED'); - $this->flushNow('-----------------------------'); - die(); - } - - $link = $newFile->AbsoluteLink(); - if ($link) { - echo $link; - - $testLocation = str_replace($baseURL, $baseDirWithPublic, $link); - if (!file_exists($testLocation)) { - $this->flushNow('error in migration for row - could not find Actual File (' . $testLocation . ')', 'error'); - $this->flushNow('-----------------------------'); - $this->flushNow('STOPPED'); - $this->flushNow('-----------------------------'); - die(); - } - //mark as complete - $this->flushNow('... Marking as complete'); - $newFile->OriginalDMSDocumentIDFile = $row['ID']; - $newFile->write(); - } else { - $this->flushNow('ERROR: could not link to document ... ID = ' . $newFile->ID . ' we looked at ' . $fullLocationFromAssets); - die(); - } - } else { - $this->flushNow('Could not find: ' . $fullLocationFromBase, 'error'); - } - } - } else { - die('Could not create folder: ' . $newFolderName); - } - } - - $this->runPublishClasses([DMSDocument::class]); - - $this->runSQLQueries($this->getPostQueries(), 'POST'); - } - - - protected function getPreQueries() - { - return [ - // 'ALTER TABLE "DMSDocument" CHANGE "ClassName" "ClassName" VARCHAR(255);', - // 'ALTER TABLE "DMSDocument_versions" CHANGE "ClassName" "ClassName" VARCHAR(255);', - // 'UPDATE "DMSDocument" SET "ClassName" = \'\'Sunnysideup\\DMS\\Model\\DMSDocument\'\' WHERE "ClassName" = \'\'DMSDocument\'\';', - // 'UPDATE "DMSDocument_versions" SET "ClassName" = \'\'Sunnysideup\\DMS\\Model\\DMSDocument\'\' WHERE "ClassName" = \'\'DMSDocument_versions\'\';', - ]; - } - - protected function getPostQueries() - { - $queries = []; - - $tablesAndFields = $this->Config()->my_table_and_field_for_post_queries; - foreach ($tablesAndFields as $table => $field) { - $queries = array_merge( - $queries, - $this->getPostQueriesBuilder($table, $field) - ); - } - - return $queries; - } - - protected function getPostQueriesBuilder($table, $relation) - { - $field = $relation . 'ID'; - if (!$this->tableExists($table)) { - $this->flushNow('Error: could not find the following table: ' . $table); - die(''); - } - //clean table - $baseTable = $table; - $baseTable = str_replace('_Live', '', $baseTable); - $baseTable = str_replace('_Versions', '', $baseTable); - $originalDocumentIDField = 'OriginalDMSDocumentID' . $baseTable; - if (!$this->fieldExists($table, $originalDocumentIDField)) { - $this->flushNow('Error: could not find the following field: ' . $originalDocumentIDField . ' in ' . $table); - die(''); - } - if (!$this->fieldExists($table, $field)) { - $this->flushNow('Error: could not find the following field: ' . $table . '.' . $field . ''); - die(''); - } - $queries = []; - foreach (['', '_Live', '_Versions'] as $tableExtensions) { - $fullTable = $table . $tableExtensions; - if ($this->tableExists($fullTable)) { - $queries[] = - - //set the OriginalDMSDocumentID if that has not been set yet ... - ' - UPDATE "' . $fullTable . '" - SET "' . $fullTable . '"."' . $originalDocumentIDField . '" = "' . $fullTable . '"."' . $field . '" - WHERE - ( - "' . $fullTable . '"."' . $originalDocumentIDField . '" = 0 OR - "' . $fullTable . '"."' . $originalDocumentIDField . '" IS NULL - ) AND ( - "' . $fullTable . '"."' . $field . '" > 0 AND - "' . $fullTable . '"."' . $field . '" IS NOT NULL - ); - '; - $queries[] = - - //set the field to zero in case there is a DMS Link - //but the DMS link can not be made - ' - UPDATE "' . $fullTable . '" - LEFT JOIN "File" - ON "File"."OriginalDMSDocumentIDFile" = "' . $fullTable . '"."' . $originalDocumentIDField . '" - SET "' . $fullTable . '"."' . $field . '" = 0 - WHERE - "' . $fullTable . '"."' . $originalDocumentIDField . '" > 0 AND - "' . $fullTable . '"."' . $originalDocumentIDField . '" IS NOT NULL AND - - "File"."ID" IS NULL; - '; - $queries[] = - - //update to new value ... where there is a DMSDocument connection - ' - UPDATE "' . $fullTable . '" - INNER JOIN "File" - ON "File"."OriginalDMSDocumentIDFile" = "' . $fullTable . '"."' . $originalDocumentIDField . '" - SET "' . $fullTable . '"."' . $field . '" = "File"."ID" - WHERE - "' . $fullTable . '"."' . $originalDocumentIDField . '" > 0 AND - "' . $fullTable . '"."' . $originalDocumentIDField . '" IS NOT NULL; - '; - } else { - $this->flushNow('Skipping ' . $fullTable . ' as this table does not exist.'); - } - } - - return $queries; - } - - public function setMainDMSFolder() - { - $siteConfig = SiteConfig::current_site_config(); - if (!$siteConfig->DMSFolderID) { - $folder = Folder::find_or_make('dmsassets'); - $siteConfig->DMSFolderID = $folder->ID; - $siteConfig->write(); - } - } -} diff --git a/src/Tasks/MigrateDMSToSilverstripe4HTMLShortCodeFix.php b/src/Tasks/MigrateDMSToSilverstripe4HTMLShortCodeFix.php deleted file mode 100644 index 39c181f6..00000000 --- a/src/Tasks/MigrateDMSToSilverstripe4HTMLShortCodeFix.php +++ /dev/null @@ -1,126 +0,0 @@ -count(); - $this->flushNow('DOING ' . $count . ' DMS DOCUMENTS'); - $idList = DMSDocument::get()->map('ID', 'OriginalDMSDocumentIDFile'); - foreach ($idList as $newID => $oldID) { - if ($oldID) { - $this->flushNow(''); - $this->flushNow(''); - $this->flushNow('Searching for DMS Document with ID = ' . $newID . ' and OldID = ' . $oldID); - $this->replaceShortCode($oldID, $newID); - } - } - } - - /** - * @var String Regex matching a {@link DBField} class name which is shortcode capable. - * - * This should really look for implementors of a ShortCodeParseable interface, - * but we can't extend the core Text and HTMLText class - * on existing like SiteTree.Content for this. - */ - protected $fieldSpecRegex = '/^(HTMLText)/'; - - - /** - * @param int $oldID - * @param int $newID - */ - protected function replaceShortCode($oldID, $newID) - { - $fields = $this->getShortCodeFields(SiteTree::class); - foreach ($fields as $className => $fieldNames) { - $tableName = $this->getSchemaForDataObject()->tableName($className); - $this->flushNow('... searching in ' . $tableName); - if ($this->tableExists($tableName)) { - foreach ($fieldNames as $fieldName => $fieldSpecs) { - if ($this->fieldExists($tableName, $fieldName)) { - $oldPhrase = '[dms_document_link,id=' . $oldID . ']'; - $newPhrase = '[file_link,id=' . $newID . ']'; - $this->flushNow('... ... replacing ' . $oldPhrase . ' to ' . $newPhrase . ' in ' . $tableName . '.' . $fieldName); - $sql = ' - UPDATE "' . $tableName . '" - SET - "' . $tableName . '"."' . $fieldName . '" = REPLACE( - "' . $tableName . '"."' . $fieldName . '", - \'' . $oldPhrase . '\', - \'' . $newPhrase . '\' - ) - WHERE "' . $tableName . '"."' . $fieldName . '" LIKE \'%' . $oldPhrase . '%\'; - '; - // $this->flushNow($sql); - DB::query($sql); - $this->flushNow('... ... ... DONE updated ' . DB::affected_rows() . ' rows'); - } else { - $this->flushNow('... ... skipping ' . $tableName . '.' . $fieldName . ' (does not exist)'); - } - } - } else { - $this->flushNow('... skipping: ' . $tableName . ' (does not exist)'); - } - } - } - - private $_classFieldCache = []; - - /** - * Returns a filtered list of fields which could contain shortcodes. - * - * @param String - * @return Array Map of class names to an array of field names on these classes. - */ - protected function getShortcodeFields($class) - { - if (!isset($this->_classFieldCache[$class])) { - $fields = []; - $ancestry = array_values(ClassInfo::dataClassesFor($class)); - - foreach ($ancestry as $ancestor) { - if (ClassInfo::classImplements($ancestor, 'TestOnly')) { - continue; - } - - $ancFields = $this->getSchemaForDataObject()->databaseFields($ancestor); - if ($ancFields) { - foreach ($ancFields as $ancFieldName => $ancFieldSpec) { - if (preg_match($this->fieldSpecRegex, $ancFieldSpec)) { - if (!@$fields[$ancestor]) { - $fields[$ancestor] = []; - } - $fields[$ancestor][$ancFieldName] = $ancFieldSpec; - } - } - } - } - - $this->_classFieldCache[$class] = $fields; - } - - return $this->_classFieldCache[$class]; - } -} diff --git a/src/Tasks/MigrateToDocumentSetsTask.php b/src/Tasks/MigrateToDocumentSetsTask.php deleted file mode 100644 index ce7756cb..00000000 --- a/src/Tasks/MigrateToDocumentSetsTask.php +++ /dev/null @@ -1,259 +0,0 @@ - 'create-default-document-set', - 'reassignDocuments' => 'reassign-documents' - ]; - - /** - * @var SS_HTTPRequest - */ - protected $request; - - /** - * Holds number of pages/sets/documents processed for output at the end. Example: - * - * - * array( - * 'total-pages' => 0, - * 'pages-updated' => 0 - * ) - * - * - * The individual action methods will update these metrics as required - * - * @var array - */ - protected $results = []; - - public function run($request) - { - $this->request = $request; - - $action = $request->getVar('action'); - if (!in_array($action, $this->validActions)) { - $this->output( - 'Error! Specified action is not valid. Valid actions are: ' . implode(', ', $this->validActions) - ); - $this->output('You can add "dryrun=1" to enable dryrun mode where no changes will be written to the DB.'); - return; - } - - $this->outputHeader(); - $action = array_search($action, $this->validActions); - $this->$action(); - $this->outputResults(); - } - - /** - * Returns whether dryrun mode is enabled ("dryrun=1") - * - * @return bool - */ - public function isDryrun() - { - return (bool) $this->request->getVar('dryrun') == 1; - } - - /** - * Creates a default document set for any valid page that doesn't have one - * - * @return $this - */ - protected function createDefaultSet() - { - $pages = SiteTree::get(); - foreach ($pages as $page) { - // Only handle valid page types - if (!$page->config()->get('documents_enabled')) { - $this->addResult('Skipped: documents disabled'); - continue; - } - - if ($page->DocumentSets()->count()) { - // Don't add a set if it already has one - $this->addResult('Skipped: already has a set'); - continue; - } - $this->addDefaultDocumentSet($page); - $this->addResult('Default document set added'); - } - return $this; - } - - /** - * Reassign documents to the default document set, where they'd previously have been assigned to pages - * - * @return $this - */ - protected function reassignDocuments() - { - $countCheck = SQLSelect::create('*', 'DMSDocument_Pages'); - if (!$countCheck->count()) { - $this->output('There was no data to migrate. Finishing.'); - return $this; - } - - $query = SQLSelect::create(['DMSDocumentID', 'SiteTreeID'], 'DMSDocument_Pages'); - $result = $query->execute(); - - foreach ($result as $row) { - $document = DMSDocument::get()->byId($row['DMSDocumentID']); - if (!$document) { - $this->addResult('Skipped: document does not exist'); - continue; - } - - $page = SiteTree::get()->byId($row['SiteTreeID']); - if (!$page) { - $this->addResult('Skipped: page does not exist'); - continue; - } - - // Don't try and process pages that don't have a document set. This should be created by the first - // action step in this build task, so shouldn't occur if run in correct order. - if (!$page->DocumentSets()->count()) { - $this->addResult('Skipped: no default document set'); - continue; - } - $this->addDocumentToSet($document, $page->DocumentSets()->first()); - $this->addResult('Reassigned to document set'); - } - - return $this; - } - - /** - * Create a "default" document set and add it to the given Page via the ORM relationship added by - * {@link DMSSiteTreeExtension} - * - * @param SiteTree $page - * @return $this - */ - protected function addDefaultDocumentSet(SiteTree $page) - { - if ($this->isDryrun()) { - return $this; - } - - $set = DMSDocumentSet::create(); - $set->Title = 'Default'; - $set->write(); - - $page->DocumentSets()->add($set); - - return $this; - } - - /** - * Add the given document to the given document set - * - * @param DMSDocument $document - * @param DMSDocumentSet $set - * @return $this - */ - protected function addDocumentToSet(DMSDocument $document, DMSDocumentSet $set) - { - if ($this->isDryrun()) { - return $this; - } - - $set->Documents()->add($document); - return $this; - } - - /** - * Output a header info line - * - * @return $this - */ - protected function outputHeader() - { - $this->output('Migrating DMS data to 2.x for document sets'); - if ($this->isDryrun()) { - $this->output('NOTE: Dryrun mode enabled. No changes will be written.'); - } - return $this; - } - - /** - * Output a "finished" notice and the results of what was done - * - * @return $this - */ - protected function outputResults() - { - $this->output(); - $this->output('Finished:'); - foreach ($this->results as $metric => $count) { - $this->output('+ ' . $metric . ': ' . $count); - } - return $this; - } - - /** - * Add the $increment to the result key identified by $key - * - * @param string $key - * @param int $increment - * @return $this - */ - protected function addResult($key, $increment = 1) - { - if (!array_key_exists($key, $this->results)) { - $this->results[$key] = 0; - } - $this->results[$key] += $increment; - return $this; - } - - /** - * Outputs a message formatted either for CLI or browser output - * - * @param string $message - * @return $this - */ - public function output($message = '') - { - if ($this->isCli()) { - echo $message, PHP_EOL; - } else { - echo $message . '
'; - } - return $this; - } - - /** - * Returns whether the task is called via CLI or not - * - * @return bool - */ - protected function isCli() - { - return Director::is_cli(); - } -} diff --git a/tests/DMSDocumentSetTest.php b/tests/DMSDocumentSetTest.php index 9b8d3174..ba6455c2 100644 --- a/tests/DMSDocumentSetTest.php +++ b/tests/DMSDocumentSetTest.php @@ -1,5 +1,7 @@ objFromFixture(DMSDocumentSet::class, 'ds1'); - $this->assertInternalType('array', $document->getDocumentDisplayFields()); + $this->assertIsArray($document->getDocumentDisplayFields()); - Config::modify()->update(DMSDocument::class, 'display_fields', ['apple' => 'Apple', 'orange' => 'Orange']); + Config::modify()->set(DMSDocument::class, 'display_fields', ['apple' => 'Apple', 'orange' => 'Orange']); $displayFields = $document->getDocumentDisplayFields(); $this->assertContains('Apple', $displayFields); $this->assertContains('Orange', $displayFields); @@ -136,37 +135,6 @@ public function testNiceFormattingForManuallyAddedInGridField() $this->assertSame('Query Builder', $fieldFormatting['ManuallyAdded'](0)); } - /** - * Test that query fields can be added to the gridfield - */ - public function testAddQueryFields() - { - /** @var DMSDocumentSet $set */ - $set = $this->objFromFixture(DMSDocumentSet::class, 'ds6'); - /** @var FieldList $fields */ - $fields = new FieldList(new TabSet('Root')); - /** @var FieldList $fields */ - $set->addQueryFields($fields); - $keyValuePairs = $fields->dataFieldByName('KeyValuePairs'); - $this->assertNotNull( - $keyValuePairs, - 'addQueryFields() includes KeyValuePairs composite field' - ); - $this->assertNotNull( - $keyValuePairs->fieldByName('KeyValuePairs[Title]'), - 'addQueryFields() includes KeyValuePairs composite field' - ); - - // Test that the notification field exists - $this->assertNotNull($fields->fieldByName('Root.QueryBuilder.GridFieldNotice')); - - // Test that Tags__ID field exists - $this->assertContains( - 'Tags can be set in the taxonomy area,', - $keyValuePairs->fieldByName('KeyValuePairs[Tags__ID]')->RightTitle() - ); - } - /** * Ensure that the "direction" dropdown field has user friendly field labels */ @@ -189,7 +157,7 @@ public function testQueryBuilderDirectionFieldHasFriendlyLabels() */ public function testShortcodeHandlerKeyFieldExists() { - Config::modify()->update(DMS::class, 'shortcode_handler_key', 'unit-test'); + Config::modify()->set(DMS::class, 'shortcode_handler_key', 'unit-test'); $set = DMSDocumentSet::create(['Title' => 'TestSet']); $set->write(); @@ -221,24 +189,10 @@ public function testDocumentsAreOrderable() ); } - /** - * Test that extra documents are added after write - */ - public function testSaveLinkedDocuments() - { - /** @var DMSDocumentSet $set */ - $set = $this->objFromFixture(DMSDocumentSet::class, 'dsSaveLinkedDocuments'); - // Assert initially docs - $this->assertEquals(1, $set->getDocuments()->count(), 'Set has 1 document'); - // Now apply the query and see if 2 extras were added with CreatedByID filter - $set->KeyValuePairs = '{"Filename":"extradoc3"}'; - $set->saveLinkedDocuments(); - $this->assertEquals(2, $set->getDocuments()->count(), 'Set has 2 documents'); - } - /** * Tests that an exception is thrown if no title entered for a DMSDocumentSet. - * @expectedException ValidationException + * + * @expectedException \SilverStripe\ORM\ValidationException */ public function testExceptionOnNoTitleGiven() { @@ -268,9 +222,7 @@ public function testPageFieldRemovedWhenEditingInPageContext() */ public function testPermissions() { - if ($member = Member::currentUser()) { - $member->logout(); - } + $this->logOut(); $set = $this->objFromFixture(DMSDocumentSet::class, 'ds1'); diff --git a/tests/DMSDocumentTest.php b/tests/DMSDocumentTest.php index a42f27b4..55b3d65f 100644 --- a/tests/DMSDocumentTest.php +++ b/tests/DMSDocumentTest.php @@ -1,5 +1,7 @@ update(DMSDocument::class, 'default_download_behaviour', 'open'); - // $cmsFields = $document->getCMSFields(); - // $this->assertEquals('open', $cmsFields->dataFieldByName('DownloadBehavior')->Value()); - // - // - // Config::modify()->update(DMSDocument::class, 'default_download_behaviour', 'download'); - // $cmsFields = $document->getCMSFields(); - // $this->assertEquals('download', $cmsFields->dataFieldByName('DownloadBehavior')->Value()); - // } - /** * Ensure that related documents can be retrieved for a given DMS document */ @@ -147,7 +136,7 @@ public function testGetActionTaskHtml() $this->assertContains('permission', $result); $this->assertContains('Example', $result); - $actions = ['example', 'embargo','find-usage']; + $actions = ['example', 'embargo', 'find-usage']; foreach ($actions as $action) { // Test remove with string $document->removeActionPanelTask($action); diff --git a/tests/cms/DMSDocumentAddControllerTest.php b/tests/cms/DMSDocumentAddControllerTest.php index ab00ba93..4f96fc4a 100644 --- a/tests/cms/DMSDocumentAddControllerTest.php +++ b/tests/cms/DMSDocumentAddControllerTest.php @@ -1,5 +1,7 @@ DMSDocumentSet.home_default + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.home_default h_a_2: Title: Home Default 2 Filename: home-default-2 - Sets: =>DMSDocumentSet.home_alt + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.home_alt a_d_1: Title: About Default 1 Filename: about-default-1 - Sets: =>DMSDocumentSet.about_default + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.about_default diff --git a/tests/dmsembargotest.yml b/tests/dmsembargotest.yml index d6a6db9f..eaa4f7f2 100644 --- a/tests/dmsembargotest.yml +++ b/tests/dmsembargotest.yml @@ -5,7 +5,7 @@ SilverStripe\CMS\Model\SiteTree: s1: Title: testPage1 URLSegment: s1 - DocumentSets: =>DMSDocumentSet.ds1 + DocumentSets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds1 s2: Title: testPage2 URLSegment: s2 diff --git a/tests/dmstest.yml b/tests/dmstest.yml index 9b1036e5..0e45c009 100644 --- a/tests/dmstest.yml +++ b/tests/dmstest.yml @@ -26,7 +26,7 @@ SilverStripe\CMS\Model\SiteTree: s9: Title: testPage9 URLSegment: s9 -Group: +SilverStripe\Security\Group: content-author: Code: content-author Title: "Content Author" @@ -36,86 +36,83 @@ Group: SilverStripe\Security\Member: editor: Name: editor - Groups: =>Group.content-author + Groups: =>SilverStripe\Security\Group.content-author non-editor: Name: cable-guy - Groups: =>Group.cable-guy -DMSDocumentSet: + Groups: =>SilverStripe\Security\Group.cable-guy +Sunnysideup\DMS\Model\DMSDocumentSet: ds1: Title: Document Set 1 - Page: =>SiteTree.s1 + Page: =>SilverStripe\CMS\Model\SiteTree.s1 ds2: Title: Document Set 2 - Page: =>SiteTree.s1 + Page: =>SilverStripe\CMS\Model\SiteTree.s1 ds3: Title: Document Set 3 - Page: =>SiteTree.s2 + Page: =>SilverStripe\CMS\Model\SiteTree.s2 ds4: Title: Set containing embargoed documents - Page: =>SiteTree.s3 + Page: =>SilverStripe\CMS\Model\SiteTree.s3 ds5: Title: Set containing embargoed until publish documents - Page: =>SiteTree.s7 + Page: =>SilverStripe\CMS\Model\SiteTree.s7 ds6: Title: Test Set 6 - Page: =>SiteTree.s8 - dsSaveLinkedDocuments: - Title: Test Set 6 - Page: =>SiteTree.s9 + Page: =>SilverStripe\CMS\Model\SiteTree.s8 unlinked_set: Title: Document Set not linked -DMSDocument: +Sunnysideup\DMS\Model\DMSDocument: d1: Filename: test-file-file-doesnt-exist-1 Folder: 5 - Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds1, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds2, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds3, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds4 d2: Filename: test-file-file-doesnt-exist-2 Folder: 5 Title: File That Doesn't Exist (Title) - Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds1, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds2, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds3, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds4 document_with_relations: Filename: file-with-relations Folder: 5 - RelatedDocuments: =>DMSDocument.d1, =>DMSDocument.d2 + RelatedDocuments: =>Sunnysideup\DMS\Model\DMSDocument.d1, =>Sunnysideup\DMS\Model\DMSDocument.d2 doc-logged-in-users: FileName: doc-logged-in-users CanViewType: LoggedInUsers CanEditType: LoggedInUsers Folder: 5 - Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds1, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds2, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds3, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds4 doc-anyone: FileName: doc-anyone CanViewType: Anyone Folder: 5 - Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds1, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds2, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds3, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds4 doc-only-these-users: FileName: doc-only-these-users CanViewType: OnlyTheseUsers CanEditType: OnlyTheseUsers Folder: 5 - Sets: =>DMSDocumentSet.ds1, =>DMSDocumentSet.ds2, =>DMSDocumentSet.ds3, =>DMSDocumentSet.ds4 - ViewerGroups: =>Group.content-author - EditorGroups: =>Group.content-author + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds1, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds2, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds3, =>Sunnysideup\DMS\Model\DMSDocumentSet.ds4 + ViewerGroups: =>SilverStripe\Security\Group.content-author + EditorGroups: =>SilverStripe\Security\Group.content-author embargoed_document1: Filename: foobar EmbargoedIndefinitely: true Folder: 5 - Sets: =>DMSDocumentSet.ds4 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds4 embargo_until_publish1: Filename: embargo-until-publish1 EmbargoUntilPublish: true Folder: 5 - Sets: =>DMSDocumentSet.ds5 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds5 embargo_until_publish2: Filename: embargo-until-publish2 EmbargoUntilPublish: true Folder: 5 - Sets: =>DMSDocumentSet.ds5 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds5 extraDoc1: Filename: extradoc1 Folder: 5 - Sets: =>DMSDocumentSet.ds6 + Sets: =>Sunnysideup\DMS\Model\DMSDocumentSet.ds6 ManuallyAdded: 1 CreatedByID: 2 extraDoc2: @@ -128,7 +125,3 @@ DMSDocument: Folder: 5 ManuallyAdded: 0 CreatedByID: 2 - docSaveLinkedDocuments1: - Filename: saveLinkedDocument1 - Folder: 5 - Sets: =>DMSDocumentSet.dsSaveLinkedDocuments diff --git a/tests/extensions/DMSDocumentTaxonomyExtensionTest.php b/tests/extensions/DMSDocumentTaxonomyExtensionTest.php index d978800f..f7cec327 100644 --- a/tests/extensions/DMSDocumentTaxonomyExtensionTest.php +++ b/tests/extensions/DMSDocumentTaxonomyExtensionTest.php @@ -1,5 +1,7 @@ markTestSkipped('This test requires silverstripe/taxonomy ^1.2 to be installed. Skipping.'); - } - } - /** * Ensure that appropriate tags by taxonomy type are returned, and that their hierarchy is displayd in the title */ public function testGetAllTagsMap() { - $extension = new DMSDocumentTaxonomyExtension; + $extension = new DMSDocumentTaxonomyExtension(); $result = $extension->getAllTagsMap(); $this->assertContains('Subject > Mathematics', $result); diff --git a/tests/extensions/DMSSiteTreeExtensionTest.php b/tests/extensions/DMSSiteTreeExtensionTest.php index bccf282f..49a88f73 100644 --- a/tests/extensions/DMSSiteTreeExtensionTest.php +++ b/tests/extensions/DMSSiteTreeExtensionTest.php @@ -1,5 +1,7 @@ update(SiteTree::class, 'documents_enabled', $configSetting); + Config::modify()->set(SiteTree::class, 'documents_enabled', $configSetting); $siteTree = $this->objFromFixture(SiteTree::class, 's2'); $this->$assertionMethod($siteTree->getCMSFields()->fieldByName('Root.DocumentSets.DocumentSets')); } @@ -51,7 +53,7 @@ public function documentSetEnabledConfigProvider() */ public function testDocumentSetsGridFieldIsCorrectlyConfigured() { - Config::modify()->update(SiteTree::class, 'documents_enabled', true); + Config::modify()->set(SiteTree::class, 'documents_enabled', true); $siteTree = $this->objFromFixture(SiteTree::class, 's2'); $gridField = $siteTree->getCMSFields()->fieldByName('Root.DocumentSets.DocumentSets'); diff --git a/tests/extensions/DMSTaxonomyTypeExtensionTest.php b/tests/extensions/DMSTaxonomyTypeExtensionTest.php index 73368b0a..4905a39d 100644 --- a/tests/extensions/DMSTaxonomyTypeExtensionTest.php +++ b/tests/extensions/DMSTaxonomyTypeExtensionTest.php @@ -1,5 +1,7 @@ getMockBuilder(MigrateToDocumentSetsTask::class) - ->setMethods(['isCli']) - ->getMock(); - - $mock->expects($this->exactly(2)) - ->method('isCli') - ->will($this->returnValue($isCli)); - - ob_start(); - foreach ($lines as $line) { - $mock->output($line); - } - $result = ob_get_clean(); - $this->assertSame($expected, $result); - } - - /** - * @return array[] - */ - public function outputProvider() - { - return [ - [true, 'Test' . PHP_EOL . 'Test line 2' . PHP_EOL], - [false, 'Test
Test line 2
'] - ]; - } - - /** - * Ensure that providing an invalid action returns an error - */ - public function testShowErrorOnInvalidAction() - { - $result = $this->runTask(['action' => 'coffeetime']); - $this->assertContains('Error! Specified action is not valid.', $result); - } - - /** - * Test that default document sets can be created for those pages that don't have them already - */ - public function testCreateDefaultDocumentSets() - { - $this->fixtureOldRelations(); - - $result = $this->runTask(['action' => 'create-default-document-set']); - $this->assertContains('Finished', $result); - // There are four pages in the fixture, but one of them already has a document set, so should be unchanged - $this->assertContains('Default document set added: 3', $result); - $this->assertContains('Skipped: already has a set: 1', $result); - - // Test that some of the relationship records were written correctly - $this->assertCount(1, $firstPageSets = $this->objFromFixture(SiteTree::class, 'one')->DocumentSets()); - $this->assertSame('Default', $firstPageSets->first()->Title); - $this->assertCount(1, $this->objFromFixture(SiteTree::class, 'two')->DocumentSets()); - - // With dryrun enabled and being run the second time, nothing should be done - $result = $this->runTask(['action' => 'create-default-document-set', 'dryrun' => '1']); - $this->assertContains('Skipped: already has a set: 4', $result); - $this->assertContains('NOTE: Dryrun mode enabled', $result); - } - - /** - * Test that legacy ORM relationship maps are migrated to the new page -> document set -> document relationship - */ - public function testReassignDocumentsToFirstSet() - { - $this->fixtureOldRelations(); - - // Ensure default sets are created - $this->runTask(['action' => 'create-default-document-set']); - - // Dryrun check - $result = $this->runTask(['action' => 'reassign-documents', 'dryrun' => '1']); - $this->assertContains('NOTE: Dryrun mode enabled', $result); - $this->assertContains('Reassigned to document set: 3', $result); - - // Actual run - $result = $this->runTask(['action' => 'reassign-documents']); - $this->assertNotContains('NOTE: Dryrun mode enabled', $result); - $this->assertContains('Reassigned to document set: 3', $result); - - // Smoke ORM checks - $this->assertCount(1, $this->objFromFixture(SiteTree::class, 'one')->getAllDocuments()); - $this->assertCount(1, $this->objFromFixture(SiteTree::class, 'two')->getAllDocuments()); - $this->assertCount(0, $this->objFromFixture(SiteTree::class, 'four')->getAllDocuments()); - } - - /** - * Centralises (slightly) logic for capturing direct output from the task - * - * @param array $getVars - * @return string Task output - */ - protected function runTask(array $getVars) - { - $task = new MigrateToDocumentSetsTask; - $request = new HTTPRequest('GET', '/', $getVars); - - ob_start(); - $task->run($request); - return ob_get_clean(); - } - - /** - * Set up the old many many relationship table from documents to pages - */ - protected function fixtureOldRelations() - { - if (!DB::get_schema()->hasTable('DMSDocument_Pages')) { - DB::create_table('DMSDocument_Pages', [ - 'DMSDocumentID' => 'int(11) null', - 'SiteTreeID' => 'int(11) null' - ]); - } - - $documentIds = $this->getFixtureFactory()->getIds(DMSDocument::class); - $pageIds = $this->getFixtureFactory()->getIds(SiteTree::class); - foreach (['one', 'two', 'three'] as $fixtureName) { - $this->getFixtureFactory()->createRaw( - 'DMSDocument_Pages', - 'rln_' . $fixtureName, - ['DMSDocumentID' => $documentIds[$fixtureName], 'SiteTreeID' => $pageIds[$fixtureName]] - ); - } - } -} diff --git a/tests/tasks/MigrateToDocumentSetsTaskTest.yml b/tests/tasks/MigrateToDocumentSetsTaskTest.yml deleted file mode 100644 index 1c87707e..00000000 --- a/tests/tasks/MigrateToDocumentSetsTaskTest.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Fixtures for migration task testing. The relationships for them are -# created manually in the unit test class. -DMSDocument: - one: - Title: document1 - two: - Title: document2 - three: - Title: document3 -DMSDocumentSet: - four: - Title: documentSet4 -SilverStripe\CMS\Model\SiteTree: - one: - Title: page1 - two: - Title: page2 - three: - Title: page3 - four: - Title: page4 - DocumentSets: =>DMSDocumentSet.four