[FEATURE] Add a Format.Case ViewHelper 13/36913/5
authorAlexander Schnitzler <git@alexanderschnitzler.de>
Sat, 14 Feb 2015 20:02:43 +0000 (21:02 +0100)
committerNicole Cordes <typo3@cordes.co>
Mon, 2 Mar 2015 16:15:41 +0000 (17:15 +0100)
This adds a Format.Case ViewHelper that changes
a string's case in various manners like uppercase,
lowercase, (un-)capitalization and
each-word-capitalization.

Resolves: #58621
Releases: master
Change-Id: I182fae00a8bf11b6188e73bdd9cf15011ed3620d
Reviewed-on: http://review.typo3.org/36913
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
typo3/sysext/core/Documentation/Changelog/master/Feature-58621-FormatCaseViewHelper.rst [new file with mode: 0644]
typo3/sysext/fluid/Classes/ViewHelpers/Format/CaseViewHelper.php [new file with mode: 0644]
typo3/sysext/fluid/Tests/Unit/ViewHelpers/Format/CaseViewHelperTest.php [new file with mode: 0644]

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-58621-FormatCaseViewHelper.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-58621-FormatCaseViewHelper.rst
new file mode 100644 (file)
index 0000000..9c25f43
--- /dev/null
@@ -0,0 +1,27 @@
+======================================
+Feature: #58621 - FormatCaseViewHelper
+======================================
+
+Description
+===========
+
+Add a format case view helper to change casing of strings.
+
+Possible modes are:
+* ``upper`` Transforms the input string to its uppercase representation
+* ``lower`` Transforms the input string to its lowercase representation
+* ``capital`` Transforms the input string to its first letter upper-cased
+* ``uncapital`` Transforms the input string to its first letter lower-cased
+
+
+.. code-block:: html
+
+       <f:format.case>Some Text with miXed case</f:format.case> renders "SOME TEXT WITH MIXED CASE"
+
+       <f:format.case mode="capital">someString</f:format.case> renders "SomeString"
+
+
+Impact
+======
+
+The new ViewHelper can be used in all new projects. There is no interference with any part of existing code.
\ No newline at end of file
diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Format/CaseViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Format/CaseViewHelper.php
new file mode 100644 (file)
index 0000000..3af111f
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+namespace TYPO3\CMS\Fluid\ViewHelpers\Format;
+
+/*                                                                        *
+ * This script is backported from the TYPO3 Flow package "TYPO3.Fluid".   *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License, either version 3   *
+ *  of the License, or (at your option) any later version.                *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
+use TYPO3\CMS\Fluid\Core\ViewHelper\Exception\InvalidVariableException;
+use TYPO3\CMS\Core\Charset\CharsetConverter;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\Core\ViewHelper\Facets\CompilableInterface;
+use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
+
+/**
+ * Modifies the case of an input string to upper- or lowercase or capitalization.
+ * The default transformation will be uppercase as in ``mb_convert_case`` [1].
+ *
+ * Possible modes are:
+ *
+ * ``lower``
+ *   Transforms the input string to its lowercase representation
+ *
+ * ``upper``
+ *   Transforms the input string to its uppercase representation
+ *
+ * ``capital``
+ *   Transforms the input string to its first letter upper-cased, i.e. capitalization
+ *
+ * ``uncapital``
+ *   Transforms the input string to its first letter lower-cased, i.e. uncapitalization
+ *
+ * ``capitalWords``
+ *   Not supported yet: Transforms the input string to each containing word being capitalized
+ *
+ * Note that the behavior will be the same as in the appropriate PHP function ``mb_convert_case`` [1];
+ * especially regarding locale and multibyte behavior.
+ *
+ * @see http://php.net/manual/function.mb-convert-case.php [1]
+ *
+ * = Examples =
+ *
+ * <code title="Example">
+ * <f:format.case>Some Text with miXed case</f:format.case>
+ * </code>
+ * <output>
+ * SOME TEXT WITH MIXED CASE
+ * </output>
+ *
+ * <code title="Example with given mode">
+ * <f:format.case mode="capital">someString</f:format.case>
+ * </code>
+ * <output>
+ * SomeString
+ * </output>
+ *
+ * @api
+ */
+class CaseViewHelper extends AbstractViewHelper implements CompilableInterface {
+
+       /**
+        * Directs the input string being converted to "lowercase"
+        */
+       const CASE_LOWER = 'lower';
+
+       /**
+        * Directs the input string being converted to "UPPERCASE"
+        */
+       const CASE_UPPER = 'upper';
+
+       /**
+        * Directs the input string being converted to "Capital case"
+        */
+       const CASE_CAPITAL = 'capital';
+
+       /**
+        * Directs the input string being converted to "unCapital case"
+        */
+       const CASE_UNCAPITAL = 'uncapital';
+
+       /**
+        * Directs the input string being converted to "Capital Case For Each Word"
+        */
+       const CASE_CAPITAL_WORDS = 'capitalWords';
+
+       /**
+        * @var NULL|CharsetConverter
+        */
+       static protected $charsetConverter = NULL;
+
+       /**
+        * Changes the case of the input string
+        *
+        * @param string $value The input value. If not given, the evaluated child nodes will be used
+        * @param string $mode The case to apply, must be one of this' CASE_* constants. Defaults to uppercase application
+        * @return string the altered string.
+        * @api
+        */
+       public function render($value = NULL, $mode = self::CASE_UPPER) {
+               return self::renderStatic(
+                       array(
+                               'value' => $value,
+                               'mode' => $mode,
+                       ),
+                       $this->buildRenderChildrenClosure(),
+                       $this->renderingContext
+               );
+       }
+
+       /**
+        * Changes the case of the input string
+        *
+        * @param array $arguments
+        * @param \Closure $renderChildrenClosure
+        * @param RenderingContextInterface $renderingContext
+        * @return string
+        * @throws InvalidVariableException
+        */
+       static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) {
+               $value = $arguments['value'];
+               $mode = $arguments['mode'];
+
+               if ($value === NULL) {
+                       $value = $renderChildrenClosure();
+               }
+
+               if (is_null(static::$charsetConverter)) {
+                       static::$charsetConverter = GeneralUtility::makeInstance(CharsetConverter::class);
+               }
+               $charsetConverter = static::$charsetConverter;
+
+               switch ($mode) {
+                       case self::CASE_LOWER:
+                               $output = $charsetConverter->conv_case('utf-8', $value, 'toLower');
+                               break;
+                       case self::CASE_UPPER:
+                               $output = $charsetConverter->conv_case('utf-8', $value, 'toUpper');
+                               break;
+                       case self::CASE_CAPITAL:
+                               $output = $charsetConverter->utf8_substr($charsetConverter->convCaseFirst('utf-8', $value, 'toUpper'), 0, 1) . $charsetConverter->utf8_substr($value, 1);
+                               break;
+                       case self::CASE_UNCAPITAL:
+                               $output = $charsetConverter->utf8_substr($charsetConverter->convCaseFirst('utf-8', $value, 'toLower'), 0, 1) . $charsetConverter->utf8_substr($value, 1);
+                               break;
+                       case self::CASE_CAPITAL_WORDS:
+                               // @todo: Implement method once there is a proper solution with using the CharsetConverter
+                       default:
+                               throw new InvalidVariableException('The case mode "' . $mode . '" supplied to Fluid\'s format.case ViewHelper is not supported.', 1358349150);
+               }
+
+               return $output;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Format/CaseViewHelperTest.php b/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Format/CaseViewHelperTest.php
new file mode 100644 (file)
index 0000000..ce24e3d
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+namespace TYPO3\CMS\Fluid\Tests\Unit\ViewHelpers\Format;
+
+/*                                                                        *
+ * This script is backported from the TYPO3 Flow package "TYPO3.Fluid".   *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU General Public License, either version 3 of the   *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+use TYPO3\CMS\Fluid\Tests\Unit\ViewHelpers\ViewHelperBaseTestcase;
+use TYPO3\CMS\Fluid\ViewHelpers\Format\CaseViewHelper;
+
+/**
+ * Test case
+ */
+class CaseViewHelperTest extends ViewHelperBaseTestcase {
+
+       /**
+        * @var CaseViewHelper|\PHPUnit_Framework_MockObject_MockObject
+        */
+       protected $subject;
+
+       public function setUp() {
+               parent::setUp();
+               $this->subject = $this->getMock(CaseViewHelper::class, array('renderChildren'));
+               $this->injectDependenciesIntoViewHelper($this->subject);
+       }
+
+       /**
+        * @test
+        */
+       public function viewHelperRendersChildrenIfGivenValueIsNull() {
+               $this->subject->expects($this->once())->method('renderChildren');
+               $this->subject->render();
+       }
+
+       /**
+        * @test
+        */
+       public function viewHelperDoesNotRenderChildrenIfGivenValueIsNotNull() {
+               $this->subject->expects($this->never())->method('renderChildren');
+               $this->subject->render('');
+               $this->subject->render(0);
+               $this->subject->render('foo');
+       }
+
+       /**
+        * @test
+        * @expectedException \TYPO3\CMS\Fluid\Core\ViewHelper\Exception\InvalidVariableException
+        */
+       public function viewHelperThrowsExceptionIfIncorrectModeIsGiven() {
+               $this->subject->render('Foo', 'incorrectMode');
+       }
+
+       /**
+        * @test
+        */
+       public function viewHelperConvertsUppercasePerDefault() {
+               $this->assertSame('FOOB4R', $this->subject->render('FooB4r'));
+       }
+
+       /**
+        * Signature: $input, $mode, $expected
+        */
+       public function conversionTestingDataProvider() {
+               return array(
+                       array('FooB4r', CaseViewHelper::CASE_LOWER, 'foob4r'),
+                       array('FooB4r', CaseViewHelper::CASE_UPPER, 'FOOB4R'),
+                       array('foo bar', CaseViewHelper::CASE_CAPITAL, 'Foo bar'),
+                       array('FOO Bar', CaseViewHelper::CASE_UNCAPITAL, 'fOO Bar'),
+                       array('smørrebrød', CaseViewHelper::CASE_UPPER, 'SMØRREBRØD'),
+                       array('smørrebrød', CaseViewHelper::CASE_CAPITAL, 'Smørrebrød'),
+                       array('römtömtömtöm', CaseViewHelper::CASE_UPPER, 'RÖMTÖMTÖMTÖM'),
+                       array('Ἕλλάς α ω', CaseViewHelper::CASE_UPPER, 'ἝΛΛΆΣ Α Ω'),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider conversionTestingDataProvider
+        */
+       public function viewHelperConvertsCorrectly($input, $mode, $expected) {
+               $this->assertSame($expected, $this->subject->render($input, $mode), sprintf('The conversion with mode "%s" did not perform as expected.', $mode));
+       }
+
+}