Initial commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* ### Format: Append string content
|
||||
*
|
||||
* Appends a string after another string. Although this task is very
|
||||
* easily done in standard Fluid - i.e. {subject}{add} - this
|
||||
* ViewHelper makes advanced chained inline processing possible:
|
||||
*
|
||||
* <!-- useful when needing to chain string processing. Remove all "foo" and "bar"
|
||||
* then add a text containing both "foo" and "bar", then format as HTML -->
|
||||
* {text -> v:format.eliminate(strings: 'foo,bar')
|
||||
* -> v:format.append(add: ' - my foo and bar are the only ones in this text.')
|
||||
* -> f:format.html()}
|
||||
* <!-- NOTE: you do not have to break the lines; done here only for presentation purposes -->
|
||||
*
|
||||
* Makes no sense used as tag based ViewHelper:
|
||||
*
|
||||
* <!-- DO NOT USE - depicts COUNTERPRODUCTIVE usage! -->
|
||||
* <v:format.append add="{f:translate(key: 're')}">{subject}</v:format.append>
|
||||
* <!-- ... which is the exact same as ... -->
|
||||
* <f:translate key="re" />{subject} <!-- OR --> {f:translate(key: 're')}{subject}
|
||||
*
|
||||
* In other words: use this only when you do not have the option of
|
||||
* simply using {subject}{add}, i.e. in complex inline statements used
|
||||
* as attribute values on other ViewHelpers (where tag usage is undesirable).
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class AppendViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
* @param string $subject
|
||||
* @return string
|
||||
*/
|
||||
public function render($add, $subject = NULL) {
|
||||
if (NULL === $subject) {
|
||||
$subject = $this->renderChildren();
|
||||
}
|
||||
return $subject . $add;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use FluidTYPO3\Vhs\Utility\FrontendSimulationUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Case Formatting ViewHelper
|
||||
*
|
||||
* Formats string case according to provided arguments
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class CaseViewHelper extends AbstractViewHelper {
|
||||
|
||||
const CASE_UPPER = 'upper';
|
||||
const CASE_LOWER = 'lower';
|
||||
const CASE_UCWORDS = 'ucwords';
|
||||
const CASE_UCFIRST = 'ucfirst';
|
||||
const CASE_LCFIRST = 'lcfirst';
|
||||
const CASE_CAMELCASE = 'CamelCase';
|
||||
const CASE_LOWERCAMELCASE = 'lowerCamelCase';
|
||||
const CASE_UNDERSCORED = 'lowercase_underscored';
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param string $case
|
||||
* @return string
|
||||
*/
|
||||
public function render($string = NULL, $case = NULL) {
|
||||
if (NULL === $string) {
|
||||
$string = $this->renderChildren();
|
||||
}
|
||||
if ('BE' === TYPO3_MODE) {
|
||||
$tsfeBackup = FrontendSimulationUtility::simulateFrontendEnvironment();
|
||||
}
|
||||
switch ($case) {
|
||||
case self::CASE_LOWER:
|
||||
$string = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $string, 'toLower');
|
||||
break;
|
||||
case self::CASE_UPPER:
|
||||
$string = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $string, 'toUpper');
|
||||
break;
|
||||
case self::CASE_UCWORDS:
|
||||
$string = ucwords($string);
|
||||
break;
|
||||
case self::CASE_UCFIRST:
|
||||
$string = $GLOBALS['TSFE']->csConvObj->convCaseFirst($GLOBALS['TSFE']->renderCharset, $string, 'toUpper');
|
||||
break;
|
||||
case self::CASE_LCFIRST:
|
||||
$string = $GLOBALS['TSFE']->csConvObj->convCaseFirst($GLOBALS['TSFE']->renderCharset, $string, 'toLower');
|
||||
break;
|
||||
case self::CASE_CAMELCASE:
|
||||
$string = GeneralUtility::underscoredToUpperCamelCase($string);
|
||||
break;
|
||||
case self::CASE_LOWERCAMELCASE:
|
||||
$string = GeneralUtility::underscoredToLowerCamelCase($string);
|
||||
break;
|
||||
case self::CASE_UNDERSCORED:
|
||||
$string = GeneralUtility::camelCaseToLowerCaseUnderscored($string);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ('BE' === TYPO3_MODE) {
|
||||
FrontendSimulationUtility::resetFrontendEnvironment($tsfeBackup);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\Exception;
|
||||
|
||||
/**
|
||||
* ### Date range calculation/formatting ViewHelper
|
||||
*
|
||||
* Uses DateTime and DateInterval operations to calculate a range
|
||||
* between two DateTimes.
|
||||
*
|
||||
* #### Usages
|
||||
*
|
||||
* - As formatter, the ViewHelper can output a string value such as
|
||||
* "2013-04-30 - 2013-05-30" where you can configure both the start
|
||||
* and end date (or their common) formats as well as the "glue"
|
||||
* which binds the two dates together.
|
||||
* - As interval calculator, the ViewHelper can be used with a special
|
||||
* "intervalFormat" which is a string used in the constructor method
|
||||
* for the DateInterval class - for example, "P3M" to add three months.
|
||||
* Used this way, you can specify the start date (or rely on the
|
||||
* default "now" DateTime) and specify the "intervalFormat" to add
|
||||
* your desired duration to your starting date and use that as end
|
||||
* date. Without the "return" attribute, this mode simply outputs
|
||||
* the formatted dates with interval deciding the end date.
|
||||
* - When used with the "return" attribute you can specify which type
|
||||
* of data to return:
|
||||
* - if "return" is "DateTime", a single DateTime instance is returned
|
||||
* (which is the end date). Use this with a start date to return the
|
||||
* DateTime corresponding to "intervalFormat" into the future/past.
|
||||
* - if "return" is a string such as "w", "d", "h" etc. the corresponding
|
||||
* counter value (weeks, days, hours etc.) is returned.
|
||||
* - if "return" is an array of counter IDs, for example Array("w", "d"),
|
||||
* the corresponding counters from the range are returned as an array.
|
||||
*
|
||||
* #### Note about LLL support and array consumers
|
||||
*
|
||||
* When used with the "return" attribute and when this attribute is an
|
||||
* array, the output becomes suitable for consumption by f:translate, v:l
|
||||
* or f:format.sprintf for example - as the "arguments" attribute:
|
||||
*
|
||||
* <f:translate key="myDateDisplay"
|
||||
* arguments="{v:format.dateRange(intervalFormat: 'P3W', return: {0: 'w', 1: 'd'})}"
|
||||
* />
|
||||
*
|
||||
* Which if "myDateDisplay" is a string such as "Deadline: %d week(s) and
|
||||
* %d day(s)" would output a result such as "Deadline: 4 week(s) and 2 day(s)".
|
||||
*
|
||||
* > Tip: the values returned by this ViewHelper in both array and single
|
||||
* > value return modes, are also nicely consumable by the "math" suite
|
||||
* > of ViewHelpers, for example `v:math.division` would be able to divide
|
||||
* > number of days by two, three etc. to further divide the date range.
|
||||
*
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class DateRangeViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $escapingInterceptorEnabled = FALSE;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function initializeArguments() {
|
||||
$this->registerArgument('start', 'mixed', 'Start date which can be a DateTime object or a string consumable by DateTime constructor', FALSE, 'now');
|
||||
$this->registerArgument('end', 'mixed', 'End date which can be a DateTime object or a string consumable by DateTime constructor', FALSE, NULL);
|
||||
$this->registerArgument('intervalFormat', 'string', 'Interval format consumable by DateInterval', FALSE, NULL);
|
||||
$this->registerArgument('format', 'string', 'Date format to apply to both start and end date', FALSE, 'Y-m-d');
|
||||
$this->registerArgument('startFormat', 'string', 'Date format to apply to start date', FALSE, NULL);
|
||||
$this->registerArgument('endFormat', 'string', 'Date format to apply to end date', FALSE, NULL);
|
||||
$this->registerArgument('glue', 'string', 'Glue string to concatenate dates with', FALSE, '-');
|
||||
$this->registerArgument('spaceGlue', 'boolean', 'If TRUE glue string is surrounded with whitespace', FALSE, TRUE);
|
||||
$this->registerArgument('return', 'mixed', 'Return type; can be exactly "DateTime" to return a DateTime instance, a string like "w" ' .
|
||||
'or "d" to return weeks, days between the two dates - or an array of w, d, etc. strings to return the corresponding range count values as an array.', FALSE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render method
|
||||
*
|
||||
* @throws Exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function render() {
|
||||
if (TRUE === isset($this->arguments['start']) && FALSE === empty($this->arguments['start'])) {
|
||||
$start = $this->arguments['start'];
|
||||
} else {
|
||||
$start = 'now';
|
||||
}
|
||||
$startDateTime = $this->enforceDateTime($start);
|
||||
|
||||
if (TRUE === isset($this->arguments['end']) && FALSE === empty($this->arguments['end'])) {
|
||||
$endDateTime = $this->enforceDateTime($this->arguments['end']);
|
||||
} else {
|
||||
$endDateTime = NULL;
|
||||
}
|
||||
|
||||
if (TRUE === isset($this->arguments['intervalFormat']) && FALSE === empty($this->arguments['intervalFormat'])) {
|
||||
$intervalFormat = $this->arguments['intervalFormat'];
|
||||
}
|
||||
|
||||
if (NULL === $intervalFormat && NULL === $endDateTime) {
|
||||
throw new Exception('Either end or intervalFormat has to be provided.', 1369573110);
|
||||
}
|
||||
|
||||
if (TRUE === isset($intervalFormat) && NULL !== $intervalFormat) {
|
||||
try {
|
||||
$interval = new \DateInterval($intervalFormat);
|
||||
} catch (\Exception $exception) {
|
||||
throw new Exception('"' . $intervalFormat . '" could not be parsed by \DateInterval constructor.', 1369573111);
|
||||
}
|
||||
} else {
|
||||
$interval = $endDateTime->diff($startDateTime);
|
||||
}
|
||||
|
||||
if (NULL !== $interval && NULL === $endDateTime) {
|
||||
$endDateTime = new \DateTime();
|
||||
$endDateTime->add($endDateTime->diff($startDateTime));
|
||||
$endDateTime->add($interval);
|
||||
}
|
||||
|
||||
$return = $this->arguments['return'];
|
||||
if (NULL === $return) {
|
||||
$spaceGlue = (boolean) $this->arguments['spaceGlue'];
|
||||
$glue = strval($this->arguments['glue']);
|
||||
$startFormat = $this->arguments['format'];
|
||||
$endFormat = $this->arguments['format'];
|
||||
if (NULL !== $this->arguments['startFormat'] && FALSE === empty($this->arguments['startFormat'])) {
|
||||
$startFormat = $this->arguments['startFormat'];
|
||||
}
|
||||
if (NULL !== $this->arguments['endFormat'] && FALSE === empty($this->arguments['endFormat'])) {
|
||||
$endFormat = $this->arguments['endFormat'];
|
||||
}
|
||||
$output = $this->formatDate($startDateTime, $startFormat);
|
||||
$output .= TRUE === $spaceGlue ? ' ' : '';
|
||||
$output .= $glue;
|
||||
$output .= TRUE === $spaceGlue ? ' ' : '';
|
||||
$output .= $this->formatDate($endDateTime, $endFormat);
|
||||
} elseif ('DateTime' === $return) {
|
||||
$output = $endDateTime;
|
||||
} elseif (TRUE === is_string($return)) {
|
||||
if (FALSE === strpos($return, '%')) {
|
||||
$return = '%' . $return;
|
||||
}
|
||||
$output = $interval->format($return);
|
||||
} elseif (TRUE === is_array($return)) {
|
||||
$output = array();
|
||||
foreach ($return as $format) {
|
||||
if (FALSE === strpos($format, '%')) {
|
||||
$format = '%' . $format;
|
||||
}
|
||||
array_push($output, $interval->format($format));
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $date
|
||||
* @return \DateTime
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function enforceDateTime($date) {
|
||||
if (FALSE === $date instanceof \DateTime) {
|
||||
try {
|
||||
if (TRUE === is_integer($date)) {
|
||||
$date = new \DateTime('@' . $date);
|
||||
} else {
|
||||
$date = new \DateTime($date);
|
||||
}
|
||||
$date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
|
||||
} catch (\Exception $exception) {
|
||||
throw new Exception('"' . $date . '" could not be parsed by \DateTime constructor.', 1369573112);
|
||||
}
|
||||
}
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $date
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
protected function formatDate($date, $format = 'Y-m-d') {
|
||||
if (FALSE !== strpos($format, '%')) {
|
||||
return strftime($format, $date->format('U'));
|
||||
} else {
|
||||
return $date->format($format);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Character/string/whitespace elimination ViewHelper
|
||||
*
|
||||
* There is no example - each argument describes how it should be
|
||||
* used and arguments can be used individually or in any combination.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class EliminateViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Initialize arguments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeArguments() {
|
||||
$this->registerArgument('caseSensitive', 'boolean', 'Wether or not to perform case sensitive replacement', FALSE, TRUE);
|
||||
$this->registerArgument('characters', 'mixed', "Characters to remove. Array or string, i.e. {0: 'a', 1: 'b', 2: 'c'} or 'abc' to remove all occurrences of a, b and c");
|
||||
$this->registerArgument('strings', 'mixed', "Strings to remove. Array or CSV, i.e. {0: 'foo', 1: 'bar'} or 'foo,bar' to remove all occorrences of foo and bar. If your strings overlap then place the longest match first");
|
||||
$this->registerArgument('whitespace', 'boolean', 'Eliminate ALL whitespace characters', FALSE, FALSE);
|
||||
$this->registerArgument('whitespaceBetweenHtmlTags', 'boolean', 'Eliminate ALL whitespace characters between HTML tags', FALSE, FALSE);
|
||||
$this->registerArgument('tabs', 'boolean', 'Eliminate only tab whitespaces', FALSE, FALSE);
|
||||
$this->registerArgument('unixBreaks', 'boolean', 'Eliminate only UNIX line breaks', FALSE, FALSE);
|
||||
$this->registerArgument('windowsBreaks', 'boolean', 'Eliminates only Windows carriage returns', FALSE, FALSE);
|
||||
$this->registerArgument('digits', 'boolean', 'Eliminates all number characters (but not the dividers between floats converted to strings)', FALSE, FALSE);
|
||||
$this->registerArgument('letters', 'boolean', 'Eliminates all letters (non-numbers, non-whitespace, non-syntactical)', FALSE, FALSE);
|
||||
$this->registerArgument('nonAscii', 'boolean', 'Eliminates any ASCII char', FALSE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
if (TRUE === isset($this->arguments['characters'])) {
|
||||
$content = $this->eliminateCharacters($content, $this->arguments['characters']);
|
||||
}
|
||||
if (TRUE === isset($this->arguments['strings'])) {
|
||||
$content = $this->eliminateStrings($content, $this->arguments['strings']);
|
||||
}
|
||||
if (TRUE === $this->arguments['whitespace']) {
|
||||
$content = $this->eliminateWhitespace($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['whitespaceBetweenHtmlTags']) {
|
||||
$content = $this->eliminateWhitespaceBetweenHtmlTags($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['tabs']) {
|
||||
$content = $this->eliminateTabs($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['unixBreaks']) {
|
||||
$content = $this->eliminateUnixBreaks($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['windowsBreaks']) {
|
||||
$content = $this->eliminateWindowsCarriageReturns($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['digits']) {
|
||||
$content = $this->eliminateDigits($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['letters']) {
|
||||
$content = $this->eliminateLetters($content);
|
||||
}
|
||||
if (TRUE === $this->arguments['nonAscii']) {
|
||||
$content = $this->eliminateNonAscii($content);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param mixed $characters
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateCharacters($content, $characters) {
|
||||
$caseSensitive = (boolean) $this->arguments['caseSensitive'];
|
||||
if (TRUE === is_array($characters)) {
|
||||
$subjects = $characters;
|
||||
} else {
|
||||
$subjects = str_split($characters);
|
||||
}
|
||||
foreach ($subjects as $subject) {
|
||||
if (TRUE === $caseSensitive) {
|
||||
$content = str_replace($subject, '', $content);
|
||||
} else {
|
||||
$content = str_ireplace($subject, '', $content);
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param mixed $strings
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateStrings($content, $strings) {
|
||||
$caseSensitive = (boolean) $this->arguments['caseSensitive'];
|
||||
if (TRUE === is_array($strings)) {
|
||||
$subjects = $strings;
|
||||
} else {
|
||||
$subjects = explode(',', $strings);
|
||||
}
|
||||
foreach ($subjects as $subject) {
|
||||
if (TRUE === $caseSensitive) {
|
||||
$content = str_replace($subject, '', $content);
|
||||
} else {
|
||||
$content = str_ireplace($subject, '', $content);
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateWhitespace($content) {
|
||||
$content = preg_replace('/\s+/', '', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateWhitespaceBetweenHtmlTags($content) {
|
||||
$content = trim(preg_replace('/>\s+</', '><', $content));
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateTabs($content) {
|
||||
$content = str_replace("\t", '', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateUnixBreaks($content) {
|
||||
$content = str_replace("\n", '', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateWindowsCarriageReturns($content) {
|
||||
$content = str_replace("\r", '', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateDigits($content) {
|
||||
$content = preg_replace('#[0-9]#', '', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateLetters($content) {
|
||||
$caseSensitive = (boolean) $this->arguments['caseSensitive'];
|
||||
if (TRUE === $caseSensitive) {
|
||||
$content = preg_replace('#[a-z]#', '', $content);
|
||||
} else {
|
||||
$content = preg_replace('/[a-z]/i', '', $content);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected function eliminateNonAscii($content) {
|
||||
$caseSensitive = (boolean) $this->arguments['caseSensitive'];
|
||||
$caseSensitiveIndicator = TRUE === $caseSensitive ? 'i' : '';
|
||||
$content = preg_replace('/[^(\x20-\x7F)]*/' . $caseSensitiveIndicator, '', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Hides output from browser, but still renders tag content
|
||||
* which means any ViewHelper inside the tag content still
|
||||
* gets processed.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class HideViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeArguments() {
|
||||
$this->registerArgument('disabled', 'boolean', 'If TRUE, renders content - use to quickly enable/disable Fluid code', FALSE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render() {
|
||||
if (TRUE === (boolean) $this->arguments['disabled']) {
|
||||
return $this->renderChildren();
|
||||
} else {
|
||||
$this->renderChildren();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Json;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\Exception;
|
||||
|
||||
/**
|
||||
* Converts the JSON encoded argument into a PHP variable
|
||||
*
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format\Json
|
||||
*/
|
||||
class DecodeViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $json
|
||||
* @throws Exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($json = NULL) {
|
||||
if (NULL === $json) {
|
||||
$json = $this->renderChildren();
|
||||
if (TRUE === empty($json)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$value = json_decode($json, TRUE);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new Exception('The provided argument is invalid JSON.', 1358440054);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Json;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
|
||||
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\Exception;
|
||||
|
||||
/**
|
||||
* ### JSON Encoding ViewHelper
|
||||
*
|
||||
* Returns a string containing the JSON representation of the argument.
|
||||
* The argument may be any of the following types:
|
||||
*
|
||||
* - arrays, associative and traditional
|
||||
* - DomainObjects
|
||||
* - arrays containing DomainObjects
|
||||
* - ObjectStorage containing DomainObjects
|
||||
* - standard types (string, integer, boolean, float, NULL)
|
||||
* - DateTime including ones found as property values on DomainObjects
|
||||
*
|
||||
* Recursion protection is enabled for DomainObjects with the option to
|
||||
* add a special marker (any variable type above also supported here)
|
||||
* which is inserted where an object which would cause recursion would
|
||||
* be placed.
|
||||
*
|
||||
* Be specially careful when you JSON encode DomainObjects which have
|
||||
* recursive relations to itself using either 1:n or m:n - in this case
|
||||
* the one member of the converted relation will be whichever value you
|
||||
* specified as "recursionMarker" - or the default value, NULL. When
|
||||
* using the output of such conversion in JavaScript please make sure you
|
||||
* check the type before assuming that every member of a converted 1:n
|
||||
* or m:n recursive relation is in fact a JavaScript. Not doing so may
|
||||
* result in fatal JavaScript errors in the client browser.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format\Json
|
||||
*/
|
||||
class EncodeViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $encounteredClasses = array();
|
||||
|
||||
/**
|
||||
* @param mixed $value Array or Traversable
|
||||
* @param boolean $useTraversableKeys If TRUE, preserves keys from Traversables converted to arrays. Not recommended for ObjectStorages!
|
||||
* @param boolean $preventRecursion If FALSE, allows recursion to occur which could potentially be fatal to the output unless managed
|
||||
* @param mixed $recursionMarker Any value - string, integer, boolean, object or NULL - inserted instead of recursive instances of objects
|
||||
* @param string $dateTimeFormat A date() format for converting DateTime values to JSON-compatible values. NULL means JS UNIXTIME (time()*1000)
|
||||
* @return string
|
||||
*/
|
||||
public function render($value = NULL, $useTraversableKeys = FALSE, $preventRecursion = TRUE, $recursionMarker = NULL, $dateTimeFormat = NULL) {
|
||||
if (NULL === $value) {
|
||||
$value = $this->renderChildren();
|
||||
if (TRUE === empty($value)) {
|
||||
return '{}';
|
||||
}
|
||||
}
|
||||
$json = $this->encodeValue($value, $useTraversableKeys, $preventRecursion, $recursionMarker, $dateTimeFormat);
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param boolean $useTraversableKeys
|
||||
* @param boolean $preventRecursion
|
||||
* @param string $recursionMarker
|
||||
* @param string $dateTimeFormat
|
||||
* @throws Exception
|
||||
* @return mixed
|
||||
*/
|
||||
protected function encodeValue($value, $useTraversableKeys, $preventRecursion, $recursionMarker, $dateTimeFormat) {
|
||||
if (TRUE === $value instanceof \Traversable) {
|
||||
// Note: also converts Extbase ObjectStorage to \YourVendor\Extname\Domain\Model\ObjectType[] which are later each converted
|
||||
$value = iterator_to_array($value, $useTraversableKeys);
|
||||
} elseif (TRUE === $value instanceof DomainObjectInterface) {
|
||||
// Convert to associative array,
|
||||
$value = $this->recursiveDomainObjectToArray($value, $preventRecursion, $recursionMarker);
|
||||
} elseif (TRUE === $value instanceof \DateTime) {
|
||||
$value = $this->dateTimeToUnixtimeMiliseconds($value, $dateTimeFormat);
|
||||
}
|
||||
|
||||
// process output of initial conversion, catching any specially supported object types such as DomainObject and DateTime
|
||||
if (TRUE === is_array($value)) {
|
||||
$value = $this->recursiveArrayOfDomainObjectsToArray($value, $preventRecursion, $recursionMarker);
|
||||
$value = $this->recursiveDateTimeToUnixtimeMiliseconds($value, $dateTimeFormat);
|
||||
};
|
||||
$json = json_encode($value, JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_TAG);
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new Exception('The provided argument cannot be converted into JSON.', 1358440181);
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts any encountered DateTime instances to UNIXTIME timestamps
|
||||
* which are then multiplied by 1000 to create a JavaScript appropriate
|
||||
* time stamp - ready to be loaded into a Date object client-side.
|
||||
*
|
||||
* Works on already converted DomainObjects which are at this point just
|
||||
* associative arrays of values - which might be DateTime instances.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $dateTimeFormat
|
||||
* @return array
|
||||
*/
|
||||
protected function recursiveDateTimeToUnixtimeMiliseconds(array $array, $dateTimeFormat) {
|
||||
foreach ($array as $key => $possibleDateTime) {
|
||||
if (TRUE === $possibleDateTime instanceof \DateTime) {
|
||||
$array[$key] = $this->dateTimeToUnixtimeMiliseconds($possibleDateTime, $dateTimeFormat);
|
||||
} elseif (TRUE === is_array($possibleDateTime)) {
|
||||
$array[$key] = $this->recursiveDateTimeToUnixtimeMiliseconds($array[$key], $dateTimeFormat);
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a single DateTime instance to whichever value is demanded by
|
||||
* the format specified in $dateTimeFormat (DateTime::format syntax).
|
||||
* Default format is NULL a JS UNIXTIME (time()*1000) is produced.
|
||||
*
|
||||
* @param \DateTime $dateTime
|
||||
* @param string $dateTimeFormat
|
||||
* @return integer
|
||||
*/
|
||||
protected function dateTimeToUnixtimeMiliseconds(\DateTime $dateTime, $dateTimeFormat) {
|
||||
if (NULL === $dateTimeFormat) {
|
||||
return intval($dateTime->format('U')) * 1000;
|
||||
}
|
||||
return $dateTime->format($dateTimeFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of possible DomainObject instances. The argument
|
||||
* $possibleDomainObjects could also an associative array representation
|
||||
* of another DomainObject - which means each value could potentially
|
||||
* be another DomainObject, an ObjectStorage of DomainObjects or a simple
|
||||
* value type. The type is checked and another recursive call is used to
|
||||
* convert any nested objects.
|
||||
*
|
||||
* @param Tx_Extbase_DomainObject_DomainObjectInterface[] $domainObjects
|
||||
* @param boolean $preventRecursion
|
||||
* @param mixed $recursionMarker
|
||||
* @return array
|
||||
*/
|
||||
protected function recursiveArrayOfDomainObjectsToArray(array $domainObjects, $preventRecursion, $recursionMarker) {
|
||||
foreach ($domainObjects as $key => $possibleDomainObject) {
|
||||
if (TRUE === $possibleDomainObject instanceof DomainObjectInterface) {
|
||||
$domainObjects[$key] = $this->recursiveDomainObjectToArray($possibleDomainObject, $preventRecursion, $recursionMarker);
|
||||
} elseif (TRUE === $possibleDomainObject instanceof \Traversable) {
|
||||
$traversableAsArray = iterator_to_array($possibleDomainObject);
|
||||
$domainObjects[$key] = $this->recursiveArrayOfDomainObjectsToArray($traversableAsArray, $preventRecursion, $recursionMarker);
|
||||
}
|
||||
}
|
||||
return $domainObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a single DomainObject instance first to an array, then pass
|
||||
* that array through recursive DomainObject detection. This will convert
|
||||
* any 1:1, 1:n, n:1 and m:n relations.
|
||||
*
|
||||
* @param DomainObjectInterface $domainObject
|
||||
* @param boolean $preventRecursion
|
||||
* @param mixed $recursionMarker
|
||||
* @return array
|
||||
*/
|
||||
protected function recursiveDomainObjectToArray(DomainObjectInterface $domainObject, $preventRecursion, $recursionMarker) {
|
||||
$hash = spl_object_hash($domainObject);
|
||||
if (TRUE === $preventRecursion && TRUE === in_array($hash, $this->encounteredClasses)) {
|
||||
return $recursionMarker;
|
||||
}
|
||||
$converted = ObjectAccess::getGettableProperties($domainObject);
|
||||
array_push($this->encounteredClasses, $hash);
|
||||
$converted = $this->recursiveArrayOfDomainObjectsToArray($converted, $preventRecursion, $recursionMarker);
|
||||
return $converted;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Cache\Frontend\StringFrontend;
|
||||
use TYPO3\CMS\Core\Utility\CommandUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\Exception;
|
||||
|
||||
/**
|
||||
* Markdown Transformation ViewHelper
|
||||
*
|
||||
* Requires an installed "markdown" utility, the specific
|
||||
* implementation is less important since Markdown has no
|
||||
* configuration options. However, the utility or shell
|
||||
* scipt must:
|
||||
*
|
||||
* - accept input from STDIN
|
||||
* - output to STDOUT
|
||||
* - place errors in STDERR
|
||||
* - be executable according to `open_basedir` and others
|
||||
* - exist within (one or more of) TYPO3's configured executable paths
|
||||
*
|
||||
* In other words, *NIX standard behavior must be used.
|
||||
*
|
||||
* See: http://daringfireball.net/projects/markdown/
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class MarkdownViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $escapingInterceptorEnabled = FALSE;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $markdownExecutablePath;
|
||||
|
||||
/**
|
||||
* @var StringFrontend
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function initialize() {
|
||||
$cacheManager = isset($GLOBALS['typo3CacheManager']) ? $GLOBALS['typo3CacheManager'] : GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
|
||||
$this->cache = $cacheManager->getCache('vhs_markdown');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param boolean $trim
|
||||
* @param boolean $htmlentities
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
public function render($text = NULL, $trim = TRUE, $htmlentities = FALSE) {
|
||||
if (NULL === $text) {
|
||||
$text = $this->renderChildren();
|
||||
}
|
||||
if (NULL === $text) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$cacheIdentifier = sha1($text);
|
||||
if (TRUE === $this->cache->has($cacheIdentifier)) {
|
||||
return $this->cache->get($cacheIdentifier);
|
||||
}
|
||||
|
||||
$this->markdownExecutablePath = CommandUtility::getCommand('markdown');
|
||||
if (FALSE === is_executable($this->markdownExecutablePath)) {
|
||||
throw new Exception('Use of Markdown requires the "markdown" shell utility to be installed ' .
|
||||
'and accessible; this binary could not be found in any of your configured paths available to this script', 1350511561);
|
||||
}
|
||||
if (TRUE === (boolean) $trim) {
|
||||
$text = trim($text);
|
||||
}
|
||||
if (TRUE === (boolean) $htmlentities) {
|
||||
$text = htmlentities($text);
|
||||
}
|
||||
$transformed = $this->transform($text);
|
||||
$this->cache->set($cacheIdentifier, $transformed);
|
||||
return $transformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
public function transform($text) {
|
||||
$descriptorspec = array(
|
||||
0 => array('pipe', 'r'),
|
||||
1 => array('pipe', 'w'),
|
||||
2 => array('pipe', 'a')
|
||||
);
|
||||
|
||||
$process = proc_open($this->markdownExecutablePath, $descriptorspec, $pipes, NULL, $GLOBALS['_ENV']);
|
||||
|
||||
stream_set_blocking($pipes[0], 1);
|
||||
stream_set_blocking($pipes[1], 1);
|
||||
stream_set_blocking($pipes[2], 1);
|
||||
|
||||
fwrite($pipes[0], $text);
|
||||
fclose($pipes[0]);
|
||||
|
||||
$transformed = stream_get_contents($pipes[1]);
|
||||
fclose($pipes[1]);
|
||||
|
||||
$errors = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
$exitCode = proc_close($process);
|
||||
|
||||
if ('' !== trim($errors)) {
|
||||
throw new Exception('There was an error while executing ' . $this->markdownExecutablePath . '. The return code was ' .
|
||||
$exitCode . ' and the message reads: ' . $errors, 1350514144);
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Placeholder;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
|
||||
|
||||
/**
|
||||
* Placeholder Image ViewHelper
|
||||
*
|
||||
* Inserts a placeholder image from http://placehold.it/
|
||||
*
|
||||
* @author Claus Due
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format\Placeholder
|
||||
*/
|
||||
class ImageViewHelper extends AbstractTagBasedViewHelper {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tagName = 'img';
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeArguments() {
|
||||
parent::initializeArguments();
|
||||
$this->registerUniversalTagAttributes();
|
||||
$this->registerArgument('width', 'integer', 'Width of rendered placeholder image', FALSE, 640);
|
||||
$this->registerArgument('height', 'integer', 'Height of rendered placeholder image', FALSE, FALSE);
|
||||
$this->registerArgument('backgroundColor', 'string', 'Background color', FALSE, '333333');
|
||||
$this->registerArgument('textColor', 'string', 'Text color', FALSE, 'FFFFFF');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public function render($text = NULL) {
|
||||
if (NULL === $text) {
|
||||
$text = $this->renderChildren();
|
||||
}
|
||||
$height = $this->arguments['height'] != $this->arguments['width'] ? $this->arguments['height'] : NULL;
|
||||
$addHeight = FALSE === empty($height) ? 'x' . $height : NULL;
|
||||
$url = array(
|
||||
'http://placehold.it',
|
||||
$this->arguments['width'] . $addHeight,
|
||||
$this->arguments['backgroundColor'],
|
||||
$this->arguments['textColor'],
|
||||
);
|
||||
if (FALSE === empty($text)) {
|
||||
array_push($url, '&text=' . urlencode($text));
|
||||
}
|
||||
$imageUrl = implode('/', $url);
|
||||
$this->tag->forceClosingTag(FALSE);
|
||||
$this->tag->addAttribute('src', $imageUrl);
|
||||
$this->tag->addAttribute('alt', $imageUrl);
|
||||
$this->tag->addAttribute('width', $this->arguments['width']);
|
||||
$this->tag->addAttribute('height', FALSE === empty($height) ? $height : $this->arguments['width']);
|
||||
return $this->tag->render();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Placeholder;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
|
||||
/**
|
||||
* Lipsum ViewHelper
|
||||
*
|
||||
* Renders Lorem Ipsum text according to provided arguments.
|
||||
*
|
||||
* @author Claus Due
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format\Placeholder
|
||||
*/
|
||||
class LipsumViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $lipsum;
|
||||
|
||||
/**
|
||||
* @var ContentObjectRenderer
|
||||
*/
|
||||
protected $contentObject;
|
||||
|
||||
/**
|
||||
* @var ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function initialize() {
|
||||
$this->lipsum = $this->getDefaultLoremIpsum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigurationManagerInterface $configurationManager
|
||||
* @return void
|
||||
*/
|
||||
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager) {
|
||||
$this->configurationManager = $configurationManager;
|
||||
$this->contentObject = $this->configurationManager->getContentObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize arguments
|
||||
*/
|
||||
public function initializeArguments() {
|
||||
$this->registerArgument('paragraphs', 'integer', 'Number of paragraphs to output');
|
||||
$this->registerArgument('wordsPerParagraph', 'integer', 'Number of words per paragraph');
|
||||
$this->registerArgument('skew', 'integer', 'Amount in number of words to vary the number of words per paragraph');
|
||||
$this->registerArgument('html', 'boolean', 'If TRUE, renders output as HTML paragraph tags in the same way an RTE would');
|
||||
$this->registerArgument('parseFuncTSPath', 'string', 'If you want another parseFunc for HTML processing, enter the TS path here');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders Lorem Ipsum paragraphs. If $lipsum is provided it
|
||||
* will be used as source text. If not provided as an argument
|
||||
* or as inline argument, $lipsum is fetched from TypoScript settings.
|
||||
*
|
||||
* @param string $lipsum String of paragraphs file path or EXT:myext/path/to/file
|
||||
* @return string
|
||||
*/
|
||||
public function render($lipsum = NULL) {
|
||||
if (strlen($lipsum) === 0) {
|
||||
$lipsum = $this->lipsum;
|
||||
}
|
||||
if ((strlen($lipsum) < 255 && !preg_match('/[^a-z0-9_\.\:\/]/i', $lipsum)) || 0 === strpos($lipsum, 'EXT:')) {
|
||||
// argument is most likely a file reference.
|
||||
$sourceFile = GeneralUtility::getFileAbsFileName($lipsum);
|
||||
if (file_exists($sourceFile) === TRUE) {
|
||||
$lipsum = file_get_contents($sourceFile);
|
||||
} else {
|
||||
GeneralUtility::sysLog('Vhs LipsumViewHelper was asked to load Lorem Ipsum from a file which does not exist. ' .
|
||||
'The file was: ' . $sourceFile, 'vhs', GeneralUtility::SYSLOG_SEVERITY_WARNING);
|
||||
$lipsum = $this->lipsum;
|
||||
}
|
||||
}
|
||||
$lipsum = preg_replace('/[\\r\\n]{1,}/i', "\n", $lipsum);
|
||||
$paragraphs = explode("\n", $lipsum);
|
||||
$paragraphs = array_slice($paragraphs, 0, intval($this->arguments['paragraphs']));
|
||||
foreach ($paragraphs as $index => $paragraph) {
|
||||
$length = $this->arguments['wordsPerParagraph'] + rand(0 - intval($this->arguments['skew']), intval($this->arguments['skew']));
|
||||
$words = explode(' ', $paragraph);
|
||||
$paragraphs[$index] = implode(' ', array_slice($words, 0, $length));
|
||||
}
|
||||
|
||||
$lipsum = implode("\n", $paragraphs);
|
||||
if ((boolean) $this->arguments['html'] === TRUE) {
|
||||
$tsParserPath = (FALSE === empty($this->arguments['parseFuncTSPath']) ? '< ' . $this->arguments['parseFuncTSPath'] : NULL);
|
||||
$lipsum = $this->contentObject->parseFunc($lipsum, array(), $tsParserPath);
|
||||
}
|
||||
return $lipsum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default Lorem Ipsum. The compressed block (which is
|
||||
* of course cleaned thoroughly to avoid any injection) contains
|
||||
* 20 full paragraphs of Lorem Ipsum in standard latin. No bells
|
||||
* and whistles there.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDefaultLoremIpsum() {
|
||||
// Note: this MAY look suspicious but it really is just a whole lot of Lipsum
|
||||
// in a compressed state. Just to make sure that you trust the block, we run
|
||||
// strip_tags and htmlentities on the string before it is returned. This is not
|
||||
// done on custom Lipsum - but it is done here at no risk, since we know the
|
||||
// Lipsum to contain zero HTML and zero special characters, 100% ASCII. Source
|
||||
// of the Lipsum text is http://www.lipsum.com set at 20 paragraphs, compressed
|
||||
// through a small shell script.
|
||||
$lipsum = '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';
|
||||
$uncompressed = gzuncompress(base64_decode($lipsum));
|
||||
$safe = htmlentities(strip_tags($uncompressed));
|
||||
return $safe;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Processes output as plaintext. Will trim whitespace off
|
||||
* each line that is provided, making display in a <pre>
|
||||
* work correctly indented even if the source is not.
|
||||
*
|
||||
* Expects that you use f:format.htmlentities or similar
|
||||
* if you do not want HTML to be displayed as HTML, or
|
||||
* simply want it stripped out.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class PlaintextViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Trims content, then trims each line of content
|
||||
*
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
$content = trim($content);
|
||||
$lines = explode("\n", $content);
|
||||
$lines = array_map('trim', $lines);
|
||||
return implode(LF, $lines);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* ### Format: Prepend string content
|
||||
*
|
||||
* Prepends one string on another. Although this task is very
|
||||
* easily done in standard Fluid - i.e. {add}{subject} - this
|
||||
* ViewHelper makes advanced chained inline processing possible:
|
||||
*
|
||||
* <!-- Adds 1H to DateTime, formats using timestamp input which requires prepended @ -->
|
||||
* {dateTime.timestamp
|
||||
* -> v:math.sum(b: 3600)
|
||||
* -> v:format.prepend(add: '@')
|
||||
* -> v:format.date(format: 'Y-m-d H:i')}
|
||||
* <!-- You don't have to break the syntax into lines; done here for display only -->
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class PrependViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
* @param string $subject
|
||||
* @return string
|
||||
*/
|
||||
public function render($add, $subject = NULL) {
|
||||
if (NULL === $subject) {
|
||||
$subject = $this->renderChildren();
|
||||
}
|
||||
return $add . $subject;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Formats or gets detected substrings by regular expression.
|
||||
* Returns matches if `return="TRUE"`, otherwise replaces any
|
||||
* occurrences of `$pattern`.
|
||||
* simply returns
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class RegularExpressionViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $pattern The regular expression pattern to search for
|
||||
* @param string $replacement The desired value to insert instead of detected matches
|
||||
* @param string $subject The subject in which to perform replacements/detection; taken from tag content if not specified.
|
||||
* @param boolean $return
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($pattern, $replacement, $subject = NULL, $return = FALSE) {
|
||||
if (NULL === $subject) {
|
||||
$subject = $this->renderChildren();
|
||||
}
|
||||
if (TRUE === $return) {
|
||||
$returnValue = array();
|
||||
preg_match($pattern, $subject, $returnValue);
|
||||
} else {
|
||||
$returnValue = preg_replace($pattern, $replacement, $subject);
|
||||
}
|
||||
return $returnValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Removes XSS from $string
|
||||
*
|
||||
* Class RemoveXssViewHelper
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class RemoveXssViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Removes XSS from string
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function render($string = NULL) {
|
||||
if (NULL === $string) {
|
||||
$string = $this->renderChildren();
|
||||
}
|
||||
return GeneralUtility::removeXSS($string);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Replaces $substring in $content with $replacement.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class ReplaceViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $substring
|
||||
* @param string $content
|
||||
* @param string $replacement
|
||||
* @param integer $count
|
||||
* @param boolean $caseSensitve
|
||||
* @return string
|
||||
*/
|
||||
public function render($substring, $content = NULL, $replacement = '', $count = NULL, $caseSensitive = TRUE) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
$function = (TRUE === $caseSensitive ? 'str_replace' : 'str_ireplace');
|
||||
return str_replace($substring, $replacement, $content, $count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* URL text segment sanitizer. Sanitizes the content into a
|
||||
* valid URL segment value which is usable in an URL without
|
||||
* further processing. For example, the text "I am Mr. Brown,
|
||||
* how are you?" becomes "i-am-mr-brown-how-are-you". Special
|
||||
* characters like diacritics or umlauts are transliterated.
|
||||
* The built-in character map can be overriden or extended by
|
||||
* providing an associative array of custom mappings.
|
||||
*
|
||||
* Also useful when creating anchor link names, for example
|
||||
* for news entries in your custom EXT:news list template, in
|
||||
* which case each news item's title would become an anchor:
|
||||
*
|
||||
* <a name="{newsItem.title -> v:format.url.sanitizeString()}"></a>
|
||||
*
|
||||
* And links would look much like the detail view links:
|
||||
*
|
||||
* /news/#this-is-a-newsitem-title
|
||||
*
|
||||
* When used with list views it has the added benefit of not
|
||||
* breaking if the item referenced is removed, it can be read
|
||||
* by Javascript (for example to dynamically expand the news
|
||||
* item being referenced). The sanitized urls are also ideal
|
||||
* to use for AJAX based detail views - and in almot all cases
|
||||
* the sanitized string will be 100% identical to the one used
|
||||
* by Realurl when translating using table lookups.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class SanitizeStringViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Basic character map
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $characterMap = array(
|
||||
'¹' => 1, '²' => 2, '³' => 3, '°' => 0, '€' => 'eur', 'æ' => 'ae', 'ǽ' => 'ae', 'À' => 'A', 'Á' => 'A', 'Â' => 'A',
|
||||
'Ã' => 'A', 'Å' => 'AA', 'Ǻ' => 'A', 'Ă' => 'A', 'Ǎ' => 'A', 'Æ' => 'AE', 'Ǽ' => 'AE', 'à' => 'a', 'á' => 'a',
|
||||
'â' => 'a', 'ã' => 'a', 'å' => 'aa', 'ǻ' => 'a', 'ă' => 'a', 'ǎ' => 'a', 'ª' => 'a', '@' => 'at', 'Ĉ' => 'C',
|
||||
'Ċ' => 'C', 'ĉ' => 'c', 'ċ' => 'c', '©' => 'c', 'Ð' => 'Dj', 'Đ' => 'D', 'ð' => 'dj', 'đ' => 'd', 'È' => 'E',
|
||||
'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ĕ' => 'E', 'Ė' => 'E', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
|
||||
'ĕ' => 'e', 'ė' => 'e', 'ƒ' => 'f', 'Ĝ' => 'G', 'Ġ' => 'G', 'ĝ' => 'g', 'ġ' => 'g', 'Ĥ' => 'H', 'Ħ' => 'H',
|
||||
'ĥ' => 'h', 'ħ' => 'h', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ĩ' => 'I', 'Ĭ' => 'I', 'Ǐ' => 'I',
|
||||
'Į' => 'I', 'IJ' => 'IJ', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ĩ' => 'i', 'ĭ' => 'i', 'ǐ' => 'i',
|
||||
'į' => 'i', 'ij' => 'ij', 'Ĵ' => 'J', 'ĵ' => 'j', 'Ĺ' => 'L', 'Ľ' => 'L', 'Ŀ' => 'L', 'ĺ' => 'l', 'ľ' => 'l',
|
||||
'ŀ' => 'l', 'Ñ' => 'N', 'ñ' => 'n', 'ʼn' => 'n', 'Ò' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ō' => 'O', 'Ŏ' => 'O',
|
||||
'Ǒ' => 'O', 'Ő' => 'O', 'Ơ' => 'O', 'Ø' => 'OE', 'Ǿ' => 'O', 'Œ' => 'OE', 'ò' => 'o', 'ô' => 'o', 'õ' => 'o',
|
||||
'ō' => 'o', 'ŏ' => 'o', 'ǒ' => 'o', 'ő' => 'o', 'ơ' => 'o', 'ø' => 'oe', 'ǿ' => 'o', 'º' => 'o', 'œ' => 'oe',
|
||||
'Ŕ' => 'R', 'Ŗ' => 'R', 'ŕ' => 'r', 'ŗ' => 'r', 'Ŝ' => 'S', 'Ș' => 'S', 'ŝ' => 's', 'ș' => 's', 'ſ' => 's',
|
||||
'Ţ' => 'T', 'Ț' => 'T', 'Ŧ' => 'T', 'Þ' => 'TH', 'ţ' => 't', 'ț' => 't', 'ŧ' => 't', 'þ' => 'th', 'Ù' => 'U',
|
||||
'Ú' => 'U', 'Û' => 'U', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ű' => 'U', 'Ų' => 'U', 'Ư' => 'U', 'Ǔ' => 'U', 'Ǖ' => 'U',
|
||||
'Ǘ' => 'U', 'Ǚ' => 'U', 'Ǜ' => 'U', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ũ' => 'u', 'ŭ' => 'u', 'ű' => 'u',
|
||||
'ų' => 'u', 'ư' => 'u', 'ǔ' => 'u', 'ǖ' => 'u', 'ǘ' => 'u', 'ǚ' => 'u', 'ǜ' => 'u', 'Ŵ' => 'W', 'ŵ' => 'w',
|
||||
'Ý' => 'Y', 'Ÿ' => 'Y', 'Ŷ' => 'Y', 'ý' => 'y', 'ÿ' => 'y', 'ŷ' => 'y', 'Ъ' => '', 'Ь' => '', 'А' => 'A',
|
||||
'Б' => 'B', 'Ц' => 'C', 'Ч' => 'Ch', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'E', 'Э' => 'E', 'Ф' => 'F', 'Г' => 'G',
|
||||
'Х' => 'H', 'И' => 'I', 'Й' => 'J', 'Я' => 'Ja', 'Ю' => 'Ju', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N',
|
||||
'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Ш' => 'Sh', 'Щ' => 'Shch', 'Т' => 'T', 'У' => 'U', 'В' => 'V',
|
||||
'Ы' => 'Y', 'З' => 'Z', 'Ж' => 'Zh', 'ъ' => '', 'ь' => '', 'а' => 'a', 'б' => 'b', 'ц' => 'c', 'ч' => 'ch',
|
||||
'д' => 'd', 'е' => 'e', 'ё' => 'e', 'э' => 'e', 'ф' => 'f', 'г' => 'g', 'х' => 'h', 'и' => 'i', 'й' => 'j',
|
||||
'я' => 'ja', 'ю' => 'ju', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r',
|
||||
'с' => 's', 'ш' => 'sh', 'щ' => 'shch', 'т' => 't', 'у' => 'u', 'в' => 'v', 'ы' => 'y', 'з' => 'z', 'ж' => 'zh',
|
||||
'Ä' => 'AE', 'Ö' => 'OE', 'Ü' => 'UE', 'ß' => 'ss', 'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'Ç' => 'C', 'Ğ' => 'G',
|
||||
'İ' => 'I', 'Ş' => 'S', 'ç' => 'c', 'ğ' => 'g', 'ı' => 'i', 'ş' => 's', 'Ā' => 'A', 'Ē' => 'E', 'Ģ' => 'G',
|
||||
'Ī' => 'I', 'Ķ' => 'K', 'Ļ' => 'L', 'Ņ' => 'N', 'Ū' => 'U', 'ā' => 'a', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i',
|
||||
'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', 'ū' => 'u', 'Ґ' => 'G', 'І' => 'I', 'Ї' => 'Ji', 'Є' => 'Ye', 'ґ' => 'g',
|
||||
'і' => 'i', 'ї' => 'ji', 'є' => 'ye', 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S',
|
||||
'Ť' => 'T', 'Ů' => 'U', 'Ž' => 'Z', 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's',
|
||||
'ť' => 't', 'ů' => 'u', 'ž' => 'z', 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'E', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'O',
|
||||
'Ś' => 'S', 'Ź' => 'Z', 'Ż' => 'Z', 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o',
|
||||
'ś' => 's', 'ź' => 'z', 'ż' => 'z', 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z',
|
||||
'Η' => 'E', 'Θ' => 'Th', 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => 'X', 'Ο' => 'O',
|
||||
'Π' => 'P', 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'Ph', 'Χ' => 'Ch', 'Ψ' => 'Ps', 'Ω' => 'O',
|
||||
'Ϊ' => 'I', 'Ϋ' => 'Y', 'ά' => 'a', 'έ' => 'e', 'ή' => 'e', 'ί' => 'i', 'ΰ' => 'Y', 'α' => 'a', 'β' => 'b',
|
||||
'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'e', 'θ' => 'th', 'ι' => 'i', 'κ' => 'k', 'λ' => 'l',
|
||||
'μ' => 'm', 'ν' => 'n', 'ξ' => 'x', 'ο' => 'o', 'π' => 'p', 'ρ' => 'r', 'ς' => 's', 'σ' => 's', 'τ' => 't',
|
||||
'υ' => 'y', 'φ' => 'ph', 'χ' => 'ch', 'ψ' => 'ps', 'ω' => 'o', 'ϊ' => 'i', 'ϋ' => 'y', 'ό' => 'o', 'ύ' => 'y',
|
||||
'ώ' => 'o', 'ϐ' => 'b', 'ϑ' => 'th', 'ϒ' => 'Y', 'أ' => 'a', 'ب' => 'b', 'ت' => 't', 'ث' => 'th', 'ج' => 'g',
|
||||
'ح' => 'h', 'خ' => 'kh', 'د' => 'd', 'ذ' => 'th', 'ر' => 'r', 'ز' => 'z', 'س' => 's', 'ش' => 'sh', 'ص' => 's',
|
||||
'ض' => 'd', 'ط' => 't', 'ظ' => 'th', 'ع' => 'aa', 'غ' => 'gh', 'ف' => 'f', 'ق' => 'k', 'ك' => 'k', 'ل' => 'l',
|
||||
'م' => 'm', 'ن' => 'n', 'ه' => 'h', 'و' => 'o', 'ي' => 'y', 'ạ' => 'a', 'ả' => 'a', 'ầ' => 'a', 'ấ' => 'a',
|
||||
'ậ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ằ' => 'a', 'ắ' => 'a', 'ặ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ẹ' => 'e',
|
||||
'ẻ' => 'e', 'ẽ' => 'e', 'ề' => 'e', 'ế' => 'e', 'ệ' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ị' => 'i', 'ỉ' => 'i',
|
||||
'ọ' => 'o', 'ỏ' => 'o', 'ồ' => 'o', 'ố' => 'o', 'ộ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ờ' => 'o', 'ớ' => 'o',
|
||||
'ợ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ụ' => 'u', 'ủ' => 'u', 'ừ' => 'u', 'ứ' => 'u', 'ự' => 'u', 'ử' => 'u',
|
||||
'ữ' => 'u', 'ỳ' => 'y', 'ỵ' => 'y', 'ỷ' => 'y', 'ỹ' => 'y', 'Ạ' => 'A', 'Ả' => 'A', 'Ầ' => 'A', 'Ấ' => 'A',
|
||||
'Ậ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ằ' => 'A', 'Ắ' => 'A', 'Ặ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ẹ' => 'E',
|
||||
'Ẻ' => 'E', 'Ẽ' => 'E', 'Ề' => 'E', 'Ế' => 'E', 'Ệ' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ị' => 'I', 'Ỉ' => 'I',
|
||||
'Ọ' => 'O', 'Ỏ' => 'O', 'Ồ' => 'O', 'Ố' => 'O', 'Ộ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ờ' => 'O', 'Ớ' => 'O',
|
||||
'Ợ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ụ' => 'U', 'Ủ' => 'U', 'Ừ' => 'U', 'Ứ' => 'U', 'Ự' => 'U', 'Ử' => 'U',
|
||||
'Ữ' => 'U', 'Ỳ' => 'Y', 'Ỵ' => 'Y', 'Ỷ' => 'Y', 'Ỹ' => 'Y',
|
||||
);
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeArguments() {
|
||||
$this->registerArgument('string', 'string', 'The string to sanitize.', FALSE);
|
||||
$this->registerArgument('customMap', 'array', 'Associative array of additional characters to replace or use to override built-in mappings.', FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render() {
|
||||
$string = $this->arguments['string'];
|
||||
if (NULL === $string) {
|
||||
$string = $this->renderChildren();
|
||||
if (NULL === $string) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
$characterMap = $this->characterMap;
|
||||
$customMap = $this->arguments['customMap'];
|
||||
if (TRUE === is_array($customMap) && 0 < count($customMap)) {
|
||||
$characterMap = array_merge($characterMap, $customMap);
|
||||
}
|
||||
$specialCharsSearch = array_keys($characterMap);
|
||||
$specialCharsReplace = array_values($characterMap);
|
||||
$string = str_replace($specialCharsSearch, $specialCharsReplace, $string);
|
||||
$string = strtolower($string);
|
||||
$pattern = '/([^a-z0-9\-]){1,}/';
|
||||
$string = preg_replace($pattern, '-', $string);
|
||||
return trim($string, '-');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Gets a substring from a string or string-compatible value
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class SubstringViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Substrings a string or string-compatible value
|
||||
*
|
||||
* @param string $content Content string to substring
|
||||
* @param integer $start Positive or negative offset
|
||||
* @param integer $length Positive or negative length
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL, $start = 0, $length = NULL) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
if (NULL !== $length) {
|
||||
return substr($content, $start, $length);
|
||||
}
|
||||
return substr($content, $start);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Tidy-processes a string (HTML source), applying proper
|
||||
* indentation.
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class TidyViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $hasTidy = FALSE;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function initialize() {
|
||||
$this->hasTidy = class_exists('tidy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims content, then trims each line of content
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $encoding
|
||||
* @throws \RuntimeException
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL, $encoding = 'utf8') {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
if (TRUE === $this->hasTidy) {
|
||||
$tidy = tidy_parse_string($content, array(), $encoding);
|
||||
$tidy->cleanRepair();
|
||||
return (string) $tidy;
|
||||
}
|
||||
throw new \RuntimeException('TidyViewHelper requires the PHP extension "tidy" which is not installed or not loaded.', 1352059753);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Trims $content by stripping off $characters (string list
|
||||
* of individual chars to strip off, default is all whitespaces).
|
||||
*
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class TrimViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* Trims content by stripping off $characters
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $characters
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL, $characters = NULL) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
if (FALSE === empty($characters)) {
|
||||
$content = trim($content, $characters);
|
||||
} else {
|
||||
$content = trim($content);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Url;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Urldecodes the provided string
|
||||
*
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class DecodeViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
return rawurldecode($content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Url;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* Urlencodes the provided string
|
||||
*
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class EncodeViewHelper extends AbstractViewHelper {
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function render($content = NULL) {
|
||||
if (NULL === $content) {
|
||||
$content = $this->renderChildren();
|
||||
}
|
||||
return rawurlencode($content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format\Url;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use FluidTYPO3\Vhs\ViewHelpers\Format\SanitizeStringViewHelper as RelocatedSanitizeStringViewHelper;
|
||||
|
||||
/**
|
||||
* @author Claus Due <claus@namelesscoder.net>
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>, dreipunktnull
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format\Url
|
||||
* @deprecated Use FluidTYPO3\Vhs\ViewHelpers\Format\SanitizeStringViewHelper instead
|
||||
*/
|
||||
class SanitizeStringViewHelper extends RelocatedSanitizeStringViewHelper {
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace FluidTYPO3\Vhs\ViewHelpers\Format;
|
||||
|
||||
/*
|
||||
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.md file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
|
||||
/**
|
||||
* ### Wordwrap: Wrap a string at provided character count
|
||||
*
|
||||
* Wraps a string to $limit characters and at $break character
|
||||
* while maintaining complete words. Concatenates the resulting
|
||||
* strings with $glue. Code is heavily inspired
|
||||
* by Codeigniter's word_wrap helper.
|
||||
*
|
||||
* @author Björn Fromme <fromme@dreipunktnull.com>
|
||||
* @package Vhs
|
||||
* @subpackage ViewHelpers\Format
|
||||
*/
|
||||
class WordWrapViewHelper extends AbstractViewHelper {
|
||||
|
||||
public function initializeArguments() {
|
||||
$this->registerArgument('subject', 'string', 'Text to wrap', FALSE);
|
||||
$this->registerArgument('limit', 'integer', 'Maximum length of resulting parts after wrapping', FALSE, 80);
|
||||
$this->registerArgument('break', 'string', 'Character to wrap text at', FALSE, PHP_EOL);
|
||||
$this->registerArgument('glue', 'string', 'Character to concatenate parts with after wrapping', FALSE, PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render() {
|
||||
$subject = $this->arguments['subject'];
|
||||
if (TRUE === empty($subject)) {
|
||||
$subject = $this->renderChildren();
|
||||
}
|
||||
$limit = (integer) $this->arguments['limit'];
|
||||
$break = $this->arguments['break'];
|
||||
$glue = $this->arguments['glue'];
|
||||
$subject = preg_replace('/ +/', ' ', $subject);
|
||||
$subject = str_replace(array("\r\n", "\r"), PHP_EOL, $subject);
|
||||
$subject = wordwrap($subject, $limit, $break, FALSE);
|
||||
$output = '';
|
||||
foreach (explode($break, $subject) as $line) {
|
||||
if (mb_strlen($line) <= $limit) {
|
||||
$output .= $line . $glue;
|
||||
continue;
|
||||
}
|
||||
$temp = '';
|
||||
while (mb_strlen($line) > $limit) {
|
||||
$temp .= mb_substr($line, 0, $limit - 1);
|
||||
$line = mb_substr($line, $limit - 1);
|
||||
}
|
||||
if (FALSE === empty($temp)) {
|
||||
$output .= $temp . $glue . $line . $glue;
|
||||
} else {
|
||||
$output .= $line . $glue;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user