diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index e46734bf394e354357acf8bc0889538105a3c2ea..641a9400ae184c060e995e7b8fb7aa1fe8fac611 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -26,6 +26,7 @@ namespace SGalinski\SgNews\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use SGalinski\SgNews\Paginator\QueryBuilderPaginator; use SGalinski\SgNews\Utility\BackendNewsUtility; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\Components\ButtonBar; @@ -34,6 +35,7 @@ use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Pagination\SimplePagination; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; @@ -156,7 +158,13 @@ class BackendController extends ActionController { $filters['categories'] = [$this->pageUid]; } $tags = BackendNewsUtility::getTagsForPage($this->pageUid, $this->language); - $news = BackendNewsUtility::getNewsByFilters($this->rootPageUid, $filters, $this->language); + [$news, $newsQueryBuilder] = BackendNewsUtility::getNewsByFilters($this->rootPageUid, $filters, $this->language); + + $paginator = new QueryBuilderPaginator($newsQueryBuilder); + $pagination = new SimplePagination($paginator); + + $this->view->assign('paginator', $paginator); + $this->view->assign('pagination', $pagination); $this->view->assign('tags', $tags); $this->view->assign('news', $news); @@ -169,8 +177,10 @@ class BackendController extends ActionController { $this->view->assign('showNewsList', $showNewsList); if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $this->view->assign('V11', false); return NULL; } else { + $this->view->assign('V11', true); return $this->createBackendResponse(); } } @@ -250,7 +260,8 @@ class BackendController extends ActionController { * @return \Psr\Http\Message\ResponseInterface */ protected function createBackendResponse(): \Psr\Http\Message\ResponseInterface { - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplateFactory = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\ModuleTemplateFactory::class); + $moduleTemplate = $moduleTemplateFactory->create($this->request); $moduleTemplate->setContent($this->view->render()); return $this->htmlResponse($moduleTemplate->renderContent()); } diff --git a/Classes/Paginator/QueryBuilderPaginator.php b/Classes/Paginator/QueryBuilderPaginator.php new file mode 100644 index 0000000000000000000000000000000000000000..4dd6f5009a77f2c95948c6be6bb3e65c99a05aa5 --- /dev/null +++ b/Classes/Paginator/QueryBuilderPaginator.php @@ -0,0 +1,96 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace SGalinski\SgNews\Paginator; + +use TYPO3\CMS\Core\Pagination\AbstractPaginator; +use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; + +/** + * Copied QueryResult Paginator for us to get a raw result returned, + * just like the old Controller used to use, also alot of BE ViewHelpers want an array + */ +final class QueryBuilderPaginator extends AbstractPaginator { + /** + * @var \TYPO3\CMS\Core\Database\Query\QueryBuilder + */ + private $queryBuilder; + + /** + * @var array + */ + private $paginatedQueryResult; + + /** + * @var int + */ + protected int $totalItems = 0; + + public function __construct( + \TYPO3\CMS\Core\Database\Query\QueryBuilder $queryBuilder, + int $currentPageNumber = 1, + int $itemsPerPage = 10 + ) { + $this->queryBuilder = $queryBuilder; + $this->setCurrentPageNumber($currentPageNumber); + $this->setItemsPerPage($itemsPerPage); + + $this->updateInternalState(); + } + + /** + * @return iterable|QueryResultInterface + */ + public function getPaginatedItems(): iterable { + return $this->paginatedQueryResult; + } + + protected function updatePaginatedItems(int $limit, int $offset): void { + $this->paginatedQueryResult = $this->queryBuilder + ->setMaxResults($limit) + ->setFirstResult($offset) + ->execute()->fetchAllAssociative(); + } + + protected function getTotalAmountOfItems(): int { + $totalItems = $this->queryBuilder + ->setMaxResults(99999) + ->setFirstResult(0) + ->count('uid') + ->execute()->fetchOne(); + $this->setTotalItems($totalItems); + return $totalItems; + } + + protected function getAmountOfItemsOnCurrentPage(): int { + return count($this->paginatedQueryResult); + } + + /** + * @return int + */ + public function getTotalItems(): int { + return $this->totalItems; + } + + /** + * @param int $totalItems + */ + public function setTotalItems(int $totalItems): void { + $this->totalItems = $totalItems; + } +} diff --git a/Classes/Utility/BackendNewsUtility.php b/Classes/Utility/BackendNewsUtility.php index 753c7d747fcabc32bcdb51a1ea5293aedc787d85..b8498f665fd4828813cfd6216ecc00006926886a 100644 --- a/Classes/Utility/BackendNewsUtility.php +++ b/Classes/Utility/BackendNewsUtility.php @@ -307,7 +307,7 @@ class BackendNewsUtility { * @return array * @throws \InvalidArgumentException */ - public static function getNewsByFilters($rootPageUid = 0, array $filters = [], $languageUid = 0): array { + public static function getNewsByFilters($rootPageUid = 0, array $filters = [], $languageUid = 0, $limit = 0): array { $out = []; $rootPageUid = (int) $rootPageUid; $languageUid = (int) $languageUid; @@ -441,8 +441,11 @@ class BackendNewsUtility { ) ); } + if($limit > 0){ + $queryBuilder->setMaxResults($limit); + } - return $queryBuilder->execute()->fetchAll(); + return [$queryBuilder->execute()->fetchAllAssociative(), $queryBuilder]; } /** diff --git a/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php b/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php deleted file mode 100644 index 295a81bac8d7df7576eb07e310481fadbb79d0e7..0000000000000000000000000000000000000000 --- a/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace SGalinski\SgNews\ViewHelpers\Backend\Widget\Controller; - -/*************************************************************** - * Copyright notice - * - * (c) sgalinski Internet Services (https://www.sgalinski.de) - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - ***************************************************************/ - -use TYPO3\CMS\Extbase\Persistence\Generic\Query; -use TYPO3\CMS\Fluid\ViewHelpers\Be\Widget\Controller\PaginateController as FluidPaginateController; - -/** - * Class PaginateController - */ -class PaginateController extends FluidPaginateController { - /** - * @var mixed - */ - protected $objects; - - /** - * Renders the paginator - * - * @param int $currentPage - * @return void - * @throws \InvalidArgumentException - */ - public function indexAction($currentPage = 1) { - // set current page - $this->currentPage = (int) $currentPage; - if ($this->currentPage < 1) { - $this->currentPage = 1; - } - if ($this->currentPage > $this->numberOfPages) { - // set $modifiedObjects to NULL if the page does not exist - $modifiedObjects = NULL; - } else { - // modify query - $this->itemsPerPage = (int) $this->configuration['itemsPerPage']; - $this->offset = $this->itemsPerPage * ($this->currentPage - 1); - if (is_array($this->objects)) { - $modifiedObjects = []; - for ($index = $this->offset; $index < $this->offset + $this->itemsPerPage; $index++) { - if (isset($this->objects[$index])) { - $modifiedObjects[] = $this->objects[$index]; - } else { - break; - } - } - } else { - /** @var Query $query */ - $query = $this->objects->getQuery(); - $query->setLimit($this->itemsPerPage); - if ($this->currentPage > 1) { - $query->setOffset($this->offset); - } - $modifiedObjects = $query->execute(); - } - } - $this->view->assign( - 'contentArguments', - [ - $this->widgetConfiguration['as'] => $modifiedObjects - ] - ); - $this->view->assign('configuration', $this->configuration); - $this->view->assign('pagination', $this->buildPagination()); - } - - /** - * Returns an array with the keys "pages", "current", "numberOfPages", - * "nextPage" & "previousPage" - * - * @return array - */ - protected function buildPagination(): array { - $pagination = parent::buildPagination(); - $pagination['totalObjects'] = is_countable($this->objects) ? count($this->objects) : 0; - return $pagination; - } -} diff --git a/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php b/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php deleted file mode 100644 index 644806b9d8baa9ed11e7c0288846750fd119d2c6..0000000000000000000000000000000000000000 --- a/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -namespace SGalinski\SgNews\ViewHelpers\Backend\Widget; - -/*************************************************************** - * Copyright notice - * - * (c) sgalinski Internet Services (https://www.sgalinski.de) - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - ***************************************************************/ -use SGalinski\SgNews\ViewHelpers\Backend\Widget\Controller\PaginateController; -use TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetViewHelper; - -/** - * Class PaginateViewHelper - */ -class PaginateViewHelper extends AbstractWidgetViewHelper { - /** - * @var PaginateController - */ - protected $controller; - - /** - * Initializes the controller - * - * @param PaginateController $controller - */ - public function injectPaginateController(PaginateController $controller) { - $this->controller = $controller; - } - - /** - * Initialize the ViewHelper arguments - */ - public function initializeArguments() { - parent::initializeArguments(); - $this->registerArgument('objects', 'mixed', 'The objects to paginate', TRUE); - $this->registerArgument('as', 'string', 'The name of the variable inside the pagination', TRUE); - $this->registerArgument( - 'configuration', - 'array', - 'The configuration of the pagination', - FALSE, - [ - 'itemsPerPage' => 10, - 'insertAbove' => FALSE, - 'insertBelow' => TRUE, - 'recordsLabel' => '' - ] - ); - } - - /** - * Renders the paginator - * - * @return string - * @throws \TYPO3\CMS\Fluid\Core\Widget\Exception\MissingControllerException - */ - public function render(): string { - return $this->initiateSubRequest(); - } -} diff --git a/Resources/Private/Layouts/Backend.html b/Resources/Private/Layouts/Backend.html index 11777dd28bf8a4a54fe506d87525c293a6f8f951..7fedf9d12f6d712ba8859825c746e0dd29185b2a 100644 --- a/Resources/Private/Layouts/Backend.html +++ b/Resources/Private/Layouts/Backend.html @@ -1,52 +1,67 @@ {namespace core = TYPO3\CMS\Core\ViewHelpers} {namespace sg=SGalinski\SgNews\ViewHelpers} -<f:be.container - includeRequireJsModules="{ - 0: 'TYPO3/CMS/Backend/ContextMenu', - 1: 'TYPO3/CMS/Backend/Tooltip', - 2: 'TYPO3/CMS/SgNews/Backend'}"> - <div class="module" data-module-id="" data-module-name=""> - <div class="module-docheader t3js-module-docheader"> - <div class="module-docheader-bar module-docheader-bar-navigation t3js-module-docheader-bar t3js-module-docheader-bar-navigation"> - <div class="module-docheader-bar-column-left"> - <f:for each="{docHeader.menus}" as="menu"> - <f:be.menus.actionMenu additionalAttributes="{name: menu.identifier}"> - <f:for each="{menu.menuItems}" as="menuItem"> - <option value="{menuItem.href}" {f:if(condition: '{menuItem.active}', then: 'selected="selected"')}>{menuItem.title}</option> +<f:if condition="{V11}"> + <f:then> + <f:be.pageRenderer includeRequireJsModules="{ + 0: 'TYPO3/CMS/Backend/ContextMenu', + 1: 'TYPO3/CMS/Backend/Tooltip', + 2: 'TYPO3/CMS/SgNews/Backend'}" + /> + <h1> + <f:render section="headline" /> + </h1> + <f:render section="content" /> + </f:then> + <f:else> + <f:be.container + includeRequireJsModules="{ + 0: 'TYPO3/CMS/Backend/ContextMenu', + 1: 'TYPO3/CMS/Backend/Tooltip', + 2: 'TYPO3/CMS/SgNews/Backend'}"> + <div class="module" data-module-id="" data-module-name=""> + <div class="module-docheader t3js-module-docheader"> + <div class="module-docheader-bar module-docheader-bar-navigation t3js-module-docheader-bar t3js-module-docheader-bar-navigation"> + <div class="module-docheader-bar-column-left"> + <f:for each="{docHeader.menus}" as="menu"> + <f:be.menus.actionMenu additionalAttributes="{name: menu.identifier}"> + <f:for each="{menu.menuItems}" as="menuItem"> + <option value="{menuItem.href}" {f:if(condition: '{menuItem.active}', then: 'selected="selected"')}>{menuItem.title}</option> + </f:for> + </f:be.menus.actionMenu> </f:for> - </f:be.menus.actionMenu> - </f:for> - </div> - <div class="module-docheader-bar-column-right"> - <span class="typo3-docheader-pagePath"> - <f:if condition="{typo3Version} < 9000000"> - <f:then> - <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> - </f:then> - <f:else> - <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> - </f:else> - </f:if> - </span> - <f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw> + </div> + <div class="module-docheader-bar-column-right"> + <span class="typo3-docheader-pagePath"> + <f:if condition="{typo3Version} < 9000000"> + <f:then> + <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> + </f:then> + <f:else> + <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> + </f:else> + </f:if> + </span> + <f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw> + </div> + </div> + <div class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons"> + <div class="module-docheader-bar-column-left"> + </div> + <div class="module-docheader-bar-column-right"> + <f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}" /> + </div> + </div> </div> </div> - <div class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons"> - <div class="module-docheader-bar-column-left"> - </div> - <div class="module-docheader-bar-column-right"> - <f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}" /> + <div id="typo3-docbody"> + <div id="typo3-inner-docbody"> + <h1> + <f:render section="headline" /> + </h1> + <f:render section="content" /> </div> </div> - </div> - </div> - <div id="typo3-docbody"> - <div id="typo3-inner-docbody"> - <h1> - <f:render section="headline" /> - </h1> - <f:render section="content" /> - </div> - </div> -</f:be.container> + </f:be.container> + </f:else> +</f:if> diff --git a/Resources/Private/Partials/Backend/Pagination.html b/Resources/Private/Partials/Backend/Pagination.html new file mode 100644 index 0000000000000000000000000000000000000000..d73e7f577fdba2c1c5a66246695ba2eeac72c828 --- /dev/null +++ b/Resources/Private/Partials/Backend/Pagination.html @@ -0,0 +1,103 @@ +{namespace core=TYPO3\CMS\Core\ViewHelpers} +{namespace sg=SGalinski\SgMail\ViewHelpers} + +<nav class="pagination-wrap"> + <ul class="pagination pagination-block"> + <f:if condition="{pagination.previousPageNumber} && {pagination.previousPageNumber} >= {pagination.firstPageNumber}"> + <f:then> + <li> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: 1})}" title="{f:translate(key:'widget.pagination.first')}"> + <core:icon identifier="actions-view-paging-first" /> + </a> + </li> + <li> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: pagination.previousPageNumber})}" title="{f:translate(key:'widget.pagination.previous')}"> + <core:icon identifier="actions-view-paging-previous" /> + </a> + </li> + </f:then> + <f:else> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-first" /> + </span> + </li> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-previous" /> + </span> + </li> + </f:else> + </f:if> + <li> + <span> + <f:if condition="{recordsLabel}"> + <f:then> + {recordsLabel} + </f:then> + <f:else> + <f:translate key="widget.pagination.records" /> + </f:else> + </f:if> + {pagination.startRecordNumber} - {pagination.endRecordNumber} / {paginator.totalItems} + </span> + </li> + <li> + <span> + <f:translate key="widget.pagination.page" /> + <form id="paginator-form-{position}" onsubmit="goToPage{position}(this); return false;" style="display:inline;"> + <script type="text/javascript"> + function goToPage{position}(formObject) { + var page = formObject.elements['paginator-target-page'].value; + var url = '{f:uri.action(action:actionName, arguments:{currentPage: 987654321}) -> f:format.raw()}'; + + if (page > {pagination.lastPageNumber}) { + page = {pagination.lastPageNumber}; + } + else + if (page < 1) { + page = 1; + } + url = url.replace('987654321', page); + self.location.href = url; + } + </script> + <f:form.textfield id="paginator-{position}" name="paginator-target-page" additionalAttributes="{min: '1'}" class="form-control input-sm paginator-input" size="5" value="{currentPage}" type="number" /> + </form> + + / {pagination.lastPageNumber} + </span> + </li> + <f:if condition="{pagination.nextPageNumber} && {pagination.nextPageNumber} <= {pagination.lastPageNumber}"> + <f:then> + <li> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: pagination.nextPageNumber})}" title="{f:translate(key:'widget.pagination.next')}"> + <core:icon identifier="actions-view-paging-next" /> + </a> + </li> + <li> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: pagination.lastPageNumber})}" title="{f:translate(key:'widget.pagination.last')}"> + <core:icon identifier="actions-view-paging-last" /> + </a> + </li> + </f:then> + <f:else> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-next" /> + </span> + </li> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-last" /> + </span> + </li> + </f:else> + </f:if> + <li> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: currentPage})}" title="{f:translate(key:'widget.pagination.refresh')}"> + <core:icon identifier="actions-refresh" /> + </a> + </li> + </ul> +</nav> diff --git a/Resources/Private/Templates/Backend/Index.html b/Resources/Private/Templates/Backend/Index.html index 164b931cd4f72f930dde5780cecb47611254e9f0..e511a05940a4939154947b45746d86df1e3f19af 100644 --- a/Resources/Private/Templates/Backend/Index.html +++ b/Resources/Private/Templates/Backend/Index.html @@ -45,55 +45,54 @@ <div class="panel panel-default recordlist"> <div class="table-fit"> <table data-table="pages" class="table table-striped table-hover"> - <sg:backend.widget.paginate objects="{news}" as="paginatedNews" configuration="{insertAbove: 1, itemsPerPage: 20}"> - <tbody> - <f:for each="{paginatedNews}" as="singleNews"> - <tr data-uid="{singleNews.uid}"> - <td nowrap="nowrap" class="col-icon"> - <f:format.raw> - <sg:backend.recordIcon table="pages" row="{singleNews}" /> - </f:format.raw> - </td> - <td nowrap="nowrap"> - <f:alias map="{newsItemTags: '{sg:backend.newsItemTags(uid: singleNews.uid, languageUid: language)}'}"> - <f:if condition="{singleNews.translation_uid}"> - <f:then> - <be:link.editRecord uid="{singleNews.translation_uid}" table="pages"> - <span> - <f:if condition="{singleNews.translation_title}"> - <f:then> - {singleNews.translation_title} - </f:then> - <f:else> - {singleNews.title} - </f:else> - </f:if> - <f:if condition="{newsItemTags}">({newsItemTags})</f:if> - </span> - </be:link.editRecord> - </f:then> - <f:else> - <be:link.editRecord uid="{singleNews.uid}" table="pages"> - <span> - {singleNews.title} - <f:if condition="{newsItemTags}">({newsItemTags})</f:if> - </span> - </be:link.editRecord> - </f:else> - </f:if> - </f:alias> - <br /> - <sg:backend.translationLinks pageUid="{pageUid}" table="pages" uid="{singleNews.uid}" /> - </td> - <td nowrap="nowrap" class="col-control"> - <f:format.raw> - <sg:backend.control table="pages" row="{singleNews}" /> - </f:format.raw> - </td> - </tr> - </f:for> - </tbody> - </sg:backend.widget.paginate> + <f:render partial="Backend/Pagination" arguments="{pagination: pagination, paginator: paginator, actionName: 'index', currentPage: currentPage}"/> + <tbody> + <f:for each="{paginator.paginatedItems}" as="singleNews"> + <tr data-uid="{singleNews.uid}"> + <td nowrap="nowrap" class="col-icon"> + <f:format.raw> + <sg:backend.recordIcon table="pages" row="{singleNews}" /> + </f:format.raw> + </td> + <td nowrap="nowrap"> + <f:alias map="{newsItemTags: '{sg:backend.newsItemTags(uid: singleNews.uid, languageUid: language)}'}"> + <f:if condition="{singleNews.translation_uid}"> + <f:then> + <be:link.editRecord uid="{singleNews.translation_uid}" table="pages"> + <span> + <f:if condition="{singleNews.translation_title}"> + <f:then> + {singleNews.translation_title} + </f:then> + <f:else> + {singleNews.title} + </f:else> + </f:if> + <f:if condition="{newsItemTags}">({newsItemTags})</f:if> + </span> + </be:link.editRecord> + </f:then> + <f:else> + <be:link.editRecord uid="{singleNews.uid}" table="pages"> + <span> + {singleNews.title} + <f:if condition="{newsItemTags}">({newsItemTags})</f:if> + </span> + </be:link.editRecord> + </f:else> + </f:if> + </f:alias> + <br /> + <sg:backend.translationLinks pageUid="{pageUid}" table="pages" uid="{singleNews.uid}" /> + </td> + <td nowrap="nowrap" class="col-control"> + <f:format.raw> + <sg:backend.control table="pages" row="{singleNews}" /> + </f:format.raw> + </td> + </tr> + </f:for> + </tbody> </table> </div> </div>