Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TYPO3 v12 Support #6

Draft
wants to merge 58 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
68d4d94
feat: add v12 compatibility
maikschneider Oct 8, 2024
96c0fdd
feat: make icon optional
maikschneider Oct 8, 2024
ab84297
feat: add inline edit element
maikschneider Oct 9, 2024
a82d8e5
feat: add delete file partial
maikschneider Oct 9, 2024
63356ea
feat: add boolean partial
maikschneider Oct 9, 2024
4d2b205
feat: adjust DateTime partial for new date picker
maikschneider Oct 9, 2024
f1290e1
feat: add Category partial with Middleware to workaround category def…
maikschneider Oct 10, 2024
0963ad3
fix: search label, move search field into section
maikschneider Oct 10, 2024
59ec8b1
feat: refactor controller, extract methods
maikschneider Oct 12, 2024
f7b1cd1
feat: refactor module template methods
maikschneider Oct 12, 2024
4c6a650
fix: DateTime input markup
maikschneider Oct 13, 2024
292234b
feat: move additional database constraints to class member
maikschneider Oct 13, 2024
ed7cf99
feat: refactor controller, extract methods
maikschneider Oct 14, 2024
51eca5d
feat: add ajax endpoint for download setting modal
maikschneider Oct 19, 2024
926747f
feat: add download settings partial, csv download
maikschneider Oct 24, 2024
d273608
fix: check if configured table has translation
maikschneider Nov 15, 2024
f509d27
fix: phpfixer
maikschneider Nov 15, 2024
7060c47
fix: page record access in AbstractBackendController
pipaltree Dec 9, 2024
b8fd824
Merge pull request #2 from xima-media/fix-pid-selection-menu
maikschneider Dec 9, 2024
c3fa272
fix: initialize view before updating module data
pipaltree Dec 12, 2024
945fea2
fix: ensure getting current pid
pipaltree Dec 12, 2024
a2b8ab7
fix: remove workspace related variables from view
pipaltree Dec 13, 2024
8b09f36
fix: revert order of method calls for view initializing
pipaltree Dec 13, 2024
5dc4bc1
Merge pull request #3 from xima-media/fix-search-filter
maikschneider Dec 13, 2024
dc0541b
fix: language order of backend records, missing translation buttons
maikschneider Dec 25, 2024
8a8d691
feat: add deepl translate button partial, add to group actions
maikschneider Dec 26, 2024
3d6a60d
feat: migrate link events for table ordering into separate class
maikschneider Dec 26, 2024
9af8f10
feat: migrate search toggle, add reusable user settings class
maikschneider Dec 26, 2024
3c22a71
feat: migrate pagination
maikschneider Dec 26, 2024
b5c06e0
feat: migrate delete action button
maikschneider Dec 26, 2024
7d84307
Merge pull request #4 from xima-media/language-order
maikschneider Dec 26, 2024
9b76f28
Merge pull request #5 from xima-media/deepl-button
maikschneider Dec 26, 2024
a12fdbc
Merge commit '9b76f28f6a867090dfe9aed28734094e2201f16d' into es6
maikschneider Dec 26, 2024
967bb99
feat: add loading animations inside translate buttons when clicked
maikschneider Dec 26, 2024
a515eaf
feat: migrate button for new record selection modal
maikschneider Dec 26, 2024
13706af
feat: remove old typescript sources + unused code
maikschneider Dec 26, 2024
43c17ef
feat: add duplicate button
pipaltree Jan 3, 2025
65fd9ef
Merge pull request #8 from xima-media/es6
maikschneider Jan 3, 2025
4c04388
Merge branch 'v12' into feat-duplicate-button
pipaltree Jan 3, 2025
e9a0275
fix: replace deprecated BackendUtility::getLinkToDataHandlerAction() …
pipaltree Jan 3, 2025
a4a6115
feat: directly show edit view of duplicated record
pipaltree Jan 3, 2025
658018b
fix: move check for rendering duplicate button into template
pipaltree Jan 7, 2025
ba77342
Merge pull request #7 from xima-media/feat-duplicate-button
maikschneider Jan 7, 2025
e8f360a
feat: add workspace-ready-to-publish action js (wip)
maikschneider Jan 18, 2025
d486ace
feat: move css include from TextInlineEdit partial to layout
maikschneider Jan 18, 2025
38e0e62
feat: set typo3/cms-core dependency to v12
maikschneider Jan 18, 2025
39fca5d
feat: ready-to-publish v12 compatibility
maikschneider Jan 18, 2025
eaf82ef
feat: ngpreogress table style
maikschneider Jan 18, 2025
1cbc46b
feat: remove not needed markup in review window
maikschneider Jan 18, 2025
8f07988
feat: add js for publishing records
maikschneider Jan 18, 2025
349b938
feat: add js for revert workspace version
maikschneider Jan 18, 2025
b741d6d
feat: remove old workspace.ts
maikschneider Jan 18, 2025
5a9eb30
feat: add info modal with changelog view
maikschneider Feb 5, 2025
8af09a9
fix: remove ForceWorkspace middleware
maikschneider Feb 11, 2025
bfc172a
feat: remove record history xclass
maikschneider Feb 11, 2025
64541ed
feat: remove not needed buttons from changelog modal
maikschneider Feb 11, 2025
2532497
Merge pull request #9 from xima-media/es6-workspace
maikschneider Feb 11, 2025
f98b9bd
fix: remove expensive left join, split pagination to execute translat…
maikschneider Feb 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,047 changes: 688 additions & 359 deletions Classes/Controller/AbstractBackendController.php

