[BUGFIX] Fix several namespace related bugs
authorHelmut Hummel <helmut.hummel@typo3.org>
Wed, 17 Oct 2012 19:50:46 +0000 (21:50 +0200)
committerHelmut Hummel <helmut.hummel@typo3.org>
Wed, 7 Nov 2012 17:23:38 +0000 (18:23 +0100)
Due to the switch to namespaces several things are buggy or missing.
* DataMapper and property mapper should recognize old Extbase class names
* Adapt checks for class names in several places

Resolves: #42546
Releases: 6.0

Change-Id: I2044479ce76d4dd480cc8d93e5b0e1d52471fe87
Reviewed-on: http://review.typo3.org/16161
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
typo3/sysext/extbase/Classes/Mvc/Controller/AbstractController.php
typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php
typo3/sysext/extbase/Classes/Property/Mapper.php
typo3/sysext/extbase/Classes/Property/PropertyMapper.php
typo3/sysext/extbase/Classes/Scheduler/FieldProvider.php
typo3/sysext/extbase/Classes/Validation/ValidatorResolver.php
typo3/sysext/extbase/Tests/Unit/Mvc/Controller/AbstractControllerTest.php [new file with mode: 0644]
typo3/sysext/extbase/Tests/Unit/Scheduler/FieldProviderTest.php [new file with mode: 0644]
typo3/sysext/extbase/Tests/Unit/Validation/ValidatorResolverTest.php

