Compare commits

...

8 Commits

Author SHA1 Message Date
Sebastian Fischer
b010c5e0fd [TASK] Make compatible with v14 2025-11-27 21:09:43 +01:00
Sebastian Fischer
20f79eef93 Merge tag '2.3.1' into develop
Release improvement of css unique
2025-08-17 17:28:37 +02:00
Sebastian Fischer
55ddc3b5e2 Merge branch 'release/2.3.1' 2025-08-17 17:28:10 +02:00
6182935a22 Improve css unique 2025-08-17 17:26:24 +02:00
Sebastian Fischer
2d5729ded6 Merge tag '2.3.0' into develop
Release styles merging
2025-04-26 20:04:25 +02:00
Sebastian Fischer
46810c675e Merge branch 'release/2.3.0' 2025-04-26 20:04:13 +02:00
Sebastian Fischer
ce9a0c8ad5 [TASK] Allow unique styles per layer 2025-04-26 20:03:17 +02:00
Sebastian Fischer
5fb7965b60 Merge tag '2.0.2' into develop
Release fix to array access in viewhelper
2025-04-24 12:41:42 +02:00
24 changed files with 317 additions and 66 deletions

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -75,7 +75,7 @@ class ContentElementCommand extends Command
->executeQuery() ->executeQuery()
->fetchAllAssociative(); ->fetchAllAssociative();
(new Table($output)) new Table($output)
->setHeaderTitle('Content in tree ' . $pageId) ->setHeaderTitle('Content in tree ' . $pageId)
->setHeaders(array_keys($result[0])) ->setHeaders(array_keys($result[0]))
->setRows($result) ->setRows($result)
@ -141,7 +141,7 @@ class ContentElementCommand extends Command
* that you want to use as a WHERE fragment is not prefixed. * that you want to use as a WHERE fragment is not prefixed.
* *
* @param string $constraint The where part fragment with a possible leading AND / OR operator * @param string $constraint The where part fragment with a possible leading AND / OR operator
* @return string The modified where part without leading operator * @return string The modified where part without a leading operator
*/ */
public function stripLogicalOperatorPrefix(string $constraint): string public function stripLogicalOperatorPrefix(string $constraint): string
{ {

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
*/ */
namespace Evoweb\EwBase\Configuration; namespace Evoweb\EwBase\Configuration;

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -16,6 +16,7 @@ declare(strict_types=1);
namespace Evoweb\EwBase\EventListener; namespace Evoweb\EwBase\EventListener;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Evoweb\EwBase\Services\Tailwindcss4Merger;
use TYPO3\CMS\Core\Core\RequestId; use TYPO3\CMS\Core\Core\RequestId;
use TYPO3\CMS\Core\Page\AssetCollector; use TYPO3\CMS\Core\Page\AssetCollector;
use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent; use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent;
@ -26,7 +27,8 @@ use TYPO3\CMS\Core\Utility\PathUtility;
readonly class CssMerger readonly class CssMerger
{ {
public function __construct( public function __construct(
private RequestId $requestId private RequestId $requestId,
protected Tailwindcss4Merger $tailwindcss4Merger
) { ) {
} }
@ -34,6 +36,9 @@ readonly class CssMerger
{ {
if ($event->isInline() && $event->isPriority()) { if ($event->isInline() && $event->isPriority()) {
$assetCollector = $event->getAssetCollector(); $assetCollector = $event->getAssetCollector();
if (empty($assetCollector->getStyleSheets()) && empty($assetCollector->getInlineStyleSheets())) {
return;
}
$styles = []; $styles = [];
$styles = $this->getStylesheetFileContent($assetCollector, $styles); $styles = $this->getStylesheetFileContent($assetCollector, $styles);
@ -41,18 +46,9 @@ readonly class CssMerger
$styles = array_unique($styles); $styles = array_unique($styles);
$styles = trim(implode(LF, $styles)); $styles = trim(implode(LF, $styles));
if (empty($styles)) { $styles = $this->tailwindcss4Merger->cssUnique($styles);
return;
}
/** @var Site $site */ if ($this->assertStylesShouldBeAddedInline()) {
$site = $this->getRequest()->getAttribute('site');
if (
$site instanceof Site
&& ($siteSettings = $site->getSettings())
&& !$siteSettings->isEmpty()
&& $siteSettings->get('ew-base.inlineCssStyles')
) {
$assetCollector->addInlineStyleSheet('ew_base', $styles, [], ['priority' => true]); $assetCollector->addInlineStyleSheet('ew_base', $styles, [], ['priority' => true]);
} else { } else {
$temporaryFile = GeneralUtility::writeStyleSheetContentToTemporaryFile($styles); $temporaryFile = GeneralUtility::writeStyleSheetContentToTemporaryFile($styles);
@ -87,16 +83,6 @@ readonly class CssMerger
return $styles; return $styles;
} }
protected function getStylesheetInlineContent(AssetCollector $assetCollector, array $styles): array
{
$styleSheetsInline = $assetCollector->getInlineStyleSheets(false);
foreach ($styleSheetsInline as $identifier => $asset) {
$styles[] = $asset['source'];
$assetCollector->removeInlineStyleSheet($identifier);
}
return $styles;
}
protected function getFileContent(string $filePath): string protected function getFileContent(string $filePath): string
{ {
$absoluteFilePath = GeneralUtility::getFileAbsFileName($filePath); $absoluteFilePath = GeneralUtility::getFileAbsFileName($filePath);
@ -124,6 +110,24 @@ readonly class CssMerger
); );
} }
protected function getStylesheetInlineContent(AssetCollector $assetCollector, array $styles): array
{
$styleSheetsInline = $assetCollector->getInlineStyleSheets(false);
foreach ($styleSheetsInline as $identifier => $asset) {
$styles[] = $asset['source'];
$assetCollector->removeInlineStyleSheet($identifier);
}
return $styles;
}
protected function assertStylesShouldBeAddedInline(): bool
{
/** @var Site $site */
$site = $this->getRequest()->getAttribute('site');
return $site instanceof Site
&& $site->getSettings()?->get('ew-base.inlineCssStyles');
}
protected function getRequest(): ServerRequestInterface protected function getRequest(): ServerRequestInterface
{ {
return $GLOBALS['TYPO3_REQUEST']; return $GLOBALS['TYPO3_REQUEST'];

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -214,7 +214,7 @@ class PickColorFromImage extends AbstractFormElement
{ {
$defaultConfig = self::$defaultConfig; $defaultConfig = self::$defaultConfig;
// If ratios are set do not add default options // If ratios are set, do not add default options
if (isset($baseConfiguration['cropVariants'])) { if (isset($baseConfiguration['cropVariants'])) {
unset($defaultConfig['cropVariants']); unset($defaultConfig['cropVariants']);
} }
@ -233,7 +233,7 @@ class PickColorFromImage extends AbstractFormElement
}); });
// Aspect ratios may not contain a "." character, see Ratio::__construct() // Aspect ratios may not contain a "." character, see Ratio::__construct()
// To match them again properly, same replacement is required here. // To match them again properly, the same replacement is required here.
$preparedAllowedAspectRatios = []; $preparedAllowedAspectRatios = [];
foreach ($cropVariant['allowedAspectRatios'] as $aspectRatio => $aspectRatioDefinition) { foreach ($cropVariant['allowedAspectRatios'] as $aspectRatio => $aspectRatioDefinition) {
$preparedAllowedAspectRatios[Ratio::prepareAspectRatioId($aspectRatio)] = $aspectRatioDefinition; $preparedAllowedAspectRatios[Ratio::prepareAspectRatioId($aspectRatio)] = $aspectRatioDefinition;
@ -259,7 +259,7 @@ class PickColorFromImage extends AbstractFormElement
$config['cropVariants'] = $cropVariants; $config['cropVariants'] = $cropVariants;
// By default we allow all image extensions that can be handled by the GFX functionality // By default, we allow all image extensions that can be handled by the GFX functionality
$config['allowedExtensions'] ??= $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']; $config['allowedExtensions'] ??= $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
return $config; return $config;
} }

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -20,7 +20,7 @@ use Doctrine\DBAL\ParameterType;
use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\QueryBuilder;
/** /**
* Utility class that parses sql statements with regard to types and parameters. * Utility class that parses SQL statements with regard to types and parameters.
*/ */
class QueryBuilderHelper class QueryBuilderHelper
{ {
@ -53,7 +53,7 @@ class QueryBuilderHelper
} }
/** /**
* Gets an array of the placeholders in a sql statements as keys and their positions in the query string. * Gets an array of the placeholders in a SQL statement as keys and their positions in the query string.
* *
* For a statement with positional parameters, returns a zero-indexed list of placeholder position. * For a statement with positional parameters, returns a zero-indexed list of placeholder position.
* For a statement with named parameters, returns a map of placeholder positions to their parameter names. * For a statement with named parameters, returns a map of placeholder positions to their parameter names.
@ -127,7 +127,7 @@ class QueryBuilderHelper
} }
/** /**
* For a positional query this method can rewrite the sql statement with regard to array parameters. * For a positional query this method can rewrite the SQL statement with regard to array parameters.
* *
* @throws \Exception * @throws \Exception
*/ */
@ -160,7 +160,7 @@ class QueryBuilderHelper
$arrayPositions[$name] = false; $arrayPositions[$name] = false;
} }
// parameter are positional and no array parameter given // parameters are positional and no array parameter given
if ($isPositional && !$arrayPositions) { if ($isPositional && !$arrayPositions) {
return [$query, $params, $types]; return [$query, $params, $types];
} }
@ -210,7 +210,7 @@ class QueryBuilderHelper
$expandStr = $count ? implode(', ', array_fill(0, $count, '?')) : 'NULL'; $expandStr = $count ? implode(', ', array_fill(0, $count, '?')) : 'NULL';
$query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1); $query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1);
$paramOffset += $count - 1; // Grows larger by number of parameters minus the replaced needle. $paramOffset += $count - 1; // Grows larger by the number of parameters minus the replaced needle.
$queryOffset += strlen($expandStr) - 1; $queryOffset += strlen($expandStr) - 1;
} }

