Commit 899abdc2 authored by Benni Mack's avatar Benni Mack Committed by Georg Ringer
Browse files

[!!!][TASK] Remove internal_type=file/file_reference

This drops TCA type=group with internal_type=file and
internal_type=file_reference handling.
This patch is rather huge since detail handling of this
stuff is spread throughout the core. Additionally, some
further methods become unused and oboselete along the way.
Most of them - except DataHandler->process_uploads() - have
been used internally only and can be safetly dropped,
while process_uploads() which has always been part of the
externally called API is substituted with a no-op method.

Resolves: #87428
Releases: master
Change-Id: Ia60b5d0e021b34adf4b4187a5f1fe4475b0070b4
Reviewed-on: https://review.typo3.org/59361

Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
parent f6302cac
......@@ -533,8 +533,6 @@ class EditDocumentController
// Perform the saving operation with DataHandler:
if ($this->doSave === true) {
// @todo: Make DataHandler understand UploadedFileInterface and submit $request->getUploadedFiles() instead of $_FILES here
$tce->process_uploads($_FILES);
$tce->process_datamap();
$tce->process_cmdmap();
}
......
......@@ -293,8 +293,6 @@ class SimpleDataHandlerController
if (is_array($this->mirror)) {
$this->tce->setMirror($this->mirror);
}
// Register uploaded files
$this->tce->process_uploads($_FILES);
// Execute actions:
$this->tce->process_datamap();
$this->tce->process_cmdmap();
......
......@@ -77,25 +77,13 @@ class GroupElement extends AbstractFormElement
'tableList' => [
'renderType' => 'tableList',
],
'fileTypeList' => [
'renderType' => 'fileTypeList',
'after' => [ 'tableList' ],
],
'fileThumbnails' => [
'renderType' => 'fileThumbnails',
'after' => [ 'fileTypeList' ],
],
'recordsOverview' => [
'renderType' => 'recordsOverview',
'after' => [ 'fileThumbnails' ],
],
'fileUpload' => [
'renderType' => 'fileUpload',
'after' => [ 'recordsOverview' ],
'after' => [ 'tableList' ],
],
'localizationStateSelector' => [
'renderType' => 'localizationStateSelector',
'after' => [ 'fileUpload' ],
'after' => [ 'recordsOverview' ],
],
'otherLanguageContent' => [
'renderType' => 'otherLanguageContent',
......@@ -145,19 +133,7 @@ class GroupElement extends AbstractFormElement
$listOfSelectedValues = [];
$selectorOptionsHtml = [];
if ($internalType === 'file_reference' || $internalType === 'file') {
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
foreach ($selectedItems as $selectedItem) {
$uidOrPath = $selectedItem['uidOrPath'];
$listOfSelectedValues[] = $uidOrPath;
$title = $selectedItem['title'];
$shortenedTitle = GeneralUtility::fixed_lgd_cs($title, $maxTitleLength);
$selectorOptionsHtml[] =
'<option value="' . htmlspecialchars($uidOrPath) . '" title="' . htmlspecialchars($title) . '">'
. htmlspecialchars($this->appendValueToLabelInDebugMode($shortenedTitle, $uidOrPath))
. '</option>';
}
} elseif ($internalType === 'folder') {
if ($internalType === 'folder') {
foreach ($selectedItems as $selectedItem) {
$folder = $selectedItem['folder'];
$listOfSelectedValues[] = $folder;
......
......@@ -18,7 +18,6 @@ namespace TYPO3\CMS\Backend\Form\FieldControl;
use TYPO3\CMS\Backend\Form\AbstractNode;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
......@@ -53,16 +52,7 @@ class InsertClipboard extends AbstractNode
'element' => $elementName,
'clipboardItems' => [],
];
if ($internalType === 'file_reference' || $internalType === 'file') {
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
$title = sprintf($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.clipInsert_file'), count($clipboardElements));
foreach ($clipboardElements as $clipboardElement) {
$dataAttributes['clipboardItems'][] = [
'title' => rawurlencode(PathUtility::basename($clipboardElement['title'])),
'value' => $clipboardElement['value'],
];
}
} elseif ($internalType === 'db') {
if ($internalType === 'db') {
$title = sprintf($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.clipInsert_db'), count($clipboardElements));
foreach ($clipboardElements as $clipboardElement) {
$dataAttributes['clipboardItems'][] = [
......
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\Form\FieldWizard;
/*
* 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\AbstractNode;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Resource\ProcessedFile;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
/**
* Render thumbnails of selected files,
* typically used with type=group and internal_type=file and file_reference.
*/
class FileThumbnails extends AbstractNode
{
/**
* Render thumbnails of selected files
*
* @return array
*/
public function render(): array
{
$result = $this->initializeResultArray();
$table = $this->data['tableName'];
$fieldName = $this->data['fieldName'];
$row = $this->data['databaseRow'];
$parameterArray = $this->data['parameterArray'];
$config = $parameterArray['fieldConf']['config'];
$selectedItems = $parameterArray['itemFormElValue'];
if (!isset($config['internal_type'])
|| ($config['internal_type'] !== 'file' && $config['internal_type'] !== 'file_reference')
) {
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
// Thumbnails only make sense on file and file_reference
return $result;
}
$fileFactory = ResourceFactory::getInstance();
$thumbnailsHtml = [];
foreach ($selectedItems as $selectedItem) {
$uidOrPath = $selectedItem['uidOrPath'];
if (MathUtility::canBeInterpretedAsInteger($uidOrPath)) {
$fileObject = $fileFactory->getFileObject($uidOrPath);
if (!$fileObject->isMissing()) {
$extension = $fileObject->getExtension();
if (GeneralUtility::inList(
$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
$extension
)
) {
$thumbnailsHtml[] = '<li>';
$thumbnailsHtml[] = '<span class="thumbnail">';
$thumbnailsHtml[] = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, [])->getPublicUrl(true);
$thumbnailsHtml[] = '</span>';
$thumbnailsHtml[] = '</li>';
}
}
} else {
$rowCopy = [];
$rowCopy[$fieldName] = $uidOrPath;
try {
$icon = BackendUtility::thumbCode(
$rowCopy,
$table,
$fieldName,
'',
'',
$config['uploadfolder'],
0,
' align="middle"'
);
$thumbnailsHtml[] =
'<li>'
. '<span class="thumbnail">'
. $icon
. '</span>'
. '</li>';
} catch (\Exception $exception) {
$message = $exception->getMessage();
$flashMessage = GeneralUtility::makeInstance(
FlashMessage::class,
$message,
'',
FlashMessage::ERROR,
true
);
$flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
$defaultFlashMessageQueue->enqueue($flashMessage);
$this->logger->warning($message, ['table' => $table, 'row' => $row]);
}
}
}
$html = [];
if (!empty($thumbnailsHtml)) {
$html[] = '<ul class="list-inline">';
$html[] = implode(LF, $thumbnailsHtml);
$html[] = '</ul>';
}
$result['html'] = implode(LF, $html);
return $result;
}
}
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\Form\FieldWizard;
/*
* 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\AbstractNode;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Render list of allowed / disalowwed file types,
* typically used with type=group and internal_type=file.
*/
class FileTypeList extends AbstractNode
{
/**
* Render list of allowed and disallowed file types
*
* @return array
*/
public function render(): array
{
$result = $this->initializeResultArray();
$parameterArray = $this->data['parameterArray'];
$config = $parameterArray['fieldConf']['config'];
if (!isset($config['allowed']) || !is_string($config['allowed']) || empty($config['allowed'])
|| !isset($config['internal_type']) || $config['internal_type'] !== 'file'
) {
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
// No handling if the field has no, or funny "allowed" setting, and if internal_type is not "file"
return $result;
}
$allowed = GeneralUtility::trimExplode(',', $config['allowed'], true);
$disallowed = isset($config['disallowed']) ? GeneralUtility::trimExplode(',', $config['disallowed'], true) : [];
$allowedHtml = [];
foreach ($allowed as $item) {
$allowedHtml[] = '<span class="label label-success">' . htmlspecialchars(strtoupper($item)) . '</span> ';
}
$disallowedHtml = [];
foreach ($disallowed as $item) {
$disallowedHtml[] = '<span class="label label-danger">' . htmlspecialchars(strtoupper($item)) . '</span> ';
}
$html = [];
if (!empty($allowedHtml) || !empty($disallowedHtml)) {
$html[] = '<div class="help-block">';
$html[] = implode(LF, $allowedHtml);
$html[] = implode(LF, $disallowedHtml);
$html[] = '</div>';
}
$result['html'] = implode(LF, $html);
return $result;
}
}
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\Form\FieldWizard;
/*
* 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\AbstractNode;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Render file upload,
* typically used with type=group and internal_type=file and file_reference.
*/
class FileUpload extends AbstractNode
{
/**
* Render file upload
*
* @return array
*/
public function render(): array
{
$backendUser = $this->getBackendUserAuthentication();
$result = $this->initializeResultArray();
$parameterArray = $this->data['parameterArray'];
$itemName = $parameterArray['itemFormElName'];
$uploadFieldId = $parameterArray['itemFormElID'] . '_files';
$config = $parameterArray['fieldConf']['config'];
$maxItems = $config['maxitems'];
$isDirectFileUploadEnabled = (bool)$backendUser->uc['edit_docModuleUpload'];
if (!isset($config['internal_type'])
|| $config['internal_type'] !== 'file'
|| !$isDirectFileUploadEnabled
|| empty($config['uploadfolder'])
) {
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
// No upload if disabled for user or upload folder missing
return $result;
}
if ($maxItems === 1) {
// If maxItems = 1 then automatically replace the current item file selector
$resultArray['additionalJavaScriptPost'][] =
'TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[' . GeneralUtility::quoteJSvalue($itemName) . '] = {'
. 'itemFormElID_file: ' . GeneralUtility::quoteJSvalue($uploadFieldId)
. '}';
}
// Insert the multiple attribute to enable HTML5 multiple file upload
$selectorMultipleAttribute = '';
$multipleFilenameSuffix = '';
if ($maxItems > 1) {
$selectorMultipleAttribute = ' multiple="multiple"';
$multipleFilenameSuffix = '[]';
}
$html= [];
$html[] = '<div id="' . $uploadFieldId . '">';
$html[] = '<input';
$html[] = ' type="file"';
$html[] = $selectorMultipleAttribute;
$html[] = ' name="data_files' . $this->data['elementBaseName'] . $multipleFilenameSuffix . '"';
$html[] = ' size="35"';
$html[] = ' onchange="' . implode('', $parameterArray['fieldChangeFunc']) . '"';
$html[] = '/>';
$html[] = '</div>';
$result['html'] = implode(LF, $html);
return $result;
}
/**
* @return BackendUserAuthentication
*/
protected function getBackendUserAuthentication()
{
return $GLOBALS['BE_USER'];
}
}
......@@ -70,7 +70,7 @@ class OtherLanguageContent extends AbstractNode
if ($defaultLanguageValue !== '') {
$html[] = '<div class="t3-form-original-language">';
$html[] = $iconFactory->getIcon($this->data['systemLanguageRows'][0]['flagIconIdentifier'], Icon::SIZE_SMALL)->render();
$html[] = $this->previewFieldValue($defaultLanguageValue, $fieldConfig, $fieldName);
$html[] = $this->previewFieldValue($defaultLanguageValue);
$html[] = '</div>';
}
$additionalPreviewLanguages = $this->data['additionalLanguageRows'];
......@@ -85,7 +85,7 @@ class OtherLanguageContent extends AbstractNode
if ($defaultLanguageValue !== '') {
$html[] = '<div class="t3-form-original-language">';
$html[] = $iconFactory->getIcon($this->data['systemLanguageRows'][$previewLanguage['sys_language_uid']]['flagIconIdentifier'], Icon::SIZE_SMALL)->render();
$html[] = $this->previewFieldValue($defaultLanguageValue, $fieldConfig, $fieldName);
$html[] = $this->previewFieldValue($defaultLanguageValue);
$html[] = '</div>';
}
}
......@@ -97,57 +97,10 @@ class OtherLanguageContent extends AbstractNode
* 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
* @param array $config Configuration for field.
* @param string $field Name of field.
* @return string HTML formatted output
*/
protected function previewFieldValue($value, $config, $field = '')
protected function previewFieldValue($value)
{
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
$value = (string)$value;
if ($config['config']['type'] === 'group'
&& ($config['config']['internal_type'] === 'file' || $config['config']['internal_type'] === 'file_reference')
) {
// Ignore upload folder if internal_type is file_reference
if ($config['config']['internal_type'] === 'file_reference') {
$config['config']['uploadfolder'] = '';
}
$table = 'tt_content';
// Making the array of file items:
$itemArray = GeneralUtility::trimExplode(',', $value, true);
// Showing thumbnails:
$imgs = [];
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
foreach ($itemArray as $imgRead) {
$imgParts = explode('|', $imgRead);
$imgPath = rawurldecode($imgParts[0]);
$rowCopy = [];
$rowCopy[$field] = $imgPath;
// Icon + click menu:
$absFilePath = GeneralUtility::getFileAbsFileName($config['config']['uploadfolder'] ? $config['config']['uploadfolder'] . '/' . $imgPath : $imgPath);
$fileInformation = pathinfo($imgPath);
$title = $fileInformation['basename'] . ($absFilePath && @is_file($absFilePath))
? ' (' . GeneralUtility::formatSize(filesize($absFilePath)) . ')'
: ' - FILE NOT FOUND!';
$fileIcon = '<span title="' . htmlspecialchars($title) . '">' . $iconFactory->getIconForFileExtension($fileInformation['extension'], Icon::SIZE_SMALL)->render() . '</span>';
$imgs[] =
'<span class="text-nowrap">' .
BackendUtility::thumbCode(
$rowCopy,
$table,
$field,
'',
'',
$config['config']['uploadfolder'],
0,
' align="middle"'
) .
($absFilePath ? BackendUtility::wrapClickMenuOnIcon($fileIcon, $absFilePath) : $fileIcon) .
$imgPath .
'</span>';
}
return implode('<br />', $imgs);
}
return nl2br(htmlspecialchars($value));
return nl2br(htmlspecialchars((string)$value));
}
}
......@@ -65,64 +65,7 @@ class TcaGroup implements FormDataProviderInterface
$items = [];
$sanitizedClipboardElements = [];
$internalType = $fieldConfig['config']['internal_type'];
if ($internalType === 'file_reference' || $internalType === 'file') {
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
// Set 'allowed' config to "*" if not set
if (empty($fieldConfig['config']['allowed'])) {
$result['processedTca']['columns'][$fieldName]['config']['allowed'] = '*';
}
// Force empty uploadfolder for file_reference type
if ($internalType === 'file_reference') {
$result['processedTca']['columns'][$fieldName]['config']['uploadfolder'] = '';
}
// Simple list of files
$fileList = GeneralUtility::trimExplode(',', $databaseRowFieldContent, true);
$fileFactory = ResourceFactory::getInstance();
foreach ($fileList as $uidOrPath) {
$item = [
'uidOrPath' => $uidOrPath,
'title' => $uidOrPath,
];
try {
if (MathUtility::canBeInterpretedAsInteger($uidOrPath)) {
$fileObject = $fileFactory->getFileObject($uidOrPath);
$item['title'] = $fileObject->getName();
}
} catch (Exception $exception) {
continue;
}
$items[] = $item;
}
// Register elements from clipboard
$allowed = GeneralUtility::trimExplode(',', $result['processedTca']['columns'][$fieldName]['config']['allowed'], true);
$clipboard = GeneralUtility::makeInstance(Clipboard::class);
$clipboard->initializeClipboard();
$clipboardElements = $clipboard->elFromTable('_FILE');
if ($allowed[0] !== '*') {
// If there are a set of allowed extensions, filter the content
foreach ($clipboardElements as $elementValue) {
$pathInfo = pathinfo($elementValue);
if (in_array(strtolower($pathInfo['extension']), $allowed)) {
$sanitizedClipboardElements[] = [
'title' => $elementValue,
'value' => $elementValue,
];
}
}
} else {
// If all is allowed, insert all. This does NOT respect any disallowed extensions,
// but those will be filtered away by the DataHandler
foreach ($clipboardElements as $elementValue) {
$sanitizedClipboardElements[] = [
'title' => $elementValue,
'value' => $elementValue,
];
}
}
} elseif ($internalType === 'db') {
if ($internalType === 'db') {
if (empty($fieldConfig['config']['allowed'])) {
throw new \RuntimeException(
'Mandatory TCA config setting "allowed" missing in field "' . $fieldName . '" of table "' . $result['tableName'] . '"',
......@@ -204,7 +147,7 @@ class TcaGroup implements FormDataProviderInterface
} else {
throw new \UnexpectedValueException(
'TCA internal_type of field "' . $fieldName . '" in table ' . $result['tableName']
. ' must be set to either "db", "file" or "file_reference"',
. ' must be set to "db" or "folder".',
1438780511
);
}
......
......@@ -108,9 +108,6 @@ class NodeFactory
// Element wizards
'defaultLanguageDifferences' => FieldWizard\DefaultLanguageDifferences::class,
'fileThumbnails' => FieldWizard\FileThumbnails::class,
'fileTypeList' => FieldWizard\FileTypeList::class,
'fileUpload' => FieldWizard\FileUpload::class,
'localizationStateSelector' => FieldWizard\LocalizationStateSelector::class,
'otherLanguageContent' => FieldWizard\OtherLanguageContent::class,
'recordsOverview' => FieldWizard\RecordsOverview::class,
......
......@@ -237,8 +237,6 @@ class RecordHistory
$data[$rollbackData[0]][$rollbackData[1]][$rollbackData[2]] = $diffModified[$rollbackData[0]][$rollbackData[1]][$rollbackData[2]];
break;
}
// Removing fields:
$data = $this->removeFilefields($rollbackData[0], $data);
// Writes the data:
$tce = GeneralUtility::makeInstance(DataHandler::class);
$tce->dontProcessTransformations = true;
......@@ -400,28 +398,6 @@ class RecordHistory
*
*******************************/
/**
* Will traverse the field names in $dataArray and look in $GLOBALS['TCA'] if the fields are of types which cannot
* be handled by the sys_history (that is currently group types with internal_type set to "file")
*
* @param string $table Table name
* @param array $dataArray The data array
* @return array The modified data array
* @internal
*/
protected function removeFilefields($table, $dataArray)
{
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Deprecation logged by TcaMigration class.
if ($GLOBALS['TCA'][$table]) {
foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $config) {
if ($config['config']['type'] === 'group' && $config['config']['internal_type'] === 'file') {
unset($dataArray[$field]);
}