TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Utility\DiffUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Renders the diff-view of default language record content compared with what the record was originally
|
||||
* translated from. Will render content if any is found in the internal array.
|
||||
*
|
||||
* This is typically used of renderTypes that are based on text input
|
||||
*/
|
||||
class DefaultLanguageDifferences extends AbstractNode
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DiffUtility $diffUtility,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Render the diff view if enabled
|
||||
*
|
||||
* @return array Result array
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$result = $this->initializeResultArray();
|
||||
|
||||
$row = $this->data['databaseRow'];
|
||||
$table = $this->data['tableName'];
|
||||
$fieldName = $this->data['fieldName'];
|
||||
$fieldConfig = $this->data['processedTca']['columns'][$fieldName];
|
||||
$l10nDisplay = $this->data['parameterArray']['fieldConf']['l10n_display'] ?? '';
|
||||
$defaultLanguageRow = $this->data['defaultLanguageRow'] ?? null;
|
||||
$defaultLanguageDiffRow = $this->data['defaultLanguageDiffRow'][$table . ':' . $row['uid']] ?? null;
|
||||
|
||||
if (!is_array($defaultLanguageDiffRow)
|
||||
|| GeneralUtility::inList($l10nDisplay, 'hideDiff')
|
||||
|| GeneralUtility::inList($l10nDisplay, 'defaultAsReadonly')
|
||||
|| !isset($defaultLanguageDiffRow[$fieldName])
|
||||
|| $fieldConfig['config']['type'] === 'inline'
|
||||
|| $fieldConfig['config']['type'] === 'file'
|
||||
|| $fieldConfig['config']['type'] === 'flex'
|
||||
) {
|
||||
// Early return if there is no diff row or if display is disabled
|
||||
return $result;
|
||||
}
|
||||
|
||||
$languageService = $this->getLanguageService();
|
||||
$html = [];
|
||||
if ((string)$defaultLanguageDiffRow[$fieldName] !== (string)$defaultLanguageRow[$fieldName]) {
|
||||
// Create diff-result:
|
||||
$diffResult = $this->diffUtility->diff(
|
||||
(string)BackendUtility::getProcessedValue($table, $fieldName, $defaultLanguageDiffRow[$fieldName], 0, true, false, 0, true, 0, $defaultLanguageRow),
|
||||
(string)BackendUtility::getProcessedValue($table, $fieldName, $defaultLanguageRow[$fieldName], 0, true, false, 0, true, 0, $defaultLanguageDiffRow)
|
||||
);
|
||||
$html[] = '<div class="t3-form-original-language-diff">';
|
||||
$html[] = '<div class="t3-form-original-language-diffheader">';
|
||||
$html[] = htmlspecialchars($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.changeInOrig'));
|
||||
$html[] = '</div>';
|
||||
$html[] = '<div class="t3-form-original-language-diffcontent">';
|
||||
$html[] = '<div class="diff">';
|
||||
$html[] = '<div class="diff-item">';
|
||||
$html[] = '<div class="diff-item-result diff-item-result-inline">' . $diffResult . '</div>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</div>';
|
||||
}
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Core\DataHandling\Localization\State;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
|
||||
use TYPO3\CMS\Core\Utility\StringUtility;
|
||||
|
||||
/**
|
||||
* Allows to define the localization state per field.
|
||||
*/
|
||||
class LocalizationStateSelector extends AbstractNode
|
||||
{
|
||||
/**
|
||||
* Render the radio buttons if enabled
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
$result = $this->initializeResultArray();
|
||||
|
||||
$fieldName = $this->data['fieldName'];
|
||||
$fieldId = StringUtility::getUniqueId('formengine-localization-state-selector-');
|
||||
$l10nStateFieldName = 'l10n_state';
|
||||
|
||||
$localizationState = State::fromJSON(
|
||||
$this->data['tableName'],
|
||||
$this->data['databaseRow'][$l10nStateFieldName] ?? null
|
||||
);
|
||||
|
||||
if (
|
||||
$localizationState === null
|
||||
|| !isset($this->data['defaultLanguageRow'])
|
||||
|| !isset($this->data['processedTca']['columns'][$fieldName]['config']['behaviour']['allowLanguageSynchronization'])
|
||||
|| !$this->data['processedTca']['columns'][$fieldName]['config']['behaviour']['allowLanguageSynchronization']
|
||||
) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$l10nParentFieldName = $this->data['processedTca']['ctrl']['transOrigPointerField'] ?? null;
|
||||
$l10nSourceFieldName = $this->data['processedTca']['ctrl']['translationSource'] ?? null;
|
||||
|
||||
$sourceLanguageTitle = '';
|
||||
$fieldValueInParentRow = '';
|
||||
$fieldValueInSourceRow = null;
|
||||
if ($l10nParentFieldName && $this->data['databaseRow'][$l10nParentFieldName] > 0) {
|
||||
if ($l10nSourceFieldName && $this->data['databaseRow'][$l10nSourceFieldName] > 0) {
|
||||
$languageField = $this->data['processedTca']['ctrl']['languageField'] ?? null;
|
||||
if ($languageField
|
||||
&& isset($this->data['sourceLanguageRow'][$languageField])
|
||||
&& $this->data['sourceLanguageRow'][$languageField] > 0
|
||||
) {
|
||||
$languageUidOfSourceRow = $this->data['sourceLanguageRow'][$languageField];
|
||||
$sourceLanguageTitle = $this->data['systemLanguageRows'][$languageUidOfSourceRow]['title'] ?? '';
|
||||
$fieldValueInSourceRow = $this->data['sourceLanguageRow'][$fieldName] ?? null;
|
||||
}
|
||||
}
|
||||
$fieldValueInParentRow = (string)$this->data['defaultLanguageRow'][$fieldName];
|
||||
}
|
||||
|
||||
$fieldElementName = 'data[' . htmlspecialchars($this->data['tableName']) . ']'
|
||||
. '[' . htmlspecialchars((string)$this->data['databaseRow']['uid']) . ']'
|
||||
. '[' . htmlspecialchars($l10nStateFieldName) . ']'
|
||||
. '[' . htmlspecialchars($this->data['fieldName']) . ']';
|
||||
|
||||
$html = [];
|
||||
$html[] = '<div class="t3js-l10n-state-container">';
|
||||
$html[] = '<div class="form-label">';
|
||||
$html[] = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:localizationStateSelector.header');
|
||||
$html[] = '</div>';
|
||||
$html[] = '<div class="form-check">';
|
||||
$html[] = '<input';
|
||||
$html[] = ' id="' . $fieldId . '-custom"';
|
||||
$html[] = ' type="radio"';
|
||||
$html[] = ' name="' . htmlspecialchars($fieldElementName) . '"';
|
||||
$html[] = ' class="form-check-input t3js-l10n-state-custom"';
|
||||
$html[] = ' value="custom"';
|
||||
$html[] = $localizationState->isCustomState($fieldName) ? ' checked="checked"' : '';
|
||||
$html[] = ' data-original-language-value=""';
|
||||
$html[] = '>';
|
||||
$html[] = '<label';
|
||||
$html[] = ' for="' . $fieldId . '-custom"';
|
||||
$html[] = ' class="form-check-label"';
|
||||
$html[] = '>';
|
||||
$html[] = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:localizationStateSelector.customValue');
|
||||
$html[] = '</label>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '<div class="form-check">';
|
||||
$html[] = '<input';
|
||||
$html[] = ' id="' . $fieldId . '-parent"';
|
||||
$html[] = ' type="radio"';
|
||||
$html[] = ' name="' . htmlspecialchars($fieldElementName) . '"';
|
||||
$html[] = ' class="form-check-input"';
|
||||
$html[] = ' value="parent"';
|
||||
$html[] = $localizationState->isParentState($fieldName) ? ' checked="checked"' : '';
|
||||
$html[] = ' data-original-language-value="' . htmlspecialchars((string)$fieldValueInParentRow) . '"';
|
||||
$html[] = '>';
|
||||
$html[] = '<label';
|
||||
$html[] = ' for="' . $fieldId . '-parent"';
|
||||
$html[] = ' class="form-check-label"';
|
||||
$html[] = '>';
|
||||
$html[] = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:localizationStateSelector.defaultLanguageValue');
|
||||
$html[] = '</label>';
|
||||
$html[] = '</div>';
|
||||
if ($fieldValueInSourceRow !== null) {
|
||||
$html[] = '<div class="form-check">';
|
||||
$html[] = '<input';
|
||||
$html[] = ' id="' . $fieldId . '-source"';
|
||||
$html[] = ' type="radio"';
|
||||
$html[] = ' name="' . htmlspecialchars($fieldElementName) . '"';
|
||||
$html[] = ' class="form-check-input"';
|
||||
$html[] = ' value="source"';
|
||||
$html[] = $localizationState->isSourceState($fieldName) ? ' checked="checked"' : '';
|
||||
$html[] = ' data-original-language-value="' . htmlspecialchars((string)$fieldValueInSourceRow) . '"';
|
||||
$html[] = '>';
|
||||
$html[] = '<label';
|
||||
$html[] = ' for="' . $fieldId . '-source"';
|
||||
$html[] = ' class="form-check-label"';
|
||||
$html[] = '>';
|
||||
$html[] = sprintf($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:localizationStateSelector.sourceLanguageValue'), htmlspecialchars($sourceLanguageTitle));
|
||||
$html[] = '</label>';
|
||||
$html[] = '</div>';
|
||||
}
|
||||
$html[] = '</div>';
|
||||
|
||||
$result['javaScriptModules'][] = JavaScriptModuleInstruction::create(
|
||||
'@typo3/backend/form-engine/field-wizard/localization-state-selector.js'
|
||||
)->instance($fieldElementName);
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Render values of "other" languages. If editing a localized row, this is typically
|
||||
* the content value of the according default record, but it may render field values
|
||||
* of other languages too, depending on configuration.
|
||||
*/
|
||||
class OtherLanguageContent extends AbstractNode
|
||||
{
|
||||
public function __construct(
|
||||
private readonly IconFactory $iconFactory,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Render other language content if enabled.
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$result = $this->initializeResultArray();
|
||||
|
||||
$fieldName = $this->data['fieldName'];
|
||||
$fieldConfig = $this->data['processedTca']['columns'][$fieldName];
|
||||
$fieldType = $fieldConfig['config']['type'];
|
||||
$l10nDisplay = $this->data['parameterArray']['fieldConf']['l10n_display'] ?? '';
|
||||
$defaultLanguageRow = $this->data['defaultLanguageRow'] ?? null;
|
||||
if (!is_array($defaultLanguageRow)
|
||||
|| GeneralUtility::inList($l10nDisplay, 'hideDiff')
|
||||
|| GeneralUtility::inList($l10nDisplay, 'defaultAsReadonly')
|
||||
|| $fieldType === 'inline'
|
||||
|| $fieldType === 'file'
|
||||
|| $fieldType === 'flex'
|
||||
|| (in_array($fieldType, ['select', 'category', 'group'], true) && isset($fieldConfig['config']['MM']))
|
||||
) {
|
||||
// Early return if there is no default language row or the display is disabled
|
||||
return $result;
|
||||
}
|
||||
|
||||
$table = $this->data['tableName'];
|
||||
$html = [];
|
||||
$defaultLanguageValue = BackendUtility::getProcessedValue(
|
||||
$table,
|
||||
$fieldName,
|
||||
$defaultLanguageRow[$fieldName],
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
$defaultLanguageRow['uid'],
|
||||
true,
|
||||
$defaultLanguageRow['pid'],
|
||||
$defaultLanguageRow
|
||||
) ?? '';
|
||||
if ($defaultLanguageValue !== '') {
|
||||
$iconIdentifier = ($this->data['systemLanguageRows'][0]['flagIconIdentifier'] ?? false) ?: 'flags-multiple';
|
||||
$html[] = '<div class="t3-form-original-language">';
|
||||
$html[] = $this->iconFactory->getIcon($iconIdentifier, IconSize::SMALL)->render();
|
||||
$html[] = $this->previewFieldValue($defaultLanguageValue);
|
||||
$html[] = '</div>';
|
||||
}
|
||||
$additionalPreviewLanguages = $this->data['additionalLanguageRows'];
|
||||
foreach ($additionalPreviewLanguages as $previewLanguage) {
|
||||
$defaultLanguageValue = BackendUtility::getProcessedValue(
|
||||
$table,
|
||||
$fieldName,
|
||||
$previewLanguage[$fieldName],
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
$previewLanguage
|
||||
) ?? '';
|
||||
if ($defaultLanguageValue !== '') {
|
||||
$html[] = '<div class="t3-form-original-language">';
|
||||
$html[] = $this->iconFactory->getIcon($this->data['systemLanguageRows'][$previewLanguage['language_tag']]['flagIconIdentifier'], IconSize::SMALL)->render();
|
||||
$html[] = $this->previewFieldValue($defaultLanguageValue);
|
||||
$html[] = '</div>';
|
||||
}
|
||||
}
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering preview output of a field value which is not shown as a form field but just outputted.
|
||||
*
|
||||
* @param string $value The value to output
|
||||
* @return string HTML formatted output
|
||||
*/
|
||||
protected function previewFieldValue($value)
|
||||
{
|
||||
return nl2br(htmlspecialchars((string)$value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
|
||||
use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
|
||||
use TYPO3\CMS\Core\Resource\ProcessedFile;
|
||||
use TYPO3\CMS\Core\Resource\ResourceFactory;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Render cropped thumbnails for default and additional preview
|
||||
* languages by respecting the corresponding cropping configuration.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class OtherLanguageThumbnails extends AbstractNode
|
||||
{
|
||||
public function __construct(
|
||||
private readonly IconFactory $iconFactory,
|
||||
private readonly ResourceFactory $resourceFactory,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Render cropped thumbnails from other language rows
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$result = $this->initializeResultArray();
|
||||
$fieldConfig = $this->data['parameterArray']['fieldConf'];
|
||||
$l10nDisplay = $fieldConfig['l10n_display'] ?? '';
|
||||
$cropVariants = $fieldConfig['config']['cropVariants'] ?? ['default' => []];
|
||||
$defaultLanguageRow = $this->data['defaultLanguageRow'] ?? null;
|
||||
|
||||
if (!is_array($defaultLanguageRow)
|
||||
|| !is_array($cropVariants)
|
||||
|| $cropVariants === []
|
||||
|| $fieldConfig['config']['type'] !== 'imageManipulation'
|
||||
|| GeneralUtility::inList($l10nDisplay, 'hideDiff')
|
||||
|| GeneralUtility::inList($l10nDisplay, 'defaultAsReadonly')
|
||||
) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$html = [];
|
||||
$languages = [$defaultLanguageRow['language_tag'] => $defaultLanguageRow] + ($this->data['additionalLanguageRows'] ?? []);
|
||||
|
||||
foreach ($languages as $sysLanguageUid => $languageRow) {
|
||||
$file = null;
|
||||
$fileUid = (int)($languageRow['uid_local'] ?? 0);
|
||||
|
||||
if (!$fileUid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$file = $this->resourceFactory->getFileObject($fileUid);
|
||||
} catch (FileDoesNotExistException|\InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$processedImages = [];
|
||||
$cropVariantCollection = CropVariantCollection::create((string)($languageRow['crop'] ?? ''), $cropVariants);
|
||||
|
||||
foreach (array_keys($cropVariants) as $variant) {
|
||||
$processedFileUrl = $file
|
||||
->process(
|
||||
ProcessedFile::CONTEXT_IMAGECROPSCALEMASK,
|
||||
[
|
||||
'maxWidth' => '145',
|
||||
'maxHeight' => '45',
|
||||
'crop' => $cropVariantCollection->getCropArea($variant)->makeAbsoluteBasedOnFile($file),
|
||||
]
|
||||
)
|
||||
->getPublicUrl() ?? '';
|
||||
|
||||
if ($processedFileUrl !== '') {
|
||||
$processedImages[] = '<img ' . GeneralUtility::implodeAttributes([
|
||||
'loading' => 'lazy',
|
||||
'src' => $processedFileUrl,
|
||||
'alt' => $languageRow['alternative'] ?? $file->getProperty('alternative') ?? '',
|
||||
'title' => $languageRow['title'] ?? $file->getProperty('title') ?? '',
|
||||
], true) . ' />';
|
||||
}
|
||||
}
|
||||
|
||||
if ($processedImages !== []) {
|
||||
$iconIdentifier = $this->data['systemLanguageRows'][(int)$sysLanguageUid]['flagIconIdentifier'] ?? 'flags-multiple';
|
||||
$html[] = '<div class="t3-form-original-language">';
|
||||
$html[] = $this->iconFactory->getIcon($iconIdentifier, IconSize::SMALL)->render();
|
||||
$html[] = implode(LF, $processedImages);
|
||||
$html[] = '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Type\Bitmask\Permission;
|
||||
|
||||
/**
|
||||
* Render details of selected records,
|
||||
* typically used with type='group'.
|
||||
*/
|
||||
class RecordsOverview extends AbstractNode
|
||||
{
|
||||
public function __construct(
|
||||
private readonly IconFactory $iconFactory,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Render table with record details
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
$result = $this->initializeResultArray();
|
||||
|
||||
$parameterArray = $this->data['parameterArray'];
|
||||
$selectedItems = $parameterArray['itemFormElValue'];
|
||||
|
||||
$recordsOverviewHtml = [];
|
||||
foreach ($selectedItems as $selectedItem) {
|
||||
$title = (string)$selectedItem['title'];
|
||||
if (empty($title)) {
|
||||
$title = '[' . $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title') . ']';
|
||||
}
|
||||
$shortenedTitle = BackendUtility::cropToTitleLength($title);
|
||||
$linkedIcon = BackendUtility::wrapClickMenuOnIcon(
|
||||
$this->iconFactory->getIconForRecord($selectedItem['table'], $selectedItem['row'], IconSize::SMALL)->render(),
|
||||
$selectedItem['table'],
|
||||
$selectedItem['uid']
|
||||
);
|
||||
$linkedTitle = BackendUtility::wrapClickMenuOnIcon(
|
||||
htmlspecialchars($shortenedTitle),
|
||||
$selectedItem['table'],
|
||||
$selectedItem['uid']
|
||||
);
|
||||
$pathToContainingPage = BackendUtility::getRecordPath($selectedItem['row']['pid'], $this->getBackendUserAuthentication()->getPagePermsClause(Permission::PAGE_SHOW), 0);
|
||||
|
||||
$recordsOverviewHtml[] = '<tr>';
|
||||
$recordsOverviewHtml[] = '<td class="col-icon">';
|
||||
$recordsOverviewHtml[] = $linkedIcon;
|
||||
$recordsOverviewHtml[] = '</td>';
|
||||
$recordsOverviewHtml[] = '<td class="col-title">';
|
||||
$recordsOverviewHtml[] = $linkedTitle;
|
||||
$recordsOverviewHtml[] = '<span class="text-variant">';
|
||||
$recordsOverviewHtml[] = ' [' . $selectedItem['uid'] . ']';
|
||||
$recordsOverviewHtml[] = ' ' . htmlspecialchars($pathToContainingPage);
|
||||
$recordsOverviewHtml[] = '</span>';
|
||||
$recordsOverviewHtml[] = '</td>';
|
||||
$recordsOverviewHtml[] = '</tr>';
|
||||
}
|
||||
|
||||
$html = [];
|
||||
if (!empty($recordsOverviewHtml)) {
|
||||
$html[] = '<div class="table-fit mt-1">';
|
||||
$html[] = '<table class="table">';
|
||||
$html[] = '<tbody>';
|
||||
$html[] = implode(LF, $recordsOverviewHtml);
|
||||
$html[] = '</tbody>';
|
||||
$html[] = '</table>';
|
||||
$html[] = '</div>';
|
||||
}
|
||||
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getBackendUserAuthentication(): BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
|
||||
|
||||
/**
|
||||
* Render thumbnails of icons,
|
||||
* typically used with type=select.
|
||||
*/
|
||||
class SelectIcons extends AbstractNode
|
||||
{
|
||||
/**
|
||||
* Render thumbnails of selected files
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$selectIcons = [];
|
||||
$result = $this->initializeResultArray();
|
||||
|
||||
$parameterArray = $this->data['parameterArray'];
|
||||
$selectItems = $parameterArray['fieldConf']['config']['items'];
|
||||
|
||||
$selectItemCounter = 0;
|
||||
foreach ($selectItems as $item) {
|
||||
if ($item['value'] === '--div--') {
|
||||
continue;
|
||||
}
|
||||
$icon = !empty($item['icon']) ? FormEngineUtility::getIconHtml($item['icon'], $item['label'], $item['label']) : '';
|
||||
if ($icon) {
|
||||
$fieldValue = $this->data['databaseRow'][$this->data['fieldName']];
|
||||
$selectIcons[] = [
|
||||
'title' => $item['label'],
|
||||
'active' => ($fieldValue[0] ?? false) === (string)($item['value'] ?? ''),
|
||||
'icon' => $icon,
|
||||
'index' => $selectItemCounter,
|
||||
];
|
||||
}
|
||||
$selectItemCounter++;
|
||||
}
|
||||
|
||||
$html = [];
|
||||
if (!empty($selectIcons)) {
|
||||
$html[] = '<div class="t3js-forms-select-single-icons form-wizard-icon-list">';
|
||||
foreach ($selectIcons as $selectIcon) {
|
||||
$active = $selectIcon['active'] ? ' active' : '';
|
||||
$html[] = '<div class="form-wizard-icon-list-item">';
|
||||
$html[] = '<button type="button" class="' . $active . '" title="' . htmlspecialchars($selectIcon['title'], ENT_COMPAT, 'UTF-8', false) . '" data-select-index="' . htmlspecialchars((string)$selectIcon['index']) . '">';
|
||||
$html[] = $selectIcon['icon'];
|
||||
$html[] = '</button>';
|
||||
$html[] = '</div>';
|
||||
}
|
||||
$html[] = '</div>';
|
||||
}
|
||||
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
|
||||
|
||||
/**
|
||||
* Field wizard to toggle field required state for the "shortcut" field.
|
||||
*
|
||||
* This element injects a JS module so the client can re-evaluate
|
||||
* the required state when "shortcut_mode" changes.
|
||||
*/
|
||||
class ShortcutValidation extends AbstractNode
|
||||
{
|
||||
public function render(): array
|
||||
{
|
||||
$result['javaScriptModules']['requiredByCondition'] = JavaScriptModuleInstruction::create(
|
||||
'@typo3/backend/form-engine/field-wizard/shortcut-validation.js'
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?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\Backend\Form\FieldWizard;
|
||||
|
||||
use TYPO3\CMS\Backend\Form\AbstractNode;
|
||||
use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Site\Entity\Site;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Render list of tables and link to element browser,
|
||||
* typically used with type=group and internal_type=db.
|
||||
*/
|
||||
class TableList extends AbstractNode
|
||||
{
|
||||
public function __construct(
|
||||
private readonly IconFactory $iconFactory,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Render table buttons
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
$result = $this->initializeResultArray();
|
||||
|
||||
$parameterArray = $this->data['parameterArray'];
|
||||
$config = $parameterArray['fieldConf']['config'];
|
||||
$itemName = $parameterArray['itemFormElName'];
|
||||
|
||||
if (empty($config['allowed']) || !is_string($config['allowed'])) {
|
||||
// No handling if the field has no, or funny "allowed" settings.
|
||||
return $result;
|
||||
}
|
||||
|
||||
$allowed = GeneralUtility::trimExplode(',', $config['allowed'], true);
|
||||
$allowedTablesHtml = [];
|
||||
foreach ($allowed as $tableName) {
|
||||
if ($tableName === '*') {
|
||||
$label = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.allTables');
|
||||
$allowedTablesHtml[] = '<span>';
|
||||
$allowedTablesHtml[] = htmlspecialchars($label);
|
||||
$allowedTablesHtml[] = '</span>';
|
||||
} else {
|
||||
$tableSchema = $this->data['tcaSchemata']->has($tableName) ? $this->data['tcaSchemata']->get($tableName) : null;
|
||||
$label = $languageService->sL($tableSchema?->getTitle() ?? '');
|
||||
$icon = $this->iconFactory->getIconForRecord($tableName, [], IconSize::SMALL)->render();
|
||||
if ((bool)($config['fieldControl']['elementBrowser']['disabled'] ?? false)) {
|
||||
$allowedTablesHtml[] = '<span class="tablelist-item-nolink">';
|
||||
$allowedTablesHtml[] = $icon;
|
||||
$allowedTablesHtml[] = htmlspecialchars($label);
|
||||
$allowedTablesHtml[] = '</span>';
|
||||
} else {
|
||||
// Initialize attributes
|
||||
$attributes = [
|
||||
'class' => 'btn btn-default t3js-element-browser',
|
||||
'data-mode' => $tableName === 'sys_file' ? 'file' : 'db',
|
||||
'data-field-reference' => $itemName,
|
||||
'data-allowed-types' => $tableName,
|
||||
];
|
||||
|
||||
// Add the entry point - if found
|
||||
$attributes = $this->addEntryPoint($tableName, $config, $attributes);
|
||||
|
||||
$allowedTablesHtml[] = '<button ' . GeneralUtility::implodeAttributes($attributes, true) . '>';
|
||||
$allowedTablesHtml[] = $icon;
|
||||
$allowedTablesHtml[] = htmlspecialchars($label);
|
||||
$allowedTablesHtml[] = '</button>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html = [];
|
||||
$html[] = '<div class="form-text">';
|
||||
$html[] = implode(LF, $allowedTablesHtml);
|
||||
$html[] = '</div>';
|
||||
|
||||
$result['html'] = implode(LF, $html);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to resolve a configured default entry point - page / folder
|
||||
* to be expanded - and add it to the attributes if found.
|
||||
*/
|
||||
protected function addEntryPoint(string $tableName, array $fieldConfig, array $attributes): array
|
||||
{
|
||||
if (!isset($fieldConfig['elementBrowserEntryPoints']) || !is_array($fieldConfig['elementBrowserEntryPoints'])) {
|
||||
// Early return in case no entry points are defined
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
// Fetch the configured value (which might be a marker) - falls back to _default
|
||||
$entryPoint = (string)($fieldConfig['elementBrowserEntryPoints'][$tableName] ?? $fieldConfig['elementBrowserEntryPoints']['_default'] ?? '');
|
||||
|
||||
if ($entryPoint === '') {
|
||||
// In case no entry point exists for the given table and also no default is defined, return
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
// Check and resolve possible marker
|
||||
if (str_starts_with($entryPoint, '###') && str_ends_with($entryPoint, '###')) {
|
||||
if ($entryPoint === '###CURRENT_PID###') {
|
||||
// Use the current pid
|
||||
$entryPoint = (string)$this->data['effectivePid'];
|
||||
} elseif ($entryPoint === '###SITEROOT###' && ($this->data['site'] ?? null) instanceof Site) {
|
||||
// Use the root page id from the current site
|
||||
$entryPoint = (string)$this->data['site']->getRootPageId();
|
||||
} else {
|
||||
// Check for special TSconfig marker
|
||||
$TSconfig = FormEngineUtility::getTCEFORM_TSconfig($this->data['tableName'], ['pid' => $this->data['effectivePid']]);
|
||||
$keyword = substr($entryPoint, 3, -3);
|
||||
if (str_starts_with($keyword, 'PAGE_TSCONFIG_')) {
|
||||
$entryPoint = (string)($TSconfig[$this->data['fieldName']][$keyword] ?? '');
|
||||
} else {
|
||||
$entryPoint = (string)($TSconfig['_' . $keyword] ?? '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the entry point to the attribute - if resolved
|
||||
if ($entryPoint !== '') {
|
||||
$attributes['data-entry-point'] = $entryPoint;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user