index 32318a5..8be1bc4 100644 (file)
@@ -129,7 +129,18 @@ abstract class AbstractController implements \TYPO3\CMS\Extbase\Mvc\Controller\C
         * Constructs the controller.
         */
        public function __construct() {
-               list(, $this->extensionName) = explode('_', get_class($this));
+               $className = get_class($this);
+               if (strpos($className, '\\') !== FALSE) {
+                       $classNameParts = explode('\\', $className, 4);
+                       // Skip vendor and product name for core classes
+                       if (strpos($className, 'TYPO3\\CMS\\') === 0) {
+                               $this->extensionName = $classNameParts[2];
+                       } else {
+                               $this->extensionName = $classNameParts[1];
+                       }
+               } else {
+                       list(, $this->extensionName) = explode('_', $className);
+               }
        }
 
        /**
index 3af1712..11a0723 100644 (file)
@@ -271,7 +271,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
                                        // $propertyValue = $this->mapArray($row[$columnName]); // Not supported, yet!
                                        break;
                                case 'SplObjectStorage':
-
+                               case 'Tx_Extbase_Persistence_ObjectStorage':
                                case 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage':
                                        $propertyValue = $this->mapResultToPropertyValue($object, $propertyName, $this->fetchRelated($object, $propertyName, $row[$columnName]));
                                        break;
@@ -318,7 +318,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        public function fetchRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = TRUE) {
                $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
                if ($enableLazyLoading === TRUE && $propertyMetaData['lazy']) {
-                       if ($propertyMetaData['type'] === 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage') {
+                       if (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
                                $result = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyObjectStorage', $parentObject, $propertyName, $fieldValue);
                        } else {
                                if (empty($fieldValue)) {
@@ -453,14 +453,14 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
                        $propertyValue = $result;
                } else {
                        $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
-                       if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'SplObjectStorage', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage'))) {
+                       if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage'), TRUE)) {
                                $objects = array();
                                foreach ($result as $value) {
                                        $objects[] = $value;
                                }
                                if ($propertyMetaData['type'] === 'ArrayObject') {
                                        $propertyValue = new \ArrayObject($objects);
-                               } elseif ($propertyMetaData['type'] === 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage') {
+                               } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
                                        $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
                                        foreach ($objects as $object) {
                                                $propertyValue->attach($object);
index f91a3d7..93d7a80 100644 (file)
@@ -222,7 +222,7 @@ class Mapper implements \TYPO3\CMS\Core\SingletonInterface {
                        } else {
                                if ($targetClassSchema !== NULL && $targetClassSchema->hasProperty($propertyName)) {
                                        $propertyMetaData = $targetClassSchema->getProperty($propertyName);
-                                       if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage')) && (strpbrk($propertyMetaData['type'], '_\\') !== FALSE || $propertyValue === '')) {
+                                       if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE) && (strpbrk($propertyMetaData['elementType'], '_\\') !== FALSE || $propertyValue === '')) {
                                                $objects = array();
                                                if (is_array($propertyValue)) {
                                                        foreach ($propertyValue as $value) {
@@ -235,7 +235,7 @@ class Mapper implements \TYPO3\CMS\Core\SingletonInterface {
                                                // make sure we hand out what is expected
                                                if ($propertyMetaData['type'] === 'ArrayObject') {
                                                        $propertyValue = new \ArrayObject($objects);
-                                               } elseif ($propertyMetaData['type'] === 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage') {
+                                               } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
                                                        $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
                                                        foreach ($objects as $object) {
                                                                $propertyValue->attach($object);
index d87257d..affd308 100644 (file)
@@ -157,6 +157,9 @@ class PropertyMapper implements \TYPO3\CMS\Core\SingletonInterface {
                if ($source === NULL) {
                        $source = '';
                }
+               // This is needed to correctly convert old class names to new ones
+               // This compatibility layer will be removed with 7.0
+               $targetType = \TYPO3\CMS\Core\Core\ClassLoader::getClassNameForAlias($targetType);
                $typeConverter = $this->findTypeConverter($source, $targetType, $configuration);
                if (!is_object($typeConverter) || !$typeConverter instanceof \TYPO3\CMS\Extbase\Property\TypeConverterInterface) {
                        throw new \TYPO3\CMS\Extbase\Property\Exception\TypeConverterException('Type converter for "' . $source . '" -> "' . $targetType . '" not found.');
index 91a22fb..377906a 100644 (file)
@@ -134,7 +134,19 @@ class FieldProvider implements \TYPO3\CMS\Scheduler\AdditionalFieldProviderInter
                $options = array();
                foreach ($commands as $command) {
                        if ($command->isInternal() === FALSE) {
-                               $classNameParts = explode('_', $command->getControllerClassName());
+                               $className = $command->getControllerClassName();
+                               if (strpos($command->getControllerClassName(), '\\')) {
+                                       $classNameParts = explode('\\', $className);
+                                       // Skip vendor and product name for core classes
+                                       if (strpos($className, 'TYPO3\\CMS\\') === 0) {
+                                               $classPartsToSkip = 2;
+                                       } else {
+                                               $classPartsToSkip = 1;
+                                       }
+                                       $classNameParts = array_slice($classNameParts, $classPartsToSkip);
+                               } else {
+                                       $classNameParts = explode('_', $className);
+                               }
                                $identifier = $command->getCommandIdentifier();
                                $options[$identifier] = $classNameParts[1] . ' ' . str_replace('CommandController', '', $classNameParts[3]) . ': ' . $command->getControllerCommandName();
                        }
index c75428f..5e43f10 100644 (file)
@@ -310,7 +310,7 @@ class ValidatorResolver implements \TYPO3\CMS\Core\SingletonInterface {
         * @return string|boolean Name of the validator object or FALSE
         */
        protected function resolveValidatorObjectName($validatorName) {
-               if ((strpbrk($validatorName, '_\\') !== FALSE) && class_exists($validatorName)) {
+               if (strpbrk($validatorName, '_\\') !== FALSE && class_exists($validatorName)) {
                        return $validatorName;
                }
                list($extensionName, $extensionValidatorName) = explode(':', $validatorName);
diff --git a/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/AbstractControllerTest.php b/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/AbstractControllerTest.php
new file mode 100644 (file)
index 0000000..dae8c9d
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Stefan Neufeind <info@speedpartner.de>
+ *  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.
+ *
+ *  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!
+ ***************************************************************/
+
+/**
+ * Abstract Controller Test Class
+ */
+class AbstractControllerTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+       /**
+        * @test
+        */
+       public function constructResolvesExtensionnameFromOldStyle() {
+               $className = uniqid('Tx_Extbase_Tests_Fixtures_Controller');
+               eval('class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\Mvc\\Controller\\AbstractController { function getExtensionName() { return $this->extensionName; } }');
+               $mockController = new $className();
+               $expectedResult = 'Extbase';
+               $actualResult = $mockController->getExtensionName();
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+
+       /**
+        * @test
+        */
+       public function constructResolvesExtensionnameFromNamespaced() {
+               $className = uniqid('DummyController');
+               eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\Mvc\\Controller\\AbstractController { function getExtensionName() { return $this->extensionName; } }');
+               $classNameNamespaced = __NAMESPACE__ . '\\' . $className;
+               $mockController = new $classNameNamespaced();
+               $expectedResult = 'Extbase';
+               $actualResult = $mockController->getExtensionName();
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Tests/Unit/Scheduler/FieldProviderTest.php b/typo3/sysext/extbase/Tests/Unit/Scheduler/FieldProviderTest.php
new file mode 100644 (file)
index 0000000..ad3698d
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+namespace TYPO3\CMS\Extbase\Tests\Unit\Scheduler;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Stefan Neufeind <info@speedpartner.de>
+ *  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.
+ *
+ *  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!
+ ***************************************************************/
+
+/**
+ * FieldProvider Test Class
+ */
+class FieldProviderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
+        */
+       protected $mockObjectManager;
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager
+        */
+       protected $commandManager;
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Scheduler\FieldProvider
+        */
+       protected $fieldProvider;
+
+       /**
+        * @test
+        */
+       public function getCommandControllerActionFieldFetchesCorrectClassNames() {
+               $fieldProvider = $fieldProvider = $this->getMock($this->buildAccessibleProxy('\TYPO3\CMS\Extbase\Scheduler\FieldProvider'), array('dummy'));
+               $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['extbase']['commandControllers'] = array(
+                       'TYPO3\\CMS\\Extbase\\Tests\\MockACommandController'
+               );
+               eval('namespace TYPO3\\CMS\\Extbase\\Tests; class MockACommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController { function MockACommand() {} } ');
+
+               $actualResult = $fieldProvider->_call('getCommandControllerActionField', array());
+               $this->assertContains('<option title="test" value="extbase:mocka:mocka">Tests : MockA</option>', $actualResult['code']);
+       }
+
+       /**
+        * @test
+        */
+       public function constructResolvesExtensionnameFromNamespaced() {
+               $className = uniqid('DummyController');
+               eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\Mvc\\Controller\\AbstractController { function getExtensionName() { return $this->extensionName; } }');
+               $classNameNamespaced = __NAMESPACE__ . '\\' . $className;
+               $mockController = new $classNameNamespaced();
+               $expectedResult = 'Extbase';
+               $actualResult = $mockController->getExtensionName();
+               $this->assertSame($expectedResult, $actualResult);
+       }
+}
+
+?>
\ No newline at end of file
index 2a37a9e..121efc5 100644 (file)
@@ -67,7 +67,7 @@ class ValidatorResolverTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
        /**
         * @test
         */
-       public function resolveValidatorObjectNameCanResolveShorthandValidatornames() {
+       public function resolveValidatorObjectNameCanResolveShorthandNotNamespacedValidatorNames() {
                $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
                eval('class Tx_Mypkg_Validation_Validator_MyFirstValidator {}');
                $validatorResolver = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Validation\\ValidatorResolver', array('dummy'));