TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
<?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 TYPO3\CMS\Core\SystemResource\Publishing;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Symfony\Component\DependencyInjection\Attribute\AsAlias;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Http\NormalizedParams;
|
||||
use TYPO3\CMS\Core\Messaging\FlashMessage;
|
||||
use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
|
||||
use TYPO3\CMS\Core\Package\Exception\PackageAssetsPublishingFailedException;
|
||||
use TYPO3\CMS\Core\Package\PackageInterface;
|
||||
use TYPO3\CMS\Core\SystemResource\Exception\CanNotGenerateUriException;
|
||||
use TYPO3\CMS\Core\SystemResource\Publishing\FileSystem\FileSystemPublisherInterface;
|
||||
use TYPO3\CMS\Core\SystemResource\Type\PublicResourceInterface;
|
||||
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* This implementation publishes (when implemented) public assets from extension
|
||||
* packages to the public _assets directory using a hash as directory name.
|
||||
* Subsequently, it can also generate URIs to public resource objects within that _assets folder
|
||||
*
|
||||
* @internal Never use or reference it directly, use SystemResourcePublisherInterface to inject it (or a proper replacement).
|
||||
*/
|
||||
#[Autoconfigure(public: true), AsAlias(SystemResourcePublisherInterface::class, public: true)]
|
||||
final readonly class DefaultSystemResourcePublisher implements SystemResourcePublisherInterface
|
||||
{
|
||||
private const string PUBLISHING_DIRECTORY = '_assets/';
|
||||
private const string PUBLISHING_DIRECTORY_INSTALL = '_assets_install/';
|
||||
|
||||
/**
|
||||
* @var FileSystemPublisherInterface[]
|
||||
*/
|
||||
private array $fileSystemPublishers;
|
||||
|
||||
private string $publishingDirectory;
|
||||
|
||||
public function __construct(
|
||||
array $fileSystemPublishers = [],
|
||||
bool $failsafe = false,
|
||||
) {
|
||||
$this->fileSystemPublishers = $fileSystemPublishers;
|
||||
$this->publishingDirectory = $failsafe ? self::PUBLISHING_DIRECTORY_INSTALL : self::PUBLISHING_DIRECTORY;
|
||||
}
|
||||
|
||||
public function publishResources(
|
||||
PackageInterface $package,
|
||||
): FlashMessageQueue {
|
||||
$queue = new FlashMessageQueue('asset:publish');
|
||||
$resourceDefinitions = $package
|
||||
->getResources()
|
||||
->getPublicResourceDefinitions();
|
||||
|
||||
foreach ($resourceDefinitions as $definition) {
|
||||
$publishingContext = new ResourcePublishingContext(
|
||||
package: $package,
|
||||
definition: $definition,
|
||||
);
|
||||
if ($publishingContext->isSourcePublic) {
|
||||
continue;
|
||||
}
|
||||
$publicResourcesPath = Environment::getPublicPath() . '/' . $this->publishingDirectory . $publishingContext->prefix;
|
||||
GeneralUtility::mkdir_deep(dirname($publicResourcesPath));
|
||||
try {
|
||||
foreach ($this->fileSystemPublishers as $publisher) {
|
||||
if (!$publisher->canPublish($publishingContext->filesystemPath, $publicResourcesPath)) {
|
||||
continue;
|
||||
}
|
||||
if (is_file($publishingContext->filesystemPath)) {
|
||||
$publisher->publishFile($publishingContext->filesystemPath, $publicResourcesPath);
|
||||
} else {
|
||||
if (!is_dir($publishingContext->filesystemPath)) {
|
||||
$queue->addMessage(new FlashMessage(
|
||||
sprintf(
|
||||
'Did not publish public resource for extension "%s".'
|
||||
. chr(10)
|
||||
. 'The source file/directory "%s" does not exist.',
|
||||
$package->getPackageKey(),
|
||||
substr($publishingContext->filesystemPath, strlen(Environment::getProjectPath())),
|
||||
),
|
||||
$package->getPackageKey(),
|
||||
ContextualFeedbackSeverity::INFO,
|
||||
));
|
||||
break;
|
||||
}
|
||||
$publisher->publishFolder($publishingContext->filesystemPath, $publicResourcesPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (PackageAssetsPublishingFailedException $e) {
|
||||
$queue->addMessage(new FlashMessage(
|
||||
sprintf(
|
||||
'Could not publish public resources for extension "%s" by using the "%s" strategy.'
|
||||
. chr(10)
|
||||
. 'Check whether the target directory "%s" already exists'
|
||||
. chr(10)
|
||||
. 'and TYPO3 has permissions to write inside the "_assets" directory.',
|
||||
$package->getPackageKey(),
|
||||
$e->publishingStrategy,
|
||||
'.' . substr($publicResourcesPath, strlen(Environment::getProjectPath())),
|
||||
),
|
||||
$package->getPackageKey(),
|
||||
ContextualFeedbackSeverity::ERROR,
|
||||
));
|
||||
}
|
||||
}
|
||||
return $queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws CanNotGenerateUriException
|
||||
*/
|
||||
public function generateUri(PublicResourceInterface $publicResource, ?ServerRequestInterface $request, ?UriGenerationOptions $options = null): UriInterface
|
||||
{
|
||||
if (!$publicResource->isPublished()) {
|
||||
throw new CanNotGenerateUriException(sprintf('Can not generate Uri for an unpublished resource %s', $publicResource), 1761211273);
|
||||
}
|
||||
$request ??= $GLOBALS['TYPO3_REQUEST'] ?? null;
|
||||
$options ??= new UriGenerationOptions();
|
||||
return $publicResource->getPublicUri(
|
||||
new DefaultSystemResourceUriGenerator(
|
||||
$this->publishingDirectory,
|
||||
$this->extractPublicPrefixFromRequest($request, $options->uriPrefix),
|
||||
$request,
|
||||
$options,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private function extractPublicPrefixFromRequest(?ServerRequestInterface $request, ?string $publicPrefix): string
|
||||
{
|
||||
if ($publicPrefix !== null) {
|
||||
return $publicPrefix;
|
||||
}
|
||||
if ($request === null) {
|
||||
return '/';
|
||||
}
|
||||
$normalizedParams = $request->getAttribute('normalizedParams');
|
||||
return $this->getFrontendUrlPrefix($request->getAttribute('frontend.typoscript')?->getConfigArray(), $normalizedParams)
|
||||
?? $normalizedParams->getSitePath();
|
||||
}
|
||||
|
||||
private function getFrontendUrlPrefix(?array $typoScriptConfigArray, NormalizedParams $normalizedParams): ?string
|
||||
{
|
||||
if ($typoScriptConfigArray === null) {
|
||||
return null;
|
||||
}
|
||||
if ($typoScriptConfigArray['forceAbsoluteUrls'] ?? false) {
|
||||
return $normalizedParams->getSiteUrl();
|
||||
}
|
||||
$absRefPrefix = trim($typoScriptConfigArray['absRefPrefix'] ?? '');
|
||||
return $absRefPrefix === 'auto' ? $normalizedParams->getSitePath() : $absRefPrefix;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user