Large diffs are not rendered by default.

142 changes: 139 additions & 3 deletions Classes/Controller/AjaxController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,45 @@

namespace Xima\XimaTypo3Recordlist\Controller;

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\Exception;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendViewFactory;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class AjaxController
{
protected const DOWNLOAD_FORMATS = [
'csv' => [
'options' => [
'delimiter' => [
'comma' => ',',
'semicolon' => ';',
'pipe' => '|',
],
'quote' => [
'doublequote' => '"',
'singlequote' => '\'',
'space' => ' ',
],
],
'defaults' => [
'delimiter' => ',',
'quote' => '"',
],
],
];

public function __construct(
private readonly ResponseFactoryInterface $responseFactory
private readonly ResponseFactoryInterface $responseFactory,
private readonly ResourceFactory $resourceFactory,
protected BackendViewFactory $backendViewFactory,
) {
}

Expand Down Expand Up @@ -51,7 +75,6 @@ protected function updateUserSettings(array $postBody): void

/**
* @throws Exception
* @throws DBALException
*/
public function deleteRecord(ServerRequestInterface $request): ResponseInterface
{
Expand Down Expand Up @@ -93,4 +116,117 @@ public function deleteRecord(ServerRequestInterface $request): ResponseInterface

return $this->responseFactory->createResponse();
}

/**
* @throws Exception|\Doctrine\DBAL\Exception
*/
public function deleteFile(ServerRequestInterface $request): ResponseInterface
{
$body = $request->getParsedBody();
$sysFileMetaDataUid = $body['uid'] ?? '';

if (!$sysFileMetaDataUid) {
return $this->responseFactory->createResponse(501, 'No sys_file_metadata UID provided');
}

$qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_metadata');
$sysFileUid = $qb->select('file')
->from('sys_file_metadata')
->where($qb->expr()->eq('uid', $qb->createNamedParameter($sysFileMetaDataUid, \PDO::PARAM_INT)))
->executeQuery()
->fetchOne();

if (!$sysFileUid) {
// FAL record not found, try to delete sys_file_metadata record
if ($GLOBALS['BE_USER']->check('tables_modify', 'sys_file_metadata')) {
$cmd['sys_file_metadata'][$sysFileMetaDataUid]['delete'] = 1;
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);
$dataHandler->start([], $cmd);
$dataHandler->process_cmdmap();

return $this->responseFactory->createResponse();
}
return $this->responseFactory->createResponse(501, 'File not found');
}

$isAllowedToDelete = false;
try {
$file = $this->resourceFactory->getFileObject($sysFileUid);
$storage = $file->getStorage();
$isAllowedToDelete = $storage?->checkFileActionPermission('delete', $file) ?? false;
} catch (\Exception) {
}

if (!$isAllowedToDelete) {
return $this->responseFactory->createResponse(403, 'No permissions to delete file');
}

try {
$storage?->deleteFile($file);
} catch (\Exception) {
return $this->responseFactory->createResponse(501, 'Error while deleting file');
}

return $this->responseFactory->createResponse();
}

