/**
  * @test
  */
 public function databaseRowCompatibilityImplodesSelectArrayWithValuesAtSecondPosition()
 {
     $input = ['uid' => 42, 'simpleArray' => [0 => [0 => 'aLabel', 1 => 'aValue'], 1 => [0 => 'anotherLabel', 1 => 'anotherValue']]];
     $expected = $input;
     $expected['simpleArray'] = 'aValue,anotherValue';
     $this->assertEquals($expected, FormEngineUtility::databaseRowCompatibility($input));
 }
Esempio n. 2
0
 /**
  * Creates the editing form with FormEnigne, based on the input from GPvars.
  *
  * @return string HTML form elements wrapped in tables
  */
 public function makeEditForm()
 {
     // Initialize variables:
     $this->elementsData = array();
     $this->errorC = 0;
     $this->newC = 0;
     $editForm = '';
     $trData = null;
     $beUser = $this->getBackendUser();
     // Traverse the GPvar edit array
     // Tables:
     foreach ($this->editconf as $table => $conf) {
         if (is_array($conf) && $GLOBALS['TCA'][$table] && $beUser->check('tables_modify', $table)) {
             // Traverse the keys/comments of each table (keys can be a commalist of uids)
             foreach ($conf as $cKey => $command) {
                 if ($command == 'edit' || $command == 'new') {
                     // Get the ids:
                     $ids = GeneralUtility::trimExplode(',', $cKey, true);
                     // Traverse the ids:
                     foreach ($ids as $theUid) {
                         // Don't save this document title in the document selector if the document is new.
                         if ($command === 'new') {
                             $this->dontStoreDocumentRef = 1;
                         }
                         /** @var TcaDatabaseRecord $formDataGroup */
                         $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
                         /** @var FormDataCompiler $formDataCompiler */
                         $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
                         /** @var NodeFactory $nodeFactory */
                         $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
                         try {
                             // Reset viewId - it should hold data of last entry only
                             $this->viewId = 0;
                             $this->viewId_addParams = '';
                             $formDataCompilerInput = ['tableName' => $table, 'vanillaUid' => (int) $theUid, 'command' => $command, 'returnUrl' => $this->R_URI];
                             if (is_array($this->overrideVals) && is_array($this->overrideVals[$table])) {
                                 $formDataCompilerInput['overrideValues'] = $this->overrideVals[$table];
                             }
                             $formData = $formDataCompiler->compile($formDataCompilerInput);
                             // Set this->viewId if possible
                             if ($command === 'new' && $table !== 'pages' && !empty($formData['parentPageRow']['uid'])) {
                                 $this->viewId = $formData['parentPageRow']['uid'];
                             } else {
                                 if ($table == 'pages') {
                                     $this->viewId = $formData['databaseRow']['uid'];
                                 } elseif (!empty($formData['parentPageRow']['uid'])) {
                                     $this->viewId = $formData['parentPageRow']['uid'];
                                     // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero!
                                     if (!empty($formData['processedTca']['ctrl']['languageField']) && is_array($formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']]) && $formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']][0] > 0) {
                                         $this->viewId_addParams = '&L=' . $formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']][0];
                                     }
                                 }
                             }
                             // Determine if delete button can be shown
                             $deleteAccess = false;
                             if ($command === 'edit') {
                                 $permission = $formData['userPermissionOnPage'];
                                 if ($formData['tableName'] === 'pages') {
                                     $deleteAccess = $permission & Permission::PAGE_DELETE ? true : false;
                                 } else {
                                     $deleteAccess = $permission & Permission::CONTENT_EDIT ? true : false;
                                 }
                             }
                             // Display "is-locked" message:
                             if ($command === 'edit') {
                                 $lockInfo = BackendUtility::isRecordLocked($table, $formData['databaseRow']['uid']);
                                 if ($lockInfo) {
                                     /** @var $flashMessage \TYPO3\CMS\Core\Messaging\FlashMessage */
                                     $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, htmlspecialchars($lockInfo['msg']), '', FlashMessage::WARNING);
                                     /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
                                     $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
                                     /** @var $defaultFlashMessageQueue FlashMessageQueue */
                                     $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
                                     $defaultFlashMessageQueue->enqueue($flashMessage);
                                 }
                             }
                             // Record title
                             if (!$this->storeTitle) {
                                 $this->storeTitle = $this->recTitle ? htmlspecialchars($this->recTitle) : BackendUtility::getRecordTitle($table, FormEngineUtility::databaseRowCompatibility($formData['databaseRow']), true);
                             }
                             $this->elementsData[] = array('table' => $table, 'uid' => $formData['databaseRow']['uid'], 'pid' => $formData['databaseRow']['pid'], 'cmd' => $command, 'deleteAccess' => $deleteAccess);
                             if ($command !== 'new') {
                                 BackendUtility::lockRecords($table, $formData['databaseRow']['uid'], $table === 'tt_content' ? $formData['databaseRow']['pid'] : 0);
                             }
                             // Set list if only specific fields should be rendered. This will trigger
                             // ListOfFieldsContainer instead of FullRecordContainer in OuterWrapContainer
                             if ($this->columnsOnly) {
                                 if (is_array($this->columnsOnly)) {
                                     $formData['fieldListToRender'] = $this->columnsOnly[$table];
                                 } else {
                                     $formData['fieldListToRender'] = $this->columnsOnly;
                                 }
                             }
                             $formData['renderType'] = 'outerWrapContainer';
                             $formResult = $nodeFactory->create($formData)->render();
                             $html = $formResult['html'];
                             $formResult['html'] = '';
                             $formResult['doSaveFieldName'] = 'doSave';
                             // @todo: Put all the stuff into FormEngine as final "compiler" class
                             // @todo: This is done here for now to not rewrite JStop()
                             // @todo: and printNeededJSFunctions() now
                             $this->formResultCompiler->mergeResult($formResult);
                             // Seems the pid is set as hidden field (again) at end?!
                             if ($command == 'new') {
                                 // @todo: looks ugly
                                 $html .= LF . '<input type="hidden"' . ' name="data[' . $table . '][' . $formData['databaseRow']['uid'] . '][pid]"' . ' value="' . $formData['databaseRow']['pid'] . '" />';
                                 $this->newC++;
                             }
                             $editForm .= $html;
                         } catch (AccessDeniedException $e) {
                             $this->errorC++;
                             // Try to fetch error message from "recordInternals" be user object
                             // @todo: This construct should be logged and localized and de-uglified
                             $message = $beUser->errorMsg;
                             if (empty($message)) {
                                 // Create message from exception.
                                 $message = $e->getMessage() . ' ' . $e->getCode();
                             }
                             $editForm .= $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noEditPermission', true) . '<br /><br />' . htmlspecialchars($message) . '<br /><br />';
                         }
                     }
                     // End of for each uid
                 }
             }
         }
     }
     return $editForm;
 }
    /**
     * 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;
    }