first commit

This commit is contained in:
salam committed 2026-10-19 08:18:39 +02:00
commit 1218dd1517
12716 files changed
+989233

No files matched your search

+116
View File
@@ -0,0 +1,116 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor;
/*
* 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!
*/
/**
* Represents an addon for CodeMirror
* @internal
*/
class Addon
{
/**
* @var string
*/
protected $identifier = '';
/**
* @var array
*/
protected $modes = [];
/**
* @var array
*/
protected $options = [];
/**
* @var array
*/
protected $cssFiles = [];
/**
* @param string $identifier
*/
public function __construct(string $identifier)
{
$this->identifier = $identifier;
}
/**
* @return string
*/
public function getIdentifier(): string
{
return $this->identifier;
}
/**
* @param array $modes
* @return self
*/
public function setModes(array $modes): Addon
{
$this->modes = $modes;
return $this;
}
/**
* @return array
*/
public function getModes(): array
{
return $this->modes;
}
/**
* @param array $options
* @return self
*/
public function setOptions(array $options): Addon
{
$this->options = $options;
return $this;
}
/**
* @return array
*/
public function getOptions(): array
{
return $this->options;
}
/**
* @param array $cssFiles
* @return self
*/
public function setCssFiles(array $cssFiles): Addon
{
$this->cssFiles = $cssFiles;
return $this;
}
/**
* @return array
*/
public function getCssFiles(): array
{
return $this->cssFiles;
}
}
@@ -0,0 +1,124 @@
<?php
namespace TYPO3\CMS\T3editor\Controller;
/*
* 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!
*/
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Http\JsonResponse;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;
/**
* Code completion for t3editor
* @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API.
*/
class CodeCompletionController
{
/**
* Loads all templates up to a given page id (walking the rootline) and
* cleans parts that are not required for the t3editor codecompletion.
*
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function loadCompletions(ServerRequestInterface $request): ResponseInterface
{
// Check whether access is granted (only admin have access to sys_template records):
if (!$GLOBALS['BE_USER']->isAdmin()) {
return new HtmlResponse($this->getLanguageService()->sL('LLL:EXT:t3editor/Resources/Private/Language/locallang.xlf:noPermission'), 500);
}
$pageId = (int)($request->getParsedBody()['pageId'] ?? $request->getQueryParams()['pageId']);
// Check whether there is a pageId given:
if (!$pageId) {
return new HtmlResponse($this->getLanguageService()->sL('LLL:EXT:t3editor/Resources/Private/Language/locallang.xlf:pageIDInteger'), 500);
}
// Fetch the templates
return (new JsonResponse())->setPayload($this->getMergedTemplates($pageId));
}
/**
* Gets merged templates by walking the rootline to a given page id.
*
* @todo oliver@typo3.org: Refactor this method and comment what's going on there
* @param int $pageId
* @return array Setup part of merged template records
*/
protected function getMergedTemplates($pageId)
{
$tsParser = GeneralUtility::makeInstance(ExtendedTemplateService::class);
// Gets the rootLine
$rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $pageId)->get();
// This generates the constants/config + hierarchy info for the template.
$tsParser->runThroughTemplates($rootLine);
// ts-setup & ts-constants of the currently edited template should not be included
// therefor we have to delete the last template from the stack
array_pop($tsParser->config);
array_pop($tsParser->constants);
$tsParser->linkObjects = true;
$tsParser->ext_regLinenumbers = false;
$tsParser->generateConfig();
$result = $this->treeWalkCleanup($tsParser->setup);
return $result;
}
/**
* Walks through a tree of TypoScript configuration an cleans it up.
*
* @TODO oliver@typo3.org: Define and comment why this is necessary and exactly happens below
* @param array $treeBranch TypoScript configuration or sub branch of it
* @return array Cleaned TypoScript branch
*/
private function treeWalkCleanup(array $treeBranch)
{
$cleanedTreeBranch = [];
foreach ($treeBranch as $key => $value) {
//type definition or value-assignment
if (substr($key, -1) !== '.') {
if ($value != '') {
if (mb_strlen($value) > 20) {
$value = mb_substr($value, 0, 20);
}
if (!isset($cleanedTreeBranch[$key])) {
$cleanedTreeBranch[$key] = [];
}
$cleanedTreeBranch[$key]['v'] = $value;
}
} else {
// subtree (definition of properties)
$subBranch = $this->treeWalkCleanup($value);
if ($subBranch) {
if (substr($key, -1) === '.') {
$key = rtrim($key, '.');
}
if (!isset($cleanedTreeBranch[$key])) {
$cleanedTreeBranch[$key] = [];
}
$cleanedTreeBranch[$key]['c'] = $subBranch;
}
}
}
return $cleanedTreeBranch;
}
/**
* @return LanguageService
*/
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}
@@ -0,0 +1,93 @@
<?php
namespace TYPO3\CMS\T3editor\Controller;
/*
* 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!
*/
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\JsonResponse;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Loads TSref information from a XML file an responds to an AJAX call.
* @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API.
*/
class TypoScriptReferenceController
{
/**
* @var \DOMDocument
*/
protected $xmlDoc;
/**
* Load TypoScript reference
*
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function loadReference(ServerRequestInterface $request): ResponseInterface
{
// Load the TSref XML information:
$this->loadFile(GeneralUtility::getFileAbsFileName('EXT:t3editor/Resources/Private/tsref.xml'));
return (new JsonResponse())->setPayload($this->getTypes());
}
/**
* Load XML file
*
* @param string $filepath
*/
protected function loadFile($filepath)
{
// Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
$previousValueOfEntityLoader = libxml_disable_entity_loader();
$this->xmlDoc = new \DOMDocument('1.0', 'utf-8');
$this->xmlDoc->loadXML(file_get_contents($filepath));
libxml_disable_entity_loader($previousValueOfEntityLoader);
// @TODO: oliver@typo3.org: I guess this is not required here
$this->xmlDoc->saveXML();
}
/**
* Get types from XML
*
* @return array
*/
protected function getTypes(): array
{
$types = $this->xmlDoc->getElementsByTagName('type');
$typeArr = [];
foreach ($types as $type) {
$typeId = $type->getAttribute('id');
$typeName = $type->getAttribute('name');
if (!$typeName) {
$typeName = $typeId;
}
$properties = $type->getElementsByTagName('property');
$propArr = [];
foreach ($properties as $property) {
$p = [];
$p['name'] = $property->getAttribute('name');
$p['type'] = $property->getAttribute('type');
$propArr[$property->getAttribute('name')] = $p;
}
$typeArr[$typeId] = [];
$typeArr[$typeId]['properties'] = $propArr;
$typeArr[$typeId]['name'] = $typeName;
if ($type->hasAttribute('extends')) {
$typeArr[$typeId]['extends'] = $type->getAttribute('extends');
}
}
return $typeArr;
}
}
@@ -0,0 +1,26 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor\Exception;
/*
* 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!
*/
use TYPO3\CMS\Core\Exception;
/**
* Exception thrown for invalid modes
* @internal
*/
class InvalidModeException extends Exception
{
}
@@ -0,0 +1,251 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor\Form\Element;
/*
* 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!
*/
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\T3editor\Exception\InvalidModeException;
use TYPO3\CMS\T3editor\Mode;
use TYPO3\CMS\T3editor\Registry\AddonRegistry;
use TYPO3\CMS\T3editor\Registry\ModeRegistry;
use TYPO3\CMS\T3editor\T3editor;
/**
* t3editor FormEngine widget
* @internal
*/
class T3editorElement extends AbstractFormElement
{
/**
* @var array
*/
protected $resultArray;
/**
* @var string
*/
protected $mode = '';
/**
* Default field information enabled for this element.
*
* @var array
*/
protected $defaultFieldInformation = [
'tcaDescription' => [
'renderType' => 'tcaDescription',
],
];
/**
* Default field wizards enabled for this element.
*
* @var array
*/
protected $defaultFieldWizard = [
'localizationStateSelector' => [
'renderType' => 'localizationStateSelector',
],
'otherLanguageContent' => [
'renderType' => 'otherLanguageContent',
'after' => [
'localizationStateSelector',
],
],
'defaultLanguageDifferences' => [
'renderType' => 'defaultLanguageDifferences',
'after' => [
'otherLanguageContent',
],
],
];
/**
* Render t3editor element
*
* @return array As defined in initializeResultArray() of AbstractNode
* @throws \TYPO3\CMS\T3editor\Exception\InvalidModeException
* @throws \InvalidArgumentException
* @throws \BadFunctionCallException
*/
public function render(): array
{
$this->resultArray = $this->initializeResultArray();
$this->resultArray['stylesheetFiles'][] = 'EXT:t3editor/Resources/Public/JavaScript/Contrib/cm/lib/codemirror.css';
$this->resultArray['stylesheetFiles'][] = 'EXT:t3editor/Resources/Public/Css/t3editor.css';
$this->resultArray['requireJsModules'][] = [
'TYPO3/CMS/T3editor/T3editor' => 'function(T3editor) {T3editor.observeEditorCandidates()}'
];
// Compile and register t3editor configuration
GeneralUtility::makeInstance(T3editor::class)->registerConfiguration();
$registeredAddons = AddonRegistry::getInstance()->getForMode($this->getMode()->getFormatCode());
foreach ($registeredAddons as $addon) {
foreach ($addon->getCssFiles() as $cssFile) {
$this->resultArray['stylesheetFiles'][] = $cssFile;
}
}
$parameterArray = $this->data['parameterArray'];
$attributes = [];
if (isset($parameterArray['fieldConf']['config']['rows']) && MathUtility::canBeInterpretedAsInteger($parameterArray['fieldConf']['config']['rows'])) {
$attributes['rows'] = $parameterArray['fieldConf']['config']['rows'];
}
$attributes['wrap'] = 'off';
$attributes['style'] = 'width:100%;';
$attributes['onchange'] = GeneralUtility::quoteJSvalue($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']);
$attributeString = GeneralUtility::implodeAttributes($attributes, true);
$editorHtml = $this->getHTMLCodeForEditor(
$parameterArray['itemFormElName'],
'text-monospace enable-tab',
$parameterArray['itemFormElValue'],
$attributeString,
$this->data['tableName'] . ' > ' . $this->data['fieldName'],
[
'target' => 0,
'effectivePid' => $this->data['effectivePid']
]
);
$fieldInformationResult = $this->renderFieldInformation();
$fieldInformationHtml = $fieldInformationResult['html'];
$this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $fieldInformationResult, false);
$fieldControlResult = $this->renderFieldControl();
$fieldControlHtml = $fieldControlResult['html'];
$this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $fieldControlResult, false);
$fieldWizardResult = $this->renderFieldWizard();
$fieldWizardHtml = $fieldWizardResult['html'];
$this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $fieldWizardResult, false);
$html = [];
$html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
$html[] = $fieldInformationHtml;
$html[] = '<div class="form-control-wrap">';
$html[] = '<div class="form-wizards-wrap">';
$html[] = '<div class="form-wizards-element">';
$html[] = '<div class="t3editor-wrapper">';
$html[] = $editorHtml;
$html[] = '</div>';
$html[] = '</div>';
if (!empty($fieldControlHtml)) {
$html[] = '<div class="form-wizards-items-aside">';
$html[] = '<div class="btn-group">';
$html[] = $fieldControlHtml;
$html[] = '</div>';
$html[] = '</div>';
}
if (!empty($fieldWizardHtml)) {
$html[] = '<div class="form-wizards-items-bottom">';
$html[] = $fieldWizardHtml;
$html[] = '</div>';
}
$html[] = '</div>';
$html[] = '</div>';
$html[] = '</div>';
$this->resultArray['html'] = implode(LF, $html);
return $this->resultArray;
}
/**
* Generates HTML with code editor
*
* @param string $name Name attribute of HTML tag
* @param string $class Class attribute of HTML tag
* @param string $content Content of the editor
* @param string $additionalParams Any additional editor parameters
* @param string $alt Alt attribute
* @param array $hiddenfields
*
* @return string Generated HTML code for editor
* @throws \TYPO3\CMS\T3editor\Exception\InvalidModeException
*/
protected function getHTMLCodeForEditor(
string $name,
string $class = '',
string $content = '',
string $additionalParams = '',
string $alt = '',
array $hiddenfields = []
): string {
$code = [];
$attributes = [];
$mode = $this->getMode();
$registeredAddons = AddonRegistry::getInstance()->getForMode($mode->getFormatCode());
$attributes['class'] = $class . ' t3editor';
$attributes['alt'] = $alt;
$attributes['id'] = 't3editor_' . md5($name);
$attributes['name'] = $name;
$settings = AddonRegistry::getInstance()->compileSettings($registeredAddons);
$addons = [];
foreach ($registeredAddons as $addon) {
$addons[] = $addon->getIdentifier();
}
$attributes['data-codemirror-config'] = json_encode([
'mode' => $mode->getIdentifier(),
'addons' => json_encode($addons),
'options' => json_encode($settings)
]);
$attributesString = '';
foreach ($attributes as $attribute => $value) {
$attributesString .= $attribute . '="' . htmlspecialchars((string)$value) . '" ';
}
$attributesString .= $additionalParams;
$code[] = '<textarea ' . $attributesString . '>' . htmlspecialchars($content) . '</textarea>';
if (!empty($hiddenfields)) {
foreach ($hiddenfields as $attributeName => $value) {
$code[] = '<input type="hidden" name="' . htmlspecialchars($attributeName) . '" value="' . htmlspecialchars((string)$value) . '" />';
}
}
return implode(LF, $code);
}
/**
* @return Mode
* @throws InvalidModeException
*/
protected function getMode(): Mode
{
$config = $this->data['parameterArray']['fieldConf']['config'];
if (!isset($config['format'])) {
return ModeRegistry::getInstance()->getDefaultMode();
}
$identifier = $config['format'];
if (strpos($config['format'], '/') !== false) {
$parts = explode('/', $config['format']);
$identifier = end($parts);
}
return ModeRegistry::getInstance()->getByFormatCode($identifier);
}
}
@@ -0,0 +1,61 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor\Hook;
/*
* 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!
*/
use TYPO3\CMS\Backend\Controller\File\EditFileController;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\T3editor\Exception\InvalidModeException;
use TYPO3\CMS\T3editor\Registry\ModeRegistry;
use TYPO3\CMS\T3editor\T3editor;
/**
* File edit hook for t3editor
* @internal This is a specific hook implementation and is not considered part of the Public TYPO3 API.
*/
class FileEditHook
{
/**
* Hook-function: inject t3editor JavaScript code before the page is compiled
* called in file_edit module
*
* @param array $parameters
* @param EditFileController $pObj
*
* @throws \InvalidArgumentException
*/
public function preOutputProcessingHook(array $parameters, EditFileController $pObj)
{
// Compile and register t3editor configuration
GeneralUtility::makeInstance(T3editor::class)->registerConfiguration();
$target = '';
if (isset($parameters['target']) && is_string($parameters['target'])) {
$target = $parameters['target'];
}
$fileExtension = ResourceFactory::getInstance()->retrieveFileOrFolderObject($target)->getExtension();
$modeRegistry = GeneralUtility::makeInstance(ModeRegistry::class);
try {
$mode = $modeRegistry->getByFileExtension($fileExtension);
} catch (InvalidModeException $e) {
$mode = $modeRegistry->getDefaultMode();
}
$parameters['dataColumnDefinition']['config']['renderType'] = 't3editor';
$parameters['dataColumnDefinition']['config']['format'] = $mode->getFormatCode();
}
}
+115
View File
@@ -0,0 +1,115 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor;
/*
* 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!
*/
/**
* Represents a mode for CodeMirror
* @internal
*/
class Mode
{
/**
* @var string
*/
protected $identifier = '';
/**
* @var string
*/
protected $formatCode = '';
/**
* @var array
*/
protected $fileExtensions = [];
/**
* @var bool
*/
protected $isDefault = false;
/**
* @param string $identifier
*/
public function __construct(string $identifier)
{
$this->identifier = $identifier;
}
/**
* @return string
*/
public function getIdentifier(): string
{
return $this->identifier;
}
/**
* @return string
*/
public function getFormatCode(): string
{
return $this->formatCode;
}
/**
* @param string $formatCode
* @return Mode
*/
public function setFormatCode(string $formatCode): Mode
{
$this->formatCode = $formatCode;
return $this;
}
/**
* @param array $fileExtensions
* @return self
*/
public function bindToFileExtensions(array $fileExtensions): Mode
{
$this->fileExtensions = $fileExtensions;
return $this;
}
/**
* @return array
*/
public function getBoundFileExtensions(): array
{
return $this->fileExtensions;
}
/**
* @return Mode
*/
public function setAsDefault(): Mode
{
$this->isDefault = true;
return $this;
}
/**
* @return bool
*/
public function isDefault(): bool
{
return $this->isDefault;
}
}
@@ -0,0 +1,85 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor\Registry;
/*
* 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!
*/
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\T3editor\Addon;
/**
* Registers and holds t3editor modes
* @internal
*/
class AddonRegistry implements SingletonInterface
{
/**
* @var Addon[]
*/
protected $registeredAddons = [];
/**
* @return self
* @throws \InvalidArgumentException
*/
public static function getInstance(): AddonRegistry
{
return GeneralUtility::makeInstance(static::class);
}
/**
* Registers addons for global use in t3editor
*
* @param Addon $addon
* @return self
*/
public function register(Addon $addon): AddonRegistry
{
$this->registeredAddons[$addon->getIdentifier()] = $addon;
return $this;
}
/**
* @param string $mode
* @return Addon[]
*/
public function getForMode(string $mode = ''): array
{
$addons = [];
foreach ($this->registeredAddons as $addon) {
if (empty($addon->getModes()) || in_array($mode, $addon->getModes(), true)) {
$addons[] = $addon;
}
}
return $addons;
}
/**
* @param Addon[] $addons
* @return array
*/
public function compileSettings(array $addons): array
{
$settings = [];
foreach ($addons as $addon) {
$settings = array_merge($settings, $addon->getOptions());
}
return $settings;
}
}
@@ -0,0 +1,141 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor\Registry;
/*
* 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!
*/
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\T3editor\Exception\InvalidModeException;
use TYPO3\CMS\T3editor\Mode;
/**
* Registers and holds t3editor modes
* @internal
*/
class ModeRegistry implements SingletonInterface
{
/**
* @var Mode[]
*/
protected $registeredModes = [];
/**
* @var Mode
*/
protected $defaultMode;
/**
* @return self
* @throws \InvalidArgumentException
*/
public static function getInstance(): ModeRegistry
{
return GeneralUtility::makeInstance(static::class);
}
/**
* Registers modes for t3editor
*
* @param Mode $mode
* @return self
*/
public function register(Mode $mode): ModeRegistry
{
$this->registeredModes[$mode->getIdentifier()] = $mode;
if ($mode->isDefault()) {
$this->defaultMode = $mode;
}
return $this;
}
/**
* Removes registered modes
*
* @param string $identifier
* @return self
*/
public function unregister(string $identifier): ModeRegistry
{
if (isset($this->registeredModes[$identifier])) {
unset($this->registeredModes[$identifier]);
}
return $this;
}
/**
* @param string $identifier
* @return bool
*/
public function isRegistered(string $identifier): bool
{
return isset($this->registeredModes[$identifier]);
}
/**
* @param string $identifier
* @return Mode
* @throws InvalidModeException
*/
public function getByIdentifier(string $identifier): Mode
{
if ($this->isRegistered($identifier)) {
return $this->registeredModes[$identifier];
}
throw new InvalidModeException('Tried to get unregistered t3editor mode "' . $identifier . '"', 1499710202);
}
/**
* @param string $formatCode
* @return Mode
* @throws InvalidModeException
*/
public function getByFormatCode(string $formatCode): Mode
{
foreach ($this->registeredModes as $mode) {
if ($mode->getFormatCode() === $formatCode) {
return $mode;
}
}
throw new InvalidModeException('Tried to get unregistered t3editor mode by format code "' . $formatCode . '"', 1499710203);
}
/**
* @param string $fileExtension
* @return Mode
* @throws InvalidModeException
*/
public function getByFileExtension(string $fileExtension): Mode
{
foreach ($this->registeredModes as $mode) {
if (in_array($fileExtension, $mode->getBoundFileExtensions(), true)) {
return $mode;
}
}
throw new InvalidModeException('Cannot find a registered mode for requested file extension "' . $fileExtension . '"', 1500306488);
}
/**
* @return Mode
*/
public function getDefaultMode(): Mode
{
return $this->defaultMode;
}
}
+156
View File
@@ -0,0 +1,156 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\T3editor;
/*
* 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!
*/
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\T3editor\Registry\AddonRegistry;
use TYPO3\CMS\T3editor\Registry\ModeRegistry;
/**
* Provides necessary code to setup a t3editor instance in FormEngine
* @internal
*/
class T3editor implements SingletonInterface
{
/**
* @var array
*/
protected $configuration;
/**
* Registers the configuration and bootstraps the modes / addons.
*
* @throws \InvalidArgumentException
*/
public function registerConfiguration()
{
$configuration = $this->buildConfiguration();
if (isset($configuration['modes'])) {
$modeRegistry = ModeRegistry::getInstance();
foreach ($configuration['modes'] as $formatCode => $mode) {
$modeInstance = GeneralUtility::makeInstance(Mode::class, $mode['module'])->setFormatCode($formatCode);
if (!empty($mode['extensions']) && is_array($mode['extensions'])) {
$modeInstance->bindToFileExtensions($mode['extensions']);
}
if (isset($mode['default']) && $mode['default'] === true) {
$modeInstance->setAsDefault();
}
$modeRegistry->register($modeInstance);
}
}
$addonRegistry = GeneralUtility::makeInstance(AddonRegistry::class);
if (isset($configuration['addons'])) {
foreach ($configuration['addons'] as $addon) {
$addonInstance = GeneralUtility::makeInstance(Addon::class, $addon['module']);
if (!empty($addon['cssFiles']) && is_array($addon['cssFiles'])) {
$addonInstance->setCssFiles($addon['cssFiles']);
}
if (!empty($addon['options']) && is_array($addon['options'])) {
$addonInstance->setOptions($addon['options']);
}
if (!empty($addon['modes']) && is_array($addon['modes'])) {
$addonInstance->setModes($addon['modes']);
}
$addonRegistry->register($addonInstance);
}
}
}
/**
* Compiles the configuration for t3editor. Configuration is stored in caching framework.
*
* @return array
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException
* @throws \InvalidArgumentException
*/
protected function buildConfiguration(): array
{
if ($this->configuration !== null) {
return $this->configuration;
}
$this->configuration = [
'modes' => [],
'addons' => [],
];
$cache = $this->getCache();
$cacheIdentifier = $this->generateCacheIdentifier('T3editorConfiguration');
$configurationFromCache = $cache->get($cacheIdentifier);
if ($configurationFromCache !== false) {
$this->configuration = $configurationFromCache;
} else {
$packageManager = GeneralUtility::makeInstance(PackageManager::class);
$packages = $packageManager->getActivePackages();
foreach ($packages as $package) {
$configurationPath = $package->getPackagePath() . 'Configuration/Backend/T3editor';
$modesFileNameForPackage = $configurationPath . '/Modes.php';
if (is_file($modesFileNameForPackage)) {
$definedModes = require_once $modesFileNameForPackage;
if (is_array($definedModes)) {
$this->configuration['modes'] = array_merge($this->configuration['modes'], $definedModes);
}
}
$addonsFileNameForPackage = $configurationPath . '/Addons.php';
if (is_file($addonsFileNameForPackage)) {
$definedAddons = require_once $addonsFileNameForPackage;
if (is_array($definedAddons)) {
$this->configuration['addons'] = array_merge($this->configuration['addons'], $definedAddons);
}
}
}
$cache->set($cacheIdentifier, $this->configuration);
}
return $this->configuration;
}
/**
* @param string $key
* @return string
*/
protected function generateCacheIdentifier(string $key): string
{
return $key . '_' . sha1(TYPO3_version . Environment::getProjectPath() . $key);
}
/**
* @return FrontendInterface
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \InvalidArgumentException
*/
protected function getCache(): FrontendInterface
{
return GeneralUtility::makeInstance(CacheManager::class)->getCache('assets');
}
}