[BUGFIX] Allow Tx_ as class prefix
authorAndreas Kiessling <kiessling@pluspol.info>
Fri, 29 Apr 2011 15:07:48 +0000 (17:07 +0200)
committerJigal van Hemert <jigal@xs4all.nl>
Fri, 20 May 2011 14:09:36 +0000 (16:09 +0200)
Although extbase urges to use Tx_ as prefix for class name, this prefix
is not accepted in all places of the core.

Change-Id: Icb46d875fdf66eaf6f51367cf3ef5030c07a4128
Resolves: #22594
Releases: 4.6, 4.5, 4.4, 4.3
Reviewed-on: http://review.typo3.org/1609
Tested-by: Philipp Gampe
Reviewed-by: Kay Strobach
Tested-by: Kay Strobach
Reviewed-by: Steffen Gebert
Tested-by: Steffen Gebert
Reviewed-by: Jigal van Hemert
t3lib/class.t3lib_div.php
t3lib/class.t3lib_extmgm.php
t3lib/class.t3lib_registry.php
t3lib/class.t3lib_tceforms.php
t3lib/class.t3lib_tcemain.php
t3lib/jsfunc.evalfield.js
t3lib/matchcondition/class.t3lib_matchcondition_abstract.php
tests/t3lib/class.t3lib_divTest.php
typo3/sysext/cms/tslib/class.tslib_content.php
typo3/sysext/setup/mod/index.php

index bbd7a88..1c68436 100644 (file)
@@ -4887,10 +4887,7 @@ final class t3lib_div {
                }
 
                        // Check prefix is valid:
