*
* {bodytext}
*
*
*
*
Seite
*
*
*
*
* -
* {page.number}
*
*
*
* -
*
*
*
* {page.number}
*
*
*
*
* {page.number}
*
*
*
*
*
*
*
*
*
*
*
*/
class PaginateBodytextViewHelper extends AbstractViewHelper
{
/**
* @var bool
*/
protected $escapeOutput = false;
/**
* Initialize arguments
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('object', News::class, 'news item', true);
$this->registerArgument('as', 'string', 'as', true);
$this->registerArgument('currentPage', 'int', 'current page', true);
$this->registerArgument('token', 'string', 'token', '###more###');
}
/**
* Render everything
*
* @return string
*/
public function render(): string
{
$as = $this->arguments['as'];
$currentPage = $this->arguments['currentPage'];
$parts = GeneralUtility::trimExplode($this->arguments['token'], $this->arguments['object']->getBodytext(), true);
$numberOfPages = count($parts);
if ($numberOfPages === 1) {
$result = $parts[0];
} else {
$currentPage = (int)$currentPage;
if ($currentPage < 1) {
$currentPage = 1;
} elseif ($currentPage > $numberOfPages) {
$currentPage = $numberOfPages;
}
$tagsToOpen = [];
$tagsToClose = [];
for ($j = 0; $j < $currentPage; $j++) {
$chunk = $parts[$j];
while (($chunk = mb_strstr($chunk, '<'))) {
$tag = $this->extractTag($chunk);
$tagStrLen = mb_strlen($tag);
if ($this->isOpeningTag($tag)) {
if ($j < $currentPage - 1) {
$tagsToOpen[] = $tag;
}
$tagsToClose[] = $tag;
} elseif ($this->isClosingTag($tag)) {
if ($j < $currentPage - 1) {
array_pop($tagsToOpen);
} elseif (mb_strpos($parts[$j], $chunk) === 0) {
$parts[$j] = mb_substr($parts[$j], $tagStrLen);
array_pop($tagsToOpen);
}
array_pop($tagsToClose);
}
$chunk = mb_substr($chunk, $tagStrLen);
}
}
$result = implode('', $tagsToOpen) . $parts[$currentPage - 1];
while ($tag = array_pop($tagsToClose)) {
$result .= $this->getClosingTagByOpeningTag($tag);
}
}
$pages = [];
for ($i = 1; $i <= $numberOfPages; $i++) {
$pages[] = ['number' => $i, 'isCurrent' => ($i === $currentPage)];
}
$pagination = [
'pages' => $pages,
'numberOfPages' => $numberOfPages,
'current' => $currentPage
];
if ($currentPage < $numberOfPages) {
$pagination['nextPage'] = $currentPage + 1;
}
if ($currentPage > 1) {
$pagination['previousPage'] = $currentPage - 1;
}
$this->templateVariableContainer->add($as, $result);
$this->templateVariableContainer->add('pagination', $pagination);
return $this->renderChildren();
}
/**
* Extracts the first html tag for a given html string
*
* @param string $html
* @return string
*/
protected function extractTag($html): string
{
$tag = '';
$length = mb_strlen($html);
for ($i = 0; $i < $length; $i++) {
$char = mb_substr($html, $i, 1);
$tag .= $char;
if ($char === '>') {
break;
}
}
return $tag;
}
/**
* Checks whether a given tag is self closing
*
* @param string $tag
* @return bool
*/
protected function isSelfClosingTag($tag): bool
{
return mb_substr($tag, -2) === '/>';
}
/**
* Checks whether a given tag is closing tag
*
* @param string $tag
* @return bool
*/
protected function isClosingTag($tag): bool
{
return mb_substr($tag, 0, 2) === '';
}
/**
* Checks whether a given Tag is a an opening tag
*
* @param string $tag
* @return bool
*/
protected function isOpeningTag($tag): bool
{
return !($this->isSelfClosingTag($tag) || $this->isClosingTag($tag));
}
/**
* Gets a closing tag from a given opening tag
*
* @param string $openingTag
* @return string
*/
protected function getClosingTagByOpeningTag($openingTag): string
{
if (!$tag = mb_strstr(mb_substr($openingTag, 1), ' ', true)) {
$tag = mb_strstr(mb_substr($openingTag, 1), '>', true);
}
return '' . $tag . '>';
}
}