From 5e963014549d3ca9511e58ea2f9a766474033619 Mon Sep 17 00:00:00 2001 From: Alexander Schnitzler <git@alexanderschnitzler.de> Date: Sat, 14 Feb 2015 21:02:43 +0100 Subject: [PATCH] [FEATURE] Add a Format.Case ViewHelper 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> --- .../Feature-58621-FormatCaseViewHelper.rst | 27 +++ .../ViewHelpers/Format/CaseViewHelper.php | 160 ++++++++++++++++++ .../ViewHelpers/Format/CaseViewHelperTest.php | 90 ++++++++++ 3 files changed, 277 insertions(+) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-58621-FormatCaseViewHelper.rst create mode 100644 typo3/sysext/fluid/Classes/ViewHelpers/Format/CaseViewHelper.php create mode 100644 typo3/sysext/fluid/Tests/Unit/ViewHelpers/Format/CaseViewHelperTest.php 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 index 000000000000..9c25f43f6b28 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-58621-FormatCaseViewHelper.rst @@ -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 index 000000000000..3af111fd576c --- /dev/null +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Format/CaseViewHelper.php @@ -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 index 000000000000..ce24e3df592e --- /dev/null +++ b/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Format/CaseViewHelperTest.php @@ -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)); + } + +} -- GitLab