/** * Renders a HTML Block with file information * * @param File $file * @return string */ protected function renderFileInformationContent(File $file = null) { /** @var LanguageService $lang */ $lang = $GLOBALS['LANG']; if ($file !== null) { $processedFile = $file->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => 150, 'height' => 150)); $previewImage = $processedFile->getPublicUrl(true); $content = ''; if ($file->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($file); $content .= $flashMessage->render(); } if ($previewImage) { $content .= '<img src="' . htmlspecialchars($previewImage) . '" ' . 'width="' . $processedFile->getProperty('width') . '" ' . 'height="' . $processedFile->getProperty('height') . '" ' . 'alt="" class="t3-tceforms-sysfile-imagepreview" />'; } $content .= '<strong>' . htmlspecialchars($file->getName()) . '</strong>'; $content .= ' (' . htmlspecialchars(GeneralUtility::formatSize($file->getSize())) . 'bytes)<br />'; $content .= BackendUtility::getProcessedValue('sys_file', 'type', $file->getType()) . ' (' . $file->getMimeType() . ')<br />'; $content .= $lang->sL('LLL:EXT:lang/locallang_misc.xlf:fileMetaDataLocation', true) . ': '; $content .= htmlspecialchars($file->getStorage()->getName()) . ' - ' . htmlspecialchars($file->getIdentifier()) . '<br />'; $content .= '<br />'; } else { $content = '<h2>' . $lang->sL('LLL:EXT:lang/locallang_misc.xlf:fileMetaErrorInvalidRecord', true) . '</h2>'; } return $content; }
/** * Returns a linked image-tag for thumbnail(s)/fileicons/truetype-font-previews from a database row with a list of image files in a field * All $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] extension are made to thumbnails + ttf file (renders font-example) * Thumbsnails are linked to the show_item.php script which will display further details. * * @param array $row Row is the database row from the table, $table. * @param string $table Table name for $row (present in TCA) * @param string $field Field is pointing to the list of image files * @param string $backPath Back path prefix for image tag src="" field * @param string $thumbScript Optional: $thumbScript - not used anymore since FAL * @param string $uploaddir Optional: $uploaddir is the directory relative to PATH_site where the image files from the $field value is found (Is by default set to the entry in $GLOBALS['TCA'] for that field! so you don't have to!) * @param boolean $abs If set, uploaddir is NOT prepended with "../ * @param string $tparams Optional: $tparams is additional attributes for the image tags * @param integer $size Optional: $size is [w]x[h] of the thumbnail. 56 is default. * @param boolean $linkInfoPopup Whether to wrap with a link opening the info popup * @return string Thumbnail image tag. */ public static function thumbCode($row, $table, $field, $backPath, $thumbScript = '', $uploaddir = NULL, $abs = 0, $tparams = '', $size = '', $linkInfoPopup = TRUE) { // Check and parse the size parameter $sizeParts = array(64, 64); if ($size = trim($size)) { $sizeParts = explode('x', $size . 'x' . $size); if (!(int) $sizeParts[0]) { $size = ''; } } $thumbData = ''; $fileReferences = static::resolveFileReferences($table, $field, $row); // FAL references if ($fileReferences !== NULL) { foreach ($fileReferences as $fileReferenceObject) { $fileObject = $fileReferenceObject->getOriginalFile(); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbData .= $flashMessage->render(); continue; } // Web image if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileReferenceObject->getExtension())) { $imageUrl = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => $sizeParts[0], 'height' => $sizeParts[1]))->getPublicUrl(TRUE); $imgTag = '<img src="' . $imageUrl . '" alt="' . htmlspecialchars($fileReferenceObject->getName()) . '" />'; } else { // Icon $imgTag = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName())); } if ($linkInfoPopup) { $onClick = 'top.launchView(\'_FILE\',\'' . $fileObject->getUid() . '\',\'' . $backPath . '\'); return false;'; $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $imgTag . '</a> '; } else { $thumbData .= $imgTag; } } } else { // Find uploaddir automatically if (is_null($uploaddir)) { $uploaddir = $GLOBALS['TCA'][$table]['columns'][$field]['config']['uploadfolder']; } $uploaddir = rtrim($uploaddir, '/'); // Traverse files: $thumbs = GeneralUtility::trimExplode(',', $row[$field], TRUE); $thumbData = ''; foreach ($thumbs as $theFile) { if ($theFile) { $fileName = trim($uploaddir . '/' . $theFile, '/'); try { /** @var File $fileObject */ $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileName); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbData .= $flashMessage->render(); continue; } } catch (\TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException $exception) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', htmlspecialchars($exception->getMessage()), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing', TRUE), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); $thumbData .= $flashMessage->render(); continue; } $fileExtension = $fileObject->getExtension(); if ($fileExtension == 'ttf' || GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) { $imageUrl = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => $sizeParts[0], 'height' => $sizeParts[1]))->getPublicUrl(TRUE); $image = '<img src="' . htmlspecialchars($imageUrl) . '" hspace="2" border="0" title="' . htmlspecialchars($fileObject->getName()) . '"' . $tparams . ' alt="" />'; if ($linkInfoPopup) { $onClick = 'top.launchView(\'_FILE\', \'' . $fileName . '\',\'\',\'' . $backPath . '\');return false;'; $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $image . '</a> '; } else { $thumbData .= $image; } } else { // Gets the icon $fileIcon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName())); if ($linkInfoPopup) { $onClick = 'top.launchView(\'_FILE\', \'' . $fileName . '\',\'\',\'' . $backPath . '\'); return false;'; $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $fileIcon . '</a> '; } else { $thumbData .= $fileIcon; } } } } } return $thumbData; }
/** * This returns tablerows for the files in the array $items['sorting']. * * @param File[] $files File items * @return string HTML table rows. */ public function formatFileList(array $files) { $out = ''; // first two keys are "0" (default) and "-1" (multiple), after that comes the "other languages" $allSystemLanguages = GeneralUtility::makeInstance(TranslationConfigurationProvider::class)->getSystemLanguages(); $systemLanguages = array_filter($allSystemLanguages, function ($languageRecord) { if ($languageRecord['uid'] === -1 || $languageRecord['uid'] === 0 || !$this->getBackendUser()->checkLanguageAccess($languageRecord['uid'])) { return FALSE; } else { return TRUE; } }); foreach ($files as $fileObject) { // Initialization $this->counter++; $this->totalbytes += $fileObject->getSize(); $ext = $fileObject->getExtension(); $fileName = trim($fileObject->getName()); // The icon with link $theIcon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileName . ' [' . (int) $fileObject->getUid() . ']')); if ($this->clickMenus) { $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($theIcon, $fileObject->getCombinedIdentifier()); } // Preparing and getting the data-array $theData = array(); foreach ($this->fieldArray as $field) { switch ($field) { case 'size': $theData[$field] = GeneralUtility::formatSize($fileObject->getSize(), $this->getLanguageService()->getLL('byteSizeUnits', TRUE)); break; case 'rw': $theData[$field] = '' . (!$fileObject->checkActionPermission('read') ? ' ' : '<strong class="text-danger">' . $this->getLanguageService()->getLL('read', TRUE) . '</strong>') . (!$fileObject->checkActionPermission('write') ? '' : '<strong class="text-danger">' . $this->getLanguageService()->getLL('write', TRUE) . '</strong>'); break; case 'fileext': $theData[$field] = strtoupper($ext); break; case 'tstamp': $theData[$field] = BackendUtility::date($fileObject->getModificationTime()); break; case '_CONTROL_': $theData[$field] = $this->makeEdit($fileObject); break; case '_CLIPBOARD_': $theData[$field] = $this->makeClip($fileObject); break; case '_LOCALIZATION_': if (!empty($systemLanguages) && $fileObject->isIndexed() && $fileObject->checkActionPermission('write') && $this->getBackendUser()->check('tables_modify', 'sys_file_metadata')) { $metaDataRecord = $fileObject->_getMetaData(); $translations = $this->getTranslationsForMetaData($metaDataRecord); $languageCode = ''; foreach ($systemLanguages as $language) { $languageId = $language['uid']; $flagIcon = $language['flagIcon']; if (array_key_exists($languageId, $translations)) { $flagButtonIcon = IconUtility::getSpriteIcon('actions-document-open', array('title' => sprintf($GLOBALS['LANG']->getLL('editMetadataForLanguage'), $language['title'])), array($flagIcon . '-overlay' => array())); $data = array('sys_file_metadata' => array($translations[$languageId]['uid'] => 'edit')); $editOnClick = BackendUtility::editOnClick(GeneralUtility::implodeArrayForUrl('edit', $data), $GLOBALS['BACK_PATH'], $this->listUrl()); $languageCode .= '<a href="#" class="btn btn-default" onclick="' . htmlspecialchars($editOnClick) . '">' . $flagButtonIcon . '</a>'; } else { $parameters = ['justLocalized' => 'sys_file_metadata:' . $metaDataRecord['uid'] . ':' . $languageId, 'returnUrl' => $this->listURL()]; $returnUrl = BackendUtility::getModuleUrl('record_edit', $parameters, $this->backPath) . BackendUtility::getUrlToken('editRecord'); $href = $GLOBALS['SOBE']->doc->issueCommand('&cmd[sys_file_metadata][' . $metaDataRecord['uid'] . '][localize]=' . $languageId, $returnUrl); $flagButtonIcon = IconUtility::getSpriteIcon($flagIcon, array('title' => sprintf($GLOBALS['LANG']->getLL('createMetadataForLanguage'), $language['title'])), array($flagIcon . '-overlay' => array())); $languageCode .= '<a href="' . htmlspecialchars($href) . '" class="btn btn-default">' . $flagButtonIcon . '</a> '; } } // Hide flag button bar when not translated yet $theData[$field] = ' <div class="localisationData btn-group" data-fileid="' . $fileObject->getUid() . '"' . (empty($translations) ? ' style="display: none;"' : '') . '>' . $languageCode . '</div>'; $theData[$field] .= '<a class="btn btn-default filelist-translationToggler" data-fileid="' . $fileObject->getUid() . '">' . IconUtility::getSpriteIcon('mimetypes-x-content-page-language-overlay', array('title' => $GLOBALS['LANG']->getLL('translateMetadata'))) . '</a>'; } break; case '_REF_': $theData[$field] = $this->makeRef($fileObject); break; case 'file': // Edit metadata of file $theData[$field] = $this->linkWrapFile(htmlspecialchars($fileName), $fileObject); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $theData[$field] .= $flashMessage->render(); // Thumbnails? } elseif ($this->thumbs && $this->isImage($ext)) { $processedFile = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array()); if ($processedFile) { $thumbUrl = $processedFile->getPublicUrl(TRUE); $theData[$field] .= '<br /><img src="' . $thumbUrl . '" ' . 'width="' . $processedFile->getProperty('width') . '" ' . 'height="' . $processedFile->getProperty('height') . '" ' . 'title="' . htmlspecialchars($fileName) . '" alt="" />'; } } break; default: $theData[$field] = ''; if ($fileObject->hasProperty($field)) { $theData[$field] = htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getProperty($field), $this->fixedL)); } } } $out .= $this->addelement(1, $theIcon, $theData); } return $out; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $rec The current record of that foreign_table * @param array $config content of $PA['fieldConf']['config'] * @param boolean $isVirtualRecord * @return string The HTML code of the header * @todo Define visibility */ public function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol); // Render title for everything else than group/db: if ($foreignConfig['type'] != 'groupdb') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(TRUE); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, $rec, TRUE); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = IconUtility::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); $thumbnail = FALSE; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode(',', $fieldValue)); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing was successful. if (!$processedImage->usesOriginalFile()) { $imageUrl = $processedImage->getPublicUrl(TRUE); $thumbnail = '<img class="t3-form-field-header-inline-thumbnail-image" src="' . $imageUrl . '" alt="' . htmlspecialchars($altText) . '" title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $headerClasses = ' t3-form-field-header-inline-has-thumbnail'; $mediaContainer = '<div class="t3-form-field-header-inline-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $headerClasses = ' t3-form-field-header-inline-has-icon'; $mediaContainer = '<div class="t3-form-field-header-inline-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = '<div class="t3-form-field-header-inline-wrap' . $headerClasses . '">' . '<div class="t3-form-field-header-inline-ctrl">' . $ctrl . '</div>' . '<div class="t3-form-field-header-inline-body">' . $mediaContainer . '<div class="t3-form-field-header-inline-summary">' . $label . '</div>' . '</div>' . '</div>'; return $header; }
/** * Render preview for current record * * @return string */ protected function renderPreview() { // Perhaps @todo in future: Also display preview for records - without fileObject if (!$this->fileObject) { return ''; } $previewTag = ''; $showLink = ''; // check if file is marked as missing if ($this->fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($this->fileObject); $previewTag .= $flashMessage->render(); } else { /** @var \TYPO3\CMS\Core\Resource\Rendering\RendererRegistry $rendererRegistry */ $rendererRegistry = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Rendering\RendererRegistry::class); $fileRenderer = $rendererRegistry->getRenderer($this->fileObject); $fileExtension = $this->fileObject->getExtension(); $url = $this->fileObject->getPublicUrl(true); // Check if there is a FileRenderer if ($fileRenderer !== null) { $previewTag = $fileRenderer->render($this->fileObject, '590m', '400m', array(), true); // else check if we can create an Image preview } elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) { $processedFile = $this->fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => '590m', 'height' => '400m')); // Create thumbnail image? if ($processedFile) { $thumbUrl = $processedFile->getPublicUrl(true); $previewTag .= '<img class="img-responsive img-thumbnail" src="' . $thumbUrl . '" ' . 'width="' . $processedFile->getProperty('width') . '" ' . 'height="' . $processedFile->getProperty('height') . '" ' . 'alt="' . htmlspecialchars(trim($this->fileObject->getName())) . '" ' . 'title="' . htmlspecialchars(trim($this->fileObject->getName())) . '" />'; } } // Show if ($url) { $showLink .= ' <a class="btn btn-primary" href="' . htmlspecialchars($url) . '" target="_blank"> ' . $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.show', true) . ' </a>'; } } return ($previewTag ? '<p>' . $previewTag . '</p>' : '') . ($showLink ? '<p>' . $showLink . '</p>' : ''); }
/** * This will render a selector box into which elements from either * the file system or database can be inserted. Relations. * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $table = $this->globalOptions['table']; $fieldName = $this->globalOptions['fieldName']; $row = $this->globalOptions['databaseRow']; $parameterArray = $this->globalOptions['parameterArray']; $config = $parameterArray['fieldConf']['config']; $show_thumbs = $config['show_thumbs']; $resultArray = $this->initializeResultArray(); $size = isset($config['size']) ? (int)$config['size'] : $this->minimumInputWidth; $maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0); if (!$maxitems) { $maxitems = 100000; } $minitems = MathUtility::forceIntegerInRange($config['minitems'], 0); $thumbnails = array(); $allowed = GeneralUtility::trimExplode(',', $config['allowed'], TRUE); $disallowed = GeneralUtility::trimExplode(',', $config['disallowed'], TRUE); $disabled = ($this->isGlobalReadonly() || $config['readOnly']); $info = array(); $parameterArray['itemFormElID_file'] = $parameterArray['itemFormElID'] . '_files'; // whether the list and delete controls should be disabled $noList = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'list'); $noDelete = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'delete'); // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']); // Register properties in requiredElements $resultArray['requiredElements'][$parameterArray['itemFormElName']] = array( $minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $fieldName ); $tabAndInlineStack = $this->globalOptions['tabAndInlineStack']; if (!empty($tabAndInlineStack) && preg_match('/^(.+\\])\\[(\\w+)\\]$/', $parameterArray['itemFormElName'], $match)) { array_shift($match); $resultArray['requiredNested'][$parameterArray['itemFormElName']] = array( 'parts' => $match, 'level' => $tabAndInlineStack, ); } // If maxitems==1 then automatically replace the current item (in list and file selector) if ($maxitems === 1) { $resultArray['additionalJavaScriptPost'][] = 'TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . '] = { itemFormElID_file: ' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElID_file']) . ' }'; $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', \'Remove\'); ' . $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']; } elseif ($noList) { // If the list controls have been removed and the maximum number is reached, remove the first entry to avoid "write once" field $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', \'RemoveFirstIfFull\', ' . GeneralUtility::quoteJSvalue($maxitems) . '); ' . $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']; } $html = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />'; // Acting according to either "file" or "db" type: switch ((string)$config['internal_type']) { case 'file_reference': $config['uploadfolder'] = ''; // Fall through case 'file': // Creating string showing allowed types: if (!count($allowed)) { $allowed = array('*'); } // Making the array of file items: $itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE); $fileFactory = ResourceFactory::getInstance(); // Correct the filename for the FAL items foreach ($itemArray as &$fileItem) { list($fileUid, $fileLabel) = explode('|', $fileItem); if (MathUtility::canBeInterpretedAsInteger($fileUid)) { $fileObject = $fileFactory->getFileObject($fileUid); $fileLabel = $fileObject->getName(); } $fileItem = $fileUid . '|' . $fileLabel; } // Showing thumbnails: if ($show_thumbs) { foreach ($itemArray as $imgRead) { $imgP = explode('|', $imgRead); $imgPath = rawurldecode($imgP[0]); // FAL icon production if (MathUtility::canBeInterpretedAsInteger($imgP[0])) { $fileObject = $fileFactory->getFileObject($imgP[0]); if ($fileObject->isMissing()) { $thumbnails[] = array( 'message' => \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject)->render() ); } elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) { $thumbnails[] = array( 'name' => htmlspecialchars($fileObject->getName()), 'image' => $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array())->getPublicUrl(TRUE) ); } else { // Icon $thumbnails[] = array( 'name' => htmlspecialchars($fileObject->getName()), 'image' => IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName())) ); } } else { $rowCopy = array(); $rowCopy[$fieldName] = $imgPath; try { $thumbnails[] = array( 'name' => $imgPath, 'image' => BackendUtility::thumbCode( $rowCopy, $table, $fieldName, '', '', $config['uploadfolder'], 0, ' align="middle"' ) ); } catch (\Exception $exception) { /** @var $flashMessage FlashMessage */ $message = $exception->getMessage(); $flashMessage = GeneralUtility::makeInstance( FlashMessage::class, htmlspecialchars($message), '', FlashMessage::ERROR, TRUE ); /** @var $flashMessageService FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); $logMessage = $message . ' (' . $table . ':' . $row['uid'] . ')'; GeneralUtility::sysLog($logMessage, 'core', GeneralUtility::SYSLOG_SEVERITY_WARNING); } } } } // Creating the element: $params = array( 'size' => $size, 'allowed' => $allowed, 'disallowed' => $disallowed, 'dontShowMoveIcons' => $maxitems <= 1, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'maxitems' => $maxitems, 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : '', 'thumbnails' => $thumbnails, 'readOnly' => $disabled, 'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'), 'noList' => $noList, 'noDelete' => $noDelete ); $html .= $this->dbFileIcons( $parameterArray['itemFormElName'], 'file', implode(',', $allowed), $itemArray, '', $params, $parameterArray['onFocus'], '', '', '', $config); if (!$disabled && !(isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'upload'))) { // Adding the upload field: $isDirectFileUploadEnabled = (bool)$this->getBackendUserAuthentication()->uc['edit_docModuleUpload']; if ($isDirectFileUploadEnabled && $config['uploadfolder']) { // Insert the multiple attribute to enable HTML5 multiple file upload $multipleAttribute = ''; $multipleFilenameSuffix = ''; if (isset($config['maxitems']) && $config['maxitems'] > 1) { $multipleAttribute = ' multiple="multiple"'; $multipleFilenameSuffix = '[]'; } $html .= ' <div id="' . $parameterArray['itemFormElID_file'] . '"> <input type="file"' . $multipleAttribute . ' name="data_files' . $this->globalOptions['elementBaseName'] . $multipleFilenameSuffix . '" size="35" onchange="' . implode('', $parameterArray['fieldChangeFunc']) . '" /> </div>'; } } break; case 'folder': // If the element is of the internal type "folder": // Array of folder items: $itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE); // Creating the element: $params = array( 'size' => $size, 'dontShowMoveIcons' => $maxitems <= 1, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'maxitems' => $maxitems, 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : '', 'readOnly' => $disabled, 'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'), 'noList' => $noList ); $html .= $this->dbFileIcons( $parameterArray['itemFormElName'], 'folder', '', $itemArray, '', $params, $parameterArray['onFocus'] ); break; case 'db': // If the element is of the internal type "db": // Creating string showing allowed types: $onlySingleTableAllowed = FALSE; $languageService = $this->getLanguageService(); $allowedTables = array(); if ($allowed[0] === '*') { $allowedTables = array( 'name' => htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.allTables')) ); } elseif ($allowed) { $onlySingleTableAllowed = count($allowed) == 1; foreach ($allowed as $allowedTable) { $allowedTables[] = array( 'name' => htmlspecialchars($languageService->sL($GLOBALS['TCA'][$allowedTable]['ctrl']['title'])), 'icon' => IconUtility::getSpriteIconForRecord($allowedTable, array()), 'onClick' => 'setFormValueOpenBrowser(\'db\', ' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'] . '|||' . $allowedTable) . '); return false;' ); } } $perms_clause = $this->getBackendUserAuthentication()->getPagePermsClause(1); $itemArray = array(); // Thumbnails: $temp_itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE); foreach ($temp_itemArray as $dbRead) { $recordParts = explode('|', $dbRead); list($this_table, $this_uid) = BackendUtility::splitTable_Uid($recordParts[0]); // For the case that no table was found and only a single table is defined to be allowed, use that one: if (!$this_table && $onlySingleTableAllowed) { $this_table = $allowed; } $itemArray[] = array('table' => $this_table, 'id' => $this_uid); if (!$disabled && $show_thumbs) { $rr = BackendUtility::getRecordWSOL($this_table, $this_uid); $thumbnails[] = array( 'name' => BackendUtility::getRecordTitle($this_table, $rr, TRUE), 'image' => IconUtility::getSpriteIconForRecord($this_table, $rr), 'path' => BackendUtility::getRecordPath($rr['pid'], $perms_clause, 15), 'uid' => $rr['uid'], 'table' => $this_table ); } } // Creating the element: $params = array( 'size' => $size, 'dontShowMoveIcons' => $maxitems <= 1, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'maxitems' => $maxitems, 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : '', 'info' => $info, 'allowedTables' => $allowedTables, 'thumbnails' => $thumbnails, 'readOnly' => $disabled, 'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'), 'noList' => $noList ); $html .= $this->dbFileIcons( $parameterArray['itemFormElName'], 'db', implode(',', $allowed), $itemArray, '', $params, $parameterArray['onFocus'], $table, $fieldName, $row['uid'], $config ); break; } // Wizards: $altItem = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />'; if (!$disabled) { $html = $this->renderWizards( array( $html, $altItem ), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specConf ); } $resultArray['html'] = $html; return $resultArray; }
/** * Returns a linked image-tag for thumbnail(s)/fileicons/truetype-font-previews from a database row with a list of image files in a field * All $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] extension are made to thumbnails + ttf file (renders font-example) * Thumbsnails are linked to the show_item.php script which will display further details. * * @param array $row Row is the database row from the table, $table. * @param string $table Table name for $row (present in TCA) * @param string $field Field is pointing to the list of image files * @param string $backPath Back path prefix for image tag src="" field * @param string $thumbScript UNUSED since FAL * @param string $uploaddir Optional: $uploaddir is the directory relative to PATH_site where the image files from the $field value is found (Is by default set to the entry in $GLOBALS['TCA'] for that field! so you don't have to!) * @param int $abs UNUSED * @param string $tparams Optional: $tparams is additional attributes for the image tags * @param int|string $size Optional: $size is [w]x[h] of the thumbnail. 64 is default. * @param bool $linkInfoPopup Whether to wrap with a link opening the info popup * @return string Thumbnail image tag. */ public static function thumbCode($row, $table, $field, $backPath = '', $thumbScript = '', $uploaddir = null, $abs = 0, $tparams = '', $size = '', $linkInfoPopup = true) { // Check and parse the size parameter $size = trim($size); $sizeParts = array(64, 64); if ($size) { $sizeParts = explode('x', $size . 'x' . $size); } $thumbData = ''; $fileReferences = static::resolveFileReferences($table, $field, $row); // FAL references $iconFactory = GeneralUtility::makeInstance(IconFactory::class); if ($fileReferences !== null) { foreach ($fileReferences as $fileReferenceObject) { $fileObject = $fileReferenceObject->getOriginalFile(); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbData .= $flashMessage->render(); continue; } // Preview web image or media elements if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] . ',' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['mediafile_ext'], $fileReferenceObject->getExtension())) { $processedImage = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, array('width' => $sizeParts[0], 'height' => $sizeParts[1] . 'c', 'crop' => $fileReferenceObject->getProperty('crop'))); $imageUrl = $processedImage->getPublicUrl(true); $imgTag = '<img src="' . $imageUrl . '" ' . 'width="' . $processedImage->getProperty('width') . '" ' . 'height="' . $processedImage->getProperty('height') . '" ' . 'alt="' . htmlspecialchars($fileReferenceObject->getName()) . '" />'; } else { // Icon $imgTag = '<span title="' . htmlspecialchars($fileObject->getName()) . '">' . $iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL)->render() . '</span>'; } if ($linkInfoPopup) { $onClick = 'top.launchView(\'_FILE\',\'' . (int) $fileObject->getUid() . '\',' . GeneralUtility::quoteJSvalue($backPath) . '); return false;'; $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $imgTag . '</a> '; } else { $thumbData .= $imgTag; } } } else { // Find uploaddir automatically if (is_null($uploaddir)) { $uploaddir = $GLOBALS['TCA'][$table]['columns'][$field]['config']['uploadfolder']; } $uploaddir = rtrim($uploaddir, '/'); // Traverse files: $thumbs = GeneralUtility::trimExplode(',', $row[$field], true); $thumbData = ''; foreach ($thumbs as $theFile) { if ($theFile) { $fileName = trim($uploaddir . '/' . $theFile, '/'); try { /** @var File $fileObject */ $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileName); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbData .= $flashMessage->render(); continue; } } catch (ResourceDoesNotExistException $exception) { /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, htmlspecialchars($exception->getMessage()), static::getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing', true), FlashMessage::ERROR); $thumbData .= $flashMessage->render(); continue; } $fileExtension = $fileObject->getExtension(); if ($fileExtension == 'ttf' || GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) { $imageUrl = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => $sizeParts[0], 'height' => $sizeParts[1]))->getPublicUrl(true); $image = '<img src="' . htmlspecialchars($imageUrl) . '" hspace="2" border="0" title="' . htmlspecialchars($fileObject->getName()) . '"' . $tparams . ' alt="" />'; if ($linkInfoPopup) { $onClick = 'top.launchView(\'_FILE\', ' . GeneralUtility::quoteJSvalue($fileName) . ',\'\',' . GeneralUtility::quoteJSvalue($backPath) . ');return false;'; $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $image . '</a> '; } else { $thumbData .= $image; } } else { // Gets the icon $fileIcon = '<span title="' . htmlspecialchars($fileObject->getName()) . '">' . $iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL)->render() . '</span>'; if ($linkInfoPopup) { $onClick = 'top.launchView(\'_FILE\', ' . GeneralUtility::quoteJSvalue($fileName) . ',\'\',' . GeneralUtility::quoteJSvalue($backPath) . '); return false;'; $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $fileIcon . '</a> '; } else { $thumbData .= $fileIcon; } } } } } return $thumbData; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param array $data Current data * @return string The HTML code of the header */ protected function renderForeignRecordHeader(array $data) { $languageService = $this->getLanguageService(); $inlineConfig = $data['inlineParentConfig']; $foreignTable = $inlineConfig['foreign_table']; $rec = $data['databaseRow']; // Init: $domObjectId = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($data['inlineFirstPid']); $objectId = $domObjectId . '-' . $foreignTable . '-' . $rec['uid']; $recordTitle = $data['recordTitle']; if (empty($recordTitle)) { $recordTitle = '<em>[' . $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title', true) . ']</em>'; } $altText = BackendUtility::getRecordIconAltText($rec, $foreignTable); $iconImg = '<span title="' . $altText . '" id="' . htmlspecialchars($objectId) . '_icon' . '">' . $this->iconFactory->getIconForRecord($foreignTable, $rec, Icon::SIZE_SMALL)->render() . '</span>'; $label = '<span id="' . $objectId . '_label">' . $recordTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($data); $thumbnail = false; // Renders a thumbnail for the header if (!empty($inlineConfig['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$inlineConfig['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode('|', array_shift(GeneralUtility::trimExplode(',', $fieldValue)))); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { try { $fileObject = ResourceFactory::getInstance()->getFileObject($fileUid); } catch (\InvalidArgumentException $e) { $fileObject = null; } if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $inlineConfig['appearance']['headerThumbnail']; unset($imageSetup['field']); if (!empty($rec['crop'])) { $imageSetup['crop'] = $rec['crop']; } $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing process was successful by checking if image width is set if ($processedImage->getProperty('width')) { $imageUrl = $processedImage->getPublicUrl(true); $thumbnail = '<img src="' . $imageUrl . '" ' . 'width="' . $processedImage->getProperty('width') . '" ' . 'height="' . $processedImage->getProperty('height') . '" ' . 'alt="' . htmlspecialchars($altText) . '" ' . 'title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($inlineConfig['appearance']['headerThumbnail']['field']) && $thumbnail) { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = $mediaContainer . ' <div class="form-irre-header-cell form-irre-header-body">' . $label . '</div> <div class="form-irre-header-cell form-irre-header-control t3js-formengine-irre-control">' . $ctrl . '</div>'; return $header; }
/** * Generation of TCEform elements of the type "group" * This will render a selectorbox into which elements from either the file system or database can be inserted. Relations. * * @param string $table The table name of the record * @param string $field The field name which this element is supposed to edit * @param array $row The record data array where the value(s) for the field can be found * @param array $PA An array with additional configuration options. * @return string The HTML code for the TCEform field * @todo Define visibility */ public function getSingleField_typeGroup($table, $field, $row, &$PA) { // Init: $config = $PA['fieldConf']['config']; $show_thumbs = $config['show_thumbs']; $size = isset($config['size']) ? (int) $config['size'] : 5; $maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0); if (!$maxitems) { $maxitems = 100000; } $minitems = MathUtility::forceIntegerInRange($config['minitems'], 0); $allowed = trim($config['allowed']); $disallowed = trim($config['disallowed']); $item = ''; $disabled = ''; if ($this->renderReadonly || $config['readOnly']) { $disabled = ' disabled="disabled"'; } $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />'; $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field)); $info = ''; // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']); $PA['itemFormElID_file'] = $PA['itemFormElID'] . '_files'; // whether the list and delete controls should be disabled $noList = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'list'); $noDelete = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'delete'); // if maxitems==1 then automatically replace the current item (in list and file selector) if ($maxitems === 1) { $this->additionalJS_post[] = 'TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[\'' . $PA['itemFormElName'] . '\'] = { itemFormElID_file: \'' . $PA['itemFormElID_file'] . '\' }'; $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(\'' . $PA['itemFormElName'] . '\', \'Remove\'); ' . $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged']; } elseif ($noList) { // If the list controls have been removed and the maximum number is reached, remove the first entry to avoid "write once" field $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(\'' . $PA['itemFormElName'] . '\', \'RemoveFirstIfFull\', \'' . $maxitems . '\'); ' . $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged']; } // Acting according to either "file" or "db" type: switch ((string) $config['internal_type']) { case 'file_reference': $config['uploadfolder'] = ''; // Fall through // Fall through case 'file': // Creating string showing allowed types: $tempFT = GeneralUtility::trimExplode(',', $allowed, TRUE); if (!count($tempFT)) { $info .= '*'; } foreach ($tempFT as $ext) { if ($ext) { $info .= strtoupper($ext) . ' '; } } // Creating string, showing disallowed types: $tempFT_dis = GeneralUtility::trimExplode(',', $disallowed, TRUE); if (count($tempFT_dis)) { $info .= '<br />'; } foreach ($tempFT_dis as $ext) { if ($ext) { $info .= '-' . strtoupper($ext) . ' '; } } // Making the array of file items: $itemArray = GeneralUtility::trimExplode(',', $PA['itemFormElValue'], TRUE); $fileFactory = ResourceFactory::getInstance(); // Correct the filename for the FAL items foreach ($itemArray as &$fileItem) { list($fileUid, $fileLabel) = explode('|', $fileItem); if (MathUtility::canBeInterpretedAsInteger($fileUid)) { $fileObject = $fileFactory->getFileObject($fileUid); $fileLabel = $fileObject->getName(); } $fileItem = $fileUid . '|' . $fileLabel; } // Showing thumbnails: $thumbsnail = ''; if ($show_thumbs) { $imgs = array(); foreach ($itemArray as $imgRead) { $imgP = explode('|', $imgRead); $imgPath = rawurldecode($imgP[0]); // FAL icon production if (MathUtility::canBeInterpretedAsInteger($imgP[0])) { $fileObject = $fileFactory->getFileObject($imgP[0]); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $imgs[] = $flashMessage->render(); } elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) { $imageUrl = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array())->getPublicUrl(TRUE); $imgTag = '<img src="' . $imageUrl . '" alt="' . htmlspecialchars($fileObject->getName()) . '" />'; $imgs[] = '<span class="nobr">' . $imgTag . htmlspecialchars($fileObject->getName()) . '</span>'; } else { // Icon $imgTag = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName())); $imgs[] = '<span class="nobr">' . $imgTag . htmlspecialchars($fileObject->getName()) . '</span>'; } } else { $rowCopy = array(); $rowCopy[$field] = $imgPath; $thumbnailCode = ''; try { $thumbnailCode = BackendUtility::thumbCode($rowCopy, $table, $field, $this->backPath, 'thumbs.php', $config['uploadfolder'], 0, ' align="middle"'); $thumbnailCode = '<span class="nobr">' . $thumbnailCode . $imgPath . '</span>'; } catch (\Exception $exception) { /** @var $flashMessage FlashMessage */ $message = $exception->getMessage(); $flashMessage = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', htmlspecialchars($message), '', FlashMessage::ERROR, TRUE); $class = 'TYPO3\\CMS\\Core\\Messaging\\FlashMessageService'; /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance($class); $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); $logMessage = $message . ' (' . $table . ':' . $row['uid'] . ')'; GeneralUtility::sysLog($logMessage, 'core', GeneralUtility::SYSLOG_SEVERITY_WARNING); } $imgs[] = $thumbnailCode; } } $thumbsnail = implode('<br />', $imgs); } // Creating the element: $params = array('size' => $size, 'dontShowMoveIcons' => $maxitems <= 1, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'maxitems' => $maxitems, 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"', 'info' => $info, 'thumbnails' => $thumbsnail, 'readOnly' => $disabled, 'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'), 'noList' => $noList, 'noDelete' => $noDelete); $item .= $this->dbFileIcons($PA['itemFormElName'], 'file', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus'], '', '', '', $config); if (!$disabled && !(isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'upload'))) { // Adding the upload field: if ($this->edit_docModuleUpload && $config['uploadfolder']) { // Insert the multiple attribute to enable HTML5 multiple file upload $multipleAttribute = ''; $multipleFilenameSuffix = ''; if (isset($config['maxitems']) && $config['maxitems'] > 1) { $multipleAttribute = ' multiple="multiple"'; $multipleFilenameSuffix = '[]'; } $item .= '<div id="' . $PA['itemFormElID_file'] . '"><input type="file"' . $multipleAttribute . ' name="' . $PA['itemFormElName_file'] . $multipleFilenameSuffix . '" size="35" onchange="' . implode('', $PA['fieldChangeFunc']) . '" /></div>'; } } break; case 'folder': // If the element is of the internal type "folder": // Array of folder items: $itemArray = GeneralUtility::trimExplode(',', $PA['itemFormElValue'], TRUE); // Creating the element: $params = array('size' => $size, 'dontShowMoveIcons' => $maxitems <= 1, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'maxitems' => $maxitems, 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"', 'info' => $info, 'readOnly' => $disabled, 'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'), 'noList' => $noList); $item .= $this->dbFileIcons($PA['itemFormElName'], 'folder', '', $itemArray, '', $params, $PA['onFocus']); break; case 'db': // If the element is of the internal type "db": // Creating string showing allowed types: $tempFT = GeneralUtility::trimExplode(',', $allowed, TRUE); $onlySingleTableAllowed = FALSE; if (trim($tempFT[0]) === '*') { $info .= '<span class="nobr">' . htmlspecialchars($this->getLL('l_allTables')) . '</span><br />'; } elseif ($tempFT) { $onlySingleTableAllowed = count($tempFT) == 1; foreach ($tempFT as $theT) { $aOnClick = 'setFormValueOpenBrowser(\'db\', \'' . ($PA['itemFormElName'] . '|||' . $theT) . '\'); return false;'; $info .= '<span class="nobr"> <a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . IconUtility::getSpriteIconForRecord($theT, array()) . htmlspecialchars($this->sL($GLOBALS['TCA'][$theT]['ctrl']['title'])) . '</a></span><br />'; } } $perms_clause = $this->getBackendUserAuthentication()->getPagePermsClause(1); $itemArray = array(); $imgs = array(); // Thumbnails: $temp_itemArray = GeneralUtility::trimExplode(',', $PA['itemFormElValue'], TRUE); foreach ($temp_itemArray as $dbRead) { $recordParts = explode('|', $dbRead); list($this_table, $this_uid) = BackendUtility::splitTable_Uid($recordParts[0]); // For the case that no table was found and only a single table is defined to be allowed, use that one: if (!$this_table && $onlySingleTableAllowed) { $this_table = $allowed; } $itemArray[] = array('table' => $this_table, 'id' => $this_uid); if (!$disabled && $show_thumbs) { $rr = BackendUtility::getRecordWSOL($this_table, $this_uid); $imgs[] = '<span class="nobr">' . $this->getClickMenu(IconUtility::getSpriteIconForRecord($this_table, $rr, array('style' => 'vertical-align:top', 'title' => htmlspecialchars(BackendUtility::getRecordPath($rr['pid'], $perms_clause, 15) . ' [UID: ' . $rr['uid'] . ']'))), $this_table, $this_uid) . ' ' . BackendUtility::getRecordTitle($this_table, $rr, TRUE) . ' <span class="typo3-dimmed"><em>[' . $rr['uid'] . ']</em></span>' . '</span>'; } } $thumbsnail = ''; if (!$disabled && $show_thumbs) { $thumbsnail = implode('<br />', $imgs); } // Creating the element: $params = array('size' => $size, 'dontShowMoveIcons' => $maxitems <= 1, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'maxitems' => $maxitems, 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"', 'info' => $info, 'thumbnails' => $thumbsnail, 'readOnly' => $disabled, 'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'), 'noList' => $noList); $item .= $this->dbFileIcons($PA['itemFormElName'], 'db', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus'], $table, $field, $row['uid'], $config); break; } // Wizards: $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />'; if (!$disabled) { $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf); } return $item; }
/** * Returns where clause for the news table * * @return string */ protected function getEnableFieldsWhereClauseForTable() { $table = 'tx_news_domain_model_news'; if (is_object($GLOBALS['TSFE']) && is_object($GLOBALS['TSFE']->sys_page)) { return $GLOBALS['TSFE']->sys_page->enableFields($table); } elseif (is_object($GLOBALS['BE_USER'])) { return \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($table) . \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields($table) . \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getWorkspaceWhereClause($table); } elseif (TYPO3_MODE === 'BE' && TYPO3_cliMode === TRUE) { return ''; } throw new \UnexpectedValueException('No TSFE for frontend and no BE_USER for Backend defined, please report the issue!'); }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $data Current data * @param array $config content of $PA['fieldConf']['config'] * @param bool $isVirtualRecord * @return string The HTML code of the header */ protected function renderForeignRecordHeader($parentUid, $foreign_table, $data, $config, $isVirtualRecord = false) { $rec = $data['databaseRow']; // Init: $domObjectId = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']); $objectId = $domObjectId . '-' . $foreign_table . '-' . $rec['uid']; // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = (bool) (!$isOnSymmetricSide && $config['foreign_label']); $hasSymmetricLabel = (bool) $isOnSymmetricSide && $config['symmetric_label']; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = null; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $recTitle = $data['recordTitle']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; // Render title for everything else than group/db: if (isset($this->data['processedTca']['columns'][$titleCol]['config']['type']) && $this->data['processedTca']['columns'][$titleCol]['config']['type'] === 'group' && isset($this->data['processedTca']['columns'][$titleCol]['config']['internal_type']) && $this->data['processedTca']['columns'][$titleCol]['config']['internal_type'] === 'db') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, false); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(true); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, FormEngineUtility::databaseRowCompatibility($rec), true); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = '<span title="' . $altText . '" id="' . htmlspecialchars($objectId) . '_icon' . '">' . $this->iconFactory->getIconForRecord($foreign_table, $rec, Icon::SIZE_SMALL)->render() . '</span>'; $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $data, $config, $isVirtualRecord); $thumbnail = false; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode('|', array_shift(GeneralUtility::trimExplode(',', $fieldValue)))); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); if (!empty($rec['crop'])) { $imageSetup['crop'] = $rec['crop']; } $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing process was successful by checking if image width is set if ($processedImage->getProperty('width')) { $imageUrl = $processedImage->getPublicUrl(true); $thumbnail = '<img src="' . $imageUrl . '" ' . 'width="' . $processedImage->getProperty('width') . '" ' . 'height="' . $processedImage->getProperty('height') . '" ' . 'alt="' . htmlspecialchars($altText) . '" ' . 'title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = $mediaContainer . ' <div class="form-irre-header-cell form-irre-header-body">' . $label . '</div> <div class="form-irre-header-cell form-irre-header-control t3js-formengine-irre-control">' . $ctrl . '</div>'; return $header; }
/** * Render preview for current record * * @return string */ protected function renderPreview() { // Perhaps @TODO in future: Also display preview for records - without fileObject if (!$this->fileObject) { return; } $imageTag = ''; $downloadLink = ''; // check if file is marked as missing if ($this->fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($this->fileObject); $imageTag .= $flashMessage->render(); } else { $fileExtension = $this->fileObject->getExtension(); $thumbUrl = ''; if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) { $thumbUrl = $this->fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => '400m', 'height' => '400m'))->getPublicUrl(TRUE); } // Create thumbnail image? if ($thumbUrl) { $imageTag .= '<img src="' . $thumbUrl . '" ' . 'alt="' . htmlspecialchars(trim($this->fileObject->getName())) . '" ' . 'title="' . htmlspecialchars(trim($this->fileObject->getName())) . '" />'; } // Display download link? $url = $this->fileObject->getPublicUrl(TRUE); if ($url) { $downloadLink .= '<a href="' . htmlspecialchars($url) . '" target="_blank" class="t3-button">' . IconUtility::getSpriteIcon('actions-edit-download') . ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:download', TRUE) . '</a>'; } } return ($imageTag ? '<p>' . $imageTag . '</p>' : '') . ($downloadLink ? '<p>' . $downloadLink . '</p>' : ''); }
/** * This returns tablerows for the files in the array $items['sorting']. * * @param \TYPO3\CMS\Core\Resource\File[] $files File items * @return string HTML table rows. * @todo Define visibility */ public function formatFileList(array $files) { $out = ''; // first two keys are "0" (default) and "-1" (multiple), after that comes the "other languages" $allSystemLanguages = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Configuration\\TranslationConfigurationProvider')->getSystemLanguages(); $systemLanguages = array_filter($allSystemLanguages, function ($languageRecord) { if ($languageRecord['uid'] === -1 || $languageRecord['uid'] === 0 || !$GLOBALS['BE_USER']->checkLanguageAccess($languageRecord['uid'])) { return FALSE; } else { return TRUE; } }); foreach ($files as $fileObject) { list($flag, $code) = $this->fwd_rwd_nav(); $out .= $code; if ($flag) { // Initialization $this->counter++; $this->totalbytes += $fileObject->getSize(); $ext = $fileObject->getExtension(); $fileName = trim($fileObject->getName()); // The icon with link $theIcon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileName)); if ($this->clickMenus) { $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($theIcon, $fileObject->getCombinedIdentifier()); } // Preparing and getting the data-array $theData = array(); foreach ($this->fieldArray as $field) { switch ($field) { case 'size': $theData[$field] = GeneralUtility::formatSize($fileObject->getSize(), $GLOBALS['LANG']->getLL('byteSizeUnits', TRUE)); break; case 'rw': $theData[$field] = '' . (!$fileObject->checkActionPermission('read') ? ' ' : '<span class="typo3-red"><strong>' . $GLOBALS['LANG']->getLL('read', TRUE) . '</strong></span>') . (!$fileObject->checkActionPermission('write') ? '' : '<span class="typo3-red"><strong>' . $GLOBALS['LANG']->getLL('write', TRUE) . '</strong></span>'); break; case 'fileext': $theData[$field] = strtoupper($ext); break; case 'tstamp': $theData[$field] = BackendUtility::date($fileObject->getProperty('modification_date')); break; case '_CLIPBOARD_': $temp = ''; if ($this->bigControlPanel) { $temp .= $this->makeEdit($fileObject); } $temp .= $this->makeClip($fileObject); if (!empty($systemLanguages)) { $temp .= '<a class="filelist-translationToggler" data-fileid="' . $fileObject->getUid() . '">' . IconUtility::getSpriteIcon('mimetypes-x-content-page-language-overlay') . '</a>'; } $theData[$field] = $temp; break; case '_REF_': $theData[$field] = $this->makeRef($fileObject); break; case 'file': $theData[$field] = $this->linkWrapFile(htmlspecialchars($fileName), $fileObject); if ($fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $theData[$field] .= $flashMessage->render(); // Thumbnails? } elseif ($this->thumbs && $this->isImage($ext)) { $processedFile = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW, array()); if ($processedFile) { $thumbUrl = $processedFile->getPublicUrl(TRUE); $theData[$field] .= '<br /><img src="' . $thumbUrl . '" title="' . htmlspecialchars($fileName) . '" alt="" />'; } } if (!empty($systemLanguages)) { $metaDataRecord = $fileObject->_getMetaData(); $translations = $this->getTranslationsForMetaData($metaDataRecord); $languageCode = ''; foreach ($systemLanguages as $language) { $languageId = $language['uid']; $flagIcon = $language['flagIcon']; if (array_key_exists($languageId, $translations)) { $flagButtonIcon = IconUtility::getSpriteIcon('actions-document-open', array('title' => $fileName), array($flagIcon . '-overlay' => array())); $data = array('sys_file_metadata' => array($translations[$languageId]['uid'] => 'edit')); $editOnClick = BackendUtility::editOnClick(GeneralUtility::implodeArrayForUrl('edit', $data), $GLOBALS['BACK_PATH'], $this->listUrl()); $languageCode .= sprintf('<a href="#" onclick="%s">%s</a>', htmlspecialchars($editOnClick), $flagButtonIcon); } else { $href = $GLOBALS['SOBE']->doc->issueCommand('&cmd[sys_file_metadata][' . $metaDataRecord['uid'] . '][localize]=' . $languageId, $this->backPath . 'alt_doc.php?justLocalized=' . rawurlencode('sys_file_metadata:' . $metaDataRecord['uid'] . ':' . $languageId) . '&returnUrl=' . rawurlencode($this->listURL()) . BackendUtility::getUrlToken('editRecord')); $flagButtonIcon = IconUtility::getSpriteIcon($flagIcon); $languageCode .= sprintf('<a href="%s">%s</a> ', htmlspecialchars($href), $flagButtonIcon); } } // Hide flag button bar when not translated yet $theData[$field] .= '<div class="localisationData" data-fileid="' . $fileObject->getUid() . '"' . (empty($translations) ? ' style="display: none;"' : '') . '>' . $languageCode . '</div>'; } break; default: $theData[$field] = ''; if ($fileObject->hasProperty($field)) { $theData[$field] = htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getProperty($field), $this->fixedL)); } } } $out .= $this->addelement(1, $theIcon, $theData); } $this->eCounter++; } return $out; }