first commit
This commit is contained in:
commit
1218dd1517
12716 files changed
+989233
No files matched your search
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user