[!!!][TASK] Make all enumerations final 76/56976/8
authorMathias Brodala <mbrodala@pagemachine.de>
Wed, 16 May 2018 10:57:56 +0000 (12:57 +0200)
committerAndreas Fernandez <a.fernandez@scripting-base.de>
Fri, 1 Jun 2018 12:57:09 +0000 (14:57 +0200)
Code which uses enumerations expects a known set of values, adding
more values by extending these classes leads to undefined behavior.

Since it is now impossible to create a mock of an enumeration also
drop a few Enumeration tests and stick to testing of the public API.

Resolves: #85025
Releases: master
Change-Id: I3d0238c85ae916052dc1aa503f7f8e39c1765ac6
Reviewed-on: https://review.typo3.org/56976
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Tested-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Tested-by: Jan Helke <typo3@helke.de>
Reviewed-by: Jan Helke <typo3@helke.de>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
16 files changed:
typo3/sysext/backend/Classes/Toolbar/Enumeration/InformationStatus.php
typo3/sysext/core/Classes/DataHandling/TableColumnSubType.php
typo3/sysext/core/Classes/DataHandling/TableColumnType.php
typo3/sysext/core/Classes/Resource/DuplicationBehavior.php
typo3/sysext/core/Classes/Type/Bitmask/JsConfirmation.php
typo3/sysext/core/Classes/Type/Bitmask/Permission.php
typo3/sysext/core/Classes/Type/Icon/IconState.php
typo3/sysext/core/Classes/Versioning/VersionState.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-85025-EnumerationsAreNowFinal.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Type/EnumerationTest.php
typo3/sysext/core/Tests/Unit/Type/Fixture/Enumeration/CompleteEnumeration.php
typo3/sysext/core/Tests/Unit/Type/Fixture/Enumeration/DuplicateConstantValueEnumeration.php
typo3/sysext/core/Tests/Unit/Type/Fixture/Enumeration/InvalidConstantEnumeration.php
typo3/sysext/core/Tests/Unit/Type/Fixture/Enumeration/MissingConstantsEnumeration.php
typo3/sysext/core/Tests/Unit/Type/Fixture/Enumeration/MissingDefaultEnumeration.php
typo3/sysext/indexed_search/Classes/Utility/LikeWildcard.php

index 14f0ee1..b1f8fe6 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Backend\Toolbar\Enumeration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * This class holds the severities of the SystemInformation toolbar menu
  */
