198 lines
8.6 KiB
PHP
198 lines
8.6 KiB
PHP
<?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\Utility;
|
|
|
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
|
use TYPO3\CMS\Core\Cache\CacheManager;
|
|
use TYPO3\CMS\Core\Imaging\IconFactory;
|
|
use TYPO3\CMS\Core\Imaging\IconSize;
|
|
use TYPO3\CMS\Core\SystemResource\Exception\SystemResourceException;
|
|
use TYPO3\CMS\Core\SystemResource\Publishing\SystemResourcePublisherInterface;
|
|
use TYPO3\CMS\Core\SystemResource\SystemResourceFactory;
|
|
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
use TYPO3\CMS\Core\Utility\MathUtility;
|
|
|
|
/**
|
|
* This is a static, internal and intermediate helper class for various
|
|
* FormEngine related tasks.
|
|
*
|
|
* This class was introduced to help disentangling FormEngine and
|
|
* its sub classes. It MUST NOT be used in other extensions and will
|
|
* change or vanish without further notice.
|
|
*
|
|
* @internal
|
|
* @todo: These helpers are target to be dropped if further FormEngine refactoring is done
|
|
*/
|
|
class FormEngineUtility
|
|
{
|
|
/**
|
|
* Whitelist that allows TCA field configuration to be overridden by TSconfig
|
|
*
|
|
* @see overrideFieldConf()
|
|
* @var array
|
|
*/
|
|
protected static $allowOverrideMatrix = [
|
|
'input' => ['size', 'max', 'readOnly'],
|
|
'number' => ['size', 'readOnly'],
|
|
'email' => ['size', 'readOnly'],
|
|
'link' => ['size', 'readOnly'],
|
|
'password' => ['size', 'readOnly'],
|
|
'datetime' => ['size', 'readOnly'],
|
|
'color' => ['size', 'readOnly'],
|
|
'uuid' => ['size', 'enableCopyToClipboard'],
|
|
'text' => ['cols', 'rows', 'wrap', 'max', 'readOnly'],
|
|
'json' => ['cols', 'rows', 'readOnly'],
|
|
'check' => ['cols', 'readOnly'],
|
|
'select' => ['size', 'autoSizeMax', 'maxitems', 'minitems', 'readOnly', 'treeConfig', 'fileFolderConfig'],
|
|
'category' => ['size', 'maxitems', 'minitems', 'readOnly', 'treeConfig'],
|
|
'group' => ['size', 'autoSizeMax', 'maxitems', 'minitems', 'readOnly', 'elementBrowserEntryPoints'],
|
|
'folder' => ['size', 'autoSizeMax', 'maxitems', 'minitems', 'readOnly', 'elementBrowserEntryPoints'],
|
|
'inline' => ['appearance', 'behaviour', 'foreign_label', 'foreign_selector', 'foreign_unique', 'maxitems', 'minitems', 'size', 'autoSizeMax', 'symmetric_label', 'readOnly'],
|
|
'file' => ['appearance', 'behaviour', 'maxitems', 'minitems', 'readOnly'],
|
|
'imageManipulation' => ['ratios', 'cropVariants'],
|
|
];
|
|
|
|
/**
|
|
* Overrides the TCA field configuration by TSconfig settings.
|
|
*
|
|
* Example TSconfig: TCEform.<table>.<field>.config.appearance.useSortable = 1
|
|
* This overrides the setting in $GLOBALS['TCA'][<table>]['columns'][<field>]['config']['appearance']['useSortable'].
|
|
*
|
|
* @param array $fieldConfig $GLOBALS['TCA'] field configuration
|
|
* @param array $TSconfig TSconfig
|
|
* @return array Changed TCA field configuration
|
|
* @internal
|
|
*/
|
|
public static function overrideFieldConf($fieldConfig, $TSconfig)
|
|
{
|
|
if (is_array($TSconfig)) {
|
|
$TSconfig = GeneralUtility::removeDotsFromTS($TSconfig);
|
|
$type = $fieldConfig['type'] ?? '';
|
|
if (isset($TSconfig['config']) && is_array($TSconfig['config']) && is_array(static::$allowOverrideMatrix[$type] ?? null)) {
|
|
// Check if the keys in TSconfig['config'] are allowed to override TCA field config:
|
|
foreach ($TSconfig['config'] as $key => $_) {
|
|
if (!in_array($key, static::$allowOverrideMatrix[$type], true)) {
|
|
unset($TSconfig['config'][$key]);
|
|
}
|
|
}
|
|
// Override $GLOBALS['TCA'] field config by remaining TSconfig['config']:
|
|
if (!empty($TSconfig['config'])) {
|
|
ArrayUtility::mergeRecursiveWithOverrule($fieldConfig, $TSconfig['config']);
|
|
}
|
|
}
|
|
}
|
|
return $fieldConfig;
|
|
}
|
|
|
|
/**
|
|
* Returns TSconfig for given table and row
|
|
*
|
|
* @param string $table The table name
|
|
* @param array $row The table row - Must at least contain the "uid" value, even if "NEW..." string.
|
|
* The "pid" field is important as well, negative values will be interpreted as pointing to a record from the same table.
|
|
* @param string $field Optionally specify the field name as well. In that case the TSconfig for this field is returned.
|
|
* @return mixed The TSconfig values - probably in an array
|
|
* @internal
|
|
*/
|
|
public static function getTSconfigForTableRow($table, $row, $field = '')
|
|
{
|
|
$runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
|
|
$cache = $runtimeCache->get('formEngineUtilityTsConfigForTableRow') ?: [];
|
|
$cacheIdentifier = $table . ':' . $row['uid'];
|
|
if (!isset($cache[$cacheIdentifier])) {
|
|
$cache[$cacheIdentifier] = self::getTCEFORM_TSconfig($table, $row);
|
|
$runtimeCache->set('formEngineUtilityTsConfigForTableRow', $cache);
|
|
}
|
|
if ($field && isset($cache[$cacheIdentifier][$field])) {
|
|
return $cache[$cacheIdentifier][$field];
|
|
}
|
|
return $cache[$cacheIdentifier];
|
|
}
|
|
|
|
/**
|
|
* Returns TSConfig for the TCEFORM object in page TSconfig.
|
|
* Used in TCEFORMs
|
|
*
|
|
* @param string $table Table name present in TCA
|
|
* @param array $row Row from table
|
|
*/
|
|
public static function getTCEFORM_TSconfig(string $table, array $row): array
|
|
{
|
|
$res = [];
|
|
$uid = $row['uid'] ?? 0;
|
|
$pid = $row['pid'] ?? 0;
|
|
// Get main config for the table
|
|
// If pid is negative (referring to another record) the pid of the other record is fetched and returned.
|
|
$cPid = BackendUtility::getTSconfig_pidValue($table, $uid, $pid);
|
|
// $TScID is the id of $table = pages, else it's the pid of the record.
|
|
$TScID = $table === 'pages' && MathUtility::canBeInterpretedAsInteger($uid) ? $uid : $cPid;
|
|
if ($TScID >= 0) {
|
|
$tsConfig = BackendUtility::getPagesTSconfig($TScID)['TCEFORM.'][$table . '.'] ?? [];
|
|
$typeVal = BackendUtility::getTCAtypeValue($table, $row, true);
|
|
foreach ($tsConfig as $key => $val) {
|
|
if (is_array($val)) {
|
|
$fieldN = substr($key, 0, -1);
|
|
$res[$fieldN] = $val;
|
|
unset($res[$fieldN]['types.']);
|
|
if ($typeVal !== null && is_array($val['types.'][$typeVal . '.'] ?? false)) {
|
|
$res[$fieldN] = array_replace_recursive($res[$fieldN], $val['types.'][$typeVal . '.']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$res['_CURRENT_PID'] = $cPid;
|
|
$res['_THIS_UID'] = $row['uid'] ?? 0;
|
|
// So the row will be passed to foreign_table_where_query()
|
|
$res['_THIS_ROW'] = $row;
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* Renders the $icon, supports a filename for skinImg or sprite-icon-name
|
|
*
|
|
* @param string $icon The icon passed, could be a file-reference or a sprite Icon name
|
|
* @param string $alt Alt attribute of the icon returned
|
|
* @param string $title Title attribute of the icon return
|
|
* @return string A tag representing to show the asked icon
|
|
* @internal
|
|
*/
|
|
public static function getIconHtml($icon, $alt = '', $title = '')
|
|
{
|
|
$icon = (string)$icon;
|
|
try {
|
|
$resourceFactory = GeneralUtility::makeInstance(SystemResourceFactory::class);
|
|
$resource = $resourceFactory->createPublicResource($icon);
|
|
$resourcePublisher = GeneralUtility::makeInstance(SystemResourcePublisherInterface::class);
|
|
$iconUri = $resourcePublisher->generateUri($resource, null);
|
|
return '<img'
|
|
. ' loading="lazy" '
|
|
. ' src="' . htmlspecialchars((string)$iconUri) . '"'
|
|
. ' alt="' . htmlspecialchars($alt) . '" '
|
|
. ($title ? 'title="' . htmlspecialchars($title) . '"' : '')
|
|
. ' />';
|
|
} catch (SystemResourceException) {
|
|
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
|
|
return $iconFactory
|
|
->getIcon($icon, IconSize::SMALL)
|
|
->setTitle($title)
|
|
->render('inline');
|
|
}
|
|
}
|
|
}
|