diff --git a/typo3/sysext/core/Classes/Resource/Collection/FileCollectionRegistry.php b/typo3/sysext/core/Classes/Resource/Collection/FileCollectionRegistry.php new file mode 100644 index 0000000000000000000000000000000000000000..5a39b8967b0f9c4a7b263501cde9b949845e7243 --- /dev/null +++ b/typo3/sysext/core/Classes/Resource/Collection/FileCollectionRegistry.php @@ -0,0 +1,146 @@ +<?php +namespace TYPO3\CMS\Core\Resource\Collection; + +/*************************************************************** + * Copyright notice + * + * (c) 2013 - Frans Saris <franssaris@gmail.com> + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * A copy is found in the text file GPL.txt and important notices to the license + * from the author is found in LICENSE.txt distributed with these scripts. + * + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +/** + * Registry for FileCollection classes + */ +class FileCollectionRegistry implements \TYPO3\CMS\Core\SingletonInterface { + + /** + * Registered FileCollection types + * + * @var array + */ + protected $types = array(); + + /** + * Constructor + */ + public function __construct() { + foreach ($GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['registeredCollections'] as $type => $class) { + $this->registerFileCollectionClass($class, $type); + } + } + + /** + * Register a (new) FileCollection type + * + * @param string $className + * @param string $type FileCollection type max length 30 chars (db field restriction) + * @param bool $override existing FileCollection type + * @return bool TRUE if registration succeeded + * @throws \InvalidArgumentException + */ + public function registerFileCollectionClass($className, $type, $override = FALSE) { + + if (strlen($type) > 30) { + throw new \InvalidArgumentException('FileCollection type can have a max string length of 30 bytes', 1391295611); + } + + if (!class_exists($className)) { + throw new \InvalidArgumentException('Class ' . $className . ' does not exist.', 1391295613); + } + + if (!in_array('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection', class_parents($className), TRUE)) { + throw new \InvalidArgumentException('FileCollection ' . $className . ' needs to extend the AbstractFileCollection.', 1391295633); + } + + if (isset($this->types[$type])) { + // Return immediately without changing configuration + if ($this->types[$type] === $className) { + return TRUE; + } elseif (!$override) { + throw new \InvalidArgumentException('FileCollections ' . $type . ' is already registered.', 1391295643); + } + } + + $this->types[$type] = $className; + return TRUE; + } + + /** + * Add the type to the TCA of sys_file_collection + * + * @param string $type + * @param string $label + * @param string $availableFields comma separated list of fields to show + * @param array $additionalColumns Additional columns configuration + * @return array adjusted TCA for sys_file_collection + */ + public function addTypeToTCA($type, $label, $availableFields, array $additionalColumns = array()) { + + $GLOBALS['TCA']['sys_file_collection']['types'][$type] = array( + 'showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, title;;1, type, ' . $availableFields + ); + + // search for existing type when found override label + $typeFound = FALSE; + foreach ($GLOBALS['TCA']['sys_file_collection']['columns']['type']['config']['items'] as $key => $item) { + if ($item[1] === $type) { + $typeFound = TRUE; + $GLOBALS['TCA']['sys_file_collection']['columns']['type']['config']['items'][$key][0] = $label; + } + } + if (!$typeFound) { + $GLOBALS['TCA']['sys_file_collection']['columns']['type']['config']['items'][] = array( + 0 => $label, + 1 => $type + ); + } + if ($additionalColumns !== array()) { + \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA']['sys_file_collection']['columns'], $additionalColumns); + } + return $GLOBALS['TCA']['sys_file_collection']; + } + + /** + * Returns a class name for a given type + * + * @param string $type + * @return string The class name + * @throws \InvalidArgumentException + */ + public function getFileCollectionClass($type) { + if (!isset($this->types[$type])) { + throw new \InvalidArgumentException('Desired FileCollection type "' . $type . '" is not in the list of available FileCollections.', 1391295644); + } + return $this->types[$type]; + } + + /** + * Checks if the given FileCollection type exists + * + * @param string $type Type of the FileCollection + * @return boolean TRUE if the FileCollection exists, FALSE otherwise + */ + public function fileCollectionTypeExists($type) { + return isset($this->types[$type]); + } + +} \ No newline at end of file diff --git a/typo3/sysext/core/Classes/Resource/ResourceFactory.php b/typo3/sysext/core/Classes/Resource/ResourceFactory.php index c75478f1488bf14eef8078cfeba9b2483453525b..0d5a1f6b90e46f2ac02afb7827c2626c8d4c6136 100644 --- a/typo3/sysext/core/Classes/Resource/ResourceFactory.php +++ b/typo3/sysext/core/Classes/Resource/ResourceFactory.php @@ -296,20 +296,11 @@ class ResourceFactory implements \TYPO3\CMS\Core\SingletonInterface { * @return Collection\AbstractFileCollection */ public function createCollectionObject(array $collectionData) { - switch ($collectionData['type']) { - case 'static': - $collection = Collection\StaticFileCollection::create($collectionData); - break; - case 'folder': - $collection = Collection\FolderBasedFileCollection::create($collectionData); - break; - case 'category': - $collection = Collection\CategoryBasedFileCollection::create($collectionData); - break; - default: - $collection = NULL; - } - return $collection; + /** @var $registry Collection\FileCollectionRegistry */ + $registry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Collection\\FileCollectionRegistry'); + $class = $registry->getFileCollectionClass($collectionData['type']); + + return $class::create($collectionData); } /** diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index a9b829dabb67e207f1c32ea036186e11d342eade..49bd89bc851d80c1c186d711947859bf71b5802a 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -247,6 +247,11 @@ return array( 'processingTaskTypes' => array( 'Image.Preview' => 'TYPO3\\CMS\\Core\\Resource\\Processing\\ImagePreviewTask', 'Image.CropScaleMask' => 'TYPO3\\CMS\\Core\\Resource\\Processing\\ImageCropScaleMaskTask' + ), + 'registeredCollections' => array( + 'static' => 'TYPO3\\CMS\\Core\\Resource\\Collection\\StaticFileCollection', + 'folder' => 'TYPO3\\CMS\\Core\\Resource\\Collection\\FolderBasedFileCollection', + 'category' => 'TYPO3\\CMS\\Core\\Resource\\Collection\\CategoryBasedFileCollection', ) ), 'isInitialInstallationInProgress' => FALSE, // Boolean: If TRUE, the installation is 'in progress'. This value is handled within the install tool step installer internally. diff --git a/typo3/sysext/core/Tests/Unit/Resource/Collection/FileCollectionRegistryTest.php b/typo3/sysext/core/Tests/Unit/Resource/Collection/FileCollectionRegistryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7ccee569dc1ef2fa1e06e79c2b0d14179ee31fe4 --- /dev/null +++ b/typo3/sysext/core/Tests/Unit/Resource/Collection/FileCollectionRegistryTest.php @@ -0,0 +1,188 @@ +<?php +namespace TYPO3\CMS\Core\Tests\Unit\Resource\Collection; + +/*************************************************************** + * Copyright notice + * + * (c) 2013 - Frans Saris <franssaris@gmail.com> + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * A copy is found in the text file GPL.txt and important notices to the license + * from the author is found in LICENSE.txt distributed with these scripts. + * + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +/** + * Test cases for FileCollectionRegistry + */ +class FileCollectionRegistryTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase { + + /** + * @var \TYPO3\CMS\Core\Resource\Collection\FileCollectionRegistry + */ + protected $testSubject; + + public function setUp() { + $this->initializeTestSubject(); + } + + protected function initializeTestSubject() { + $this->testSubject = new \TYPO3\CMS\Core\Resource\Collection\FileCollectionRegistry(); + } + + /** + * @test + */ + public function registeredFileCollectionClassesCanBeRetrieved() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $this->testSubject->registerFileCollectionClass($className, 'foobar'); + $returnedClassName = $this->testSubject->getFileCollectionClass('foobar'); + $this->assertEquals($className, $returnedClassName); + } + + /** + * @test + * @expectedException InvalidArgumentException + * @expectedExceptionCode 1391295613 + */ + public function registerFileCollectionClassThrowsExceptionIfClassDoesNotExist() { + $this->testSubject->registerFileCollectionClass(uniqid(), uniqid()); + } + + /** + * @test + * @expectedException InvalidArgumentException + * @expectedExceptionCode 1391295611 + */ + public function registerFileCollectionClassThrowsExceptionIfTypeIsTooLong() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $type = str_pad('', 40); + $this->testSubject->registerFileCollectionClass($className, $type); + } + + /** + * @test + * @expectedException InvalidArgumentException + * @expectedExceptionCode 1391295643 + */ + public function registerFileCollectionClassThrowsExceptionIfTypeIsAlreadyRegistered() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $className2 = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\StaticFileCollection')); + $this->testSubject->registerFileCollectionClass($className, 'foobar'); + $this->testSubject->registerFileCollectionClass($className2, 'foobar'); + } + + /** + * @test + */ + public function registerFileCollectionClassOverridesExistingRegisteredFileCollectionClass() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $className2 = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\StaticFileCollection')); + $this->testSubject->registerFileCollectionClass($className, 'foobar'); + $this->testSubject->registerFileCollectionClass($className2, 'foobar', TRUE); + } + + /** + * @test + * @expectedException InvalidArgumentException + * @expectedExceptionCode 1391295644 + */ + public function getFileCollectionClassThrowsExceptionIfClassIsNotRegistered() { + $this->testSubject->getFileCollectionClass(uniqid()); + } + + /** + * @test + */ + public function getFileCollectionClassAcceptsClassNameIfClassIsRegistered() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $this->testSubject->registerFileCollectionClass($className, 'foobar'); + $this->assertEquals($className, $this->testSubject->getFileCollectionClass('foobar')); + } + + /** + * @test + */ + public function fileCollectionRegistryIsInitializedWithPreconfiguredFileCollections() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $type = uniqid(); + $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['registeredCollections'] = array( + $type => $className + ); + $this->initializeTestSubject(); + $this->assertEquals($className, $this->testSubject->getFileCollectionClass($type)); + } + + /** + * @test + */ + public function fileCollectionExistsReturnsTrueForAllExistingFileCollections() { + $className = get_class($this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Collection\\AbstractFileCollection')); + $type = 'foo'; + $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['registeredCollections'] = array( + $type => $className + ); + $this->initializeTestSubject(); + $this->assertTrue($this->testSubject->fileCollectionTypeExists($type)); + $this->assertFalse($this->testSubject->fileCollectionTypeExists('bar')); + } + + /** + * @test + */ + public function fileCollectionExistsReturnsFalseIfFileCollectionDoesNotExist() { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['registeredFileCollections'] = array(); + $this->initializeTestSubject(); + $this->assertFalse($this->testSubject->fileCollectionTypeExists(uniqid())); + } + + /** + * @test + */ + public function addNewTypeToTCA() { + + // Create a TCA fixture for sys_file_collection + $GLOBALS['TCA']['sys_file_collection'] = array( + 'types' => array( + 'typeB' => array('showitem' => 'fieldA, fieldB, fieldC;labelC;paletteC;specialC, fieldD'), + ), + 'columns' => array( + 'type' => array( + 'config' => array( + 'items' => array('Type A', 'typeA'), + 'items' => array('Type B', 'typeB') + ) + ) + ) + ); + + $type = 'my_type'; + $label = 'The Label'; + + $this->testSubject->addTypeToTCA($type, $label, 'something'); + + // check type + $this->assertEquals('sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, title;;1, type, something', $GLOBALS['TCA']['sys_file_collection']['types']['my_type']['showitem']); + + $indexOfNewType = count($GLOBALS['TCA']['sys_file_collection']['columns']['type']['config']['items']) - 1; + + // check if columns.type.item exist + $this->assertEquals($type, $GLOBALS['TCA']['sys_file_collection']['columns']['type']['config']['items'][$indexOfNewType][1]); + $this->assertEquals($label, $GLOBALS['TCA']['sys_file_collection']['columns']['type']['config']['items'][$indexOfNewType][0]); + } +} \ No newline at end of file