public function editRecord(ServerRequestInterface $request): ResponseInterface
{
$body = $request->getParsedBody();
$table = $body['table'] ?? '';
$uid = $body['uid'] ?? '';
$column = $body['column'] ?? '';
$newValue = $body['newValue'] ?? '';

// access check #1
if (!$GLOBALS['BE_USER']->check('tables_modify', $table)) {
return $this->responseFactory->createResponse(403, 'No permissions to edit record');
}

// access check #2
$record = BackendUtility::getRecord($table, $uid);
if (!$record) {
return $this->responseFactory->createResponse(501, 'Record not found');
}
if ($record['pid'] !== 0) {
$access = BackendUtility::readPageAccess(
$record['pid'],
$GLOBALS['BE_USER']->getPagePermsClause(Permission::CONTENT_EDIT)
) ?: [];
if (empty($access)) {
return $this->responseFactory->createResponse(403, 'No permissions to edit record');
}
}

$data = [];
$data[$table][$uid] = [
$column => $newValue,
];

/** @var DataHandler $dataHandler */
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);
$dataHandler->start($data, []);
$dataHandler->process_datamap();

return $this->responseFactory->createResponse(200);
}

public function downloadSettings(ServerRequestInterface $request): ResponseInterface
{
$downloadArguments = $request->getQueryParams();

$view = $this->backendViewFactory->create($request);
$view->assignMultiple([
'table' => 'fwef',
'downloadArguments' => $downloadArguments,
'formats' => array_keys(self::DOWNLOAD_FORMATS),
'formatOptions' => self::DOWNLOAD_FORMATS,
]);

$response = $this->responseFactory->createResponse()
->withHeader('Content-Type', 'text/html; charset=utf-8');

$response->getBody()->write($view->render('RecordDownloadSettings'));
return $response;
}
}
54 changes: 54 additions & 0 deletions Classes/Middleware/CategoryTreeManipulation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Xima\XimaTypo3Recordlist\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Backend\Routing\Route;
use TYPO3\CMS\Core\Http\JsonResponse;

class CategoryTreeManipulation implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
/**
* Make sure it is the ajax request for fetching tree data
*
* @var Route $route
* @phpstan-ignore-next-line
*/
$route = $request->getAttribute('route');
if ($route->getOption('_identifier') !== 'ajax_record_tree_data') {
return $handler->handle($request);
}

$params = $request->getQueryParams();
$overrideValues = json_decode($params['overrideValues'] ?? '[]', true, 512, JSON_THROW_ON_ERROR);
$command = $params['command'] ?? '';
$fieldName = $params['fieldName'] ?? '';
$uid = $params['uid'] ?? '';

// make sure it is the right request
if (empty($overrideValues) || $command !== 'new' || $fieldName !== 'categories' || $uid !== '1') {
return $handler->handle($request);
}

try {
// manually check the selected categories from overrideValues
$response = $handler->handle($request);
$treeData = json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
foreach ($treeData as &$teeItem) {
if (!in_array((int)$teeItem['identifier'], $overrideValues, true)) {
continue;
}
$teeItem['checked'] = true;
}
return new JsonResponse($treeData);
} catch (\Exception) {
}

return $handler->handle($request);
}
}
62 changes: 0 additions & 62 deletions Classes/Middleware/ForceWorkspace.php

This file was deleted.

55 changes: 55 additions & 0 deletions Classes/Pagination/EditableArrayPaginator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Xima\XimaTypo3Recordlist\Pagination;

use TYPO3\CMS\Core\Pagination\AbstractPaginator;

class EditableArrayPaginator extends AbstractPaginator
{
private $items;

/**
* @var array
*/
private $paginatedItems = [];

public function __construct(
array $items,
int $currentPageNumber = 1,
int $itemsPerPage = 10
) {
$this->items = $items;
$this->setCurrentPageNumber($currentPageNumber);
$this->setItemsPerPage($itemsPerPage);

$this->updateInternalState();
}

/**
* @return iterable|array
*/
public function getPaginatedItems(): iterable
{
return $this->paginatedItems;
}

public function setPaginatedItems($items)
{
$this->paginatedItems = $items;
}

protected function updatePaginatedItems(int $itemsPerPage, int $offset): void
{
$this->paginatedItems = array_slice($this->items, $offset, $itemsPerPage);
}

protected function getTotalAmountOfItems(): int
{
return count($this->items);
}

protected function getAmountOfItemsOnCurrentPage(): int
{
return count($this->paginatedItems);
}
}
Loading