TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<?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\Form\Mvc\Configuration;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Symfony\Component\DependencyInjection\Attribute\AsAlias;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||
use TYPO3\CMS\Core\Site\Entity\Site;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface as ExtFormConfigurationManagerInterface;
|
||||
|
||||
/**
|
||||
* Extend the ExtbaseConfigurationManager to read YAML configurations.
|
||||
*
|
||||
* YAML files are discovered automatically from every active extension's
|
||||
* Configuration/Form/<SetName>/ directory (see {@see \TYPO3\CMS\Form\DependencyInjection\FormYamlCollectorConfigurator}).
|
||||
*
|
||||
* Scope: frontend / backend
|
||||
* @internal
|
||||
*/
|
||||
#[AsAlias(ConfigurationManagerInterface::class, public: true)]
|
||||
readonly class ConfigurationManager implements ExtFormConfigurationManagerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private YamlSource $yamlSource,
|
||||
#[Autowire(service: 'cache.assets')]
|
||||
private FrontendInterface $cache,
|
||||
private TypoScriptService $typoScriptService,
|
||||
private FormYamlCollector $formYamlCollector,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Load and parse YAML files for the current rendering context.
|
||||
*
|
||||
* Files are resolved via auto-discovery: {@see FormYamlCollector} scans every
|
||||
* active extension's Configuration/Form/<SetName>/ directory and returns
|
||||
* all paths sorted by priority.
|
||||
*
|
||||
* The following post-processing steps are applied to the merged configuration:
|
||||
*
|
||||
* * Remove all keys whose values are NULL
|
||||
* * Sort by array keys if all keys within a nesting level are numerical
|
||||
* * Resolve possible TypoScript settings in FE mode
|
||||
*/
|
||||
public function getYamlConfiguration(array $typoScriptSettings, bool $isFrontend, ?ServerRequestInterface $request = null): array
|
||||
{
|
||||
$yamlSettingsFilePaths = $this->formYamlCollector->getPaths();
|
||||
$cacheKey = strtolower('YamlSettings_form' . md5(json_encode($yamlSettingsFilePaths)));
|
||||
if ($this->cache->has($cacheKey)) {
|
||||
$yamlSettings = $this->cache->get($cacheKey);
|
||||
} else {
|
||||
$yamlSettings = $this->yamlSource->load($yamlSettingsFilePaths);
|
||||
$yamlSettings = ArrayUtility::removeNullValuesRecursive($yamlSettings);
|
||||
$yamlSettings = ArrayUtility::sortArrayWithIntegerKeysRecursive($yamlSettings);
|
||||
$this->cache->set($cacheKey, $yamlSettings);
|
||||
}
|
||||
|
||||
$this->applySiteSettingsOverrides($yamlSettings, $request);
|
||||
|
||||
if (is_array($typoScriptSettings['yamlSettingsOverrides'] ?? null) && !empty($typoScriptSettings['yamlSettingsOverrides'])) {
|
||||
$yamlSettingsOverrides = $typoScriptSettings['yamlSettingsOverrides'];
|
||||
if ($isFrontend) {
|
||||
if ($request === null) {
|
||||
throw new \RuntimeException('Frontend rendering an ext:form requires the request being hand over', 1760451538);
|
||||
}
|
||||
$yamlSettingsOverrides = $this->typoScriptService->resolvePossibleTypoScriptConfiguration($yamlSettingsOverrides, $request);
|
||||
}
|
||||
ArrayUtility::mergeRecursiveWithOverrule($yamlSettings, $yamlSettingsOverrides);
|
||||
}
|
||||
return $yamlSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read form template/translation site set settings from the current site
|
||||
* and merge them into the YAML configuration.
|
||||
* Non-empty values are added at key 20 so they overlay the base paths (key 10)
|
||||
* while still allowing higher-priority overrides from form sets or yamlSettingsOverrides.
|
||||
*/
|
||||
private function applySiteSettingsOverrides(array &$yamlSettings, ?ServerRequestInterface $request): void
|
||||
{
|
||||
$site = $request?->getAttribute('site');
|
||||
if (!$site instanceof Site) {
|
||||
return;
|
||||
}
|
||||
|
||||
$siteSettings = $site->getSettings();
|
||||
$renderingOptionsOverrides = [];
|
||||
|
||||
$templateRootPath = (string)$siteSettings->get('form.templates.templateRootPath', '');
|
||||
if ($templateRootPath !== '') {
|
||||
$renderingOptionsOverrides['templateRootPaths'][20] = $templateRootPath;
|
||||
}
|
||||
|
||||
$partialRootPath = (string)$siteSettings->get('form.templates.partialRootPath', '');
|
||||
if ($partialRootPath !== '') {
|
||||
$renderingOptionsOverrides['partialRootPaths'][20] = $partialRootPath;
|
||||
}
|
||||
|
||||
$layoutRootPath = (string)$siteSettings->get('form.templates.layoutRootPath', '');
|
||||
if ($layoutRootPath !== '') {
|
||||
$renderingOptionsOverrides['layoutRootPaths'][20] = $layoutRootPath;
|
||||
}
|
||||
|
||||
$translationFile = (string)$siteSettings->get('form.translation.translationFile', '');
|
||||
if ($translationFile !== '') {
|
||||
$renderingOptionsOverrides['translation']['translationFiles'][20] = $translationFile;
|
||||
}
|
||||
|
||||
if ($renderingOptionsOverrides !== []) {
|
||||
$overrides = [
|
||||
'prototypes' => [
|
||||
'standard' => [
|
||||
'formElementsDefinition' => [
|
||||
'Form' => [
|
||||
'renderingOptions' => $renderingOptionsOverrides,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
ArrayUtility::mergeRecursiveWithOverrule($yamlSettings, $overrides);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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\Form\Mvc\Configuration;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Scope: frontend / backend
|
||||
* @internal
|
||||
*/
|
||||
interface ConfigurationManagerInterface
|
||||
{
|
||||
public function getYamlConfiguration(array $typoScriptSettings, bool $isFrontend, ?ServerRequestInterface $request = null): array;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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\Form\Mvc\Configuration;
|
||||
|
||||
use TYPO3\CMS\Form\Exception as FormException;
|
||||
|
||||
/**
|
||||
* A generic Form configuration Exception
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Exception extends FormException {}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* 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\Form\Mvc\Configuration\Exception;
|
||||
|
||||
use TYPO3\CMS\Form\Mvc\Configuration\Exception;
|
||||
|
||||
/**
|
||||
* Exception for file write errors
|
||||
* @internal
|
||||
*/
|
||||
class FileWriteException extends Exception {}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* 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\Form\Mvc\Configuration\Exception;
|
||||
|
||||
use TYPO3\CMS\Form\Mvc\Configuration\Exception;
|
||||
|
||||
/**
|
||||
* A No Such File exception
|
||||
* @internal
|
||||
*/
|
||||
class NoSuchFileException extends Exception {}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* 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\Form\Mvc\Configuration\Exception;
|
||||
|
||||
use TYPO3\CMS\Form\Mvc\Configuration\Exception;
|
||||
|
||||
/**
|
||||
* A Parse Error exception
|
||||
* @internal
|
||||
*/
|
||||
class ParseErrorException extends Exception {}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?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\Form\Mvc\Configuration;
|
||||
|
||||
/**
|
||||
* Collects all auto-discovered form YAML configuration files across
|
||||
* all active TYPO3 extensions.
|
||||
*
|
||||
* Each extension can provide YAML files under
|
||||
* EXT:my_extension/Configuration/Form/<SetName>/
|
||||
* with an accompanying config.yaml that declares name, label and priority.
|
||||
* The collector is populated by {@see \TYPO3\CMS\Form\DependencyInjection\FormYamlCollectorConfigurator}
|
||||
* and provides a priority-sorted list of file paths to {@see ConfigurationManager}.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class FormYamlCollector
|
||||
{
|
||||
/** @var list<FormYamlConfiguration> */
|
||||
private array $configurations = [];
|
||||
|
||||
public function add(FormYamlConfiguration $configuration): void
|
||||
{
|
||||
$this->configurations[] = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all registered file paths sorted by ascending priority
|
||||
* (lower = loaded first = acts as base, higher = override).
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getPaths(): array
|
||||
{
|
||||
$sorted = $this->configurations;
|
||||
usort($sorted, static fn(FormYamlConfiguration $a, FormYamlConfiguration $b): int => $a->priority <=> $b->priority);
|
||||
|
||||
return array_values(array_map(
|
||||
static fn(FormYamlConfiguration $c): string => $c->path,
|
||||
$sorted
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all registered configurations, regardless of priority.
|
||||
* Useful for diagnostic/debug purposes.
|
||||
*
|
||||
* @return list<FormYamlConfiguration>
|
||||
*/
|
||||
public function getAllConfigurations(): array
|
||||
{
|
||||
return array_values($this->configurations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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\Form\Mvc\Configuration;
|
||||
|
||||
/**
|
||||
* Represents a single auto-discovered form YAML configuration file.
|
||||
*
|
||||
* Carries the EXT: path, the priority used for merge ordering, and the
|
||||
* declared set name from config.yaml. A lower priority value is loaded first
|
||||
* (acts as base); higher priority values are merged on top and can override
|
||||
* earlier values.
|
||||
*
|
||||
* The {@see $setName} field mirrors the "name" key from config.yaml
|
||||
* (e.g. "my-vendor/my-set") and is used both for the disable mechanism
|
||||
* ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['form']['disabledSets']) and
|
||||
* for diagnostic / logging output.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final readonly class FormYamlConfiguration
|
||||
{
|
||||
/**
|
||||
* @param string $path EXT: path to the YAML file, e.g. 'EXT:my_extension/Configuration/Form/MySet/config.yaml'
|
||||
* @param int $priority Load order: lower = earlier = acts as base (default: 100)
|
||||
* @param string $setName Declared "name" from config.yaml, e.g. "my-vendor/my-set". Empty string if omitted.
|
||||
*/
|
||||
public function __construct(
|
||||
public string $path,
|
||||
public int $priority,
|
||||
public string $setName = '',
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?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\Form\Mvc\Configuration;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Core\TypoScript\TypoScriptService as CoreTypoScriptService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
|
||||
/**
|
||||
* Utilities to manage and convert TypoScript
|
||||
*
|
||||
* Scope: frontend
|
||||
*/
|
||||
readonly class TypoScriptService
|
||||
{
|
||||
public function __construct(
|
||||
protected CoreTypoScriptService $coreTypoScriptService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Parse a configuration with ContentObjectRenderer::cObjGetSingle()
|
||||
* and return the result.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function resolvePossibleTypoScriptConfiguration(array $configuration, ServerRequestInterface $request): array
|
||||
{
|
||||
$configuration = $this->coreTypoScriptService->convertPlainArrayToTypoScriptArray($configuration);
|
||||
$contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$contentObjectRenderer->setRequest($request);
|
||||
// @todo: Setting request to COR is probably important, but setting page record here *may* not be needed in this case?
|
||||
$contentObjectRenderer->start($request->getAttribute('frontend.page.information')->getPageRecord(), 'pages');
|
||||
$configuration = $this->resolveTypoScriptConfiguration($configuration, $contentObjectRenderer);
|
||||
return $this->coreTypoScriptService->convertTypoScriptArrayToPlainArray($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a configuration with ContentObjectRenderer::cObjGetSingle()
|
||||
* if there is an array key without and with a dot at the end.
|
||||
* This sample would be identified as a TypoScript parsable configuration
|
||||
* part:
|
||||
*
|
||||
* [
|
||||
* 'example' => 'TEXT'
|
||||
* 'example.' => [
|
||||
* 'value' => 'some value'
|
||||
* ]
|
||||
* ]
|
||||
*/
|
||||
protected function resolveTypoScriptConfiguration(array $configuration, ContentObjectRenderer $contentObjectRenderer): array
|
||||
{
|
||||
foreach ($configuration as $key => $value) {
|
||||
$keyWithoutDot = rtrim((string)$key, '.');
|
||||
if (isset($configuration[$keyWithoutDot]) && isset($configuration[$keyWithoutDot . '.'])) {
|
||||
$value = $contentObjectRenderer->cObjGetSingle(
|
||||
$configuration[$keyWithoutDot],
|
||||
$configuration[$keyWithoutDot . '.'],
|
||||
$keyWithoutDot
|
||||
);
|
||||
$configuration[$keyWithoutDot] = $value;
|
||||
} elseif (!isset($configuration[$keyWithoutDot]) && isset($configuration[$keyWithoutDot . '.'])) {
|
||||
$configuration[$keyWithoutDot] = $this->resolveTypoScriptConfiguration($value, $contentObjectRenderer);
|
||||
}
|
||||
unset($configuration[$keyWithoutDot . '.']);
|
||||
}
|
||||
return $configuration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?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!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Inspired by and partially taken from the Neos.Form package (www.neos.io)
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Form\Mvc\Configuration;
|
||||
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader;
|
||||
use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException;
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
use TYPO3\CMS\Core\Resource\FolderInterface;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Form\Mvc\Configuration\Exception\FileWriteException;
|
||||
use TYPO3\CMS\Form\Mvc\Configuration\Exception\ParseErrorException;
|
||||
use TYPO3\CMS\Form\Slot\FilePersistenceSlot;
|
||||
|
||||
/**
|
||||
* Configuration source based on YAML files
|
||||
*
|
||||
* Scope: frontend / backend
|
||||
* @internal
|
||||
*/
|
||||
readonly class YamlSource
|
||||
{
|
||||
public function __construct(
|
||||
private FilePersistenceSlot $filePersistenceSlot,
|
||||
private YamlFileLoader $yamlFileLoader,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Loads the specified configuration files and returns its merged content
|
||||
* as an array.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function load(array $filesToLoad): array
|
||||
{
|
||||
$configuration = [];
|
||||
foreach ($filesToLoad as $fileToLoad) {
|
||||
if ($fileToLoad instanceof File) {
|
||||
$loadedConfiguration = $this->loadFromFile($fileToLoad);
|
||||
} else {
|
||||
$loadedConfiguration = $this->loadFromFilePath($fileToLoad);
|
||||
if (isset($loadedConfiguration['TYPO3']['CMS']['Form'])) {
|
||||
$namespacedConfiguration = $loadedConfiguration['TYPO3']['CMS']['Form'];
|
||||
unset($loadedConfiguration['TYPO3']);
|
||||
$loadedConfiguration = array_replace_recursive($namespacedConfiguration, $loadedConfiguration);
|
||||
}
|
||||
}
|
||||
$configuration = array_replace_recursive($configuration, $loadedConfiguration);
|
||||
}
|
||||
return ArrayUtility::convertBooleanStringsToBooleanRecursive($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the specified configuration array to the given file in YAML format.
|
||||
*
|
||||
* @param File|string $fileToSave The file to write to.
|
||||
* @param array $configuration The configuration to save
|
||||
* @throws FileWriteException if the file could not be written
|
||||
* @internal
|
||||
*/
|
||||
public function save(File|string $fileToSave, array $configuration): void
|
||||
{
|
||||
try {
|
||||
$header = $this->getHeaderFromFile($fileToSave);
|
||||
} catch (InsufficientFileAccessPermissionsException $e) {
|
||||
throw new FileWriteException($e->getMessage(), 1512584488, $e);
|
||||
}
|
||||
|
||||
$yaml = Yaml::dump($configuration, 99, 2);
|
||||
|
||||
if ($fileToSave instanceof File) {
|
||||
// @deprecated: Remove in v16 along with the FileFormsToDatabaseUpgradeWizard
|
||||
try {
|
||||
$this->filePersistenceSlot->allowInvocation(
|
||||
FilePersistenceSlot::COMMAND_FILE_SET_CONTENTS,
|
||||
$this->buildCombinedIdentifier(
|
||||
$fileToSave->getParentFolder(),
|
||||
$fileToSave->getName()
|
||||
),
|
||||
$this->filePersistenceSlot->getContentSignature(
|
||||
$header . LF . $yaml
|
||||
)
|
||||
);
|
||||
$fileToSave->setContents($header . LF . $yaml);
|
||||
} catch (InsufficientFileAccessPermissionsException $e) {
|
||||
throw new FileWriteException($e->getMessage(), 1512582753, $e);
|
||||
}
|
||||
} else {
|
||||
$byteCount = @file_put_contents($fileToSave, $header . LF . $yaml);
|
||||
if ($byteCount === false) {
|
||||
$error = error_get_last();
|
||||
$errorMessage = $error['message'] ?? 'Check that the file exists and can be written.';
|
||||
throw new FileWriteException($errorMessage, 1512582929);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load YAML configuration from a local file path
|
||||
*
|
||||
* @throws ParseErrorException
|
||||
*/
|
||||
protected function loadFromFilePath(string $filePath): array
|
||||
{
|
||||
try {
|
||||
$loadedConfiguration = $this->yamlFileLoader->load($filePath);
|
||||
} catch (\RuntimeException $e) {
|
||||
throw new ParseErrorException(
|
||||
sprintf('An error occurred while parsing file "%s": %s', $filePath, $e->getMessage()),
|
||||
1480195405,
|
||||
$e
|
||||
);
|
||||
}
|
||||
return $loadedConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load YAML configuration from a FAL file
|
||||
*
|
||||
* @throws ParseErrorException
|
||||
*/
|
||||
protected function loadFromFile(File $file): array
|
||||
{
|
||||
$fileIdentifier = $file->getIdentifier();
|
||||
$rawYamlContent = $file->getContents();
|
||||
try {
|
||||
$loadedConfiguration = Yaml::parse($rawYamlContent);
|
||||
} catch (ParseException $e) {
|
||||
throw new ParseErrorException(
|
||||
sprintf('An error occurred while parsing file "%s": %s', $fileIdentifier, $e->getMessage()),
|
||||
1574422322,
|
||||
$e
|
||||
);
|
||||
}
|
||||
return $loadedConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the header part from the given file. That means, every line
|
||||
* until the first non comment line is found.
|
||||
*
|
||||
* @return string The header of the given YAML file
|
||||
*/
|
||||
protected function getHeaderFromFile(File|string $file): string
|
||||
{
|
||||
$header = '';
|
||||
if ($file instanceof File) {
|
||||
$fileLines = explode(LF, $file->getContents());
|
||||
} elseif (is_file($file)) {
|
||||
$fileLines = file($file);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
foreach ($fileLines as $line) {
|
||||
if (str_starts_with($line, '#')) {
|
||||
$header .= $line;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $header;
|
||||
}
|
||||
|
||||
/*
|
||||
* @deprecated: Remove in v16 along with the FileFormsToDatabaseUpgradeWizard
|
||||
*/
|
||||
protected function buildCombinedIdentifier(FolderInterface $folder, string $fileName): string
|
||||
{
|
||||
return sprintf(
|
||||
'%d:%s%s',
|
||||
$folder->getStorage()->getUid(),
|
||||
$folder->getIdentifier(),
|
||||
$fileName
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user