-class InformationStatus extends \TYPO3\CMS\Core\Type\Enumeration
+final class InformationStatus extends Enumeration
 {
     const __default = self::STATUS_INFO;
 
index 4703f79..54a693d 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\DataHandling;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * Enumeration object for tca internal type
  */
-class TableColumnSubType extends \TYPO3\CMS\Core\Type\Enumeration
+final class TableColumnSubType extends Enumeration
 {
     const __default = self::DEFAULT_TYPE;
 
index 92f5a27..4d07d98 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\DataHandling;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * Enumeration object for tca type
  */
-class TableColumnType extends \TYPO3\CMS\Core\Type\Enumeration
+final class TableColumnType extends Enumeration
 {
     const __default = self::INPUT;
 
index 13ce9e6..93a5206 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Resource;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * Enumeration object for DuplicationBehavior
  */
-class DuplicationBehavior extends \TYPO3\CMS\Core\Type\Enumeration
+final class DuplicationBehavior extends Enumeration
 {
     const __default = self::CANCEL;
 
index b0a7d73..09c04d9 100644 (file)
@@ -20,7 +20,7 @@ use TYPO3\CMS\Core\Type\Exception;
 /**
  * A class providing constants for bitwise operations on javascript confirmation popups
  */
-class JsConfirmation extends Enumeration
+final class JsConfirmation extends Enumeration
 {
     /**
      * @var int
index 30ec4f6..86f55cd 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Type\Bitmask;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * A class providing constants for bitwise operations on page access check
  */
-class Permission extends \TYPO3\CMS\Core\Type\Enumeration
+final class Permission extends Enumeration
 {
     /**
      * @var int
index 4504104..897fd58 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Type\Icon;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * A class providing constants for icon states
  */
-class IconState extends \TYPO3\CMS\Core\Type\Enumeration
+final class IconState extends Enumeration
 {
     const __default = self::STATE_DEFAULT;
 
index 456a945..d08e22d 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Versioning;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * Enumeration object for VersionState
  */
-class VersionState extends \TYPO3\CMS\Core\Type\Enumeration
+final class VersionState extends Enumeration
 {
     const __default = self::DEFAULT_STATE;
 
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-85025-EnumerationsAreNowFinal.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-85025-EnumerationsAreNowFinal.rst
new file mode 100644 (file)
index 0000000..c402b42
--- /dev/null
@@ -0,0 +1,36 @@
+.. include:: ../../Includes.txt
+
+=============================================
+Breaking: #85025 - Enumerations are now final
+=============================================
+
+See :issue:`85025`
+
+Description
+===========
+
+All enumeration classes in TYPO3 have been marked as :php:`final` which prevents extension by 3rd party code.
+
+By definition an enumeration is a limited and known set of values, any code which uses enumeration relies on this fact. If an enumeration was extended by 3rd party code undefined behavior would occur. For this reason no enumerations must be extended.
+
+Developers of 3rd party extensions are also encouraged to mark their enumerations as :php:`final`.
+
+
+Impact
+======
+
+Classes extending TYPO3 enumerations will trigger a fatal PHP error.
+
+
+Affected Installations
+======================
+
+Instances with classes extending TYPO3 enumerations.
+
+
+Migration
+=========
+
+Remove the classes which extend TYPO3 enumerations.
+
+.. index:: PHP-API, NotScanned
\ No newline at end of file
index 45b1629..2cfe101 100644 (file)
@@ -95,148 +95,43 @@ class EnumerationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     }
 
     /**
-     * @test
-     */
-    public function loadValuesSetsStaticEnumConstants()
-    {
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy']
-        );
-
-        $enumClassName = get_class($enumeration);
-
-        $expectedValue = [
-            'INTEGER_VALUE' => 1,
-            'STRING_VALUE' => 'foo',
-             '__default' => 1
-        ];
-
-        $result = $enumeration->_getStatic('enumConstants');
-        $this->assertArrayHasKey($enumClassName, $result);
-        $this->assertSame($expectedValue, $result[$enumClassName]);
-    }
-
-    /**
-     * @test
-     */
-    public function constructorSetsValue()
-    {
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy'],
-            [1]
-        );
-        $this->assertEquals(1, $enumeration->_get('value'));
-    }
-
-    /**
-     * @test
-     */
-    public function setValueSetsValue()
-    {
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy'],
-            [1]
-        );
-        $enumeration->_call('setValue', 'foo');
-        $this->assertEquals('foo', $enumeration->_get('value'));
-    }
-
-    /**
-     * @test
-     */
-    public function setValueToAnInvalidValueThrowsException()
-    {
-        $this->expectException(InvalidEnumerationValueException::class);
-        $this->expectExceptionCode(1381615295);
-
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy'],
-            [1]
-        );
-        $enumeration->_call('setValue', 2);
-        $this->assertEquals(2, $enumeration->_get('value'));
-    }
-
-    /**
      * Array of value pairs and expected comparison result
      */
-    public function isValidComparisonExpectations()
+    public function looseEnumerationValues()
     {
         return [
             [
                 1,
-                1,
-                true
-            ],
-            [
-                1,
-                '1',
-                true
+                Enumeration\CompleteEnumeration::INTEGER_VALUE,
             ],
             [
                 '1',
-                1,
-                true
+                Enumeration\CompleteEnumeration::INTEGER_VALUE,
             ],
             [
-                'a1',
-                1,
-                false
+                2,
+                Enumeration\CompleteEnumeration::STRING_INTEGER_VALUE,
             ],
             [
-                1,
-                'a1',
-                false
-            ],
-            [
-                '1a',
-                1,
-                false
+                '2',
+                Enumeration\CompleteEnumeration::STRING_INTEGER_VALUE,
             ],
             [
-                1,
-                '1a',
-                false
-            ],
-            [
-                'foo',
                 'foo',
-                true
+                Enumeration\CompleteEnumeration::STRING_VALUE,
             ],
-            [
-                'foo',
-                'bar',
-                false
-            ],
-            [
-                'foo',
-                'foobar',
-                false
-            ]
         ];
     }
 
     /**
      * @test
-     * @dataProvider isValidComparisonExpectations
+     * @dataProvider looseEnumerationValues
      */
-    public function isValidDoesTypeLooseComparison($enumerationValue, $testValue, $expectation)
+    public function doesTypeLooseComparison($testValue, $expectedValue)
     {
-        $mockName = $this->getUniqueId('CompleteEnumerationMock');
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy'],
-            [],
-            $mockName,
-            false
-        );
-        $enumeration->_setStatic('enumConstants', [$mockName => ['CONSTANT_NAME' => $enumerationValue]]);
-        $enumeration->_set('value', $enumerationValue);
-        $this->assertSame($expectation, $enumeration->_call('isValid', $testValue));
+        $value = new Enumeration\CompleteEnumeration($testValue);
+
+        $this->assertEquals((string)$expectedValue, (string)$value);
     }
 
     /**
@@ -244,7 +139,13 @@ class EnumerationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function getConstantsReturnsArrayOfPossibleValuesWithoutDefault()
     {
-        $this->assertEquals(['INTEGER_VALUE' => 1, 'STRING_VALUE' => 'foo'], Enumeration\CompleteEnumeration::getConstants());
+        $expected = [
+            'INTEGER_VALUE' => 1,
+            'STRING_INTEGER_VALUE' => '2',
+            'STRING_VALUE' => 'foo',
+        ];
+
+        $this->assertEquals($expected, Enumeration\CompleteEnumeration::getConstants());
     }
 
     /**
@@ -252,7 +153,14 @@ class EnumerationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function getConstantsReturnsArrayOfPossibleValuesWithDefaultIfRequested()
     {
-        $this->assertEquals(['INTEGER_VALUE' => 1, 'STRING_VALUE' => 'foo', '__default' => 1], Enumeration\CompleteEnumeration::getConstants(true));
+        $expected = [
+            'INTEGER_VALUE' => 1,
+            'STRING_INTEGER_VALUE' => '2',
+            'STRING_VALUE' => 'foo',
+            '__default' => 1,
+        ];
+
+        $this->assertEquals($expected, Enumeration\CompleteEnumeration::getConstants(true));
     }
 
     /**
@@ -261,7 +169,13 @@ class EnumerationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     public function getConstantsCanBeCalledOnInstances()
     {
         $enumeration = new Enumeration\CompleteEnumeration();
-        $this->assertEquals(['INTEGER_VALUE' => 1, 'STRING_VALUE' => 'foo'], $enumeration->getConstants());
+        $expected = [
+            'INTEGER_VALUE' => 1,
+            'STRING_INTEGER_VALUE' => '2',
+            'STRING_VALUE' => 'foo',
+        ];
+
+        $this->assertEquals($expected, $enumeration->getConstants());
     }
 
     /**
@@ -307,12 +221,9 @@ class EnumerationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function castCastsStringToEnumerationWithCorrespondingValue()
     {
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy'],
-            ['1']
-        );
-        $this->assertSame(1, $enumeration->_get('value'));
+        $value = new Enumeration\CompleteEnumeration(Enumeration\CompleteEnumeration::STRING_VALUE);
+
+        $this->assertSame((string)Enumeration\CompleteEnumeration::STRING_VALUE, (string)$value);
     }
 
     /**
@@ -320,12 +231,9 @@ class EnumerationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function castCastsIntegerToEnumerationWithCorrespondingValue()
     {
-        $enumeration = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration\CompleteEnumeration::class,
-            ['dummy'],
-            [1]
-        );
-        $this->assertSame(1, $enumeration->_get('value'));
+        $value = new Enumeration\CompleteEnumeration(Enumeration\CompleteEnumeration::INTEGER_VALUE);
+
+        $this->assertSame((int)(string)Enumeration\CompleteEnumeration::INTEGER_VALUE, (int)(string)$value);
     }
 
     /**
index 6035987..01b894c 100644 (file)
@@ -14,12 +14,15 @@ namespace TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * This is an complete enumeration with all possible constant values
  */
-class CompleteEnumeration extends \TYPO3\CMS\Core\Type\Enumeration
+final class CompleteEnumeration extends Enumeration
 {
     const __default = self::INTEGER_VALUE;
     const INTEGER_VALUE = 1;
+    const STRING_INTEGER_VALUE = '2';
     const STRING_VALUE = 'foo';
 }
index 85e62ec..de2b2f4 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * This is an invalid enumeration because the constant values are not unique
  */
-class DuplicateConstantValueEnumeration extends \TYPO3\CMS\Core\Type\Enumeration
+final class DuplicateConstantValueEnumeration extends Enumeration
 {
     const FOO = 1;
     const BAR = 1;
index a0c7d3c..01ee80a 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * This is an invalid enumeration because an unsupported constant value is used
  */
-class InvalidConstantEnumeration extends \TYPO3\CMS\Core\Type\Enumeration
+final class InvalidConstantEnumeration extends Enumeration
 {
     const FOO = 1.11;
 }
index 356363b..7eb2d12 100644 (file)
@@ -14,9 +14,11 @@ namespace TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * This is an invalid enumeration because no constants are defined
  */
-class MissingConstantsEnumeration extends \TYPO3\CMS\Core\Type\Enumeration
+final class MissingConstantsEnumeration extends Enumeration
 {
 }
index bafbeda..907a20c 100644 (file)
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Tests\Unit\Type\Fixture\Enumeration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Type\Enumeration;
+
 /**
  * This is an enumeration without a default value so it must be called with a value
  */
-class MissingDefaultEnumeration extends \TYPO3\CMS\Core\Type\Enumeration
+final class MissingDefaultEnumeration extends Enumeration
 {
     const FOO = 1;
 }
index 867703c..973026e 100644 (file)
@@ -14,12 +14,13 @@ namespace TYPO3\CMS\IndexedSearch\Utility;
  * The TYPO3 project - inspiring people to share!
  */
 use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Type\Enumeration;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Enumeration object for LikeWildcard
  */
-class LikeWildcard extends \TYPO3\CMS\Core\Type\Enumeration
+final class LikeWildcard extends Enumeration
 {
     const __default = self::BOTH;