EXTMVC:
authorJochen Rau <j.rau@web.de>
Mon, 23 Mar 2009 14:30:12 +0000 (14:30 +0000)
committerJochen Rau <j.rau@web.de>
Mon, 23 Mar 2009 14:30:12 +0000 (14:30 +0000)
* Changed validation of floats
* Revised View Helpers (changed signature!)

typo3/sysext/extbase/Classes/Configuration/TX_EXTMVC_Configuration_Manager.php
typo3/sysext/extbase/Classes/Validation/Validator/TX_EXTMVC_Validation_Validator_Float.php
typo3/sysext/extbase/Classes/View/Helper/TX_EXTMVC_View_Helper_ConvertHelper.php
typo3/sysext/extbase/Classes/View/Helper/TX_EXTMVC_View_Helper_ForHelper.php
typo3/sysext/extbase/Classes/View/Helper/TX_EXTMVC_View_Helper_LinkHelper.php
typo3/sysext/extbase/Classes/View/Helper/TX_EXTMVC_View_Helper_TranslateHelper.php
typo3/sysext/extbase/Classes/View/Helper/TX_EXTMVC_View_Helper_URIHelper.php
typo3/sysext/extbase/Classes/View/TX_EXTMVC_View_TemplateView.php

index 84886bc..b32c32f 100644 (file)
@@ -74,6 +74,8 @@ class TX_EXTMVC_Configuration_Manager implements t3lib_Singleton {
                                }
                        }
                        // SK: TODO: Look at this in detail
+                       // JR: This is an overlay of TS settings; "local" values overwrite more "global" values
+                       // TODO Should we provide a hierarchical TS setting overlay?
                        // if (!empty($controllerName) && is_array($settings[$controllerName])) {
                        //      foreach ($settings[$controllerName] as $key => $value) {
                        //              if (array_key_exists($key, $settings)) {
