예제 #1
0
    /**
     * 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'])) {
            $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 = FormEngineUtility::getInlinePossibleRecordsSelectorConfig($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, 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;
    }
예제 #2
0
 /**
  * Get a selector as used for the select type, to select from all available
  * records and to create a relation to the embedding record (e.g. like MM).
  *
  * @param array $selItems Array of all possible records
  * @param array $conf TCA configuration of the parent(!) field
  * @param array $uniqueIds The uids that have already been used and should be unique
  * @return string A HTML <select> box with all possible records
  */
 protected function renderPossibleRecordsSelector($selItems, $conf, $uniqueIds = array())
 {
     $foreign_selector = $conf['foreign_selector'];
     $selConfig = FormEngineUtility::getInlinePossibleRecordsSelectorConfig($conf, $foreign_selector);
     $item = '';
     if ($selConfig['type'] === 'select') {
         $item = $this->renderPossibleRecordsSelectorTypeSelect($selItems, $conf, $selConfig['PA'], $uniqueIds);
     } elseif ($selConfig['type'] === 'groupdb') {
         $item = $this->renderPossibleRecordsSelectorTypeGroupDB($conf, $selConfig['PA']);
     }
     return $item;
 }
예제 #3
0
 /**
  * Handle AJAX calls to show a new inline-record of the given table.
  *
  * @param string $domObjectId The calling object in hierarchy, that requested a new record.
  * @param string|int $foreignUid If set, the new record should be inserted after that one.
  * @return array An array to be used for JSON
  */
 protected function renderInlineNewChildRecord($domObjectId, $foreignUid)
 {
     // The current table - for this table we should add/import records
     $current = $this->inlineStackProcessor->getUnstableStructure();
     // The parent table - this table embeds the current table
     $parent = $this->inlineStackProcessor->getStructureLevel(-1);
     $config = $parent['config'];
     if (empty($config['foreign_table']) || !is_array($GLOBALS['TCA'][$config['foreign_table']])) {
         return $this->getErrorMessageForAJAX('Wrong configuration in table ' . $parent['table']);
     }
     $inlineRelatedRecordResolver = GeneralUtility::makeInstance(InlineRelatedRecordResolver::class);
     $config = FormEngineUtility::mergeInlineConfiguration($config);
     $collapseAll = isset($config['appearance']['collapseAll']) && $config['appearance']['collapseAll'];
     $expandSingle = isset($config['appearance']['expandSingle']) && $config['appearance']['expandSingle'];
     $inlineFirstPid = FormEngineUtility::getInlineFirstPidFromDomObjectId($domObjectId);
     // Dynamically create a new record using \TYPO3\CMS\Backend\Form\DataPreprocessor
     if (!$foreignUid || !MathUtility::canBeInterpretedAsInteger($foreignUid) || $config['foreign_selector']) {
         $record = $inlineRelatedRecordResolver->getNewRecord($inlineFirstPid, $current['table']);
         // Set default values for new created records
         if (isset($config['foreign_record_defaults']) && is_array($config['foreign_record_defaults'])) {
             $foreignTableConfig = $GLOBALS['TCA'][$current['table']];
             // The following system relevant fields can't be set by foreign_record_defaults
             $notSettableFields = array('uid', 'pid', 't3ver_oid', 't3ver_id', 't3ver_label', 't3ver_wsid', 't3ver_state', 't3ver_stage', 't3ver_count', 't3ver_tstamp', 't3ver_move_id');
             $configurationKeysForNotSettableFields = array('crdate', 'cruser_id', 'delete', 'origUid', 'transOrigDiffSourceField', 'transOrigPointerField', 'tstamp');
             foreach ($configurationKeysForNotSettableFields as $configurationKey) {
                 if (isset($foreignTableConfig['ctrl'][$configurationKey])) {
                     $notSettableFields[] = $foreignTableConfig['ctrl'][$configurationKey];
                 }
             }
             foreach ($config['foreign_record_defaults'] as $fieldName => $defaultValue) {
                 if (isset($foreignTableConfig['columns'][$fieldName]) && !in_array($fieldName, $notSettableFields)) {
                     $record[$fieldName] = $defaultValue;
                 }
             }
         }
         // Set language of new child record to the language of the parent record:
         if ($parent['localizationMode'] === 'select') {
             $parentRecord = $inlineRelatedRecordResolver->getRecord($parent['table'], $parent['uid']);
             $parentLanguageField = $GLOBALS['TCA'][$parent['table']]['ctrl']['languageField'];
             $childLanguageField = $GLOBALS['TCA'][$current['table']]['ctrl']['languageField'];
             if ($parentRecord[$parentLanguageField] > 0) {
                 $record[$childLanguageField] = $parentRecord[$parentLanguageField];
             }
         }
     } else {
         // @todo: Check this: Else also hits if $foreignUid = 0?
         $record = $inlineRelatedRecordResolver->getRecord($current['table'], $foreignUid);
     }
     // Now there is a foreign_selector, so there is a new record on the intermediate table, but
     // this intermediate table holds a field, which is responsible for the foreign_selector, so
     // we have to set this field to the uid we get - or if none, to a new uid
     if ($config['foreign_selector'] && $foreignUid) {
         $selConfig = FormEngineUtility::getInlinePossibleRecordsSelectorConfig($config, $config['foreign_selector']);
         // For a selector of type group/db, prepend the tablename (<tablename>_<uid>):
         $record[$config['foreign_selector']] = $selConfig['type'] != 'groupdb' ? '' : $selConfig['table'] . '_';
         $record[$config['foreign_selector']] .= $foreignUid;
         if ($selConfig['table'] === 'sys_file') {
             $fileRecord = $inlineRelatedRecordResolver->getRecord($selConfig['table'], $foreignUid);
             if ($fileRecord !== FALSE && !$this->checkInlineFileTypeAccessForField($selConfig, $fileRecord)) {
                 return $this->getErrorMessageForAJAX('File extension ' . $fileRecord['extension'] . ' is not allowed here!');
             }
         }
     }
     // The HTML-object-id's prefix of the dynamically created record
     $objectName = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($inlineFirstPid);
     $objectPrefix = $objectName . '-' . $current['table'];
     $objectId = $objectPrefix . '-' . $record['uid'];
     $options = $this->getConfigurationOptionsForChildElements();
     $options['databaseRow'] = array('uid' => $parent['uid']);
     $options['inlineFirstPid'] = $inlineFirstPid;
     $options['inlineRelatedRecordToRender'] = $record;
     $options['inlineRelatedRecordConfig'] = $config;
     $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
     $options['isAjaxContext'] = TRUE;
     $options['renderType'] = 'inlineRecordContainer';
     $childArray = $this->nodeFactory->create($options)->render();
     if ($childArray === FALSE) {
         return $this->getErrorMessageForAJAX('Access denied');
     }
     $this->mergeResult($childArray);
     $jsonArray = array('data' => $childArray['html'], 'scriptCall' => array());
     if (!$current['uid']) {
         $jsonArray['scriptCall'][] = 'inline.domAddNewRecord(\'bottom\',' . GeneralUtility::quoteJSvalue($objectName . '_records') . ',' . GeneralUtility::quoteJSvalue($objectPrefix) . ',json.data);';
         $jsonArray['scriptCall'][] = 'inline.memorizeAddRecord(' . GeneralUtility::quoteJSvalue($objectPrefix) . ',' . GeneralUtility::quoteJSvalue($record['uid']) . ',null,' . GeneralUtility::quoteJSvalue($foreignUid) . ');';
     } else {
         $jsonArray['scriptCall'][] = 'inline.domAddNewRecord(\'after\',' . GeneralUtility::quoteJSvalue($domObjectId . '_div') . ',' . GeneralUtility::quoteJSvalue($objectPrefix) . ',json.data);';
         $jsonArray['scriptCall'][] = 'inline.memorizeAddRecord(' . GeneralUtility::quoteJSvalue($objectPrefix) . ',' . GeneralUtility::quoteJSvalue($record['uid']) . ',' . GeneralUtility::quoteJSvalue($current['uid']) . ',' . GeneralUtility::quoteJSvalue($foreignUid) . ');';
     }
     $jsonArray = $this->getInlineAjaxCommonScriptCalls($jsonArray, $config, $inlineFirstPid);
     // Collapse all other records if requested:
     if (!$collapseAll && $expandSingle) {
         $jsonArray['scriptCall'][] = 'inline.collapseAllRecords(' . GeneralUtility::quoteJSvalue($objectId) . ', ' . GeneralUtility::quoteJSvalue($objectPrefix) . ', ' . GeneralUtility::quoteJSvalue($record['uid']) . ');';
     }
     // Tell the browser to scroll to the newly created record
     $jsonArray['scriptCall'][] = 'Element.scrollTo(' . GeneralUtility::quoteJSvalue($objectId . '_div') . ');';
     // Fade out and fade in the new record in the browser view to catch the user's eye
     $jsonArray['scriptCall'][] = 'inline.fadeOutFadeIn(' . GeneralUtility::quoteJSvalue($objectId . '_div') . ');';
     return $jsonArray;
 }