Initial commit

This commit is contained in:
2018-04-02 08:07:38 +02:00
commit 7330c1ed3e
2054 changed files with 405203 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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, '-');
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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 {
}

View File

@@ -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;
}
}