Skip to content
Snippets Groups Projects
Commit 7d8ae3e8 authored by Matthias Adrowski's avatar Matthias Adrowski
Browse files

[TASK] Fix BE Layout, Create QueryBuilderPaginator

parent 42311d5c
No related branches found
No related tags found
1 merge request!38Feature upgrade to typo3 11
......@@ -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());
}
......
<?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;
}
}
......@@ -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];
}
/**
......
<?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;
}
}
<?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();
}
}
{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>
{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>
......@@ -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>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment