|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Acme\Sitepackage\Middleware;
|
|
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
use Psr\Http\Server\MiddlewareInterface;
|
|
use Psr\Http\Server\RequestHandlerInterface;
|
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
|
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
|
|
|
class PreventSavingUnchangedInlineRecords implements MiddlewareInterface
|
|
{
|
|
private ConnectionPool $connectionPool;
|
|
|
|
public function __construct(ConnectionPool $connectionPool)
|
|
{
|
|
$this->connectionPool = $connectionPool;
|
|
}
|
|
|
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
|
{
|
|
if (!$this->isSubmittedRecordFormRequest($request)) {
|
|
return $handler->handle($request);
|
|
}
|
|
|
|
$request = $this->removeRecordsWithOnlyUnchangedHiddenField($request);
|
|
|
|
return $handler->handle($request);
|
|
}
|
|
|
|
private function isSubmittedRecordFormRequest(ServerRequestInterface $request): bool
|
|
{
|
|
if ($request->getMethod() !== 'POST') {
|
|
return false;
|
|
}
|
|
return ($request->getQueryParams()['route'] ?? '') === '/record/edit';
|
|
}
|
|
|
|
private function removeRecordsWithOnlyUnchangedHiddenField(ServerRequestInterface $request): ServerRequestInterface
|
|
{
|
|
$parsedBody = $request->getParsedBody();
|
|
if (empty($parsedBody['data'])) {
|
|
return $request;
|
|
}
|
|
|
|
foreach ($parsedBody['data'] as $tableName => $records) {
|
|
if (empty($GLOBALS['TCA'][$tableName]['ctrl']['enablecolumns']['disabled'])) {
|
|
continue; // table does not feature a hidden field
|
|
}
|
|
$hiddenFieldName = $GLOBALS['TCA'][$tableName]['ctrl']['enablecolumns']['disabled'];
|
|
foreach ($records as $recordUid => $record) {
|
|
if (array_keys($record) !== [$hiddenFieldName]) {
|
|
continue; // not only the hidden field is changed
|
|
}
|
|
if ((bool)$record[$hiddenFieldName] !== $this->isHiddenInDatabase($tableName, $recordUid)) {
|
|
continue; // the hidden value was changed
|
|
}
|
|
unset($parsedBody['data'][$tableName][$recordUid]);
|
|
$request = $request->withParsedBody($parsedBody);
|
|
}
|
|
}
|
|
|
|
return $request;
|
|
}
|
|
|
|
private function isHiddenInDatabase(string $tableName, int $recordUid): bool
|
|
{
|
|
$queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
|
|
$queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
|
|
$value = $queryBuilder
|
|
->select($GLOBALS['TCA'][$tableName]['ctrl']['enablecolumns']['disabled'])
|
|
->from($tableName)
|
|
->where(
|
|
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($recordUid, \PDO::PARAM_INT))
|
|
)
|
|
->execute()
|
|
->fetchOne();
|
|
return (bool)$value;
|
|
}
|
|
}
|