View File

@ -0,0 +1,157 @@
<?php
declare(strict_types=1);
/*
* This file is developed by evoWeb.
*
* 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.
*/
namespace Evoweb\EwBase\Services;
class Tailwindcss4Merger
{
public function cssUnique(string $styles): string
{
$atLayerOrder = $this->getLayerOrder($styles);
$atLayerBase = $this->getLayerBase($styles);
$atLayerTheme = $this->getLayerTheme($styles);
$atLayerUtilities = $this->getLayerUtilities($styles);
$atLayerComponents = $this->getLayerComponents($styles);
$atProperty = $this->getProperties($styles);
$atLayerProperties = $this->getLayerProperties($styles);
$unlayered = $this->getUnlayered($styles);
return implode(chr(10), [
$atLayerOrder,
$atLayerBase,
$atLayerTheme,
$atLayerUtilities,
$atLayerComponents,
$atProperty,
$atLayerProperties,
$unlayered,
]);
}
protected function getLayerOrder(string $styles): string
{
preg_match_all('/(?<layer>@layer[^;{]+;)/i', $styles, $matches);
return implode(chr(10), array_unique($matches['layer'] ?? []));
}
protected function getLayerBase(string $styles): string
{
$matches = $this->getLayerByName($styles, 'base');
$base = [];
foreach ($matches as $match) {
$match = $this->unwrapLayer($match, 'base');
$match = preg_replace('/}\n *\./', "}\n||.", $match);
$match = preg_replace('/}\n\W*@/', "}\n||@", $match);
$parts = explode('||', $match);
$base = array_merge($base, $parts);
}
return $this->wrapLayer('base', array_unique($base));
}
protected function getLayerTheme(string $styles): string
{
$matches = $this->getLayerByName($styles, 'theme');
$themes = [];
foreach ($matches as $match) {
preg_match_all('/(?<theme>--[^;]+;)/i', $match, $subMatches);
$themes = array_merge($themes, $subMatches['theme'] ?? []);
}
return '@layer theme {
:root, :host {'
. chr(10)
. implode(chr(10), array_unique($themes))
. chr(10)
. ' }
}';
}
protected function getLayerUtilities(string $styles): string
{
$matches = $this->getLayerByName($styles, 'utilities');
$utilities = [];
foreach ($matches as $match) {
$match = $this->unwrapLayer($match, 'utilities');
$match = preg_replace('/}\n *\./', "}\n||.", $match);
$parts = explode('||', $match);
$utilities = array_merge($utilities, $parts);
}
return $this->wrapLayer('utilities', array_unique($utilities));
}
protected function getLayerComponents(string $styles): string
{
$matches = $this->getLayerByName($styles, 'components');
$components = [];
foreach ($matches as $match) {
$match = $this->unwrapLayer($match, 'components');
$match = preg_replace('/}\n *\./', "}\n||.", $match);
$parts = explode('||', $match);
$components = array_merge($components, $parts);
}
return $this->wrapLayer('components', array_unique($components));
}
protected function getLayerByName(string $styles, string $name): array
{
preg_match_all('/@layer[^{;]+\{.+?(?=\n})\n}/s', $styles, $matches);
$layer = [];
foreach ($matches['0'] as $match) {
if (str_starts_with($match, '@layer ' . $name) !== false) {
$layer[] = $match;
}
}
return $layer;
}
protected function getProperties(string $styles): string
{
preg_match_all('/(?<property>@property[^{]+\{[^}]+})/i', $styles, $matches);
return implode(chr(10), array_unique($matches['property'] ?? []));
}
protected function getLayerProperties(string $styles): string
{
$matches = $this->getLayerByName($styles, 'properties');
$properties = [
' @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline)'
. ' and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {'
];
foreach ($matches as $match) {
preg_match_all('/(?<properties>--tw[^ ]+: [^;]+;)/i', $match, $subMatches);
$properties = array_merge($properties, $subMatches['properties']);
}
$properties = array_unique($properties);
$properties[] = ' }
}';
return $this->wrapLayer('properties', $properties);
}
protected function unwrapLayer(string $styles, string $name): string
{
return trim(str_replace('@layer ' . $name . ' {', '', substr($styles, 0, -1)));
}
protected function wrapLayer(string $name, array $styles): string
{
return '@layer ' . $name . " {\n" . implode("\n", $styles) . "\n}";
}
protected function getUnlayered(string $styles): string
{
$unlayered = preg_replace('/(?<layer>@layer[^;{]+;)/i', '', $styles, -1);
$unlayered = preg_replace('/@layer[^{;]+\{.+?(?=\n})\n}/s', '', $unlayered, -1);
return preg_replace('/(?<property>@property[^{]+\{[^}]+})/i', '', $unlayered, -1);
}
}

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -15,6 +15,9 @@ declare(strict_types=1);
namespace Evoweb\EwBase\User; namespace Evoweb\EwBase\User;
use TYPO3\CMS\Core\SystemResource\Exception\CanNotResolvePublicResourceException;
use TYPO3\CMS\Core\SystemResource\Exception\CanNotResolveSystemResourceException;
use TYPO3\CMS\Core\SystemResource\Publishing\UriGenerationOptions;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility; use TYPO3\CMS\Core\Utility\PathUtility;
@ -27,10 +30,18 @@ use TYPO3\CMS\Core\Utility\PathUtility;
*/ */
class AssetPath class AssetPath
{ {
/**
* @throws CanNotResolvePublicResourceException
* @throws CanNotResolveSystemResourceException
*/
public function getAbsolutePublicPath(string $content, array $conf): string public function getAbsolutePublicPath(string $content, array $conf): string
{ {
return $content return $content
. GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . GeneralUtility::getIndpEnv('TYPO3_SITE_URL')
. ltrim(PathUtility::getPublicResourceWebPath($conf['file']), '/'); . ltrim((string)PathUtility::getSystemResourceUri(
$conf['file'],
null,
new UriGenerationOptions(cacheBusting: false)
), '/');
} }
} }

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -16,13 +16,22 @@ declare(strict_types=1);
namespace Evoweb\EwBase\ViewHelpers\Be; namespace Evoweb\EwBase\ViewHelpers\Be;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\RelationHandler;
use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Imaging\IconSize; use TYPO3\CMS\Core\Imaging\IconSize;
use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Core\Resource\ProcessedFile; use TYPO3\CMS\Core\Resource\ProcessedFile;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Schema\Field\FileFieldType;
use TYPO3\CMS\Core\Schema\TcaSchema;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
@ -48,7 +57,7 @@ class ThumbnailViewHelper extends AbstractViewHelper
$field = $this->arguments['fieldName']; $field = $this->arguments['fieldName'];
$row = $this->arguments['row']; $row = $this->arguments['row'];
$fileReferences = BackendUtility::resolveFileReferences($table, $field, $row); $fileReferences = $this->resolveFileReferences($table, $field, $row);
$fileObject = is_array($fileReferences) ? current($fileReferences)->getOriginalFile() : null; $fileObject = is_array($fileReferences) ? current($fileReferences)->getOriginalFile() : null;
if ($fileObject && $fileObject->isMissing()) { if ($fileObject && $fileObject->isMissing()) {
@ -74,6 +83,65 @@ class ThumbnailViewHelper extends AbstractViewHelper
return $this->linkEditContent('<img src="' . $previewFile->getPublicUrl() . '"/>', $row ); return $this->linkEditContent('<img src="' . $previewFile->getPublicUrl() . '"/>', $row );
} }
public function resolveFileReferences(
string $tableName,
string $fieldName,
array $element,
?int $workspaceId = null
): ?array {
if (!($schema = self::getTcaSchema($tableName))?->hasField($fieldName)) {
return null;
}
$field = $schema->getField($fieldName);
if ($field instanceof FileFieldType === false) {
return null;
}
$fileReferences = [];
$relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
if ($workspaceId !== null) {
$relationHandler->setWorkspaceId($workspaceId);
}
$relationHandler->initializeForField(
$tableName,
$field->getConfiguration(),
$element,
$element[$fieldName],
);
$relationHandler->processDeletePlaceholder();
$referenceUids = $relationHandler->tableArray[$field->getConfiguration()['foreign_table']] ?? [];
foreach ($referenceUids as $referenceUid) {
try {
$fileReference = GeneralUtility::makeInstance(ResourceFactory::class)->getFileReferenceObject(
$referenceUid,
[],
$workspaceId === 0
);
$fileReferences[$fileReference->getUid()] = $fileReference;
} catch (FileDoesNotExistException $e) {
/**
* We just catch the exception here
* Reasoning: There is nothing an editor or even admin could do
*/
} catch (\InvalidArgumentException $e) {
/**
* The storage does not exist anymore
* Log the exception message for admins as they maybe can restore the storage
*/
// @extensionScannerIgnoreLine
self::getLogger()->error($e->getMessage(), [
'table' => $tableName,
'fieldName' => $fieldName,
'referenceUid' => $referenceUid,
'exception' => $e,
]);
}
}
return $fileReferences;
}
protected function linkEditContent(string $linkText, $row): string protected function linkEditContent(string $linkText, $row): string
{ {
if (empty($linkText)) { if (empty($linkText)) {
@ -84,10 +152,8 @@ class ThumbnailViewHelper extends AbstractViewHelper
if ( if (
$backendUser->check('tables_modify', 'tt_content') $backendUser->check('tables_modify', 'tt_content')
&& $backendUser->recordEditAccessInternals('tt_content', $row) && $backendUser->recordEditAccessInternals('tt_content', $row)
&& ( && new Permission(
new Permission( $backendUser->calcPerms(BackendUtility::getRecord('pages', $row['pid']) ?? [])
$backendUser->calcPerms(BackendUtility::getRecord('pages', $row['pid']) ?? [])
)
)->editContentPermissionIsGranted() )->editContentPermissionIsGranted()
) { ) {
$urlParameters = [ $urlParameters = [
@ -112,6 +178,17 @@ class ThumbnailViewHelper extends AbstractViewHelper
return $linkText; return $linkText;
} }
protected static function getLogger(): LoggerInterface
{
return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
}
protected static function getTcaSchema(string $tableName): ?TcaSchema
{
$schemaFactory = GeneralUtility::makeInstance(TcaSchemaFactory::class);
return $schemaFactory->has($tableName) ? $schemaFactory->get($tableName) : null;
}
protected function getBackendUser(): BackendUserAuthentication protected function getBackendUser(): BackendUserAuthentication
{ {
return $GLOBALS['BE_USER']; return $GLOBALS['BE_USER'];

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.
@ -16,6 +16,9 @@ declare(strict_types=1);
namespace Evoweb\EwBase\ViewHelpers; namespace Evoweb\EwBase\ViewHelpers;
use TYPO3\CMS\Core\Resource\Exception\InvalidFileException; use TYPO3\CMS\Core\Resource\Exception\InvalidFileException;
use TYPO3\CMS\Core\SystemResource\Exception\CanNotResolvePublicResourceException;
use TYPO3\CMS\Core\SystemResource\Exception\CanNotResolveSystemResourceException;
use TYPO3\CMS\Core\SystemResource\Publishing\UriGenerationOptions;
use TYPO3\CMS\Core\Utility\PathUtility; use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
@ -25,9 +28,6 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
* <code title="Simple Loop"> * <code title="Simple Loop">
* <ewb:publicPath path="{data}">....</ewb:publicPath> * <ewb:publicPath path="{data}">....</ewb:publicPath>
* </code> * </code>
* <output>
* fixed flexform data for extbase controller
* </output>
* *
* @api * @api
*/ */
@ -45,11 +45,12 @@ class PublicPathViewHelper extends AbstractViewHelper
} }
/** /**
* @throws InvalidFileException * @throws CanNotResolvePublicResourceException
* @throws CanNotResolveSystemResourceException
*/ */
public function renderStatic(): string public function render(): string
{ {
$path = (string)$this->arguments['path']; $path = (string)$this->arguments['path'];
return PathUtility::getPublicResourceWebPath($path); return (string)PathUtility::getSystemResourceUri($path, null, new UriGenerationOptions(cacheBusting: false));
} }
} }

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
* *
* It is free software; you can redistribute it and/or modify it under * It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2 * the terms of the GNU General Public License, either version 2
* of the License, or any later version. * of the License or any later version.
* *
* For the full copyright and license information, please read the * For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code. * LICENSE.txt file that was distributed with this source code.

View File

@ -1,6 +1,7 @@
{ {
"name": "evoweb/ew-base", "name": "evoweb/ew-base",
"type": "typo3-cms-extension", "type": "typo3-cms-extension",
"description": "Site base",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Evoweb\\EwBase\\": "Classes/" "Evoweb\\EwBase\\": "Classes/"