-               if ($checkPrefix &&
-                               !self::isFirstPartOfStr(trim($funcRef), $checkPrefix) &&
-                               !self::isFirstPartOfStr(trim($funcRef), 'tx_')
-               ) {
+               if ($checkPrefix && !self::hasValidClassPrefix($funcRef, array($checkPrefix))) {
                        $errorMsg = "Function/class '$funcRef' was not prepended with '$checkPrefix'";
                        if ($errorMode == 2) {
                                throw new InvalidArgumentException($errorMsg, 1294585864);
@@ -4968,7 +4965,7 @@ final class t3lib_div {
         * Usage: 5
         *
         * @param       string          Class reference, '[file-reference":"]["&"]class-name'. You can prefix the class name with "[file-reference]:" and t3lib_div::getFileAbsFileName() will then be used to resolve the filename and subsequently include it by "require_once()" which means you don't have to worry about including the class file either! Example: "EXT:realurl/class.tx_realurl.php:&tx_realurl". Finally; for the class name you can prefix it with "&" and you will reuse the previous instance of the object identified by the full reference string (meaning; if you ask for the same $classRef later in another place in the code you will get a reference to the first created one!).
-        * @param       string          Required prefix of class name. By default "tx_" is allowed.
+        * @param       string          Required prefix of class name. By default "tx_" and "Tx_" are allowed.
         * @param       boolean         If set, no debug() error message is shown if class/function is not present.
         * @return      object          The instance of the class asked for. Instance is created with t3lib_div::makeInstance
         * @see callUserFunction()
@@ -5000,10 +4997,7 @@ final class t3lib_div {
                        }
 
                                // Check prefix is valid:
-                       if ($checkPrefix &&
-                                       !self::isFirstPartOfStr(trim($class), $checkPrefix) &&
-                                       !self::isFirstPartOfStr(trim($class), 'tx_')
-                       ) {
+                       if ($checkPrefix && !self::hasValidClassPrefix($class, array($checkPrefix))) {
                                if (!$silent) {
                                        debug("Class '" . $class . "' was not prepended with '" . $checkPrefix . "'", 't3lib_div::getUserObj');
                                }
@@ -5029,6 +5023,32 @@ final class t3lib_div {
        }
 
        /**
+        * Checks if a class or function has a valid prefix: tx_, Tx_ or custom, e.g. user_
+        *
+        * @param string $classRef The class or function to check
+        * @param array $additionalPrefixes Additional allowed prefixes, mostly this will be user_
+        * @return bool TRUE if name is allowed
+        */
+       public static function hasValidClassPrefix($classRef, array $additionalPrefixes = array()) {
+               $hasValidPrefix = FALSE;
+               $validPrefixes = array('tx_', 'Tx_', $GLOBALS['TYPO3_CONF_VARS']['FE']['userFuncClassPrefix']);
+               $classRef = trim($classRef);
+
+               if (count($additionalPrefixes)) {
+                       $validPrefixes = array_merge($validPrefixes, $additionalPrefixes);
+               }
+
+               foreach ($validPrefixes as $prefixToCheck) {
+                       if (self::isFirstPartOfStr($classRef, $prefixToCheck)) {
+                               $hasValidPrefix = TRUE;
+                               break;
+                       }
+               }
+
+               return $hasValidPrefix;
+       }
+
+       /**
         * Creates an instance of a class taking into account the class-extensions
         * API of TYPO3. USE THIS method instead of the PHP "new" keyword.
         * Eg. "$obj = new myclass;" should be "$obj = t3lib_div::makeInstance("myclass")" instead!
index e59534e..2bc12c8 100644 (file)
@@ -976,8 +976,8 @@ final class t3lib_extMgm {
         * Adds a service to the global services array
         *
         * @param       string          Extension key
-        * @param       string          Service type, cannot be prefixed "tx_"
-        * @param       string          Service key, must be prefixed "tx_" or "user_"
+        * @param       string          Service type, must not be prefixed "tx_" or "Tx_"
+        * @param       string          Service key, must be prefixed "tx_", "Tx_" or "user_"
         * @param       array           Service description array
         * @return      void
         * @author      RenĂ© Fritz <r.fritz@colorcube.de>
@@ -987,8 +987,8 @@ final class t3lib_extMgm {
                        // but maybe it's better to move non-available services to a different array??
 
                if ($serviceType &&
-                               !t3lib_div::isFirstPartOfStr($serviceType, 'tx_') &&
-                               (t3lib_div::isFirstPartOfStr($serviceKey, 'tx_') || t3lib_div::isFirstPartOfStr($serviceKey, 'user_')) &&
+                               !t3lib_div::hasValidClassPrefix($serviceType) &&
+                               t3lib_div::hasValidClassPrefix($serviceKey, array('user_')) &&
                                is_array($info)) {
 
                        $info['priority'] = max(0, min(100, $info['priority']));
@@ -1001,7 +1001,7 @@ final class t3lib_extMgm {
 
 
                                // mapping a service key to a service type
-                               // all service keys begin with tx_ - service types don't
+                               // all service keys begin with tx_ or Tx_ - service types don't
                                // this way a selection of a special service key as service type is easy
                        $GLOBALS['T3_SERVICES'][$serviceKey][$serviceKey] = &$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey];
 
@@ -1714,4 +1714,4 @@ $TYPO3_LOADED_EXT = unserialize(stripslashes(\'' . addslashes(serialize($extensi
        }
 }
 
-?>
\ No newline at end of file
+?>
index b07a8fc..c6fed3b 100644 (file)
@@ -53,7 +53,7 @@ class t3lib_Registry implements t3lib_Singleton {
        /**
         * Returns a persistent entry.
         *
-        * @param       string  Extension key for extensions starting with 'tx_' / 'user_' or 'core' for core registry entries
+        * @param       string  Extension key for extensions starting with 'tx_' / 'Tx_' / 'user_' or 'core' for core registry entries
         * @param       string  The key of the entry to return.
         * @param       mixed   Optional default value to use if this entry has never been set. Defaults to NULL.
         * @return      mixed   The value of the entry.
@@ -72,7 +72,7 @@ class t3lib_Registry implements t3lib_Singleton {
         * Do not store binary data into the registry, it's not build to do that,
         * instead use the proper way to store binary data: The filesystem.
         *
-        * @param       string  Extension key for extensions starting with 'tx_' / 'user_' or 'core' for core registry entries.
+        * @param       string  Extension key for extensions starting with 'tx_' / 'Tx_' / 'user_' or 'core' for core registry entries.
         * @param       string  The key of the entry to set.
         * @param       mixed   The value to set. This can be any PHP data type; this class takes care of serialization if necessary.
         * @return      void
@@ -174,20 +174,20 @@ class t3lib_Registry implements t3lib_Singleton {
        /**
         * Checks the given namespace. If it does not have a valid format an
         * exception is thrown.
-        * Allowed namespaces are 'core', 'tx_*' and 'user_*'
+        * Allowed namespaces are 'core', 'tx_*', 'Tx_*' and 'user_*'
         *
         * @param       string  Namespace. extension key for extensions or 'core' for core registry entries
         * @return      void
         * @throws      InvalidArgumentException        Throws an exception if the given namespace is not valid
         */
        protected function validateNamespace($namespace) {
-               if (t3lib_div::isFirstPartOfStr($namespace, 'tx_') || t3lib_div::isFirstPartOfStr($namespace, 'user_')) {
+               if (t3lib_div::hasValidClassPrefix($namespace, array('user_'))) {
                        return;
                }
 
                if ($namespace !== 'core') {
                        throw new InvalidArgumentException(
-                               '"' . $namespace . '" is no valid Namespace. The namespace has to be prefixed with "tx_", "user_" or must be equal to "core"',
+                               '"' . $namespace . '" is no valid Namespace. The namespace has to be prefixed with "tx_", "Tx_", "user_" or must be equal to "core"',
                                1249755131
                        );
                }
index b6a7fef..c05d9b8 100644 (file)
@@ -1138,7 +1138,7 @@ class t3lib_TCEforms {
                                        }
                                break;
                                default:
-                                       if (substr($func, 0, 3) == 'tx_') {
+                                       if (t3lib_div::hasValidClassPrefix($func)) {
                                                        // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval()
                                                $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
                                                if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
@@ -1188,7 +1188,7 @@ class t3lib_TCEforms {
 
                        // going through all custom evaluations configured for this field
                foreach ($evalList as $evalData) {
-                       if (substr($evalData, 0, 3) == 'tx_') {
+                       if (t3lib_div::hasValidClassPrefix($evalData)) {
                                $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData] . ':&' . $evalData);
                                if (is_object($evalObj) && method_exists($evalObj, 'returnFieldJS')) {
                                        $this->extJSCODE .= "\n\nfunction " . $evalData . "(value) {\n" . $evalObj->returnFieldJS() . "\n}\n";
@@ -1343,7 +1343,7 @@ class t3lib_TCEforms {
                                                        $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
                                                break;
                                                default:
-                                                       if (substr($func, 0, 3) == 'tx_') {
+                                                       if (t3lib_div::hasValidClassPrefix($func)) {
                                                                        // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval() and t3lib_TCEmain::checkValue_text_Eval()
                                                                $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
                                                                if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
@@ -6554,4 +6554,4 @@ if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLA
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tceforms.php']);
 }
 
-?>
\ No newline at end of file
+?>
index f8eba5f..66acb09 100644 (file)
@@ -2106,7 +2106,7 @@ class t3lib_TCEmain {
                                        }
                                break;
                                default:
-                                       if (substr($func, 0, 3) == 'tx_') {
+                                       if (t3lib_div::hasValidClassPrefix($func)) {
                                                $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
                                                if (is_object($evalObj) && method_exists($evalObj, 'evaluateFieldValue')) {
                                                        $value = $evalObj->evaluateFieldValue($value, $is_in, $set);
@@ -2212,7 +2212,7 @@ class t3lib_TCEmain {
                                        $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value);
                                break;
                                default:
-                                       if (substr($func, 0, 3) == 'tx_') {
+                                       if (t3lib_div::hasValidClassPrefix($func)) {
                                                $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
                                                if (is_object($evalObj) && method_exists($evalObj, 'evaluateFieldValue')) {
                                                        $value = $evalObj->evaluateFieldValue($value, $is_in, $set);
@@ -7238,4 +7238,4 @@ if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLA
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']);
 }
 
-?>
\ No newline at end of file
+?>
index 978f715..f43b158 100644 (file)
@@ -62,7 +62,7 @@ function evalFunc_evalObjValue(FObj,value)    {
        var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false;
        var newValue=value;
        while (theEvalType) {
-               if (theEvalType.slice(0, 3) == 'tx_') {
+               if (theEvalType.slice(0, 3) == 'tx_' || theEvalType.slice(0, 3) == 'Tx_') {
                        if(typeof window[theEvalType] == 'function') {
                                newValue = window[theEvalType](newValue);       // variable function call, calling functions like tx_myext_myeval(value)
                        }
@@ -519,4 +519,4 @@ function evalFunc_convertClientTimestampToUTC(timestamp, timeonly)  {
                        // seconds since the "unix-epoch"
                return this.getTimestamp(timeObj);
        }
-}
+}
\ No newline at end of file
index 27fd2a8..13b93f4 100644 (file)
@@ -406,8 +406,7 @@ abstract class t3lib_matchCondition_abstract {
                                $funcValue = t3lib_div::trimExplode(',', $values[1]);
                                $prefix = $this->getUserFuncClassPrefix();
                                if ($prefix &&
-                                       !t3lib_div::isFirstPartOfStr(trim($funcName), $prefix) &&
-                                       !t3lib_div::isFirstPartOfStr(trim($funcName), 'tx_')
+                                       !t3lib_div::hasValidClassPrefix($funcName, array($prefix))
                                ) {
                                        $this->log('Match condition: Function "' . $funcName . '" was not prepended with "' . $prefix . '"');
                                        return FALSE;
@@ -665,4 +664,4 @@ abstract class t3lib_matchCondition_abstract {
        abstract protected function log($message);
 }
 
-?>
\ No newline at end of file
+?>
index e449968..7716eb8 100644 (file)
@@ -2728,5 +2728,66 @@ class t3lib_divTest extends tx_phpunit_testcase {
 
                $this->assertEquals($resultFilePermissions, '0777');
        }
+
+       ///////////////////////////////////////////////////
+       // Tests concerning hasValidClassPrefix
+       ///////////////////////////////////////////////////
+
+       /**
+        * @return array
+        */
+       public function validClassPrefixDataProvider() {
+               return array(
+                       array('tx_foo'),
+                       array('tx_foo_bar'),
+                       array('Tx_foo'),
+                       array($GLOBALS['TYPO3_CONF_VARS']['FE']['userFuncClassPrefix'] . 'foo'),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider validClassPrefixDataProvider
+        * @param string $className Class name to test
+        */
+       public function hasValidClassPrefixAcceptsValidPrefixes($className) {
+               $this->assertTrue(
+                       t3lib_div::hasValidClassPrefix($className)
+               );
+       }
+
+       /**
+        * @return array
+        */
+       public function invalidClassPrefixDataProvider() {
+               return array(
+                       array(''),
+                       array('ab_c'),
+                       array('txfoo'),
+                       array('Txfoo'),
+                       array('userfoo'),
+                       array('User_foo'),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider invalidClassPrefixDataProvider
+        * @param string $className Class name to test
+        */
+       public function hasValidClassPrefixRefusesInvalidPrefixes($className) {
+               $this->assertFalse(
+                       t3lib_div::hasValidClassPrefix($className)
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function hasValidClassPrefixAcceptsAdditionalPrefixes() {
+               $this->assertTrue(
+                       t3lib_div::hasValidClassPrefix('customPrefix_foo', array('customPrefix_'))
+               );
+       }
 }
-?>
\ No newline at end of file
+?>
index 3f3ad13..56bb8af 100644 (file)
@@ -6329,7 +6329,7 @@ class tslib_cObj {
         */
        function callUserFunction($funcName, $conf, $content) {
                $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
-               if ($pre && !t3lib_div::isFirstPartOfStr(trim($funcName), $pre) && !t3lib_div::isFirstPartOfStr(trim($funcName), 'tx_')) {
+               if ($pre && !t3lib_div::hasValidClassPrefix($funcName, array($pre))) {
                        $GLOBALS['TT']->setTSlogMessage('Function "' . $funcName . '" was not prepended with "' . $pre . '"', 3);
                        return $content;
                }
@@ -8148,4 +8148,4 @@ if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLA
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php']);
 }
 
-?>
\ No newline at end of file
+?>
index ca388cb..69b1718 100755 (executable)
@@ -938,7 +938,7 @@ class SC_mod_user_setup_index {
        protected function checkAccess(array $config) {
                $access = $config['access'];
                        // check for hook
-               if (strpos($access, 'tx_') === 0) {
+               if (t3lib_div::hasValidClassPrefix($access)) {
                        $accessObject = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['setup']['accessLevelCheck'][$access] . ':&' . $access);
                        if (is_object($accessObject) && method_exists($accessObject, 'accessLevelCheck'))       {
                                        // initialize vars. If method fails, $set will be set to FALSE
@@ -1035,4 +1035,4 @@ $LANG->includeLLFile('EXT:setup/mod/locallang.xml');
 $SOBE->init();
 $SOBE->main();
 $SOBE->printContent();
-?>
\ No newline at end of file
+?>