TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:09 +02:00
commit af8cc155b5
6818 changed files with 642608 additions and 0 deletions
@@ -0,0 +1,38 @@
<?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\FileSystem;
use TYPO3\CMS\Core\Package\Exception\PackageAssetsPublishingFailedException;
/**
* @internal Only to be used in TYPO3\CMS\Core\SystemResource namespace
*/
interface FileSystemPublisherInterface
{
public function canPublish(string $source, string $target): bool;
/**
* @throws PackageAssetsPublishingFailedException
*/
public function publishFolder(string $source, string $target): void;
/**
* @throws PackageAssetsPublishingFailedException
*/
public function publishFile(string $source, string $target): void;
}
@@ -0,0 +1,80 @@
<?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\FileSystem;
use Symfony\Component\Filesystem\Exception\IOException;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Package\Exception\PackageAssetsPublishingFailedException;
use TYPO3\CMS\Core\Utility\File\FileSystem;
/**
* @internal Only to be used in TYPO3\CMS\Core\SystemResource namespace
*/
final readonly class JunctionPublisher implements FileSystemPublisherInterface
{
private PublishingConfiguration $config;
public function __construct(private FileSystem $fileSystem)
{
$this->config = new PublishingConfiguration();
}
public function canPublish(string $source, string $target): bool
{
return Environment::isWindows()
&& $this->config->isLinkPublishingEnabled();
}
/**
* @throws PackageAssetsPublishingFailedException
*/
public function publishFolder(string $source, string $target): void
{
$this->ensureJunctionExists($source, $target);
}
/**
* @throws \LogicException
*/
public function publishFile(string $source, string $target): void
{
throw new \LogicException(self::class . ' can not be used to publish single files', 1772535297);
}
/**
* @throws PackageAssetsPublishingFailedException
*/
private function ensureJunctionExists(string $target, string $junction): void
{
$e = null;
if (!$this->fileSystem->isJunction($junction)) {
try {
$this->fileSystem->junction($target, $junction);
} catch (IOException $e) {
}
}
if ($e !== null || realpath($target) !== realpath($junction)) {
throw new PackageAssetsPublishingFailedException(
'junction',
1717488535,
$e,
);
}
}
}
@@ -0,0 +1,74 @@
<?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\FileSystem;
use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
use TYPO3\CMS\Core\Package\Exception\PackageAssetsPublishingFailedException;
/**
* @internal Only to be used in TYPO3\CMS\Core\SystemResource namespace
*/
final readonly class MirrorPublisher implements FileSystemPublisherInterface
{
private PublishingConfiguration $config;
public function __construct()
{
$this->config = new PublishingConfiguration();
}
public function canPublish(string $source, string $target): bool
{
return $this->config->isMirrorPublishingEnabled();
}
public function publishFolder(string $source, string $target): void
{
if (realpath($source) === realpath($target)) {
throw new PackageAssetsPublishingFailedException(
'mirror',
1773140314,
);
}
$symfonyFilesystem = new SymfonyFilesystem();
$symfonyFilesystem->mirror(
$source,
$target,
null,
[
'delete' => true,
'override' => true,
],
);
}
public function publishFile(string $source, string $target): void
{
if (!is_file($source)) {
throw new \LogicException('Can not publish file, because source is not a file', 1772538042);
}
if (realpath($source) === realpath($target)) {
throw new PackageAssetsPublishingFailedException(
'mirror',
1773140294,
);
}
$symfonyFilesystem = new SymfonyFilesystem();
$symfonyFilesystem->copy($source, $target, true);
}
}
@@ -0,0 +1,60 @@
<?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\FileSystem;
use TYPO3\CMS\Core\Core\Environment;
/**
* @internal Only to be used in TYPO3\CMS\Core\SystemResource namespace
*/
final readonly class PublishingConfiguration
{
private string $publishingType;
public function __construct(?string $publishingType = null)
{
$publishingType = $publishingType ?? $GLOBALS['TYPO3_CONF_VARS']['SYS']['SystemResources']['filesystemPublishingType'] ?? 'auto';
if ($publishingType === 'auto') {
$publishingType = Environment::getContext()->isDevelopment() ? 'link' : 'mirror';
}
$this->publishingType = $publishingType;
}
public function isLinkPublishingEnabled(): bool
{
return $this->publishingType === 'link';
}
public function isMirrorPublishingEnabled(): bool
{
return $this->publishingType === 'mirror';
}
public function hasCustomPublishingType(): bool
{
return !$this->isMirrorPublishingEnabled() && !$this->isLinkPublishingEnabled();
}
public function getCustomPublishingType(): string
{
if (!$this->hasCustomPublishingType()) {
throw new \LogicException('There is no custom publishing type enabled', 1773138713);
}
return $this->publishingType;
}
}
@@ -0,0 +1,82 @@
<?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\FileSystem;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Package\Exception\PackageAssetsPublishingFailedException;
use TYPO3\CMS\Core\Utility\File\FileSystem;
/**
* @internal Only to be used in TYPO3\CMS\Core\SystemResource namespace
*/
final readonly class SymlinkPublisher implements FileSystemPublisherInterface
{
private PublishingConfiguration $config;
public function __construct(private FileSystem $fileSystem)
{
$this->config = new PublishingConfiguration();
}
public function canPublish(string $source, string $target): bool
{
return !Environment::isWindows()
&& $this->config->isLinkPublishingEnabled();
}
public function publishFolder(string $source, string $target): void
{
$this->ensureSymlinkExists($source, $target, 'dir');
}
public function publishFile(string $source, string $target): void
{
$this->ensureSymlinkExists($source, $target, 'file');
}
/**
* @throws PackageAssetsPublishingFailedException
*/
private function ensureSymlinkExists(string $target, string $link, string $type): void
{
$success = true;
if (!$this->isSymlinked($link, $type)) {
$success = $this->fileSystem->relativeSymlink($target, $link);
}
$this->ensureIsValid($target, $link, $success);
}
private function isSymlinked(string $link, string $type): bool
{
return match ($type) {
'file' => $this->fileSystem->isSymlinkedFile($link),
'dir' => $this->fileSystem->isSymlinkedDirectory($link),
default => throw new \UnexpectedValueException(sprintf('Type can only be "file" or "dir", "%s" given.', $type), 1774611766),
};
}
private function ensureIsValid(string $target, string $link, bool $success): void
{
if (!$success || realpath($target) !== realpath($link)) {
throw new PackageAssetsPublishingFailedException(
'symlink',
1717488536,
);
}
}
}