index 9defd56..aef95df 100644 (file)
@@ -43,7 +43,7 @@ class TX_EXTMVC_Validation_Validator_Float implements TX_EXTMVC_Validation_Valid
         * @return boolean TRUE if the value is valid, FALSE if an error occured
         */
        public function isValid($value, TX_EXTMVC_Validation_Errors &$errors, array $validationOptions = array()) {
-               if (is_float($value) || (is_string($value) && strpos($value, '.') !== FALSE && preg_match('/^[0-9.e+-]+$/', $value))) {
+               if ($value !== filter_var($value, FILTER_SANITIZE_FLOAT)) {
                        return TRUE;
                }
                $errors->append('The given subject was not a valid float.');
index a93f12d..1f08b50 100644 (file)
@@ -23,7 +23,7 @@
 ***************************************************************/
 
 /**
- * A For Helper
+ * A Converter Helper
  *
  * @package TYPO3
  * @subpackage extmvc
@@ -31,7 +31,7 @@
  */
 class TX_EXTMVC_View_Helper_ConvertHelper extends TX_EXTMVC_View_Helper_AbstractHelper {
 
-       public function render($view, $content, $arguments) {
+       public function render($view, $arguments, $templateSource, $variables) {
                $value = $content;
                $format = $arguments['format'];
                if (!is_string($format)) ; // TODO Throw exception?
index f677b56..e37ced1 100644 (file)
@@ -31,7 +31,7 @@
  */
 class TX_EXTMVC_View_Helper_ForHelper extends TX_EXTMVC_View_Helper_AbstractHelper {
 
-       public function render($view, $content, $arguments, $templateSource, $variables) {
+       public function render($view, $arguments, $templateSource, $variables) {
                if (is_array($arguments['each'])) {
                        foreach ($arguments['each'] as $singleElement) {
                                $variables[TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($arguments['as'])] = $singleElement; // FIXME strtolower
index ee54661..e8262c7 100644 (file)
@@ -49,7 +49,18 @@ class TX_EXTMVC_View_Helper_LinkHelper extends TX_EXTMVC_View_Helper_AbstractHel
                }
        }
 
-       public function render($view, $content, $arguments, $templateResource, $variables) {
+       /**
+        * This method renders the link of the View Helper
+        *
+        * @param string $view The view invoked the view helper
+        * @param string $content The content
+        * @param string $arguments 
+        * @param string $templateSource 
+        * @param string $variables 
+        * @return string A content wrapped in a link
+        */
+       public function render($view, $arguments, $templateSource, $variables) {
+               // TODO Check for security issues
                $parameters = t3lib_div::_GET();
                $prefixedExtensionKey = 'tx_' . strtolower($this->request->getControllerExtensionKey());
                if (!empty($arguments['to'])) {
@@ -71,20 +82,15 @@ class TX_EXTMVC_View_Helper_LinkHelper extends TX_EXTMVC_View_Helper_AbstractHel
                                }
                        }
                }
-               
-               
-               $linkText = $view->renderTemplate($templateResource, $variables);
-
+               $linkText = $view->renderTemplate($templateSource, $variables);
                $parameters = is_array($parameters) ? t3lib_div::implodeArrayForUrl('', $parameters, '', 1) : '';
-
                $link = $this->contentObject->typoLink(
                        $linkText,
                        array(
-                               'parameter' => $linkTo, // FIXME
+                               'parameter' => $linkTo,
                                'additionalParams' => $parameters
                        )
                );
-               
                return $link;
        }
                        
index 586d085..1d57f4f 100644 (file)
  * @subpackage extmvc
  * @version $ID:$
  */
+// TODO Enable caching for translations?
 class TX_EXTMVC_View_Helper_TranslateHelper extends TX_EXTMVC_View_Helper_AbstractHelper {
 
        /**
         * @var string
         */
-       protected $languagePath = 'Resources/Language/';
+       protected $languagePath = 'Resources/Private/Language/';
 
        /**
         * Local Language content
@@ -62,15 +63,15 @@ class TX_EXTMVC_View_Helper_TranslateHelper extends TX_EXTMVC_View_Helper_Abstra
         *
         * @var string
         **/
-       protected $LLkey = 'default';
-       var $altLLkey='';                       // .
-       var $LLtestPrefix='';                   // You can set this during development to some value that makes it easy for you to spot all labels that ARe delivered by the getLL function.
-       var $LLtestPrefixAlt='';                // Save as LLtestPrefix, but additional prefix for the alternative value in getLL() function calls
+       protected $alternativeLanguageKey = '';
+       // var $LLtestPrefix='';                        // You can set this during development to some value that makes it easy for you to spot all labels that ARe delivered by the getLL function.
+       // var $LLtestPrefixAlt='';             // Save as LLtestPrefix, but additional prefix for the alternative value in getLL() function calls
        
 
-       public function render($view, $content, $arguments, $templateResource, $variables) {
-               $this->initializeLocalization();
-               
+       public function render($view, $arguments, $templateSource, $variables) {
+               $this->initializeLocalization($view);
+               $translation = $this->translate($arguments['key']);
+               return (is_string($translation) && !empty($translation)) ? $translation : '';
        }
        
        /**
@@ -79,39 +80,39 @@ class TX_EXTMVC_View_Helper_TranslateHelper extends TX_EXTMVC_View_Helper_Abstra
         *
         * @return      void
         */
-       protected function initializeLocalization()     {
-                       $languageFilePath = t3lib_extMgm::extPath(strtolower($this->request->getControllerExtensionKey())) . $this->languagePath . 'locallang.php';
+       protected function initializeLocalization($view)        {
+               $languageFilePath = t3lib_extMgm::extPath(strtolower($this->request->getControllerExtensionKey())) . $this->languagePath . 'locallang.php';
 
-                       if ($GLOBALS['TSFE']->config['config']['language'])     {
-                               $this->languageKey = $GLOBALS['TSFE']->config['config']['language'];
-                               if ($GLOBALS['TSFE']->config['config']['language_alt']) {
-                                       $this->alternativeLanguageKey = $GLOBALS['TSFE']->config['config']['language_alt'];
-                               }
+               if ($GLOBALS['TSFE']->config['config']['language'])     {
+                       $this->languageKey = $GLOBALS['TSFE']->config['config']['language'];
+                       if ($GLOBALS['TSFE']->config['config']['language_alt']) {
+                               $this->alternativeLanguageKey = $GLOBALS['TSFE']->config['config']['language_alt'];
                        }
+               }
 
-                       // Read the strings in the required charset (since TYPO3 4.2)
-                       $this->LOCAL_LANG = t3lib_div::readLLfile($languageFilePath, $this->languageKey, $GLOBALS['TSFE']->renderCharset);
-                       if ($this->alternativeLanguageKey)      {
-                               $tempLOCAL_LANG = t3lib_div::readLLfile($languageFilePath, $this->alternativeLanguageKey);
-                               $this->LOCAL_LANG = array_merge(is_array($this->LOCAL_LANG) ? $this->LOCAL_LANG : array(), $tempLOCAL_LANG);
-                       }
+               // Read the strings in the required charset (since TYPO3 4.2)
+               $this->LOCAL_LANG = t3lib_div::readLLfile($languageFilePath, $this->languageKey, $GLOBALS['TSFE']->renderCharset);
+               if ($this->alternativeLanguageKey)      {
+                       $tempLOCAL_LANG = t3lib_div::readLLfile($languageFilePath, $this->alternativeLanguageKey);
+                       $this->LOCAL_LANG = array_merge(is_array($this->LOCAL_LANG) ? $this->LOCAL_LANG : array(), $tempLOCAL_LANG);
+               }
 
-                       // TODO Overlaying labels from TypoScript (including fictitious language keys for non-system languages!):
-                       if (is_array($this->conf['_LOCAL_LANG.']))      {
-                               reset($this->conf['_LOCAL_LANG.']);
-                               while(list($k,$lA)=each($this->conf['_LOCAL_LANG.']))   {
-                                       if (is_array($lA))      {
-                                               $k = substr($k,0,-1);
-                                               foreach($lA as $llK => $llV)    {
-                                                       if (!is_array($llV))    {
-                                                               $this->LOCAL_LANG[$k][$llK] = $llV;
-                                                                       // For labels coming from the TypoScript (database) the charset is assumed to be "forceCharset" and if that is not set, assumed to be that of the individual system languages
-                                                               $this->LOCAL_LANG_charset[$k][$llK] = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : $GLOBALS['TSFE']->csConvObj->charSetArray[$k];
-                                                       }
+               // TODO Overlaying labels from TypoScript (including fictitious language keys for non-system languages!):
+               $configurationManager = t3lib_div::makeInstance('TX_EXTMVC_Configuration_Manager');
+               $settings = $configurationManager->getSettings($this->request->getControllerExtensionKey());
+               if (is_array($settings['_LOCAL_LANG'])) {
+                       foreach ($settings['_LOCAL_LANG'] as $k => $lA) {
+                               if (is_array($lA)) {
+                                       foreach($lA as $llK => $llV) {
+                                               if (!is_array($llV)) {
+                                                       $this->LOCAL_LANG[$k][$llK] = $llV;
+                                                               // For labels coming from the TypoScript (database) the charset is assumed to be "forceCharset" and if that is not set, assumed to be that of the individual system languages
+                                                       $this->LOCAL_LANG_charset[$k][$llK] = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : $GLOBALS['TSFE']->csConvObj->charSetArray[$k];
                                                }
                                        }
                                }
                        }
+               }
        }
        
        /**
@@ -123,7 +124,7 @@ class TX_EXTMVC_View_Helper_TranslateHelper extends TX_EXTMVC_View_Helper_Abstra
         * @param       boolean         If true, the output label is passed through htmlspecialchars()
         * @return      string          The value from LOCAL_LANG.
         */
-       function translate($key, $default = '', $hsc=FALSE)     {
+       function translate($key, $default = '', $filterTranslation = FALSE)     {
                // The "from" charset of csConv() is only set for strings from TypoScript via _LOCAL_LANG
                if (isset($this->LOCAL_LANG[$this->languageKey][$key])) {
                        $translation = $GLOBALS['TSFE']->csConv($this->LOCAL_LANG[$this->languageKey][$key], $this->LOCAL_LANG_charset[$this->languageKey][$key]);
@@ -134,8 +135,7 @@ class TX_EXTMVC_View_Helper_TranslateHelper extends TX_EXTMVC_View_Helper_Abstra
                } else {
                        $translation = $default;
                }
-
-               return $hsc ? htmlspecialchars($translation) : $translation;
+               return $filterTranslation === TRUE ? htmlspecialchars($translation) : $translation;
        }
        
        
index 1b5a91d..3c103e8 100644 (file)
@@ -36,16 +36,6 @@ class TX_EXTMVC_View_Helper_URIHelper extends TX_EXTMVC_View_Helper_AbstractHelp
         */
        protected $router;
 
-       /**
-        * Injects the Router
-        * 
-        * @param TX_EXTMVC_Web_Routing_RouterInterface $router
-        * @return void
-        */
-       public function injectRouter(TX_EXTMVC_Web_Routing_RouterInterface $router) {
-               $this->router = $router;
-       }
-
        /**
         * Creates a link by making use of the Routers reverse routing mechanism.
         * 
index 3705e5b..879fa20 100644 (file)
@@ -34,6 +34,8 @@ require_once(PATH_t3lib . 'class.t3lib_parsehtml.php');
  * @version $ID:$
  * @scope prototype
  */
+// TODO Should we provide IF THEN ELSE statements?
+// TODO Should we allow chaining (e.g. pervorm a convertion after translation)?
 class TX_EXTMVC_View_TemplateView extends TX_EXTMVC_View_AbstractView {
 
        /**
@@ -45,7 +47,7 @@ class TX_EXTMVC_View_TemplateView extends TX_EXTMVC_View_AbstractView {
        const SCAN_PATTERN_SUBPARTS = '/<!--\s*###(?P<SubpartName>[^#]*)###.*?-->(?P<SubpartTemplateSource>.*?)<!--\s*###(?P=SubpartName)###.*?-->/sm';
        const SCAN_PATTERN_MARKER = '/###(?P<MarkerName>.*?)###/sm';
 
-       const SPLIT_PATTERN_MARKER = '/^(?:(?P<ViewHelperName>[a-zA-Z0-9_]+):)?(?P<ContextVariable>(?:\s*[a-zA-Z0-9_]+)(?=(\s|$)))?(?P<ObjectAndProperty>(?:\s*[a-zA-Z0-9_]+\.(?:[a-zA-Z0-9_]+)(?=(\s|$))))?(?P<Attributes>(?:\s*[a-zA-Z0-9_]+=(?:"(?:[^"])*"|\'(?:[^\'])*\'|\{(?:[^\{])*\}|[a-zA-Z0-9_\.]+)\s*)*)\s*$/';
+       const SPLIT_PATTERN_STATEMENT = '/(?:\s*(?P<ViewHelperName>[a-zA-Z0-9_]+):)?(?P<ContextVariable>(?:\s*[a-zA-Z0-9_]+)(?=(\s|$)))?(?P<ObjectAndProperty>(?:\s*[a-zA-Z0-9_]+\.(?:[a-zA-Z0-9_]+)(?=(\s|$))))?(?P<Attributes>(?:\s*[a-zA-Z0-9_]+=(?:"(?:[^"])*"|\'(?:[^\'])*\'|\{(?:[^\{])*\}|[a-zA-Z0-9_\.]+)\s*)*)/';
        const SPLIT_PATTERN_ARGUMENTS = '/(?P<ArgumentKey>[a-zA-Z][a-zA-Z0-9_]*)=(?:(?:"(?P<ValueDoubleQuoted>[^"]+)")|(?:\'(?P<ValueSingleQuoted>[^\']+)\')|(?:\{(?P<ValueObject>[^\'\s]+)\})|(?:(?P<ValueUnquoted>[^"\'\s]*)))/';
 
        /**
@@ -179,7 +181,7 @@ class TX_EXTMVC_View_TemplateView extends TX_EXTMVC_View_AbstractView {
                } else {
                        $templateSource = $this->templateSource;
                }
-               // TODO exception if a template was not defined
+               // TODO Throw exception if a template was not defined
                $content = $this->renderTemplate($templateSource, $this->contextVariables);
                $this->removeUnfilledMarkers($content);
                return $content;
@@ -192,18 +194,20 @@ class TX_EXTMVC_View_TemplateView extends TX_EXTMVC_View_AbstractView {
         * @return void
         */
        public function renderTemplate($templateSource, $variables) {
+               $content = '';
                $subpartArray = array();
                $subparts = $this->getSubparts($templateSource);
                foreach ($subparts as $subpartMarker => $subpartSource) {
                        $subpartArray['###' . $subpartMarker . '###'] = $this->getMarkerContent($subpartMarker, $variables, $subpartSource);
                }
-               // $content = $this->cObj->substituteMarkerArrayCached($templateSource, $markerArray, $subpartArray, $wrappedSubpartArray);
+
                $markerArray = array();
                $markers = $this->getMarkers($templateSource);
                foreach ($markers as $marker => $foo) {
                        $markerArray['###' . $marker . '###'] = $this->getMarkerContent($marker, $variables);
                }
-               $content = $this->cObj->substituteMarkerArrayCached($templateSource, $markerArray, $subpartArray, $wrappedSubpartArray);
+               
+               $content = $this->cObj->substituteMarkerArrayCached($templateSource, $markerArray, $subpartArray);
 
                return $content;
        }
@@ -227,34 +231,41 @@ class TX_EXTMVC_View_TemplateView extends TX_EXTMVC_View_AbstractView {
        /**
         * Returns the value of a marker
         *
-        * @param string $marker The marker name as string (without ###|###)
+        * @param string $marker The marker as string (without ###|###)
         * @param array $variables The variables of the context (these may be assigned by the controller or determined inside this view)
         * @param string $templateSource The template source code
         * @return string The value
         */
-       protected function getMarkerContent($marker, $variables = NULL, $templateSource = NULL) {
-               preg_match(self::SPLIT_PATTERN_MARKER, $marker, $explodedMarker);
-               $viewHelperName = TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($explodedMarker['ViewHelperName']);
-               $contextVariable = TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($explodedMarker['ContextVariable']);
-               $explodedObjectAndProperty = explode('.', $explodedMarker['ObjectAndProperty']);
-               $objectName = TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($explodedObjectAndProperty[0]);
-               $property = TX_EXTMVC_Utility_Strings::underscoredToLowerCamelCase($explodedObjectAndProperty[1]);
-               if (!empty($explodedMarker['Attributes'])) {
-                       $arguments = $this->getArguments($explodedMarker['Attributes'], $variables);
-               }
-               if ($variables[$objectName] instanceof TX_EXTMVC_DomainObject_AbstractDomainObject) {
-                       $object = $variables[$objectName];
-                       $possibleMethodName = 'get' . $property;
-                       if (method_exists($object, $possibleMethodName)) {
-                               $content = $object->$possibleMethodName();
+       public function getMarkerContent($marker, $variables = NULL, $templateSource = NULL) {
+               $explodedMarker = t3lib_div::trimExplode('|', $marker);
+               foreach ($explodedMarker as $key => $statement) {
+                       preg_match(self::SPLIT_PATTERN_STATEMENT, $statement, $explodedStatement);
+                       $viewHelperName = TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($explodedStatement['ViewHelperName']);
+                       $contextVariableName = TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($explodedStatement['ContextVariable']);
+                       $explodedObjectAndProperty = explode('.', $explodedStatement['ObjectAndProperty']);
+                       $objectName = TX_EXTMVC_Utility_Strings::underscoredToUpperCamelCase($explodedObjectAndProperty[0]);
+                       $property = TX_EXTMVC_Utility_Strings::underscoredToLowerCamelCase($explodedObjectAndProperty[1]);
+                       if (!empty($explodedStatement['Attributes'])) {
+                               $arguments = $this->getArguments($explodedStatement['Attributes'], $variables);
+                       }
+                       
+                       if ($variables[$objectName] instanceof TX_EXTMVC_DomainObject_AbstractDomainObject) {
+                               $object = $variables[$objectName];
+                               $possibleMethodName = 'get' . ucfirst($property);
+                               if (method_exists($object, $possibleMethodName)) {
+                                       $content = $object->$possibleMethodName(); // Properties should be already secure (XSS)
+                               }
+                       } elseif (!empty($variables[$contextVariableName])) {
+                               // TODO Maybe filter_var() is too much. Make it configurable? Or should we check it at assign time?
+                               $content = filter_var($variables[$contextVariableName], FILTER_SANITIZE_STRING);
+                       }
+
+                       if (!empty($viewHelperName)) {
+                               // TODO Make this configurable by injecting the viewHelpers?
+                               $viewHelperClassName = 'TX_EXTMVC_View_Helper_' . $viewHelperName . 'Helper';
+                               $viewHelper = $this->getViewHelper($viewHelperClassName);
+                               $content = $viewHelper->render($this, $arguments, $templateSource, $variables);
                        }
-               }
-               
-               if (!empty($viewHelperName)) {
-                       // TODO Make this configurable by injecting the viewHelpers
-                       $viewHelperClassName = 'TX_EXTMVC_View_Helper_' . $viewHelperName . 'Helper';
-                       $viewHelper = $this->getViewHelper($viewHelperClassName);
-                       $content = $viewHelper->render($this, $content, $arguments, $templateSource, $variables);
                }
                return $content;
        }