/**
  * Handler for unknown types.
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $resultArray = $this->initializeResultArray();
     $languageService = $this->getLanguageService();
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     // If ratios are set do not add default options
     if (isset($parameterArray['fieldConf']['config']['ratios'])) {
         unset($this->defaultConfig['ratios']);
     }
     $config = ArrayUtility::arrayMergeRecursiveOverrule($this->defaultConfig, $parameterArray['fieldConf']['config']);
     // By default we allow all image extensions that can be handled by the GFX functionality
     if ($config['allowedExtensions'] === null) {
         $config['allowedExtensions'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
     }
     if ($config['readOnly']) {
         $options = array();
         $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $parameterArray['itemFormElValue']);
         $options['renderType'] = 'none';
         return $this->nodeFactory->create($options)->render();
     }
     $file = $this->getFile($row, $config['file_field']);
     if (!$file) {
         return $resultArray;
     }
     $content = '';
     $preview = '';
     if (GeneralUtility::inList(mb_strtolower($config['allowedExtensions']), mb_strtolower($file->getExtension()))) {
         // Get preview
         $preview = $this->getPreview($file, $parameterArray['itemFormElValue']);
         // Check if ratio labels hold translation strings
         foreach ((array) $config['ratios'] as $ratio => $label) {
             $config['ratios'][$ratio] = $languageService->sL($label, true);
         }
         $formFieldId = StringUtility::getUniqueId('formengine-image-manipulation-');
         $wizardData = array('zoom' => $config['enableZoom'] ? '1' : '0', 'ratios' => json_encode($config['ratios']), 'file' => $file->getUid());
         $wizardData['token'] = GeneralUtility::hmac(implode('|', $wizardData), 'ImageManipulationWizard');
         $buttonAttributes = array('data-url' => BackendUtility::getAjaxUrl('wizard_image_manipulation', $wizardData), 'data-severity' => 'notice', 'data-image-name' => $file->getNameWithoutExtension(), 'data-image-uid' => $file->getUid(), 'data-file-field' => $config['file_field'], 'data-field' => $formFieldId);
         $button = '<button class="btn btn-default t3js-image-manipulation-trigger"';
         foreach ($buttonAttributes as $key => $value) {
             $button .= ' ' . $key . '="' . htmlspecialchars($value) . '"';
         }
         $button .= '><span class="t3-icon fa fa-crop"></span>';
         $button .= $languageService->sL('LLL:EXT:lang/locallang_wizards.xlf:imwizard.open-editor', true);
         $button .= '</button>';
         $inputField = '<input type="hidden" ' . 'id="' . $formFieldId . '" ' . 'name="' . $parameterArray['itemFormElName'] . '" ' . 'value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
         $content .= $inputField . $button;
         $content .= $this->getImageManipulationInfoTable($parameterArray['itemFormElValue']);
         $resultArray['requireJsModules'][] = array('TYPO3/CMS/Backend/ImageManipulation' => 'function(ImageManipulation){ImageManipulation.initializeTrigger()}');
     }
     $content .= '<p class="text-muted"><em>' . $languageService->sL('LLL:EXT:lang/locallang_wizards.xlf:imwizard.supported-types-message', true) . '<br />';
     $content .= mb_strtoupper(implode(', ', GeneralUtility::trimExplode(',', $config['allowedExtensions'])));
     $content .= '</em></p>';
     $item = '<div class="media">';
     $item .= $preview;
     $item .= '<div class="media-body">' . $content . '</div>';
     $item .= '</div>';
     $resultArray['html'] = $item;
     return $resultArray;
 }
示例#2
0
    public function renderHtml($name, $value, $options)
    {
        $width = $options['width'];
        // TODO: das Feld beachten!
        $maxlength = $options['maxlength'];
        $attributes = array();
        // for data-formengine-input-params
        $paramsList = array('field' => $name, 'evalList' => 'int', 'is_in' => '');
        $attributes['id'] = StringUtility::getUniqueId('formengine-input-');
        $attributes['value'] = '';
        $attributes['data-formengine-validation-rules'] = json_encode(array('type' => 'int'));
        $attributes['data-formengine-input-params'] = json_encode($paramsList);
        $attributes['data-formengine-input-name'] = htmlspecialchars($name);
        $attributeString = '';
        foreach ($attributes as $attributeName => $attributeValue) {
            $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
        }
        //$width = (int)$this->formMaxWidth($size);
        $width = $GLOBALS['TBE_TEMPLATE']->formWidth($width);
        $html = '
			<input type="text"' . $attributeString . $width . ' />';
        // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
        $html .= '<input type="hidden" name="' . $name . '" value="' . htmlspecialchars($value) . '" />';
        // Den Wrap lassen wir weg, weil es zu einem Zeilenumbruch kommt
        //			$html = '<div class="form-control-wrap"' . $width . '>' . $html . '</div>';
        return $html;
    }
    /**
     * Rendering the cObject, QTOBJECT
     *
     * @param array $conf Array of TypoScript properties
     * @return string Output
     */
    public function render($conf = array())
    {
        $params = $prefix = '';
        if ($GLOBALS['TSFE']->baseUrl) {
            $prefix = $GLOBALS['TSFE']->baseUrl;
        }
        if ($GLOBALS['TSFE']->absRefPrefix) {
            $prefix = $GLOBALS['TSFE']->absRefPrefix;
        }
        $type = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
        // If file is audio and an explicit path has not been set,
        // take path from audio fallback property
        if ($type == 'audio' && empty($conf['file'])) {
            $conf['file'] = $conf['audioFallback'];
        }
        $filename = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
        $typeConf = $conf[$type . '.'];
        // Add QTobject js-file
        $this->getPageRenderer()->addJsFile($this->getPathToLibrary('flashmedia/qtobject/qtobject.js'));
        $replaceElementIdString = StringUtility::getUniqueId('mmqt');
        $GLOBALS['TSFE']->register['MMQTID'] = $replaceElementIdString;
        $qtObject = 'QTObject' . $replaceElementIdString;
        // Merge with default parameters
        $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
        if (is_array($conf['params.']) && is_array($typeConf['mapping.']['params.'])) {
            ArrayUtility::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
            foreach ($conf['params.'] as $key => $value) {
                $params .= $qtObject . '.addParam("' . $key . '", "' . $value . '");' . LF;
            }
        }
        $params = ($params ? substr($params, 0, -2) : '') . LF . $qtObject . '.write("' . $replaceElementIdString . '");';
        $alternativeContent = isset($conf['alternativeContent.']) ? $this->cObj->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']) : $conf['alternativeContent'];
        $layout = str_replace(array('###ID###', '###QTOBJECT###'), array($replaceElementIdString, '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>'), isset($conf['layout.']) ? $this->cObj->stdWrap($conf['layout'], $conf['layout.']) : $conf['layout']);
        $width = isset($conf['width.']) ? $this->cObj->stdWrap($conf['width'], $conf['width.']) : $conf['width'];
        if (!$width) {
            $width = $conf[$type . '.']['defaultWidth'];
        }
        $height = isset($conf['height.']) ? $this->cObj->stdWrap($conf['height'], $conf['height.']) : $conf['height'];
        if (!$height) {
            $height = $conf[$type . '.']['defaultHeight'];
        }
        $fullFilename = $filename;
        // If the file name doesn't contain a scheme, prefix with appropriate data
        if (strpos($filename, '://') === false && !empty($prefix)) {
            $fullFilename = $prefix . $filename;
        }
        $embed = 'var ' . $qtObject . ' = new QTObject("' . $fullFilename . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '");';
        $content = $layout . '
			<script type="text/javascript">
				' . $embed . '
				' . $params . '
			</script>';
        if (isset($conf['stdWrap.'])) {
            $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
        }
        return $content;
    }
 /**
  * Initialize new row with unique uid
  *
  * @param array $result
  * @return array
  * @throws \InvalidArgumentException
  */
 public function addData(array $result)
 {
     if ($result['command'] !== 'new') {
         return $result;
     }
     // Throw exception if uid is already set
     if (isset($result['databaseRow']['uid'])) {
         throw new \InvalidArgumentException('uid is already set to ' . $result['databaseRow']['uid'], 1437991120);
     }
     $result['databaseRow']['uid'] = StringUtility::getUniqueId('NEW');
     return $result;
 }
示例#5
0
 /**
  * At the end of the import process all file and DB relations should be set properly (that is relations
  * to imported records are all re-created so imported records are correctly related again)
  * Relations in flexform fields are processed in setFlexFormRelations() after this function
  *
  * @return void
  * @see setFlexFormRelations()
  */
 public function setRelations()
 {
     $updateData = array();
     // import_newId contains a register of all records that was in the import memorys "records" key
     foreach ($this->import_newId as $nId => $dat) {
         $table = $dat['table'];
         $uid = $dat['uid'];
         // original UID - NOT the new one!
         // If the record has been written and received a new id, then proceed:
         if (is_array($this->import_mapId[$table]) && isset($this->import_mapId[$table][$uid])) {
             $thisNewUid = BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
             if (is_array($this->dat['records'][$table . ':' . $uid]['rels'])) {
                 $thisNewPageUid = 0;
                 if ($this->legacyImport) {
                     if ($table != 'pages') {
                         $oldPid = $this->dat['records'][$table . ':' . $uid]['data']['pid'];
                         $thisNewPageUid = BackendUtility::wsMapId($table, $this->import_mapId['pages'][$oldPid]);
                     } else {
                         $thisNewPageUid = $thisNewUid;
                     }
                 }
                 // Traverse relation fields of each record
                 foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
                     // uid_local of sys_file_reference needs no update because the correct reference uid was already written
                     // @see ImportExport::fixUidLocalInSysFileReferenceRecords()
                     if ($table === 'sys_file_reference' && $field === 'uid_local') {
                         continue;
                     }
                     switch ((string) $config['type']) {
                         case 'db':
                             if (is_array($config['itemArray']) && !empty($config['itemArray'])) {
                                 $itemConfig = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
                                 $valArray = $this->setRelations_db($config['itemArray'], $itemConfig);
                                 $updateData[$table][$thisNewUid][$field] = implode(',', $valArray);
                             }
                             break;
                         case 'file':
                             if (is_array($config['newValueFiles']) && !empty($config['newValueFiles'])) {
                                 $valArr = array();
                                 foreach ($config['newValueFiles'] as $fI) {
                                     $valArr[] = $this->import_addFileNameToBeCopied($fI);
                                 }
                                 if ($this->legacyImport && $this->legacyImportFolder === null && isset($this->legacyImportMigrationTables[$table][$field])) {
                                     // Do nothing - the legacy import folder is missing
                                 } elseif ($this->legacyImport && $this->legacyImportFolder !== null && isset($this->legacyImportMigrationTables[$table][$field])) {
                                     $refIds = array();
                                     foreach ($valArr as $tempFile) {
                                         $fileName = $this->alternativeFileName[$tempFile];
                                         $fileObject = null;
                                         try {
                                             // check, if there is alreay the same file in the folder
                                             if ($this->legacyImportFolder->hasFile($fileName)) {
                                                 $fileStorage = $this->legacyImportFolder->getStorage();
                                                 $file = $fileStorage->getFile($this->legacyImportFolder->getIdentifier() . $fileName);
                                                 if ($file->getSha1() === sha1_file($tempFile)) {
                                                     $fileObject = $file;
                                                 }
                                             }
                                         } catch (Exception $e) {
                                         }
                                         if ($fileObject === null) {
                                             try {
                                                 $fileObject = $this->legacyImportFolder->addFile($tempFile, $fileName, DuplicationBehavior::RENAME);
                                             } catch (Exception $e) {
                                                 $this->error('Error: no file could be added to the storage for file name' . $this->alternativeFileName[$tempFile]);
                                             }
                                         }
                                         if ($fileObject !== null) {
                                             $refId = StringUtility::getUniqueId('NEW');
                                             $refIds[] = $refId;
                                             $updateData['sys_file_reference'][$refId] = array('uid_local' => $fileObject->getUid(), 'uid_foreign' => $thisNewUid, 'tablenames' => $table, 'fieldname' => $field, 'pid' => $thisNewPageUid, 'table_local' => 'sys_file');
                                         }
                                     }
                                     $updateData[$table][$thisNewUid][$field] = implode(',', $refIds);
                                     if (!empty($this->legacyImportMigrationTables[$table][$field])) {
                                         $this->legacyImportMigrationRecords[$table][$thisNewUid][$field] = $refIds;
                                     }
                                 } else {
                                     $updateData[$table][$thisNewUid][$field] = implode(',', $valArr);
                                 }
                             }
                             break;
                     }
                 }
             } else {
                 $this->error('Error: no record was found in data array!');
             }
         } else {
             $this->error('Error: this records is NOT created it seems! (' . $table . ':' . $uid . ')');
         }
     }
     if (!empty($updateData)) {
         $tce = $this->getNewTCE();
         $tce->isImporting = true;
         $this->callHook('before_setRelation', array('tce' => &$tce, 'data' => &$updateData));
         $tce->start($updateData, array());
         $tce->process_datamap();
         // Replace the temporary "NEW" ids with the final ones.
         foreach ($this->legacyImportMigrationRecords as $table => $records) {
             foreach ($records as $uid => $fields) {
                 foreach ($fields as $field => $referenceIds) {
                     foreach ($referenceIds as $key => $referenceId) {
                         $this->legacyImportMigrationRecords[$table][$uid][$field][$key] = $tce->substNEWwithIDs[$referenceId];
                     }
                 }
             }
         }
         $this->callHook('after_setRelations', array('tce' => &$tce));
     }
 }
示例#6
0
    /**
     * This will render a single-line input form field, possibly with various control/validation features
     *
     * @return array As defined in initializeResultArray() of AbstractNode
     */
    public function render()
    {
        /** @var IconFactory $iconFactory */
        $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
        $languageService = $this->getLanguageService();
        $table = $this->data['tableName'];
        $fieldName = $this->data['fieldName'];
        $row = $this->data['databaseRow'];
        $parameterArray = $this->data['parameterArray'];
        $resultArray = $this->initializeResultArray();
        $isDateField = false;
        $config = $parameterArray['fieldConf']['config'];
        $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
        $size = MathUtility::forceIntegerInRange($config['size'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
        $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
        $classes = array();
        $attributes = array();
        if (!isset($config['checkbox'])) {
            $config['checkbox'] = '0';
            $checkboxIsset = false;
        } else {
            $checkboxIsset = true;
        }
        // set all date times available
        $dateFormats = array('date' => '%d-%m-%Y', 'year' => '%Y', 'time' => '%H:%M', 'timesec' => '%H:%M:%S');
        if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat']) {
            $dateFormats['date'] = '%m-%d-%Y';
        }
        $dateFormats['datetime'] = $dateFormats['time'] . ' ' . $dateFormats['date'];
        $dateFormats['datetimesec'] = $dateFormats['timesec'] . ' ' . $dateFormats['date'];
        // readonly
        if ($config['readOnly']) {
            $itemFormElValue = $parameterArray['itemFormElValue'];
            if (in_array('date', $evalList)) {
                $config['format'] = 'date';
            } elseif (in_array('datetime', $evalList)) {
                $config['format'] = 'datetime';
            } elseif (in_array('time', $evalList)) {
                $config['format'] = 'time';
            }
            if (in_array('password', $evalList)) {
                $itemFormElValue = $itemFormElValue ? '*********' : '';
            }
            $options = $this->data;
            $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $itemFormElValue);
            $options['renderType'] = 'none';
            return $this->nodeFactory->create($options)->render();
        }
        if (in_array('datetime', $evalList, true) || in_array('date', $evalList)) {
            $classes[] = 't3js-datetimepicker';
            $isDateField = true;
            if (in_array('datetime', $evalList)) {
                $attributes['data-date-type'] = 'datetime';
                $dateFormat = $dateFormats['datetime'];
            } elseif (in_array('date', $evalList)) {
                $attributes['data-date-type'] = 'date';
                $dateFormat = $dateFormats['date'];
            }
            if ($parameterArray['itemFormElValue'] > 0) {
                $parameterArray['itemFormElValue'] += date('Z', $parameterArray['itemFormElValue']);
            }
            if (isset($config['range']['lower'])) {
                $attributes['data-date-minDate'] = (int) $config['range']['lower'];
            }
            if (isset($config['range']['upper'])) {
                $attributes['data-date-maxDate'] = (int) $config['range']['upper'];
            }
        } elseif (in_array('time', $evalList)) {
            $dateFormat = $dateFormats['time'];
            $isDateField = true;
            $classes[] = 't3js-datetimepicker';
            $attributes['data-date-type'] = 'time';
        } elseif (in_array('timesec', $evalList)) {
            $dateFormat = $dateFormats['timesec'];
            $isDateField = true;
            $classes[] = 't3js-datetimepicker';
            $attributes['data-date-type'] = 'timesec';
        } else {
            if ($checkboxIsset === false) {
                $config['checkbox'] = '';
            }
        }
        // @todo: The whole eval handling is a mess and needs refactoring
        foreach ($evalList as $func) {
            switch ($func) {
                case 'required':
                    $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
                    break;
                default:
                    // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
                    // @todo: keyword like "date", or a class reference. The global registration could be dropped then
                    // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                    if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
                        if (class_exists($func)) {
                            $evalObj = GeneralUtility::makeInstance($func);
                            if (method_exists($evalObj, 'deevaluateFieldValue')) {
                                $_params = array('value' => $parameterArray['itemFormElValue']);
                                $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                            }
                        }
                    }
            }
        }
        $paramsList = array('field' => $parameterArray['itemFormElName'], 'evalList' => implode(',', $evalList), 'is_in' => trim($config['is_in']), 'checkbox' => $config['checkbox'] ? 1 : 0, 'checkboxValue' => $config['checkbox']);
        // set classes
        $classes[] = 'form-control';
        $classes[] = 't3js-clearable';
        $classes[] = 'hasDefaultValue';
        // calculate attributes
        $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString($config);
        $attributes['data-formengine-input-params'] = json_encode($paramsList);
        $attributes['data-formengine-input-name'] = htmlspecialchars($parameterArray['itemFormElName']);
        $attributes['id'] = StringUtility::getUniqueId('formengine-input-');
        $attributes['value'] = '';
        if (isset($config['max']) && (int) $config['max'] > 0) {
            $attributes['maxlength'] = (int) $config['max'];
        }
        if (!empty($classes)) {
            $attributes['class'] = implode(' ', $classes);
        }
        // This is the EDITABLE form field.
        if (!empty($config['placeholder'])) {
            $attributes['placeholder'] = trim($config['placeholder']);
        }
        if (isset($config['autocomplete'])) {
            $attributes['autocomplete'] = empty($config['autocomplete']) ? 'off' : 'on';
        }
        // Build the attribute string
        $attributeString = '';
        foreach ($attributes as $attributeName => $attributeValue) {
            $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
        }
        $html = '
			<input type="text"' . $attributeString . $parameterArray['onFocus'] . ' />';
        // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
        $html .= '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
        // Going through all custom evaluations configured for this field
        // @todo: Similar to above code!
        foreach ($evalList as $evalData) {
            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData])) {
                if (class_exists($evalData)) {
                    $evalObj = GeneralUtility::makeInstance($evalData);
                    if (method_exists($evalObj, 'returnFieldJS')) {
                        $resultArray['extJSCODE'] .= LF . 'TBE_EDITOR.customEvalFunctions[' . GeneralUtility::quoteJSvalue($evalData) . '] = function(value) {' . $evalObj->returnFieldJS() . '}';
                    }
                }
            }
        }
        // add HTML wrapper
        if ($isDateField) {
            $html = '
				<div class="input-group">
					' . $html . '
					<span class="input-group-btn">
						<label class="btn btn-default" for="' . $attributes['id'] . '">
							' . $iconFactory->getIcon('actions-edit-pick-date', Icon::SIZE_SMALL)->render() . '
						</label>
					</span>
				</div>';
        }
        // Wrap a wizard around the item?
        $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specConf);
        // Add a wrapper to remain maximum width
        $width = (int) $this->formMaxWidth($size);
        $html = '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>' . $html . '</div>';
        $resultArray['html'] = $html;
        return $resultArray;
    }
示例#7
0
 /**
  * This will render a <textarea>
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $languageService = $this->getLanguageService();
     $table = $this->data['tableName'];
     $fieldName = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $resultArray = $this->initializeResultArray();
     $backendUser = $this->getBackendUserAuthentication();
     $config = $parameterArray['fieldConf']['config'];
     // Setting columns number
     $cols = MathUtility::forceIntegerInRange($config['cols'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
     // Setting number of rows
     $rows = MathUtility::forceIntegerInRange($config['rows'] ?: 5, 1, 20);
     $originalRows = $rows;
     $itemFormElementValueLength = strlen($parameterArray['itemFormElValue']);
     if ($itemFormElementValueLength > $this->charactersPerRow * 2) {
         $cols = $this->maxInputWidth;
         $rows = MathUtility::forceIntegerInRange(round($itemFormElementValueLength / $this->charactersPerRow), count(explode(LF, $parameterArray['itemFormElValue'])), 20);
         if ($rows < $originalRows) {
             $rows = $originalRows;
         }
     }
     // must be called after the cols and rows calculation, so the parameters are applied
     // to read-only fields as well.
     // @todo: Same as in InputTextElement ...
     if ($config['readOnly']) {
         $config['cols'] = $cols;
         $config['rows'] = $rows;
         $options = $this->data;
         $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $parameterArray['itemFormElValue']);
         $options['renderType'] = 'none';
         return $this->nodeFactory->create($options)->render();
     }
     $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
     // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
     $specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     $html = '';
     // Show message, if no RTE (field can only be edited with RTE!)
     if ($specialConfiguration['rte_only']) {
         $html = '<p><em>' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noRTEfound')) . '</em></p>';
     } else {
         $attributes = array();
         // validation
         foreach ($evalList as $func) {
             if ($func === 'required') {
                 $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
             } else {
                 // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
                 // @todo: keyword like "date", or a class reference. The global registration could be dropped then
                 // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                 // There is a similar hook for "evaluateFieldValue" in DataHandler and InputTextElement
                 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
                     if (class_exists($func)) {
                         $evalObj = GeneralUtility::makeInstance($func);
                         if (method_exists($evalObj, 'deevaluateFieldValue')) {
                             $_params = array('value' => $parameterArray['itemFormElValue']);
                             $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                         }
                     }
                 }
             }
         }
         // calculate classes
         $classes = array();
         $classes[] = 'form-control';
         $classes[] = 't3js-formengine-textarea';
         $classes[] = 'formengine-textarea';
         if ($specialConfiguration['fixed-font']) {
             $classes[] = 'text-monospace';
         }
         if ($specialConfiguration['enable-tab']) {
             $classes[] = 't3js-enable-tab';
         }
         // calculate styles
         $styles = array();
         // add the max-height from the users' preference to it
         $maximumHeight = (int) $backendUser->uc['resizeTextareas_MaxHeight'];
         if ($maximumHeight > 0) {
             $styles[] = 'max-height: ' . $maximumHeight . 'px';
         }
         // calculate attributes
         $attributes['id'] = StringUtility::getUniqueId('formengine-textarea-');
         $attributes['name'] = htmlspecialchars($parameterArray['itemFormElName']);
         $attributes['data-formengine-input-name'] = htmlspecialchars($parameterArray['itemFormElName']);
         if (!empty($styles)) {
             $attributes['style'] = implode(' ', $styles);
         }
         if (!empty($classes)) {
             $attributes['class'] = implode(' ', $classes);
         }
         $attributes['rows'] = $rows;
         $attributes['wrap'] = $specialConfiguration['nowrap'] ? 'off' : ($config['wrap'] ?: 'virtual');
         $attributes['onChange'] = implode('', $parameterArray['fieldChangeFunc']);
         if (isset($config['max']) && (int) $config['max'] > 0) {
             $attributes['maxlength'] = (int) $config['max'];
         }
         $attributeString = '';
         foreach ($attributes as $attributeName => $attributeValue) {
             $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
         }
         // Build the textarea
         $placeholderAttribute = '';
         if (!empty($config['placeholder'])) {
             $placeholderAttribute = ' placeholder="' . htmlspecialchars(trim($config['placeholder'])) . '" ';
         }
         $html .= '<textarea' . $attributeString . $placeholderAttribute . '>' . htmlspecialchars($parameterArray['itemFormElValue']) . '</textarea>';
         // Wrap a wizard around the item?
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specialConfiguration, false);
         $maximumWidth = (int) $this->formMaxWidth($cols);
         $html = '<div class="form-control-wrap"' . ($maximumWidth ? ' style="max-width: ' . $maximumWidth . 'px"' : '') . '>' . $html . '</div>';
     }
     $resultArray['html'] = $html;
     return $resultArray;
 }
 /**
  * Creates SELECT query components for selecting fields ($select) from two/three tables joined
  * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
  * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
  * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
  *
  * @param string $select See exec_SELECT_mm_query()
  * @param string $local_table See exec_SELECT_mm_query()
  * @param string $mm_table See exec_SELECT_mm_query()
  * @param string $foreign_table See exec_SELECT_mm_query()
  * @param string $whereClause See exec_SELECT_mm_query()
  * @param string $groupBy See exec_SELECT_mm_query()
  * @param string $orderBy See exec_SELECT_mm_query()
  * @param string $limit See exec_SELECT_mm_query()
  * @return array SQL query components
  */
 protected function getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
 {
     $foreign_table_as = $foreign_table == $local_table ? $foreign_table . StringUtility::getUniqueId('_join') : '';
     $mmWhere = $local_table ? $local_table . '.uid=' . $mm_table . '.uid_local' : '';
     $mmWhere .= ($local_table and $foreign_table) ? ' AND ' : '';
     $tables = ($local_table ? $local_table . ',' : '') . $mm_table;
     if ($foreign_table) {
         $mmWhere .= ($foreign_table_as ?: $foreign_table) . '.uid=' . $mm_table . '.uid_foreign';
         $tables .= ',' . $foreign_table . ($foreign_table_as ? ' AS ' . $foreign_table_as : '');
     }
     return array('SELECT' => $select, 'FROM' => $tables, 'WHERE' => $mmWhere . ' ' . $whereClause, 'GROUPBY' => $groupBy, 'ORDERBY' => $orderBy, 'LIMIT' => $limit);
 }
示例#9
0
 /**
  * @param int $pageId
  * @param array $tableRecordData
  */
 public function modifyRecords($pageId, array $tableRecordData)
 {
     $dataMap = array();
     $currentUid = null;
     $previousTableName = null;
     $previousUid = null;
     foreach ($tableRecordData as $tableName => $recordData) {
         if (empty($recordData['uid'])) {
             continue;
         }
         $recordData = $this->resolvePreviousUid($recordData, $currentUid);
         $currentUid = $recordData['uid'];
         if ($recordData['uid'] === '__NEW') {
             $recordData['pid'] = $pageId;
             $currentUid = StringUtility::getUniqueId('NEW');
         }
         unset($recordData['uid']);
         $dataMap[$tableName][$currentUid] = $recordData;
         if ($previousTableName !== null && $previousUid !== null) {
             $dataMap[$previousTableName][$previousUid] = $this->resolveNextUid($dataMap[$previousTableName][$previousUid], $currentUid);
         }
         $previousTableName = $tableName;
         $previousUid = $currentUid;
     }
     $this->createDataHandler();
     $this->dataHandler->start($dataMap, array());
     $this->dataHandler->process_datamap();
 }
示例#10
0
    /**
     * Prints the selector box form-field for the db/file/select elements (multiple)
     *
     * @param string $fName Form element name
     * @param string $mode Mode "db", "file" (internal_type for the "group" type) OR blank (then for the "select" type)
     * @param string $allowed Commalist of "allowed
     * @param array $itemArray The array of items. For "select" and "group"/"file" this is just a set of value. For "db" its an array of arrays with table/uid pairs.
     * @param string $selector Alternative selector box.
     * @param array $params An array of additional parameters, eg: "size", "info", "headers" (array with "selector" and "items"), "noBrowser", "thumbnails
     * @param null $_ unused (onFocus in the past), will be removed in TYPO3 CMS 9
     * @param string $table (optional) Table name processing for
     * @param string $field (optional) Field of table name processing for
     * @param string $uid (optional) uid of table record processing for
     * @param array $config (optional) The TCA field config
     * @return string The form fields for the selection.
     * @throws \UnexpectedValueException
     * @todo: Hack this mess into pieces and inline to group / select element depending on what they need
     */
    protected function dbFileIcons($fName, $mode, $allowed, $itemArray, $selector = '', $params = [], $_ = null, $table = '', $field = '', $uid = '', $config = [])
    {
        $languageService = $this->getLanguageService();
        $disabled = '';
        if ($params['readOnly']) {
            $disabled = ' disabled="disabled"';
        }
        // INIT
        $uidList = [];
        $opt = [];
        $itemArrayC = 0;
        // Creating <option> elements:
        if (is_array($itemArray)) {
            $itemArrayC = count($itemArray);
            switch ($mode) {
                case 'db':
                    foreach ($itemArray as $pp) {
                        $pRec = BackendUtility::getRecordWSOL($pp['table'], $pp['id']);
                        if (is_array($pRec)) {
                            $pTitle = BackendUtility::getRecordTitle($pp['table'], $pRec, false, true);
                            $pUid = $pp['table'] . '_' . $pp['id'];
                            $uidList[] = $pUid;
                            $title = htmlspecialchars($pTitle);
                            $opt[] = '<option value="' . htmlspecialchars($pUid) . '" title="' . $title . '">' . $title . '</option>';
                        }
                    }
                    break;
                case 'file_reference':
                case 'file':
                    foreach ($itemArray as $item) {
                        $itemParts = explode('|', $item);
                        $uidList[] = $pUid = $pTitle = $itemParts[0];
                        $title = htmlspecialchars(rawurldecode($itemParts[1]));
                        $opt[] = '<option value="' . htmlspecialchars(rawurldecode($itemParts[0])) . '" title="' . $title . '">' . $title . '</option>';
                    }
                    break;
                case 'folder':
                    foreach ($itemArray as $pp) {
                        $pParts = explode('|', $pp);
                        $uidList[] = $pUid = $pTitle = $pParts[0];
                        $title = htmlspecialchars(rawurldecode($pParts[0]));
                        $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pParts[0])) . '" title="' . $title . '">' . $title . '</option>';
                    }
                    break;
                default:
                    foreach ($itemArray as $pp) {
                        $pParts = explode('|', $pp, 2);
                        $uidList[] = $pUid = $pParts[0];
                        $pTitle = $pParts[1];
                        $title = htmlspecialchars(rawurldecode($pTitle));
                        $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pUid)) . '" title="' . $title . '">' . $title . '</option>';
                    }
            }
        }
        // Create selector box of the options
        $sSize = $params['autoSizeMax'] ? MathUtility::forceIntegerInRange($itemArrayC + 1, MathUtility::forceIntegerInRange($params['size'], 1), $params['autoSizeMax']) : $params['size'];
        if (!$selector) {
            $maxItems = (int) ($params['maxitems'] ?? 0);
            $size = (int) ($params['size'] ?? 0);
            $classes = ['form-control', 'tceforms-multiselect'];
            if ($maxItems === 1) {
                $classes[] = 'form-select-no-siblings';
            }
            $isMultiple = $maxItems !== 1 && $size !== 1;
            $selector = '<select id="' . StringUtility::getUniqueId('tceforms-multiselect-') . '" ' . ($params['noList'] ? 'style="display: none"' : 'size="' . $sSize . '" class="' . implode(' ', $classes) . '"') . ($isMultiple ? ' multiple="multiple"' : '') . ' data-formengine-input-name="' . htmlspecialchars($fName) . '" ' . $this->getValidationDataAsDataAttribute($config) . $params['style'] . $disabled . '>' . implode('', $opt) . '</select>';
        }
        $icons = ['L' => [], 'R' => []];
        $rOnClickInline = '';
        if (!$params['readOnly'] && !$params['noList']) {
            if (!$params['noBrowser']) {
                // Check against inline uniqueness
                /** @var InlineStackProcessor $inlineStackProcessor */
                $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
                $inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
                $aOnClickInline = '';
                if ($this->data['isInlineChild'] && $this->data['inlineParentUid']) {
                    if ($this->data['inlineParentConfig']['foreign_table'] === $table && $this->data['inlineParentConfig']['foreign_unique'] === $field) {
                        $objectPrefix = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']) . '-' . $table;
                        $aOnClickInline = $objectPrefix . '|inline.checkUniqueElement|inline.setUniqueElement';
                        $rOnClickInline = 'inline.revertUnique(' . GeneralUtility::quoteJSvalue($objectPrefix) . ',null,' . GeneralUtility::quoteJSvalue($uid) . ');';
                    }
                }
                if (is_array($config['appearance']) && isset($config['appearance']['elementBrowserType'])) {
                    $elementBrowserType = $config['appearance']['elementBrowserType'];
                } else {
                    $elementBrowserType = $mode;
                }
                if (is_array($config['appearance']) && isset($config['appearance']['elementBrowserAllowed'])) {
                    $elementBrowserAllowed = $config['appearance']['elementBrowserAllowed'];
                } else {
                    $elementBrowserAllowed = $allowed;
                }
                $aOnClick = 'setFormValueOpenBrowser(' . GeneralUtility::quoteJSvalue($elementBrowserType) . ',' . GeneralUtility::quoteJSvalue($fName . '|||' . $elementBrowserAllowed . '|' . $aOnClickInline) . '); return false;';
                $icons['R'][] = '
					<a href="#"
						onclick="' . htmlspecialchars($aOnClick) . '"
						class="btn btn-default"
						title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.browse_' . ($mode == 'db' ? 'db' : 'file'))) . '">
						' . $this->iconFactory->getIcon('actions-insert-record', Icon::SIZE_SMALL)->render() . '
					</a>';
            }
            if (!$params['dontShowMoveIcons']) {
                if ($sSize >= 5) {
                    $icons['L'][] = '
						<a href="#"
							class="btn btn-default t3js-btn-moveoption-top"
							data-fieldname="' . $fName . '"
							title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.move_to_top')) . '">
							' . $this->iconFactory->getIcon('actions-move-to-top', Icon::SIZE_SMALL)->render() . '
						</a>';
                }
                $icons['L'][] = '
					<a href="#"
						class="btn btn-default t3js-btn-moveoption-up"
						data-fieldname="' . $fName . '"
						title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.move_up')) . '">
						' . $this->iconFactory->getIcon('actions-move-up', Icon::SIZE_SMALL)->render() . '
					</a>';
                $icons['L'][] = '
					<a href="#"
						class="btn btn-default t3js-btn-moveoption-down"
						data-fieldname="' . $fName . '"
						title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.move_down')) . '">
						' . $this->iconFactory->getIcon('actions-move-down', Icon::SIZE_SMALL)->render() . '
					</a>';
                if ($sSize >= 5) {
                    $icons['L'][] = '
						<a href="#"
							class="btn btn-default t3js-btn-moveoption-bottom"
							data-fieldname="' . $fName . '"
							title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.move_to_bottom')) . '">
							' . $this->iconFactory->getIcon('actions-move-to-bottom', Icon::SIZE_SMALL)->render() . '
						</a>';
                }
            }
            $clipElements = $this->getClipboardElements($allowed, $mode);
            if (!empty($clipElements)) {
                $aOnClick = '';
                foreach ($clipElements as $elValue) {
                    if ($mode == 'db') {
                        list($itemTable, $itemUid) = explode('|', $elValue);
                        $recordTitle = BackendUtility::getRecordTitle($itemTable, BackendUtility::getRecordWSOL($itemTable, $itemUid));
                        $itemTitle = GeneralUtility::quoteJSvalue($recordTitle);
                        $elValue = $itemTable . '_' . $itemUid;
                    } else {
                        // 'file', 'file_reference' and 'folder' mode
                        $itemTitle = 'unescape(' . GeneralUtility::quoteJSvalue(rawurlencode(basename($elValue))) . ')';
                    }
                    $aOnClick .= 'setFormValueFromBrowseWin(' . GeneralUtility::quoteJSvalue($fName) . ',unescape(' . GeneralUtility::quoteJSvalue(rawurlencode(str_replace('%20', ' ', $elValue))) . '),' . $itemTitle . ',' . $itemTitle . ');';
                }
                $aOnClick .= 'return false;';
                $icons['R'][] = '
					<a href="#"
						class="btn btn-default"
						onclick="' . htmlspecialchars($aOnClick) . '"
						title="' . htmlspecialchars(sprintf($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.clipInsert_' . ($mode == 'db' ? 'db' : 'file')), count($clipElements))) . '">
						' . $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render() . '
					</a>';
            }
        }
        if (!$params['readOnly'] && !$params['noDelete']) {
            $icons['L'][] = '
				<a href="#"
					class="btn btn-default t3js-btn-removeoption"
					onClick="' . $rOnClickInline . '"
					data-fieldname="' . $fName . '"
					title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.remove_selected')) . '">
					' . $this->iconFactory->getIcon('actions-selection-delete', Icon::SIZE_SMALL)->render() . '
				</a>';
        }
        // Thumbnails
        $imagesOnly = false;
        if ($params['thumbnails'] && $params['allowed']) {
            // In case we have thumbnails, check if only images are allowed.
            // In this case, render them below the field, instead of to the right
            $allowedExtensionList = $params['allowed'];
            $imageExtensionList = GeneralUtility::trimExplode(',', strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), true);
            $imagesOnly = true;
            foreach ($allowedExtensionList as $allowedExtension) {
                if (!ArrayUtility::inArray($imageExtensionList, $allowedExtension)) {
                    $imagesOnly = false;
                    break;
                }
            }
        }
        $thumbnails = '';
        if (is_array($params['thumbnails']) && !empty($params['thumbnails'])) {
            if ($imagesOnly) {
                $thumbnails .= '<ul class="list-inline">';
                foreach ($params['thumbnails'] as $thumbnail) {
                    $thumbnails .= '<li><span class="thumbnail">' . $thumbnail['image'] . '</span></li>';
                }
                $thumbnails .= '</ul>';
            } else {
                $thumbnails .= '<div class="table-fit"><table class="table table-white"><tbody>';
                foreach ($params['thumbnails'] as $thumbnail) {
                    $thumbnails .= '
						<tr>
							<td class="col-icon">
								' . ($config['internal_type'] === 'db' ? BackendUtility::wrapClickMenuOnIcon($thumbnail['image'], $thumbnail['table'], $thumbnail['uid'], 1, '', '+copy,info,edit,view') : $thumbnail['image']) . '
							</td>
							<td class="col-title">
								' . ($config['internal_type'] === 'db' ? BackendUtility::wrapClickMenuOnIcon($thumbnail['name'], $thumbnail['table'], $thumbnail['uid'], 1, '', '+copy,info,edit,view') : $thumbnail['name']) . '
								' . ($config['internal_type'] === 'db' ? ' <span class="text-muted">[' . $thumbnail['uid'] . ']</span>' : '') . '
							</td>
						</tr>
						';
                }
                $thumbnails .= '</tbody></table></div>';
            }
        }
        // Allowed Tables
        $allowedTables = '';
        if (is_array($params['allowedTables']) && !empty($params['allowedTables']) && !$params['hideAllowedTables']) {
            $allowedTables .= '<div class="help-block">';
            foreach ($params['allowedTables'] as $key => $item) {
                if (is_array($item)) {
                    if (empty($params['readOnly'])) {
                        $allowedTables .= '<a href="#" onClick="' . htmlspecialchars($item['onClick']) . '" class="btn btn-default">' . $item['icon'] . ' ' . htmlspecialchars($item['name']) . '</a> ';
                    } else {
                        $allowedTables .= '<span>' . htmlspecialchars($item['name']) . '</span> ';
                    }
                } elseif ($key === 'name') {
                    $allowedTables .= '<span>' . htmlspecialchars($item) . '</span> ';
                }
            }
            $allowedTables .= '</div>';
        }
        // Allowed
        $allowedList = '';
        if (is_array($params['allowed']) && !empty($params['allowed'])) {
            foreach ($params['allowed'] as $item) {
                $allowedList .= '<span class="label label-success">' . strtoupper($item) . '</span> ';
            }
        }
        // Disallowed
        $disallowedList = '';
        if (is_array($params['disallowed']) && !empty($params['disallowed'])) {
            foreach ($params['disallowed'] as $item) {
                $disallowedList .= '<span class="label label-danger">' . strtoupper($item) . '</span> ';
            }
        }
        // Rightbox
        $rightbox = $params['rightbox'] ?: '';
        // Hook: dbFileIcons_postProcess (requested by FAL-team for use with the "fal" extension)
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'])) {
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'] as $classRef) {
                $hookObject = GeneralUtility::getUserObj($classRef);
                if (!$hookObject instanceof DatabaseFileIconsHookInterface) {
                    throw new \UnexpectedValueException($classRef . ' must implement interface ' . DatabaseFileIconsHookInterface::class, 1290167704);
                }
                $additionalParams = ['mode' => $mode, 'allowed' => $allowed, 'itemArray' => $itemArray, 'table' => $table, 'field' => $field, 'uid' => $uid, 'config' => $GLOBALS['TCA'][$table]['columns'][$field]];
                $hookObject->dbFileIcons_postProcess($params, $selector, $thumbnails, $icons, $rightbox, $fName, $uidList, $additionalParams, $this);
            }
        }
        // Output
        $str = '
			' . ($params['headers']['selector'] ? '<label>' . $params['headers']['selector'] . '</label>' : '') . '
			<div class="form-wizards-wrap form-wizards-aside">
				<div class="form-wizards-element">
					' . $selector . '
					' . (!$params['noList'] && !empty($allowedTables) ? $allowedTables : '') . '
					' . (!$params['noList'] && (!empty($allowedList) || !empty($disallowedList)) ? '<div class="help-block">' . $allowedList . $disallowedList . ' </div>' : '') . '
				</div>
				' . (!empty($icons['L']) ? '<div class="form-wizards-items"><div class="btn-group-vertical">' . implode('', $icons['L']) . '</div></div>' : '') . '
				' . (!empty($icons['R']) ? '<div class="form-wizards-items"><div class="btn-group-vertical">' . implode('', $icons['R']) . '</div></div>' : '') . '
			</div>
			';
        if ($rightbox) {
            $str = '
				<div class="form-multigroup-wrap t3js-formengine-field-group">
					<div class="form-multigroup-item form-multigroup-element">' . $str . '</div>
					<div class="form-multigroup-item form-multigroup-element">
						' . ($params['headers']['items'] ? '<label>' . $params['headers']['items'] . '</label>' : '') . '
						' . ($params['headers']['selectorbox'] ? '<div class="form-multigroup-item-wizard">' . $params['headers']['selectorbox'] . '</div>' : '') . '
						' . $rightbox . '
					</div>
				</div>
				';
        }
        $str .= $thumbnails;
        // Creating the hidden field which contains the actual value as a comma list.
        $str .= '<input type="hidden" name="' . $fName . '" value="' . htmlspecialchars(implode(',', $uidList)) . '" />';
        return $str;
    }
 /**
  * @test
  */
 public function getUniqueIdReturnsIdWithoutDot()
 {
     $this->assertNotContains('.', StringUtility::getUniqueId());
 }
 /**
  * Entry method
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     /** @var IconFactory $iconFactory */
     $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
     $languageService = $this->getLanguageService();
     $flexFormFieldsArray = $this->data['flexFormDataStructureArray'];
     $flexFormRowData = $this->data['flexFormRowData'];
     $flexFormFieldIdentifierPrefix = $this->data['flexFormFieldIdentifierPrefix'];
     $flexFormSectionType = $this->data['flexFormSectionType'];
     $flexFormSectionTitle = $this->data['flexFormSectionTitle'];
     $userHasAccessToDefaultLanguage = $this->getBackendUserAuthentication()->checkLanguageAccess(0);
     $resultArray = $this->initializeResultArray();
     // Creating IDs for form fields:
     // It's important that the IDs "cascade" - otherwise we can't dynamically expand the flex form
     // because this relies on simple string substitution of the first parts of the id values.
     $flexFormFieldIdentifierPrefix = $flexFormFieldIdentifierPrefix . '-' . GeneralUtility::shortMd5(uniqid('id', true));
     // Render each existing container
     foreach ($flexFormRowData as $flexFormContainerCounter => $existingSectionContainerData) {
         // @todo: This relies on the fact that "_TOGGLE" is *below* the real data in the saved xml structure
         if (is_array($existingSectionContainerData)) {
             $existingSectionContainerDataStructureType = key($existingSectionContainerData);
             $existingSectionContainerData = $existingSectionContainerData[$existingSectionContainerDataStructureType];
             $containerDataStructure = $flexFormFieldsArray[$existingSectionContainerDataStructureType];
             // There may be cases where a field is still in DB but does not exist in definition
             if (is_array($containerDataStructure)) {
                 $sectionTitle = '';
                 if (!empty($containerDataStructure['title'])) {
                     $sectionTitle = $languageService->sL($containerDataStructure['title']);
                 }
                 $options = $this->data;
                 $options['flexFormRowData'] = $existingSectionContainerData['el'];
                 $options['flexFormDataStructureArray'] = $containerDataStructure['el'];
                 $options['flexFormFieldIdentifierPrefix'] = $flexFormFieldIdentifierPrefix;
                 $options['flexFormFormPrefix'] = $this->data['flexFormFormPrefix'] . '[' . $flexFormSectionType . ']' . '[el]';
                 $options['flexFormContainerName'] = $existingSectionContainerDataStructureType;
                 $options['flexFormContainerCounter'] = $flexFormContainerCounter;
                 $options['flexFormContainerTitle'] = $sectionTitle;
                 $options['flexFormContainerElementCollapsed'] = (bool) $existingSectionContainerData['el']['_TOGGLE'];
                 $options['renderType'] = 'flexFormContainerContainer';
                 $flexFormContainerContainerResult = $this->nodeFactory->create($options)->render();
                 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $flexFormContainerContainerResult);
             }
         }
     }
     // "New container" handling: Creates a "template" of each possible container and stuffs it
     // somewhere into DOM to be handled with JS magic.
     // Fun part: Handle the fact that such things may be set for children
     $containerTemplatesHtml = array();
     foreach ($flexFormFieldsArray as $flexFormContainerName => $flexFormFieldDefinition) {
         $containerTemplateHtml = array();
         $sectionTitle = '';
         if (!empty($flexFormFieldDefinition['title'])) {
             $sectionTitle = $languageService->sL($flexFormFieldDefinition['title']);
         }
         $options = $this->data;
         // @todo: this should use the prepared templateRow parallel to the single elements to have support of default values!
         $options['flexFormRowData'] = array();
         $options['flexFormDataStructureArray'] = $flexFormFieldDefinition['el'];
         $options['flexFormFieldIdentifierPrefix'] = $flexFormFieldIdentifierPrefix;
         $options['flexFormFormPrefix'] = $this->data['flexFormFormPrefix'] . '[' . $flexFormSectionType . ']' . '[el]';
         $options['flexFormContainerName'] = $flexFormContainerName;
         $options['flexFormContainerCounter'] = $flexFormFieldIdentifierPrefix . '-form';
         $options['flexFormContainerTitle'] = $sectionTitle;
         $options['flexFormContainerElementCollapsed'] = false;
         $options['renderType'] = 'flexFormContainerContainer';
         $flexFormContainerContainerTemplateResult = $this->nodeFactory->create($options)->render();
         $uniqueId = StringUtility::getUniqueId('idvar');
         $identifierPrefixJs = 'replace(/' . $flexFormFieldIdentifierPrefix . '-/g,"' . $flexFormFieldIdentifierPrefix . '-"+' . $uniqueId . '+"-")';
         $identifierPrefixJs .= '.replace(/(tceforms-(datetime|date)field-)/g,"$1" + (new Date()).getTime())';
         $onClickInsert = array();
         $onClickInsert[] = 'var ' . $uniqueId . ' = "' . 'idx"+(new Date()).getTime();';
         $onClickInsert[] = 'TYPO3.jQuery("#' . $flexFormFieldIdentifierPrefix . '").append(TYPO3.jQuery(' . json_encode($flexFormContainerContainerTemplateResult['html']) . '.' . $identifierPrefixJs . '));';
         $onClickInsert[] = 'TYPO3.jQuery("#' . $flexFormFieldIdentifierPrefix . '").t3FormEngineFlexFormElement();';
         $onClickInsert[] = 'eval(unescape("' . rawurlencode(implode(';', $flexFormContainerContainerTemplateResult['additionalJavaScriptPost'])) . '").' . $identifierPrefixJs . ');';
         $onClickInsert[] = 'TBE_EDITOR.addActionChecks("submit", unescape("' . rawurlencode(implode(';', $flexFormContainerContainerTemplateResult['additionalJavaScriptSubmit'])) . '").' . $identifierPrefixJs . ');';
         $onClickInsert[] = 'TYPO3.FormEngine.reinitialize();';
         $onClickInsert[] = 'return false;';
         $containerTemplateHtml[] = '<a href="#" class="btn btn-default" onclick="' . htmlspecialchars(implode(LF, $onClickInsert)) . '">';
         $containerTemplateHtml[] = $iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render();
         $containerTemplateHtml[] = htmlspecialchars(GeneralUtility::fixed_lgd_cs($sectionTitle, 30));
         $containerTemplateHtml[] = '</a>';
         $containerTemplatesHtml[] = implode(LF, $containerTemplateHtml);
         $flexFormContainerContainerTemplateResult['html'] = '';
         $flexFormContainerContainerTemplateResult['additionalJavaScriptPost'] = array();
         $flexFormContainerContainerTemplateResult['additionalJavaScriptSubmit'] = array();
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $flexFormContainerContainerTemplateResult);
     }
     // Create new elements links
     $createElementsHtml = array();
     if ($userHasAccessToDefaultLanguage) {
         $createElementsHtml[] = '<div class="t3-form-field-add-flexsection">';
         $createElementsHtml[] = '<div class="btn-group">';
         $createElementsHtml[] = implode('|', $containerTemplatesHtml);
         $createElementsHtml[] = '</div>';
         $createElementsHtml[] = '</div>';
     }
     // Wrap child stuff
     $toggleAll = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.toggleall', true);
     $html = array();
     $html[] = '<div class="panel panel-tab">';
     $html[] = '<div class="panel-body">';
     $html[] = '<div class="t3-form-field-container t3-form-flex">';
     $html[] = '<div class="t3-form-field-label-flexsection">';
     $html[] = '<h4>';
     $html[] = htmlspecialchars($flexFormSectionTitle);
     $html[] = '</h4>';
     $html[] = '</div>';
     $html[] = '<div class="t3js-form-field-toggle-flexsection t3-form-flexsection-toggle">';
     $html[] = '<a class="btn btn-default" href="#" title="' . $toggleAll . '">';
     $html[] = $iconFactory->getIcon('actions-move-right', Icon::SIZE_SMALL)->render() . $toggleAll;
     $html[] = '</a>';
     $html[] = '</div>';
     $html[] = '<div';
     $html[] = 'id="' . $flexFormFieldIdentifierPrefix . '"';
     $html[] = 'class="panel-group panel-hover t3-form-field-container-flexsection t3-flex-container"';
     $html[] = 'data-t3-flex-allow-restructure="' . ($userHasAccessToDefaultLanguage ? '1' : '0') . '"';
     $html[] = '>';
     $html[] = $resultArray['html'];
     $html[] = '</div>';
     $html[] = implode(LF, $createElementsHtml);
     $html[] = '</div>';
     $html[] = '</div>';
     $html[] = '</div>';
     $resultArray['html'] = implode(LF, $html);
     return $resultArray;
 }
示例#13
0
 /**
  * Renders a <select> element
  *
  * @param array $optionElements List of rendered <option> elements
  * @param array $parameterArray
  * @param array $config Field configuration
  * @return string
  */
 protected function renderSelectElement(array $optionElements, array $parameterArray, array $config)
 {
     $selectItems = $parameterArray['fieldConf']['config']['items'];
     $size = (int) $config['size'];
     $cssPrefix = $size === 1 ? 'tceforms-select' : 'tceforms-multiselect';
     if ($config['autoSizeMax']) {
         $size = MathUtility::forceIntegerInRange(count($selectItems) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']);
     }
     $attributes = ['name' => $parameterArray['itemFormElName'] . '[]', 'multiple' => 'multiple', 'onchange' => implode('', $parameterArray['fieldChangeFunc']), 'id' => StringUtility::getUniqueId($cssPrefix), 'class' => 'form-control ' . $cssPrefix];
     if ($size) {
         $attributes['size'] = $size;
     }
     if ($config['readOnly']) {
         $attributes['disabled'] = 'disabled';
     }
     if (isset($config['itemListStyle'])) {
         $attributes['style'] = $config['itemListStyle'];
     }
     $html = ['<select ' . $this->implodeAttributes($attributes) . ' ' . $parameterArray['onFocus'] . ' ' . $this->getValidationDataAsDataAttribute($config) . '>', implode(LF, $optionElements), '</select>'];
     return implode(LF, $html);
 }
 /**
  * Render side by side element.
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->data['tableName'];
     $field = $this->data['fieldName'];
     $parameterArray = $this->data['parameterArray'];
     // Field configuration from TCA:
     $config = $parameterArray['fieldConf']['config'];
     // Creating the label for the "No Matching Value" entry.
     $noMatchingLabel = isset($parameterArray['fieldTSConfig']['noMatchingValue_label']) ? $this->getLanguageService()->sL($parameterArray['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue') . ' ]';
     $selItems = $config['items'];
     $html = '';
     $disabled = '';
     if ($config['readOnly']) {
         $disabled = ' disabled="disabled"';
     }
     // Setting this hidden field (as a flag that JavaScript can read out)
     if (!$disabled) {
         $html .= '<input type="hidden" data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . ($config['multiple'] ? 1 : 0) . '" />';
     }
     // Set max and min items:
     $maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0);
     if (!$maxitems) {
         $maxitems = 100000;
     }
     // Get "removeItems":
     $removeItems = GeneralUtility::trimExplode(',', $parameterArray['fieldTSConfig']['removeItems'], true);
     // Get the array with selected items:
     $itemsArray = $parameterArray['itemFormElValue'] ?: [];
     // Perform modification of the selected items array:
     // @todo: this part should probably be moved to TcaSelectItems provider?!
     foreach ($itemsArray as $itemNumber => $itemValue) {
         $itemArray = array(0 => $itemValue, 1 => '');
         $itemIcon = null;
         $isRemoved = in_array($itemValue, $removeItems) || $config['type'] == 'select' && $config['authMode'] && !$this->getBackendUserAuthentication()->checkAuthMode($table, $field, $itemValue, $config['authMode']);
         if ($isRemoved && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
             $itemArray[1] = rawurlencode(@sprintf($noMatchingLabel, $itemValue));
         } else {
             if (isset($parameterArray['fieldTSConfig']['altLabels.'][$itemValue])) {
                 $itemArray[1] = rawurlencode($this->getLanguageService()->sL($parameterArray['fieldTSConfig']['altLabels.'][$itemValue]));
             }
             if (isset($parameterArray['fieldTSConfig']['altIcons.'][$itemValue])) {
                 $itemArray[2] = $parameterArray['fieldTSConfig']['altIcons.'][$itemValue];
             }
         }
         if ($itemArray[1] === '') {
             foreach ($selItems as $selItem) {
                 if ($selItem[1] == $itemValue) {
                     $itemArray[1] = $selItem[0];
                     break;
                 }
             }
         }
         $itemsArray[$itemNumber] = implode('|', $itemArray);
     }
     // size must be at least two, as there are always maxitems > 1 (see parent function)
     if (isset($config['size'])) {
         $size = (int) $config['size'];
     } else {
         $size = 2;
     }
     $size = $config['autoSizeMax'] ? MathUtility::forceIntegerInRange(count($itemsArray) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']) : $size;
     $itemsToSelect = [];
     $filterTextfield = [];
     $filterSelectbox = '';
     if (!$disabled) {
         // Create option tags:
         $opt = array();
         foreach ($selItems as $p) {
             $opt[] = '<option value="' . htmlspecialchars($p[1]) . '" title="' . $p[0] . '">' . $p[0] . '</option>';
         }
         // Put together the selector box:
         $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : '';
         $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
         $multiSelectId = StringUtility::getUniqueId('tceforms-multiselect-');
         $itemsToSelect[] = '<select data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '" ' . 'data-exclusivevalues="' . htmlspecialchars($config['exclusiveKeys']) . '" ' . 'id="' . $multiSelectId . '" ' . 'data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" ' . 'class="form-control t3js-formengine-select-itemstoselect" ' . ($size ? ' size="' . $size . '" ' : '') . 'onchange="' . htmlspecialchars($sOnChange) . '" ' . $parameterArray['onFocus'] . $this->getValidationDataAsDataAttribute($config) . $selector_itemListStyle . '>';
         $itemsToSelect[] = implode(LF, $opt);
         $itemsToSelect[] = '</select>';
         // enable filter functionality via a text field
         if ($config['enableMultiSelectFilterTextfield']) {
             $filterTextfield[] = '<span class="input-group input-group-sm">';
             $filterTextfield[] = '<span class="input-group-addon">';
             $filterTextfield[] = '<span class="fa fa-filter"></span>';
             $filterTextfield[] = '</span>';
             $filterTextfield[] = '<input class="t3js-formengine-multiselect-filter-textfield form-control" value="">';
             $filterTextfield[] = '</span>';
         }
         // enable filter functionality via a select
         if (isset($config['multiSelectFilterItems']) && is_array($config['multiSelectFilterItems']) && count($config['multiSelectFilterItems']) > 1) {
             $filterDropDownOptions = array();
             foreach ($config['multiSelectFilterItems'] as $optionElement) {
                 $optionValue = $this->getLanguageService()->sL(isset($optionElement[1]) && $optionElement[1] != '' ? $optionElement[1] : $optionElement[0]);
                 $filterDropDownOptions[] = '<option value="' . htmlspecialchars($this->getLanguageService()->sL($optionElement[0])) . '">' . htmlspecialchars($optionValue) . '</option>';
             }
             $filterSelectbox = '<select class="form-control input-sm t3js-formengine-multiselect-filter-dropdown">' . implode(LF, $filterDropDownOptions) . '</select>';
         }
     }
     if (!empty(trim($filterSelectbox)) && !empty($filterTextfield)) {
         $filterSelectbox = '<div class="form-multigroup-item form-multigroup-element">' . $filterSelectbox . '</div>';
         $filterTextfield = '<div class="form-multigroup-item form-multigroup-element">' . implode(LF, $filterTextfield) . '</div>';
         $selectBoxFilterContents = '<div class="t3js-formengine-multiselect-filter-container form-multigroup-wrap">' . $filterSelectbox . $filterTextfield . '</div>';
     } else {
         $selectBoxFilterContents = trim($filterSelectbox . ' ' . implode(LF, $filterTextfield));
     }
     // Pass to "dbFileIcons" function:
     $params = array('size' => $size, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : '', 'dontShowMoveIcons' => $maxitems <= 1, 'maxitems' => $maxitems, 'info' => '', 'headers' => array('selector' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.selected'), 'items' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.items'), 'selectorbox' => $selectBoxFilterContents), 'noBrowser' => 1, 'rightbox' => implode(LF, $itemsToSelect), 'readOnly' => $disabled);
     $html .= $this->dbFileIcons($parameterArray['itemFormElName'], '', '', $itemsArray, '', $params, $parameterArray['onFocus']);
     // Wizards:
     if (!$disabled) {
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $this->data['databaseRow'], $field, $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     $resultArray = $this->initializeResultArray();
     $resultArray['html'] = $html;
     return $resultArray;
 }
 /**
  * Creates a single-selector box
  *
  * @param string $table See getSingleField_typeSelect()
  * @param string $field See getSingleField_typeSelect()
  * @param array $row See getSingleField_typeSelect()
  * @param array $parameterArray See getSingleField_typeSelect()
  * @param array $config (Redundant) content of $PA['fieldConf']['config'] (for convenience)
  * @param array $selectItems Items available for selection
  * @param string $noMatchingLabel Label for no-matching-value
  * @return string The HTML code for the item
  */
 protected function getSingleField_typeSelect_single($table, $field, $row, $parameterArray, $config, $selectItems, $noMatchingLabel)
 {
     // Initialization:
     $selectId = StringUtility::getUniqueId('tceforms-select-');
     $selectedIndex = 0;
     $selectedIcon = '';
     $selectedValueFound = FALSE;
     $onlySelectedIconShown = FALSE;
     $size = (int) $config['size'];
     // Style set on <select/>
     $out = '';
     $options = '';
     $disabled = FALSE;
     if ($config['readOnly']) {
         $disabled = TRUE;
         $onlySelectedIconShown = TRUE;
     }
     // Icon configuration:
     if ($config['suppress_icons'] === 'IF_VALUE_FALSE') {
         $suppressIcons = empty($parameterArray['itemFormElValue']);
     } elseif ($config['suppress_icons'] === 'ONLY_SELECTED') {
         $suppressIcons = FALSE;
         $onlySelectedIconShown = TRUE;
     } elseif ($config['suppress_icons']) {
         $suppressIcons = TRUE;
     } else {
         $suppressIcons = FALSE;
     }
     // Prepare groups
     $selectItemCounter = 0;
     $selectItemGroupCount = 0;
     $selectItemGroups = array();
     $selectIcons = array();
     $selectedValue = '';
     if (!empty($parameterArray['itemFormElValue'])) {
         $selectedValue = (string) $parameterArray['itemFormElValue'];
     }
     foreach ($selectItems as $item) {
         if ($item[1] === '--div--') {
             // IS OPTGROUP
             if ($selectItemCounter !== 0) {
                 $selectItemGroupCount++;
             }
             $selectItemGroups[$selectItemGroupCount]['header'] = array('title' => $item[0], 'icon' => !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2]) : '');
         } else {
             // IS ITEM
             $title = htmlspecialchars($item['0'], ENT_COMPAT, 'UTF-8', FALSE);
             $selected = $selectedValue === (string) $item[1];
             if ($selected) {
                 $selectedIndex = $selectItemCounter;
                 $selectedIcon = $icon;
                 $selectedValueFound = TRUE;
             }
             $icon = !empty($item[2]) ? $this->getIconHtml($item[2], $selected) : '';
             $selectItemGroups[$selectItemGroupCount]['items'][] = array('title' => $title, 'value' => $item[1], 'icon' => $icon, 'selected' => $selected, 'index' => $selectItemCounter);
             // ICON
             if ($icon && !$suppressIcons && (!$onlySelectedIconShown || $selected)) {
                 $onClick = 'document.editform[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . '].selectedIndex=' . $selectItemCounter . ';';
                 $onClick .= implode('', $parameterArray['fieldChangeFunc']);
                 $onClick .= 'this.blur();return false;';
                 $selectIcons[] = array('title' => $title, 'icon' => $icon, 'index' => $selectItemCounter, 'onClick' => $onClick);
             }
             $selectItemCounter++;
         }
     }
     // No-matching-value:
     if ($selectedValue && !$selectedValueFound && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
         $noMatchingLabel = @sprintf($noMatchingLabel, $selectedValue);
         $options = '<option value="' . htmlspecialchars($selectedValue) . '" selected="selected">' . htmlspecialchars($noMatchingLabel) . '</option>';
     } elseif (!$selectedIcon && $selectItemGroups[0]['items'][0]['icon']) {
         $selectedIcon = $selectItemGroups[0]['items'][0]['icon'];
     }
     // Process groups
     foreach ($selectItemGroups as $selectItemGroup) {
         // suppress groups without items
         if (empty($selectItemGroup['items'])) {
             continue;
         }
         $optionGroup = is_array($selectItemGroup['header']);
         $options .= $optionGroup ? '<optgroup label="' . htmlspecialchars($selectItemGroup['header']['title'], ENT_COMPAT, 'UTF-8', FALSE) . '">' : '';
         if (is_array($selectItemGroup['items'])) {
             foreach ($selectItemGroup['items'] as $item) {
                 $options .= '<option value="' . htmlspecialchars($item['value']) . '" data-icon="' . htmlspecialchars($item['icon']) . '"' . ($item['selected'] ? ' selected="selected"' : '') . '>' . $item['title'] . '</option>';
             }
         }
         $options .= $optionGroup ? '</optgroup>' : '';
     }
     // Create item form fields:
     $sOnChange = 'if (this.options[this.selectedIndex].value==\'--div--\') {this.selectedIndex=' . $selectedIndex . ';} ';
     $sOnChange .= implode('', $parameterArray['fieldChangeFunc']);
     // Build the element
     $out .= '
         <div class="form-control-wrap">
             <select' . ' id="' . $selectId . '"' . ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"' . $this->getValidationDataAsDataAttribute($config) . ' class="form-control form-control-adapt"' . ($size ? ' size="' . $size . '"' : '') . ' onchange="' . htmlspecialchars($sOnChange) . '"' . $parameterArray['onFocus'] . ($disabled ? ' disabled="disabled"' : '') . '>
                 ' . $options . '
             </select>
         </div>';
     // Create icon table:
     if (!empty($selectIcons) && !$config['noIconsBelowSelect']) {
         $out .= '<ul name="IconSelectTable-' . $PA['itemFormElName'] . '" class="list-inline __icon-font-selector">';
         $selectIconTotalCount = count($selectIcons);
         for ($selectIconCount = 0; $selectIconCount < $selectIconTotalCount; $selectIconCount++) {
             $out .= '<li>';
             if (is_array($selectIcons[$selectIconCount])) {
                 $out .= !$onlySelectedIconShown ? '<a href="#" title="' . $selectIcons[$selectIconCount]['title'] . '" onClick="' . htmlspecialchars($selectIcons[$selectIconCount]['onClick']) . '">' : '';
                 $out .= $selectIcons[$selectIconCount]['icon'];
                 $out .= !$onlySelectedIconShown ? '</a>' : '';
             }
             $out .= '</li>';
         }
         $out .= '</ul>';
     }
     return $out;
 }
示例#16
0
 /**
  * Inserts a record in the database, passing TCA configuration values through checkValue() but otherwise does NOTHING and checks nothing regarding permissions.
  * Passes the "version" parameter to insertDB() so the copy will look like a new version in the log - should probably be changed or modified a bit for more broad usage...
  *
  * @param string $table Table name
  * @param array $fieldArray Field array to insert as a record
  * @param int $realPid The value of PID field.  -1 is indication that we are creating a new version!
  * @return int Returns the new ID of the record (if applicable)
  */
 public function insertNewCopyVersion($table, $fieldArray, $realPid)
 {
     $id = StringUtility::getUniqueId('NEW');
     // $fieldArray is set as current record.
     // The point is that when new records are created as copies with flex type fields there might be a field containing information about which DataStructure to use and without that information the flexforms cannot be correctly processed.... This should be OK since the $checkValueRecord is used by the flexform evaluation only anyways...
     $this->checkValue_currentRecord = $fieldArray;
     // Makes sure that transformations aren't processed on the copy.
     $backupDontProcessTransformations = $this->dontProcessTransformations;
     $this->dontProcessTransformations = true;
     // Traverse record and input-process each value:
     foreach ($fieldArray as $field => $fieldValue) {
         if (isset($GLOBALS['TCA'][$table]['columns'][$field])) {
             // Evaluating the value.
             $res = $this->checkValue($table, $field, $fieldValue, $id, 'new', $realPid, 0);
             if (isset($res['value'])) {
                 $fieldArray[$field] = $res['value'];
             }
         }
     }
     // System fields being set:
     if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
         $fieldArray[$GLOBALS['TCA'][$table]['ctrl']['crdate']] = $GLOBALS['EXEC_TIME'];
     }
     if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
         $fieldArray[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']] = $this->userid;
     }
     if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
         $fieldArray[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME'];
     }
     // Finally, insert record:
     $this->insertDB($table, $id, $fieldArray, true);
     // Resets dontProcessTransformations to the previous state.
     $this->dontProcessTransformations = $backupDontProcessTransformations;
     // Return new id:
     return $this->substNEWwithIDs[$id];
 }
 /**
  * This method creates the "cli_scheduler" BE user if it doesn't exist
  *
  * @return void
  */
 protected function createSchedulerUser()
 {
     // Check _cli_scheduler user status
     $checkUser = $this->checkSchedulerUser();
     // Prepare default message
     $message = $this->getLanguageService()->getLL('msg.userExists');
     $severity = FlashMessage::WARNING;
     // If the user does not exist, try creating it
     if ($checkUser == -1) {
         // Prepare necessary data for _cli_scheduler user creation
         $password = StringUtility::getUniqueId('scheduler');
         if (SaltedPasswordsUtility::isUsageEnabled()) {
             $objInstanceSaltedPW = SaltFactory::getSaltingInstance();
             $password = $objInstanceSaltedPW->getHashedPassword($password);
         }
         $data = array('be_users' => array('NEW' => array('username' => '_cli_scheduler', 'password' => $password, 'pid' => 0)));
         /** @var $tcemain \TYPO3\CMS\Core\DataHandling\DataHandler */
         $tcemain = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
         $tcemain->start($data, array());
         $tcemain->process_datamap();
         // Check if a new uid was indeed generated (i.e. a new record was created)
         // (counting TCEmain errors doesn't work as some failures don't report errors)
         $numberOfNewIDs = count($tcemain->substNEWwithIDs);
         if ($numberOfNewIDs === 1) {
             $message = $this->getLanguageService()->getLL('msg.userCreated');
             $severity = FlashMessage::OK;
         } else {
             $message = $this->getLanguageService()->getLL('msg.userNotCreated');
             $severity = FlashMessage::ERROR;
         }
     }
     $this->addMessage($message, $severity);
 }
 /**
  * @return array
  */
 public function render()
 {
     $this->initializeResultArray();
     /** @var \TYPO3\CMS\Core\Authentication\BackendUserAuthentication $beUser */
     $beUser = $GLOBALS['BE_USER'];
     /** @var string $showWizardByDefault */
     $showWizardByDefault = $beUser->getTSConfigVal('setup.default.tx_form.showWizardByDefault');
     if ((int) $showWizardByDefault == 0) {
         $content = '';
         $record = $this->getRepository()->getRecord($this->getCurrentUid(), 'tt_content');
         if ($record) {
             $content = $record->getBodytext();
         }
         $id = StringUtility::getUniqueId('formengine-textarea-');
         $this->resultArray['html'] = '<textarea id="formengine-textarea-' . $id . '"' . ' class="form-control t3js-formengine-textarea formengine-textarea" wrap="off"' . ' onchange="TBE_EDITOR.fieldChanged(\'tt_content\',\'' . $this->getCurrentUid() . '\',\'bodytext\',\'data[tt_content][' . $this->getCurrentUid() . '][bodytext]\');"' . ' rows="15" style="" name="data[tt_content][' . $this->getCurrentUid() . '][bodytext]">' . $content . '</textarea>';
         return $this->resultArray;
     }
     $this->resultAddWizardCss();
     $this->resultArray['additionalInlineLanguageLabelFiles'] += $this->getLocalization();
     $settings = $this->getPlainPageWizardModTsConfigSettingsProperties();
     $settingsCommand = $this->resultAddWizardSettingsJson($settings);
     $this->resultArray['requireJsModules'][] = array('TYPO3/CMS/Form/Wizard' => "function(){\n" . "\t" . $settingsCommand . "\n" . '}');
     $attributes = [];
     $attributes['id'] = StringUtility::getUniqueId('formengine-form-wizard-');
     /**
      * @see TYPO3.CMS/src/typo3/sysext/backend/Classes/Form/Element/AbstractFormElement.php:267 for wizard type=popup
      */
     $parameterArray = $this->data['parameterArray'];
     $attributes['name'] = $parameterArray['itemFormElName'];
     $attributeString = '';
     foreach ($attributes as $attributeName => $attributeValue) {
         $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
     }
     $input = '<input ' . $attributeString . ' type="hidden" />' . "\n";
     $content = $input . '<div id="form-wizard-element"></div>';
     $this->resultArray['html'] = '<div id="form-wizard-element-container" rel="' . $attributes['id'] . '">' . "\n" . $content . "\n" . '</div>';
     return $this->resultArray;
 }
示例#19
0
 /**
  * Test gdlib functions
  *
  * @return \TYPO3\CMS\Install\Status\StatusInterface
  */
 protected function gdlib()
 {
     $this->setUpDatabaseConnectionMock();
     $imageProcessor = $this->initializeImageProcessor();
     $parseTimeStart = GeneralUtility::milliseconds();
     $gifOrPng = $imageProcessor->gifExtension;
     $testResults = array();
     // GD with simple box
     $imageProcessor->IM_commands = array();
     $image = imagecreatetruecolor(170, 136);
     $backgroundColor = imagecolorallocate($image, 0, 0, 0);
     imagefilledrectangle($image, 0, 0, 170, 136, $backgroundColor);
     $workArea = array(0, 0, 170, 136);
     $conf = array('dimensions' => '10,50,150,36', 'color' => 'olive');
     $imageProcessor->makeBox($image, $conf, $workArea);
     $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdSimple') . '.' . $gifOrPng;
     $imageProcessor->ImageWrite($image, $outputFile);
     $result = $imageProcessor->getImageDimensions($outputFile);
     $testResults['simple'] = array();
     $testResults['simple']['title'] = 'Create simple image';
     $testResults['simple']['outputFile'] = $result[3];
     $testResults['simple']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-simple.' . $gifOrPng;
     // GD from image with box
     $imageProcessor->IM_commands = array();
     $inputFile = $this->imageBasePath . 'TestInput/Test.' . $gifOrPng;
     $image = $imageProcessor->imageCreateFromFile($inputFile);
     $workArea = array(0, 0, 170, 136);
     $conf = array('dimensions' => '10,50,150,36', 'color' => 'olive');
     $imageProcessor->makeBox($image, $conf, $workArea);
     $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdBox') . '.' . $gifOrPng;
     $imageProcessor->ImageWrite($image, $outputFile);
     $result = $imageProcessor->getImageDimensions($outputFile);
     $testResults['box'] = array();
     $testResults['box']['title'] = 'Create image from file';
     $testResults['box']['outputFile'] = $result[3];
     $testResults['box']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-box.' . $gifOrPng;
     // GD with text
     $imageProcessor->IM_commands = array();
     $image = imagecreatetruecolor(170, 136);
     $backgroundColor = imagecolorallocate($image, 128, 128, 150);
     imagefilledrectangle($image, 0, 0, 170, 136, $backgroundColor);
     $workArea = array(0, 0, 170, 136);
     $conf = array('iterations' => 1, 'angle' => 0, 'antiAlias' => 1, 'text' => 'HELLO WORLD', 'fontColor' => '#003366', 'fontSize' => 18, 'fontFile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf', 'offset' => '17,40');
     $conf['BBOX'] = $imageProcessor->calcBBox($conf);
     $imageProcessor->makeText($image, $conf, $workArea);
     $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
     $imageProcessor->ImageWrite($image, $outputFile);
     $result = $imageProcessor->getImageDimensions($outputFile);
     $testResults['text'] = array();
     $testResults['text']['title'] = 'Render text with TrueType font';
     $testResults['text']['outputFile'] = $result[3];
     $testResults['text']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-text.' . $gifOrPng;
     // GD with text, niceText
     $testResults['niceText'] = array();
     if ($this->isImageMagickEnabledAndConfigured()) {
         // Warning: Re-uses $conf from above!
         $conf['offset'] = '17,65';
         $conf['niceText'] = 1;
         $imageProcessor->makeText($image, $conf, $workArea);
         $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdNiceText') . '.' . $gifOrPng;
         $imageProcessor->ImageWrite($image, $outputFile);
         $result = $imageProcessor->getImageDimensions($outputFile);
         $testResults['niceText']['title'] = 'Render text with TrueType font using \'niceText\' option';
         $testResults['niceText']['outputFile'] = $result[3];
         $testResults['niceText']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-niceText.' . $gifOrPng;
         $testResults['niceText']['command'] = $imageProcessor->IM_commands;
         /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
         $message = $this->objectManager->get(\TYPO3\CMS\Install\Status\InfoStatus::class);
         $message->setTitle('Note on \'niceText\'');
         $message->setMessage('\'niceText\' is a concept that tries to improve the antialiasing of the rendered type by' . ' actually rendering the textstring in double size on a black/white mask, downscaling the mask' . ' and masking the text onto the image through this mask. This involves' . ' ImageMagick \'combine\'/\'composite\' and \'convert\'.');
         $testResults['niceText']['message'] = $message;
     } else {
         $result['niceText']['error'] = $this->imageGenerationFailedMessage();
     }
     // GD with text, niceText, shadow
     $testResults['shadow'] = array();
     if ($this->isImageMagickEnabledAndConfigured()) {
         // Warning: Re-uses $conf from above!
         $conf['offset'] = '17,90';
         $conf['niceText'] = 1;
         $conf['shadow.'] = array('offset' => '2,2', 'blur' => $imageProcessor->V5_EFFECTS ? '20' : '90', 'opacity' => '50', 'color' => 'black');
         // Warning: Re-uses $image from above!
         $imageProcessor->makeShadow($image, $conf['shadow.'], $workArea, $conf);
         $imageProcessor->makeText($image, $conf, $workArea);
         $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('GDwithText-niceText-shadow') . '.' . $gifOrPng;
         $imageProcessor->ImageWrite($image, $outputFile);
         $result = $imageProcessor->getImageDimensions($outputFile);
         $testResults['shadow']['title'] = 'Render \'niceText\' with a shadow under';
         $testResults['shadow']['outputFile'] = $result[3];
         $testResults['shadow']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-shadow.' . $gifOrPng;
         $testResults['shadow']['command'] = $imageProcessor->IM_commands;
         /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
         $message = $this->objectManager->get(\TYPO3\CMS\Install\Status\InfoStatus::class);
         $message->setTitle('Note on \'shadow\'');
         $message->setMessage('This test makes sense only if the above test had a correct output. But if so, you may not see' . ' a soft dropshadow from the third text string as you should. In that case you are most likely' . ' using ImageMagick 5 and should set the flag TYPO3_CONF_VARS[GFX][im_v5effects].');
         $testResults['shadow']['message'] = $message;
     } else {
         $result['shadow']['error'] = $this->imageGenerationFailedMessage();
     }
     $this->view->assign('testResults', $testResults);
     return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
 }
示例#20
0
 /**
  * Helper method for flushByTag()
  * Gets list of identifiers and tags and removes all relations of those tags
  *
  * Scales O(1) with number of cache entries
  * Scales O(n^2) with number of tags
  *
  * @param array $identifiers List of identifiers to remove
  * @param array $tags List of tags to be handled
  * @return void
  */
 protected function removeIdentifierEntriesAndRelations(array $identifiers, array $tags)
 {
     // Set a temporary entry which holds all identifiers that need to be removed from
     // the tag to identifiers sets
     $uniqueTempKey = 'temp:' . StringUtility::getUniqueId();
     $prefixedKeysToDelete = array($uniqueTempKey);
     $prefixedIdentifierToTagsKeysToDelete = array();
     foreach ($identifiers as $identifier) {
         $prefixedKeysToDelete[] = self::IDENTIFIER_DATA_PREFIX . $identifier;
         $prefixedIdentifierToTagsKeysToDelete[] = self::IDENTIFIER_TAGS_PREFIX . $identifier;
     }
     foreach ($tags as $tag) {
         $prefixedKeysToDelete[] = self::TAG_IDENTIFIERS_PREFIX . $tag;
     }
     $tagToIdentifiersSetsToRemoveIdentifiersFrom = $this->redis->sUnion($prefixedIdentifierToTagsKeysToDelete);
     // Remove the tag to identifier set of the given tags, they will be removed anyway
     $tagToIdentifiersSetsToRemoveIdentifiersFrom = array_diff($tagToIdentifiersSetsToRemoveIdentifiersFrom, $tags);
     // Diff all identifiers that must be removed from tag to identifiers sets off from a
     // tag to identifiers set and store result in same tag to identifiers set again
     $queue = $this->redis->multi(\Redis::PIPELINE);
     foreach ($identifiers as $identifier) {
         $queue->sAdd($uniqueTempKey, $identifier);
     }
     foreach ($tagToIdentifiersSetsToRemoveIdentifiersFrom as $tagToIdentifiersSet) {
         $queue->sDiffStore(self::TAG_IDENTIFIERS_PREFIX . $tagToIdentifiersSet, self::TAG_IDENTIFIERS_PREFIX . $tagToIdentifiersSet, $uniqueTempKey);
     }
     $queue->delete(array_merge($prefixedKeysToDelete, $prefixedIdentifierToTagsKeysToDelete));
     $queue->exec();
 }
示例#21
0
 /**
  * Create a test file and delete again - helper for isWritable
  *
  * @return bool TRUE if test file creation was successful
  */
 protected function canFileBeCreated()
 {
     $testFileName = StringUtility::getUniqueId('installToolTest_');
     $result = @touch($this->getAbsolutePath() . '/' . $testFileName);
     if ($result === true) {
         unlink($this->getAbsolutePath() . '/' . $testFileName);
     }
     return $result;
 }
 /**
  * Render check boxes
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $html = [];
     // Field configuration from TCA:
     $parameterArray = $this->data['parameterArray'];
     $config = $parameterArray['fieldConf']['config'];
     $disabled = !empty($config['readOnly']);
     $selItems = $config['items'];
     if (!empty($selItems)) {
         // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
         $itemArray = array_flip($parameterArray['itemFormElValue']);
         // Traverse the Array of selector box items:
         $groups = array();
         $currentGroup = 0;
         $c = 0;
         $sOnChange = '';
         if (!$disabled) {
             $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
             // Used to accumulate the JS needed to restore the original selection.
             foreach ($selItems as $p) {
                 // Non-selectable element:
                 if ($p[1] === '--div--') {
                     $selIcon = '';
                     if (isset($p[2]) && $p[2] != 'empty-empty') {
                         $selIcon = FormEngineUtility::getIconHtml($p[2]);
                     }
                     $currentGroup++;
                     $groups[$currentGroup]['header'] = array('icon' => $selIcon, 'title' => htmlspecialchars($p[0]));
                 } else {
                     // Check if some help text is available
                     // Since TYPO3 4.5 help text is expected to be an associative array
                     // with two key, "title" and "description"
                     // For the sake of backwards compatibility, we test if the help text
                     // is a string and use it as a description (this could happen if items
                     // are modified with an itemProcFunc)
                     $hasHelp = false;
                     $help = '';
                     $helpArray = array();
                     if (!empty($p[3])) {
                         $hasHelp = true;
                         if (is_array($p[3])) {
                             $helpArray = $p[3];
                         } else {
                             $helpArray['description'] = $p[3];
                         }
                     }
                     if ($hasHelp) {
                         $help = BackendUtility::wrapInHelp('', '', '', $helpArray);
                     }
                     // Selected or not by default:
                     $checked = 0;
                     if (isset($itemArray[$p[1]])) {
                         $checked = 1;
                         unset($itemArray[$p[1]]);
                     }
                     // Build item array
                     $groups[$currentGroup]['items'][] = array('id' => StringUtility::getUniqueId('select_checkbox_row_'), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $p[1], 'checked' => $checked, 'disabled' => false, 'class' => '', 'icon' => !empty($p[2]) ? FormEngineUtility::getIconHtml($p[2]) : $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render(), 'title' => htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', false), 'help' => $help);
                     $c++;
                 }
             }
         }
         // Add an empty hidden field which will send a blank value if all items are unselected.
         $html[] = '<input type="hidden" class="select-checkbox" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="">';
         // Building the checkboxes
         foreach ($groups as $groupKey => $group) {
             $groupId = htmlspecialchars($parameterArray['itemFormElID']) . '-group-' . $groupKey;
             $html[] = '<div class="panel panel-default">';
             if (is_array($group['header'])) {
                 $html[] = '<div class="panel-heading">';
                 $html[] = '<a data-toggle="collapse" href="#' . $groupId . '" aria-expanded="false" aria-controls="' . $groupId . '">';
                 $html[] = $group['header']['icon'];
                 $html[] = $group['header']['title'];
                 $html[] = '</a>';
                 $html[] = '</div>';
             }
             if (is_array($group['items']) && !empty($group['items'])) {
                 $tableRows = [];
                 $checkGroup = array();
                 $uncheckGroup = array();
                 $resetGroup = array();
                 // Render rows
                 foreach ($group['items'] as $item) {
                     $tableRows[] = '<tr class="' . $item['class'] . '">';
                     $tableRows[] = '<td class="col-checkbox">';
                     $tableRows[] = '<input type="checkbox" ' . 'id="' . $item['id'] . '" ' . 'name="' . htmlspecialchars($item['name']) . '" ' . 'value="' . htmlspecialchars($item['value']) . '" ' . 'onclick="' . htmlspecialchars($sOnChange) . '" ' . ($item['checked'] ? 'checked=checked ' : '') . ($item['disabled'] ? 'disabled=disabled ' : '') . $parameterArray['onFocus'] . '>';
                     $tableRows[] = '</td>';
                     $tableRows[] = '<td class="col-icon">';
                     $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label>';
                     $tableRows[] = '</td>';
                     $tableRows[] = '<td class="col-title">';
                     $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['title'] . '</label>';
                     $tableRows[] = '</td>';
                     $tableRows[] = '<td>' . $item['help'] . '</td>';
                     $tableRows[] = '</tr>';
                     $checkGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=1;';
                     $uncheckGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=0;';
                     $resetGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=' . $item['checked'] . ';';
                 }
                 // Build toggle group checkbox
                 $toggleGroupCheckbox = '';
                 if (!empty($resetGroup)) {
                     $toggleGroupCheckbox = '<input type="checkbox" ' . 'class="checkbox" ' . 'onclick="if (checked) {' . htmlspecialchars(implode('', $checkGroup) . '} else {' . implode('', $uncheckGroup)) . '}">';
                 }
                 // Build reset group button
                 $resetGroupBtn = '';
                 if (!empty($resetGroup)) {
                     $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection', true);
                     $resetGroupBtn = '<a href="#" ' . 'class="btn btn-default" ' . 'onclick="' . implode('', $resetGroup) . ' return false;" ' . 'title="' . $title . '">' . $this->iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection') . '</a>';
                 }
                 if (is_array($group['header'])) {
                     $html[] = '<div id="' . $groupId . '" class="panel-collapse collapse" role="tabpanel">';
                 }
                 $html[] = '<div class="table-fit">';
                 $html[] = '<table class="table table-transparent table-hover">';
                 $html[] = '<thead>';
                 $html[] = '<tr>';
                 $html[] = '<th class="col-checkbox">' . $toggleGroupCheckbox . '</th>';
                 $html[] = '<th class="col-icon"></th>';
                 $html[] = '<th class="text-right" colspan="2">' . $resetGroupBtn . '</th>';
                 $html[] = '</tr>';
                 $html[] = '</thead>';
                 $html[] = '<tbody>' . implode(LF, $tableRows) . '</tbody>';
                 $html[] = '</table>';
                 $html[] = '</div>';
                 if (is_array($group['header'])) {
                     $html[] = '</div>';
                 }
             }
             $html[] = '</div>';
         }
     }
     if (!$disabled) {
         $html = $this->renderWizards(array(implode(LF, $html)), $config['wizards'], $this->data['tableName'], $this->data['databaseRow'], $this->data['fieldName'], $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     $resultArray = $this->initializeResultArray();
     $resultArray['html'] = $html;
     return $resultArray;
 }
示例#23
0
 /**
  * Flushes a directory by first moving to a temporary resource, and then
  * triggering the remove process. This way directories can be flushed faster
  * to prevent race conditions on concurrent processes accessing the same directory.
  *
  * @param string $directory The directory to be renamed and flushed
  * @param bool $keepOriginalDirectory Whether to only empty the directory and not remove it
  * @param bool $flushOpcodeCache Also flush the opcode cache right after renaming the directory.
  * @return bool Whether the action was successful
  */
 public static function flushDirectory($directory, $keepOriginalDirectory = false, $flushOpcodeCache = false)
 {
     $result = false;
     if (is_dir($directory)) {
         $temporaryDirectory = rtrim($directory, '/') . '.' . StringUtility::getUniqueId('remove') . '/';
         if (rename($directory, $temporaryDirectory)) {
             if ($flushOpcodeCache) {
                 self::makeInstance(OpcodeCacheService::class)->clearAllActive($directory);
             }
             if ($keepOriginalDirectory) {
                 static::mkdir($directory);
             }
             clearstatcache();
             $result = static::rmdir($temporaryDirectory, true);
         }
     }
     return $result;
 }
 /**
  * Render single element
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->data['tableName'];
     $field = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $config = $parameterArray['fieldConf']['config'];
     $selectItems = $parameterArray['fieldConf']['config']['items'];
     // Check against inline uniqueness
     /** @var InlineStackProcessor $inlineStackProcessor */
     $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
     $inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
     $uniqueIds = null;
     if ($this->data['isInlineChild'] && $this->data['inlineParentUid']) {
         $inlineObjectName = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
         $inlineFormName = $inlineStackProcessor->getCurrentStructureFormPrefix();
         if ($this->data['inlineParentConfig']['foreign_table'] === $table && $this->data['inlineParentConfig']['foreign_unique'] === $field) {
             $uniqueIds = $this->data['inlineData']['unique'][$inlineObjectName . '-' . $table]['used'];
             $parameterArray['fieldChangeFunc']['inlineUnique'] = 'inline.updateUnique(this,' . GeneralUtility::quoteJSvalue($inlineObjectName . '-' . $table) . ',' . GeneralUtility::quoteJSvalue($inlineFormName) . ',' . GeneralUtility::quoteJSvalue($row['uid']) . ');';
         }
         // hide uid of parent record for symmetric relations
         if ($this->data['inlineParentConfig']['foreign_table'] === $table && ($this->data['inlineParentConfig']['foreign_field'] === $field || $this->data['inlineParentConfig']['symmetric_field'] === $field)) {
             $uniqueIds[] = $this->data['inlineParentUid'];
         }
     }
     // Initialization:
     $selectId = StringUtility::getUniqueId('tceforms-select-');
     $selectedIcon = '';
     $size = (int) $config['size'];
     // Style set on <select/>
     $options = '';
     $disabled = false;
     if (!empty($config['readOnly'])) {
         $disabled = true;
     }
     // Prepare groups
     $selectItemCounter = 0;
     $selectItemGroupCount = 0;
     $selectItemGroups = array();
     $selectIcons = array();
     $selectedValue = '';
     $hasIcons = false;
     if (!empty($parameterArray['itemFormElValue'])) {
         $selectedValue = (string) $parameterArray['itemFormElValue'][0];
     }
     foreach ($selectItems as $item) {
         if ($item[1] === '--div--') {
             // IS OPTGROUP
             if ($selectItemCounter !== 0) {
                 $selectItemGroupCount++;
             }
             $selectItemGroups[$selectItemGroupCount]['header'] = array('title' => $item[0]);
         } else {
             // IS ITEM
             $title = htmlspecialchars($item['0'], ENT_COMPAT, 'UTF-8', false);
             $icon = !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2], $title, $title) : '';
             $selected = $selectedValue === (string) $item[1];
             if ($selected) {
                 $selectedIcon = $icon;
             }
             $selectItemGroups[$selectItemGroupCount]['items'][] = array('title' => $title, 'value' => $item[1], 'icon' => $icon, 'selected' => $selected, 'index' => $selectItemCounter);
             // ICON
             if ($icon) {
                 $selectIcons[] = array('title' => $title, 'icon' => $icon, 'index' => $selectItemCounter);
             }
             $selectItemCounter++;
         }
     }
     // Fallback icon
     // @todo: assign a special icon for non matching values?
     if (!$selectedIcon && $selectItemGroups[0]['items'][0]['icon']) {
         $selectedIcon = $selectItemGroups[0]['items'][0]['icon'];
     }
     // Process groups
     foreach ($selectItemGroups as $selectItemGroup) {
         // suppress groups without items
         if (empty($selectItemGroup['items'])) {
             continue;
         }
         $optionGroup = is_array($selectItemGroup['header']);
         $options .= $optionGroup ? '<optgroup label="' . htmlspecialchars($selectItemGroup['header']['title'], ENT_COMPAT, 'UTF-8', false) . '">' : '';
         if (is_array($selectItemGroup['items'])) {
             foreach ($selectItemGroup['items'] as $item) {
                 $options .= '<option value="' . htmlspecialchars($item['value']) . '" data-icon="' . htmlspecialchars($item['icon']) . '"' . ($item['selected'] ? ' selected="selected"' : '') . '>' . $item['title'] . '</option>';
             }
             $hasIcons = !empty($item['icon']);
         }
         $options .= $optionGroup ? '</optgroup>' : '';
     }
     // Build the element
     $html = ['<div class="form-control-wrap">'];
     if ($hasIcons) {
         $html[] = '<div class="input-group">';
         $html[] = '<span class="input-group-addon input-group-icon">';
         $html[] = $selectedIcon;
         $html[] = '</span>';
     }
     $html[] = '<select' . ' id="' . $selectId . '"' . ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"' . $this->getValidationDataAsDataAttribute($config) . ' class="form-control form-control-adapt"' . ($size ? ' size="' . $size . '"' : '') . ($disabled ? ' disabled="disabled"' : '') . '>';
     $html[] = $options;
     $html[] = '</select>';
     if ($hasIcons) {
         $html[] = '</div>';
     }
     $html[] = '</div>';
     // Create icon table:
     if (!empty($selectIcons) && !empty($config['showIconTable'])) {
         $selectIconColumns = (int) $config['selicon_cols'];
         if (!$selectIconColumns) {
             $selectIconColumns = count($selectIcons);
         }
         $selectIconColumns = $selectIconColumns > 12 ? 12 : $selectIconColumns;
         $selectIconRows = ceil(count($selectIcons) / $selectIconColumns);
         $selectIcons = array_pad($selectIcons, $selectIconRows * $selectIconColumns, '');
         $html[] = '<div class="t3js-forms-select-single-icons table-icons table-fit table-fit-inline-block">';
         $html[] = '<table class="table table-condensed table-white table-center">';
         $html[] = '<tbody>';
         $html[] = '<tr>';
         foreach ($selectIcons as $i => $selectIcon) {
             if ($i % $selectIconColumns === 0 && $i !== 0) {
                 $html[] = '</tr>';
                 $html[] = '<tr>';
             }
             $html[] = '<td>';
             if (is_array($selectIcon)) {
                 $html[] = '<a href="#" title="' . $selectIcon['title'] . '" data-select-index="' . $selectIcon['index'] . '">';
                 $html[] = $selectIcon['icon'];
                 $html[] = '</a>';
             }
             $html[] = '</td>';
         }
         $html[] = '</tr>';
         $html[] = '</tbody>';
         $html[] = '</table>';
         $html[] = '</div>';
     }
     $html = implode(LF, $html);
     // Wizards:
     if (!$disabled) {
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $field, $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     $resultArray = $this->initializeResultArray();
     $resultArray['html'] = $html;
     $resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectSingleElement' => implode(LF, ['function(SelectSingleElement) {', 'SelectSingleElement.initialize(', GeneralUtility::quoteJSvalue('#' . $selectId) . ',', '{', 'onChange: function() {', implode('', $parameterArray['fieldChangeFunc']), '}', '}', ');', '}'])];
     return $resultArray;
 }
示例#25
0
    /**
     * This will render a single-line input form field, possibly with various control/validation features
     *
     * @return array As defined in initializeResultArray() of AbstractNode
     */
    public function render()
    {
        $languageService = $this->getLanguageService();
        $table = $this->data['tableName'];
        $fieldName = $this->data['fieldName'];
        $row = $this->data['databaseRow'];
        $parameterArray = $this->data['parameterArray'];
        $resultArray = $this->initializeResultArray();
        $resultArray['requireJsModules'] = array('TYPO3/CMS/Rsaauth/RsaEncryptionModule');
        $config = $parameterArray['fieldConf']['config'];
        $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
        $size = MathUtility::forceIntegerInRange($config['size'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
        $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
        $classes = array();
        $attributes = array('type' => 'text', 'value' => '');
        if ($config['readOnly']) {
            $itemFormElValue = $parameterArray['itemFormElValue'];
            $options = $this->data;
            $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $itemFormElValue);
            $options['renderType'] = 'none';
            return $this->nodeFactory->create($options)->render();
        }
        // @todo: The whole eval handling is a mess and needs refactoring
        foreach ($evalList as $func) {
            switch ($func) {
                case 'required':
                    $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
                    break;
                case 'password':
                    $attributes['type'] = 'password';
                    $attributes['value'] = '********';
                    $attributes['autocomplete'] = 'off';
                    break;
                default:
                    // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
                    // @todo: keyword like "date", or a class reference. The global registration could be dropped then
                    // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                    if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
                        if (class_exists($func)) {
                            $evalObj = GeneralUtility::makeInstance($func);
                            if (method_exists($evalObj, 'deevaluateFieldValue')) {
                                $_params = array('value' => $parameterArray['itemFormElValue']);
                                $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                            }
                        }
                    }
            }
        }
        $evalList = array_filter($evalList, function ($value) {
            return $value !== 'password';
        });
        $paramsList = array('field' => $parameterArray['itemFormElName'], 'evalList' => implode(',', $evalList), 'is_in' => trim($config['is_in']));
        // set classes
        $classes[] = 'form-control';
        $classes[] = 't3js-clearable';
        $classes[] = 'hasDefaultValue';
        // calculate attributes
        $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString($config);
        $attributes['data-formengine-input-params'] = json_encode($paramsList);
        $attributes['data-formengine-input-name'] = htmlspecialchars($parameterArray['itemFormElName']);
        $attributes['id'] = StringUtility::getUniqueId('formengine-input-');
        if (isset($config['max']) && (int) $config['max'] > 0) {
            $attributes['maxlength'] = (int) $config['max'];
        }
        if (!empty($classes)) {
            $attributes['class'] = implode(' ', $classes);
        }
        if (isset($config['max']) && (int) $config['max'] > 0) {
            $attributes['maxlength'] = (int) $config['max'];
        }
        // This is the EDITABLE form field.
        if (!empty($config['placeholder'])) {
            $attributes['placeholder'] = trim($config['placeholder']);
        }
        if (isset($config['autocomplete'])) {
            $attributes['autocomplete'] = empty($config['autocomplete']) ? 'off' : 'on';
        }
        // Build the attribute string
        $attributeString = '';
        foreach ($attributes as $attributeName => $attributeValue) {
            $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
        }
        $html = '
			<input' . $attributeString . $parameterArray['onFocus'] . ' />';
        // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
        $html .= '<input type="hidden" data-rsa-encryption="" id="' . $parameterArray['itemFormElID'] . '_hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
        // Going through all custom evaluations configured for this field
        // @todo: Similar to above code!
        foreach ($evalList as $evalData) {
            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData])) {
                if (class_exists($evalData)) {
                    $evalObj = GeneralUtility::makeInstance($evalData);
                    if (method_exists($evalObj, 'returnFieldJS')) {
                        $resultArray['extJSCODE'] .= LF . 'TBE_EDITOR.customEvalFunctions[' . GeneralUtility::quoteJSvalue($evalData) . '] = function(value) {' . $evalObj->returnFieldJS() . '}';
                    }
                }
            }
        }
        // Wrap a wizard around the item?
        $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specConf);
        // Add a wrapper to remain maximum width
        $width = (int) $this->formMaxWidth($size);
        $html = '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>' . $html . '</div>';
        $resultArray['html'] = $html;
        return $resultArray;
    }
示例#26
0
 /**
  * @param string $privateKey The private key (obtained from a call to createNewKeyPair())
  * @param string $data Data to decrypt (base64-encoded)
  * @return string Decrypted data or NULL in case of an error
  * @see \TYPO3\CMS\Rsaauth\Backend\AbstractBackend::decrypt()
  */
 public function decrypt($privateKey, $data)
 {
     // Key must be put to the file
     $privateKeyFile = tempnam($this->temporaryDirectory, StringUtility::getUniqueId());
     file_put_contents($privateKeyFile, $privateKey);
     $dataFile = tempnam($this->temporaryDirectory, StringUtility::getUniqueId());
     file_put_contents($dataFile, base64_decode($data));
     // Prepare the command
     $command = $this->opensslPath . ' rsautl -inkey ' . escapeshellarg($privateKeyFile) . ' -in ' . escapeshellarg($dataFile) . ' -decrypt';
     // Execute the command and capture the result
     $output = array();
     CommandUtility::exec($command, $output);
     // Remove the file
     @unlink($privateKeyFile);
     @unlink($dataFile);
     return implode(LF, $output);
 }
示例#27
0
    /**
     * Renders Content Elements from the tt_content table from page id
     *
     * @param int $id Page id
     * @return string HTML for the listing
     */
    public function getTable_tt_content($id)
    {
        $backendUser = $this->getBackendUser();
        $this->pageinfo = BackendUtility::readPageAccess($this->id, $backendUser->getPagePermsClause($this->ext_CALC_PERMS));
        $this->initializeLanguages();
        $this->initializeClipboard();
        $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode(BackendUtility::getRecordTitle('pages', BackendUtility::getRecordWSOL('pages', $id), true));
        /** @var $pageRenderer PageRenderer */
        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/DragDrop');
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
        $userCanEditPage = $this->ext_CALC_PERMS & Permission::PAGE_EDIT && !empty($this->id) && ($backendUser->isAdmin() || (int) $this->pageinfo['editlock'] === 0);
        if ($this->tt_contentConfig['languageColsPointer'] > 0) {
            $userCanEditPage = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay');
        }
        if ($userCanEditPage) {
            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
                PageActions.setPageId(' . (int) $this->id . ');
                PageActions.setLanguageOverlayId(' . $this->tt_contentConfig['languageColsPointer'] . ');
                PageActions.initializePageTitleRenaming();
            }');
        }
        // Get labels for CTypes and tt_content element fields in general:
        $this->CType_labels = array();
        foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) {
            $this->CType_labels[$val[1]] = $this->getLanguageService()->sL($val[0]);
        }
        $this->itemLabels = array();
        foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) {
            $this->itemLabels[$name] = $this->getLanguageService()->sL($val['label']);
        }
        $languageColumn = array();
        $out = '';
        // Setting language list:
        $langList = $this->tt_contentConfig['sys_language_uid'];
        if ($this->tt_contentConfig['languageMode']) {
            if ($this->tt_contentConfig['languageColsPointer']) {
                $langList = '0,' . $this->tt_contentConfig['languageColsPointer'];
            } else {
                $langList = implode(',', array_keys($this->tt_contentConfig['languageCols']));
            }
            $languageColumn = array();
        }
        $langListArr = GeneralUtility::intExplode(',', $langList);
        $defLanguageCount = array();
        $defLangBinding = array();
        // For each languages... :
        // If not languageMode, then we'll only be through this once.
        foreach ($langListArr as $lP) {
            $lP = (int) $lP;
            if (!isset($this->contentElementCache[$lP])) {
                $this->contentElementCache[$lP] = array();
            }
            if (count($langListArr) === 1 || $lP === 0) {
                $showLanguage = ' AND sys_language_uid IN (' . $lP . ',-1)';
            } else {
                $showLanguage = ' AND sys_language_uid=' . $lP;
            }
            $cList = explode(',', $this->tt_contentConfig['cols']);
            $content = array();
            $head = array();
            // Select content records per column
            $contentRecordsPerColumn = $this->getContentRecordsPerColumn('table', $id, array_values($cList), $showLanguage);
            // For each column, render the content into a variable:
            foreach ($cList as $key) {
                if (!isset($this->contentElementCache[$lP][$key])) {
                    $this->contentElementCache[$lP][$key] = array();
                }
                if (!$lP) {
                    $defLanguageCount[$key] = array();
                }
                // Start wrapping div
                $content[$key] .= '<div data-colpos="' . $key . '" data-language-uid="' . $lP . '" class="t3js-sortable t3js-sortable-lang t3js-sortable-lang-' . $lP . ' t3-page-ce-wrapper';
                if (empty($contentRecordsPerColumn[$key])) {
                    $content[$key] .= ' t3-page-ce-empty';
                }
                $content[$key] .= '">';
                // Add new content at the top most position
                $link = '';
                if ($this->getPageLayoutController()->pageIsNotLockedForEditors() && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)) {
                    $link = '<a href="#" onclick="' . htmlspecialchars($this->newContentElementOnClick($id, $key, $lP)) . '" title="' . $this->getLanguageService()->getLL('newContentElement', true) . '" class="btn btn-default btn-sm">' . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->getLL('content', true) . '</a>';
                }
                $content[$key] .= '
				<div class="t3-page-ce t3js-page-ce" data-page="' . (int) $id . '" id="' . StringUtility::getUniqueId() . '">
					<div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $key . '-' . 'page-' . $id . '-' . StringUtility::getUniqueId() . '">' . $link . '</div>
                    <div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div>
                </div>
				';
                $editUidList = '';
                $rowArr = $contentRecordsPerColumn[$key];
                $this->generateTtContentDataArray($rowArr);
                foreach ((array) $rowArr as $rKey => $row) {
                    $this->contentElementCache[$lP][$key][$row['uid']] = $row;
                    if ($this->tt_contentConfig['languageMode']) {
                        $languageColumn[$key][$lP] = $head[$key] . $content[$key];
                        if (!$this->defLangBinding) {
                            $languageColumn[$key][$lP] .= $this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP), $lP, $key);
                        }
                    }
                    if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
                        $singleElementHTML = '';
                        if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) {
                            $defLanguageCount[$key][] = isset($row['_ORIG_uid']) ? $row['_ORIG_uid'] : $row['uid'];
                        }
                        $editUidList .= $row['uid'] . ',';
                        $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0;
                        if (!$this->tt_contentConfig['languageMode']) {
                            $singleElementHTML .= '<div class="t3-page-ce-dragitem" id="' . StringUtility::getUniqueId() . '">';
                        }
                        $singleElementHTML .= $this->tt_content_drawHeader($row, $this->tt_contentConfig['showInfo'] ? 15 : 5, $disableMoveAndNewButtons, !$this->tt_contentConfig['languageMode'], $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT));
                        $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>' . $this->tt_content_drawItem($row) . '</div>';
                        $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div>' . $this->tt_content_drawFooter($row);
                        $isDisabled = $this->isDisabled('tt_content', $row);
                        $statusHidden = $isDisabled ? ' t3-page-ce-hidden t3js-hidden-record' : '';
                        $displayNone = !$this->tt_contentConfig['showHidden'] && $isDisabled ? ' style="display: none;"' : '';
                        $singleElementHTML = '<div class="t3-page-ce t3js-page-ce t3js-page-ce-sortable ' . $statusHidden . '" id="element-tt_content-' . $row['uid'] . '" data-table="tt_content" data-uid="' . $row['uid'] . '"' . $displayNone . '>' . $singleElementHTML . '</div>';
                        if ($this->tt_contentConfig['languageMode']) {
                            $singleElementHTML .= '<div class="t3-page-ce t3js-page-ce">';
                        }
                        $singleElementHTML .= '<div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $key . '-' . 'page-' . $id . '-' . StringUtility::getUniqueId() . '">';
                        // Add icon "new content element below"
                        if (!$disableMoveAndNewButtons && $this->getPageLayoutController()->pageIsNotLockedForEditors() && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)) {
                            // New content element:
                            if ($this->option_newWizard) {
                                $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('new_content_element') . '&id=' . $row['pid'] . '&sys_language_uid=' . $row['sys_language_uid'] . '&colPos=' . $row['colPos'] . '&uid_pid=' . -$row['uid'] . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';';
                            } else {
                                $params = '&edit[tt_content][' . -$row['uid'] . ']=new';
                                $onClick = BackendUtility::editOnClick($params);
                            }
                            $singleElementHTML .= '
								<a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $this->getLanguageService()->getLL('newContentElement', true) . '" class="btn btn-default btn-sm">' . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->getLL('content', true) . '</a>
							';
                        }
                        $singleElementHTML .= '</div></div><div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div></div>';
                        if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) {
                            $defLangBinding[$key][$lP][$row[$lP ? 'l18n_parent' : 'uid']] = $singleElementHTML;
                        } else {
                            $content[$key] .= $singleElementHTML;
                        }
                    } else {
                        unset($rowArr[$rKey]);
                    }
                }
                $content[$key] .= '</div>';
                // Add new-icon link, header:
                $newP = $this->newContentElementOnClick($id, $key, $lP);
                $colTitle = BackendUtility::getProcessedValue('tt_content', 'colPos', $key);
                $tcaItems = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getColPosListItemsParsed', $id, $this);
                foreach ($tcaItems as $item) {
                    if ($item[1] == $key) {
                        $colTitle = $this->getLanguageService()->sL($item[0]);
                    }
                }
                $pasteP = array('colPos' => $key, 'sys_language_uid' => $lP);
                $editParam = $this->doEdit && !empty($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : '';
                $head[$key] .= $this->tt_content_drawColHeader($colTitle, $editParam, $newP, $pasteP);
            }
            // For each column, fit the rendered content into a table cell:
            $out = '';
            if ($this->tt_contentConfig['languageMode']) {
                // in language mode process the content elements, but only fill $languageColumn. output will be generated later
                $sortedLanguageColumn = array();
                foreach ($cList as $key) {
                    $languageColumn[$key][$lP] = $head[$key] . $content[$key];
                    if (!$this->defLangBinding) {
                        $languageColumn[$key][$lP] .= $this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP), $lP, $key);
                    }
                    // We sort $languageColumn again according to $cList as it may contain data already from above.
                    $sortedLanguageColumn[$key] = $languageColumn[$key];
                }
                $languageColumn = $sortedLanguageColumn;
            } else {
                $backendLayout = $this->getBackendLayoutView()->getSelectedBackendLayout($this->id);
                // GRID VIEW:
                $grid = '<div class="t3-grid-container"><table border="0" cellspacing="0" cellpadding="0" width="100%" class="t3-page-columns t3-grid-table t3js-page-columns">';
                // Add colgroups
                $colCount = (int) $backendLayout['__config']['backend_layout.']['colCount'];
                $rowCount = (int) $backendLayout['__config']['backend_layout.']['rowCount'];
                $grid .= '<colgroup>';
                for ($i = 0; $i < $colCount; $i++) {
                    $grid .= '<col style="width:' . 100 / $colCount . '%"></col>';
                }
                $grid .= '</colgroup>';
                // Cycle through rows
                for ($row = 1; $row <= $rowCount; $row++) {
                    $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'];
                    if (!isset($rowConfig)) {
                        continue;
                    }
                    $grid .= '<tr>';
                    for ($col = 1; $col <= $colCount; $col++) {
                        $columnConfig = $rowConfig['columns.'][$col . '.'];
                        if (!isset($columnConfig)) {
                            continue;
                        }
                        // Which tt_content colPos should be displayed inside this cell
                        $columnKey = (int) $columnConfig['colPos'];
                        // Render the grid cell
                        $colSpan = (int) $columnConfig['colspan'];
                        $rowSpan = (int) $columnConfig['rowspan'];
                        $grid .= '<td valign="top"' . ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') . ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') . ' data-colpos="' . (int) $columnConfig['colPos'] . '" data-language-uid="' . $lP . '" class="t3js-page-lang-column-' . $lP . ' t3js-page-column t3-grid-cell t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '' ? ' t3-grid-cell-unassigned' : '') . (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !$head[$columnKey] || !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos']) ? ' t3-grid-cell-restricted' : '') . ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') . ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">';
                        // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
                        // If not, a new header without any buttons will be generated.
                        if (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey] && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])) {
                            $grid .= $head[$columnKey] . $content[$columnKey];
                        } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])) {
                            $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('noAccess'), '', '');
                        } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])) {
                            $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) . ' (' . $this->getLanguageService()->getLL('noAccess') . ')', '', '');
                        } elseif (isset($columnConfig['name']) && $columnConfig['name'] !== '') {
                            $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) . ' (' . $this->getLanguageService()->getLL('notAssigned') . ')', '', '');
                        } else {
                            $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('notAssigned'), '', '');
                        }
                        $grid .= '</td>';
                    }
                    $grid .= '</tr>';
                }
                $out .= $grid . '</table></div>';
            }
            // CSH:
            $out .= BackendUtility::cshItem($this->descrTable, 'columns_multi');
        }
        // If language mode, then make another presentation:
        // Notice that THIS presentation will override the value of $out!
        // But it needs the code above to execute since $languageColumn is filled with content we need!
        if ($this->tt_contentConfig['languageMode']) {
            // Get language selector:
            $languageSelector = $this->languageSelector($id);
            // Reset out - we will make new content here:
            $out = '';
            // Traverse languages found on the page and build up the table displaying them side by side:
            $cCont = array();
            $sCont = array();
            foreach ($langListArr as $lP) {
                // Header:
                $lP = (int) $lP;
                $cCont[$lP] = '
					<td valign="top" class="t3-page-column" data-language-uid="' . $lP . '">
						<h2>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '</h2>
					</td>';
                // "View page" icon is added:
                $viewLink = '';
                if (!VersionState::cast($this->getPageLayoutController()->pageinfo['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
                    $onClick = BackendUtility::viewOnClick($this->id, '', BackendUtility::BEgetRootLine($this->id), '', '', '&L=' . $lP);
                    $viewLink = '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars($onClick) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', true) . '">' . $this->iconFactory->getIcon('actions-view', Icon::SIZE_SMALL)->render() . '</a>';
                }
                // Language overlay page header:
                if ($lP) {
                    list($lpRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . $lP);
                    BackendUtility::workspaceOL('pages_language_overlay', $lpRecord);
                    $params = '&edit[pages_language_overlay][' . $lpRecord['uid'] . ']=edit&overrideVals[pages_language_overlay][sys_language_uid]=' . $lP;
                    $recordIcon = BackendUtility::wrapClickMenuOnIcon($this->iconFactory->getIconForRecord('pages_language_overlay', $lpRecord, Icon::SIZE_SMALL)->render(), 'pages_language_overlay', $lpRecord['uid']);
                    $editLink = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay') ? '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params)) . '" title="' . $this->getLanguageService()->getLL('edit', true) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>' : '';
                    $lPLabel = '<div class="btn-group">' . $viewLink . $editLink . '</div>' . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($lpRecord['title'], 20));
                } else {
                    $params = '&edit[pages][' . $this->id . ']=edit';
                    $recordIcon = BackendUtility::wrapClickMenuOnIcon($this->iconFactory->getIconForRecord('pages', $this->pageRecord, Icon::SIZE_SMALL)->render(), 'pages', $this->id);
                    $editLink = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay') ? '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params)) . '" title="' . $this->getLanguageService()->getLL('edit', true) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>' : '';
                    $lPLabel = '<div class="btn-group">' . $viewLink . $editLink . '</div>' . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->pageRecord['title'], 20));
                }
                $sCont[$lP] = '
					<td nowrap="nowrap" class="t3-page-column t3-page-lang-label">' . $lPLabel . '</td>';
            }
            // Add headers:
            $out .= '<tr>' . implode($cCont) . '</tr>';
            $out .= '<tr>' . implode($sCont) . '</tr>';
            unset($cCont, $sCont);
            // Traverse previously built content for the columns:
            foreach ($languageColumn as $cKey => $cCont) {
                $out .= '<tr>';
                foreach ($cCont as $languageId => $columnContent) {
                    $out .= '<td valign="top" class="t3-grid-cell t3-page-column t3js-page-column t3js-page-lang-column t3js-page-lang-column-' . $languageId . '">' . $columnContent . '</td>';
                }
                $out .= '</tr>';
                if ($this->defLangBinding) {
                    // "defLangBinding" mode
                    foreach ($defLanguageCount[$cKey] as $defUid) {
                        $cCont = array();
                        foreach ($langListArr as $lP) {
                            $cCont[] = $defLangBinding[$cKey][$lP][$defUid] . $this->newLanguageButton($this->getNonTranslatedTTcontentUids(array($defUid), $id, $lP), $lP, $cKey);
                        }
                        $out .= '
                        <tr>
							<td valign="top" class="t3-grid-cell">' . implode('</td>' . '
							<td valign="top" class="t3-grid-cell">', $cCont) . '</td>
						</tr>';
                    }
                }
            }
            // Finally, wrap it all in a table and add the language selector on top of it:
            $out = $languageSelector . '
                <div class="t3-grid-container">
                    <table cellpadding="0" cellspacing="0" class="t3-page-columns t3-grid-table t3js-page-columns">
						' . $out . '
                    </table>
				</div>';
            // CSH:
            $out .= BackendUtility::cshItem($this->descrTable, 'language_list');
        }
        return $out;
    }
示例#28
0
    /**
     * Rendering the cObject, SWFOBJECT
     *
     * @param array $conf Array of TypoScript properties
     * @return string Output
     */
    public function render($conf = array())
    {
        $params = $prefix = '';
        if ($GLOBALS['TSFE']->baseUrl) {
            $prefix = $GLOBALS['TSFE']->baseUrl;
        }
        if ($GLOBALS['TSFE']->absRefPrefix) {
            $prefix = $GLOBALS['TSFE']->absRefPrefix;
        }
        // Initialize content
        $replaceElementIdString = StringUtility::getUniqueId('mmswf');
        $GLOBALS['TSFE']->register['MMSWFID'] = $replaceElementIdString;
        $layout = isset($conf['layout.']) ? $this->cObj->stdWrap($conf['layout'], $conf['layout.']) : $conf['layout'];
        $content = str_replace('###ID###', $replaceElementIdString, $layout);
        $type = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
        $typeConf = $conf[$type . '.'];
        // Add Flowplayer js-file
        $this->getPageRenderer()->addJsFile($this->getPathToLibrary('flowplayer/flowplayer-3.2.13.min.js'));
        // Add Flowpayer css for express install
        $this->getPageRenderer()->addCssFile($this->getPathToLibrary('flowplayer/express-install/express-install.css'));
        // Add videoJS js-file
        $this->getPageRenderer()->addJsFile($this->getPathToLibrary('videojs/video-js/video.js'));
        // Add videoJS css-file
        $this->getPageRenderer()->addCssFile($this->getPathToLibrary('videojs/video-js/video-js.css'));
        // Add extended videoJS control bar
        $this->getPageRenderer()->addJsFile($this->getPathToLibrary('videojs/video-js/controls/control-bar.js'));
        $this->getPageRenderer()->addCssFile($this->getPathToLibrary('videojs/video-js/controls/control-bar.css'));
        // Build Flash configuration
        $player = isset($typeConf['player.']) ? $this->cObj->stdWrap($typeConf['player'], $typeConf['player.']) : $typeConf['player'];
        if (!$player) {
            $player = $prefix . $this->getPathToLibrary('flowplayer/flowplayer-3.2.18.swf');
        } elseif (strpos($player, 'EXT:') === 0) {
            $player = $prefix . $GLOBALS['TSFE']->tmpl->getFileName($player);
        }
        $installUrl = isset($conf['installUrl.']) ? $this->cObj->stdWrap($conf['installUrl'], $conf['installUrl.']) : $conf['installUrl'];
        if (!$installUrl) {
            $installUrl = $prefix . $this->getPathToLibrary('flowplayer/expressinstall.swf');
        } elseif (strpos($installUrl, 'EXT:') === 0) {
            $installUrl = $prefix . $GLOBALS['TSFE']->tmpl->getFileName($installUrl);
        }
        $flashVersion = isset($conf['flashVersion.']) ? $this->cObj->stdWrap($conf['flashVersion'], $conf['flashVersion.']) : $conf['flashVersion'];
        if (!$flashVersion) {
            $flashVersion = array(9, 115);
        }
        $flashConfiguration = array('src' => $player, 'expressInstall' => $installUrl, 'version' => $flashVersion, 'onFail' => '###ONFAIL###');
        $flashDownloadUrl = 'http://www.adobe.com/go/getflashplayer';
        $onFail = 'function()  {
			if (!(flashembed.getVersion()[0] > 0)) {
				var message = "<p>" + "' . $GLOBALS['TSFE']->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:media.needFlashPlugin') . '" + "</p>" + "<p>" + "<a href=\\"' . $flashDownloadUrl . '\\">' . $GLOBALS['TSFE']->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:media.downloadFlash') . '</a>" + "</p>";
				document.getElementById("' . $replaceElementIdString . '_flash_install_info").innerHTML = "<div class=\\"message\\">" + message + "</div>";
			}
		}';
        $flashConfiguration = json_encode($flashConfiguration);
        $flashConfiguration = str_replace('"###ONFAIL###"', $onFail, $flashConfiguration);
        $filename = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
        if ($filename) {
            if (strpos($filename, '://') !== false) {
                $conf['flashvars.']['url'] = $filename;
            } else {
                if ($prefix) {
                    $conf['flashvars.']['url'] = $prefix . $filename;
                } else {
                    $conf['flashvars.']['url'] = str_repeat('../', substr_count($player, '/')) . $filename;
                }
            }
        }
        if (is_array($conf['sources'])) {
            foreach ($conf['sources'] as $key => $source) {
                if (strpos($source, '://') === false) {
                    $conf['sources'][$key] = $prefix . $source;
                }
            }
        }
        if (is_array($conf['audioSources'])) {
            foreach ($conf['audioSources'] as $key => $source) {
                if (strpos($source, '://') === false) {
                    $conf['audioSources'][$key] = $prefix . $source;
                }
            }
        }
        if (isset($conf['audioFallback']) && strpos($conf['audioFallback'], '://') === false) {
            $conf['audioFallback'] = $prefix . $conf['audioFallback'];
        }
        if (isset($conf['caption']) && strpos($conf['caption'], '://') === false) {
            $conf['caption'] = $prefix . $conf['caption'];
        }
        // Write calculated values in conf for the hook
        $conf['player'] = $player ?: $filename;
        $conf['installUrl'] = $installUrl;
        $conf['filename'] = $conf['flashvars.']['url'];
        $conf['prefix'] = $prefix;
        // merge with default parameters
        $conf['flashvars.'] = array_merge((array) $typeConf['default.']['flashvars.'], (array) $conf['flashvars.']);
        $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
        $conf['attributes.'] = array_merge((array) $typeConf['default.']['attributes.'], (array) $conf['attributes.']);
        $conf['embedParams'] = 'flashvars, params, attributes';
        // Hook for manipulating the conf array, it's needed for some players like flowplayer
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'])) {
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'] as $classRef) {
                GeneralUtility::callUserFunction($classRef, $conf, $this);
            }
        }
        // Flowplayer config
        $flowplayerVideoConfig = array();
        $flowplayerAudioConfig = array();
        if (is_array($conf['flashvars.']) && is_array($typeConf['mapping.']['flashvars.'])) {
            ArrayUtility::remapArrayKeys($conf['flashvars.'], $typeConf['mapping.']['flashvars.']);
        } else {
            $conf['flashvars.'] = array();
        }
        $conf['videoflashvars'] = $conf['flashvars.'];
        $conf['audioflashvars'] = $conf['flashvars.'];
        $conf['audioflashvars']['url'] = $conf['audioFallback'];
        // Render video sources
        $videoSources = '';
        if (is_array($conf['sources'])) {
            foreach ($conf['sources'] as $source) {
                $fileinfo = GeneralUtility::split_fileref($source);
                $mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
                $videoSources .= '<source src="' . $source . '"' . ($mimeType ? ' type="' . $mimeType . '"' : '') . ' />' . LF;
            }
        }
        // Render audio sources
        $audioSources = '';
        if (is_array($conf['audioSources'])) {
            foreach ($conf['audioSources'] as $source) {
                $fileinfo = GeneralUtility::split_fileref($source);
                $mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
                $audioSources .= '<source src="' . $source . '"' . ($mimeType ? ' type="' . $mimeType . '"' : '') . ' />' . LF;
            }
        }
        // Configure captions
        if ($conf['type'] === 'video' && isset($conf['caption'])) {
            // Assemble captions track tag
            $videoCaptions = '<track id="' . $replaceElementIdString . '_captions_track" kind="captions" src="' . $conf['caption'] . '" default>' . LF;
            // Add videoJS extension for captions
            $this->getPageRenderer()->addJsFile($this->getPathToLibrary('videojs/video-js/controls/captions.js'));
            // Flowplayer captions
            $conf['videoflashvars']['captionUrl'] = $conf['caption'];
            // Flowplayer captions plugin configuration
            $flowplayerVideoConfig = array_merge_recursive($flowplayerVideoConfig, $this->flowplayerCaptionsConfig);
        }
        // Configure flowplayer audio fallback
        if (isset($conf['audioFallback'])) {
            $flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, $this->flowplayerAudioConfig);
        }
        // Configure audio description
        if ($conf['type'] == 'video') {
            if (is_array($conf['audioSources']) && !empty($conf['audioSources'])) {
                // Add videoJS audio description toggle
                $this->getPageRenderer()->addJsFile($this->getPathToLibrary('videojs/video-js/controls/audio-description.js'));
            }
            if (isset($conf['audioFallback'])) {
                // Audio description flowplayer config (remove controls)
                $flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, $this->flowplayerAudioDescriptionConfig);
            }
        }
        // Assemble Flowplayer configuration
        if (!empty($conf['videoflashvars'])) {
            $flowplayerVideoConfig = array_merge_recursive($flowplayerVideoConfig, array('clip' => $conf['videoflashvars']));
        }
        $flowplayerVideoJsonConfig = str_replace(array('"true"', '"false"'), array('true', 'false'), json_encode($flowplayerVideoConfig));
        if (!empty($conf['audioflashvars'])) {
            $flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, array('clip' => $conf['audioflashvars']));
        }
        $flowplayerAudioJsonConfig = str_replace(array('"true"', '"false"'), array('true', 'false'), json_encode($flowplayerAudioConfig));
        // Assemble param tags (required?)
        if (is_array($conf['params.']) && is_array($typeConf['mapping.']['params.'])) {
            ArrayUtility::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
        }
        $videoFlashParams = '';
        if (is_array($conf['params.'])) {
            foreach ($conf['params.'] as $name => $value) {
                $videoFlashParams .= '<param name="' . $name . '" value="' . $value . '" />' . LF;
            }
        }
        $audioFlashParams = $videoFlashParams;
        // Required param tags
        $videoFlashParams .= '<param name="movie" value="' . $player . '" />' . LF;
        $videoFlashParams .= '<param name="flashvars" value=\'config=' . $flowplayerVideoJsonConfig . '\' />' . LF;
        $audioFlashParams .= '<param name="movie" value="' . $player . '" />' . LF;
        $audioFlashParams .= '<param name="flashvars" value=\'config=' . $flowplayerAudioJsonConfig . '\' />' . LF;
        // Assemble audio/video tag attributes
        $attributes = '';
        if (is_array($conf['attributes.']) && is_array($typeConf['attributes.']['params.'])) {
            ArrayUtility::remapArrayKeys($conf['attributes.'], $typeConf['attributes.']['params.']);
        }
        foreach ($this->html5TagAttributes as $attribute) {
            if ($conf['attributes.'][$attribute] === 'true' || $conf['attributes.'][$attribute] === strtolower($attribute) || $conf['attributes.'][$attribute] === $attribute) {
                $attributes .= strtolower($attribute) . '="' . strtolower($attribute) . '" ';
            }
        }
        // Media dimensions
        $width = isset($conf['width.']) ? $this->cObj->stdWrap($conf['width'], $conf['width.']) : $conf['width'];
        if (!$width) {
            $width = $conf[$type . '.']['defaultWidth'];
        }
        $height = isset($conf['height.']) ? $this->cObj->stdWrap($conf['height'], $conf['height.']) : $conf['height'];
        if (!$height) {
            $height = $conf[$type . '.']['defaultHeight'];
        }
        // Alternate content
        $alternativeContent = isset($conf['alternativeContent.']) ? $this->cObj->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']) : $conf['alternativeContent'];
        // Render video
        if ($conf['type'] === 'video') {
            // add preview image, html5 poster attribute
            $sourceBasePath = substr($conf['sources'][1], 0, strrpos($conf['sources'][1], '.'));
            foreach (['.jpg', '.jpeg', '.png'] as $fileExtension) {
                $posterFilePath = $GLOBALS['TSFE']->tmpl->getFileName($sourceBasePath . $fileExtension);
                if (file_exists($posterFilePath)) {
                    $attributes .= ' poster="' . htmlspecialchars($posterFilePath) . '"';
                    break;
                }
            }
            if ($conf['preferFlashOverHtml5']) {
                // Flash with video tag fallback
                $conf['params.']['playerFallbackOrder'] = array('flash', 'html5');
                $flashDivContent = $videoFlashParams . LF . '<video id="' . $replaceElementIdString . '_video_js" class="video-js" ' . $attributes . 'controls="controls"  mediagroup="' . $replaceElementIdString . '" width="' . $width . '" height="' . $height . '">' . LF . $videoSources . $videoCaptions . $alternativeContent . LF . '</video>' . LF;
                $divContent = '
					<div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF . '<noscript>' . LF . '<object id="' . $replaceElementIdString . '_vjs_flash" type="application/x-shockwave-flash" data="' . $player . '" width="' . $width . '" height="' . $height . '">' . LF . $flashDivContent . '</object>' . LF . '</noscript>' . LF;
                $content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '_video" class="flashcontainer" style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $divContent . '</div>', $content);
            } else {
                // Video tag with Flash fallback
                $conf['params.']['playerFallbackOrder'] = array('html5', 'flash');
                $videoTagContent = $videoSources . $videoCaptions;
                if (isset($conf['videoflashvars']['url'])) {
                    $videoTagContent .= '
						<noscript>' . LF . '<object class="vjs-flash-fallback" id="' . $replaceElementIdString . '_vjs_flash_fallback" type="application/x-shockwave-flash" data="' . $player . '" width="' . $width . '" height="' . $height . '">' . LF . $videoFlashParams . LF . $alternativeContent . LF . '</object>' . LF . '</noscript>';
                }
                $divContent = '
					<div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF . '<video id="' . $replaceElementIdString . '_video_js" class="video-js" ' . $attributes . 'controls="controls" mediagroup="' . $replaceElementIdString . '" width="' . $width . '" height="' . $height . '">' . LF . $videoTagContent . '</video>';
                $content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '_video" class="video-js-box" style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $divContent . '</div>', $content);
            }
        }
        // Render audio
        if ($conf['type'] === 'audio' || $audioSources || isset($conf['audioFallback'])) {
            if ($conf['preferFlashOverHtml5']) {
                // Flash with audio tag fallback
                $flashDivContent = $audioFlashParams . LF . '<audio id="' . $replaceElementIdString . '_audio_element"' . $attributes . ($conf['type'] === 'video' ? ' mediagroup="' . $replaceElementIdString . 'style="position:absolute;left:-10000px;"' : ' controls="controls"') . ' style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $audioSources . $alternativeContent . LF . '</audio>' . LF;
                $divContent = ($conf['type'] === 'video' ? '' : '<div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF) . '<noscript>' . LF . '<object id="' . $replaceElementIdString . '_audio_flash" type="application/x-shockwave-flash" data="' . $player . '" width="' . ($conf['type'] === 'video' ? 0 : $width) . '" height="' . ($conf['type'] === 'video' ? 0 : $height) . '">' . LF . $flashDivContent . '</object>' . LF . '</noscript>' . LF;
                $audioContent = '<div id="' . $replaceElementIdString . '_audio_box" class="audio-flash-container" style="width:' . ($conf['type'] === 'video' ? 0 : $width) . 'px; height:' . ($conf['type'] === 'video' ? 0 : $height) . 'px;">' . LF . $divContent . '</div>';
            } else {
                // Audio tag with Flash fallback
                $audioTagContent = $audioSources;
                if (isset($conf['audioflashvars']['url'])) {
                    $audioTagContent .= '
						<noscript>' . LF . '<object class="audio-flash-fallback" id="' . $replaceElementIdString . '_audio_flash" type="application/x-shockwave-flash" data="' . $player . '" width="' . $width . '" height="' . $height . '">' . LF . $audioFlashParams . LF . $alternativeContent . LF . '</object>' . LF . '</noscript>';
                }
                $divContent = ($conf['type'] === 'video' ? '' : '<div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF) . '<audio id="' . $replaceElementIdString . '_audio_element" class="audio-element"' . $attributes . ($conf['type'] === 'video' ? ' mediagroup="' . $replaceElementIdString . '" style="position:absolute;left:-10000px;"' : ' controls="controls"') . '>' . LF . $audioTagContent . '</audio>' . LF . $audioSourcesEmbeddingJsScript;
                $audioContent = '<div id="' . $replaceElementIdString . '_audio_box" class="audio-box" style="width:' . ($conf['type'] === 'video' ? 0 : $width) . 'px; height:' . ($conf['type'] === 'video' ? 0 : $height) . 'px;">' . LF . $divContent . '</div>';
            }
            if ($conf['type'] === 'audio') {
                $content = str_replace('###SWFOBJECT###', $audioContent, $content);
            } else {
                $content .= LF . $audioContent;
            }
        }
        // Assemble inline JS code
        $videoJsSetup = '';
        $flowplayerHandlers = '';
        if ($conf['type'] === 'video') {
            // Assemble videoJS options
            $videoJsOptions = array();
            foreach ($this->videoJsOptions as $videoJsOption) {
                if (isset($conf['params.'][$videoJsOption])) {
                    $videoJsOptions[$videoJsOption] = $conf['params.'][$videoJsOption];
                }
            }
            $videoJsOptions = !empty($videoJsOptions) ? json_encode($videoJsOptions) : '{}';
            // videoJS setup and videoJS listeners for audio description synchronisation
            if ($audioSources || isset($conf['audioFallback'])) {
                $videoJsSetup = '
			var ' . $replaceElementIdString . '_video = VideoJS.setup("' . $replaceElementIdString . '_video_js", ' . $videoJsOptions . ');
			var ' . $replaceElementIdString . '_video_element = document.getElementById("' . $replaceElementIdString . '_video_js");
			var ' . $replaceElementIdString . '_audio_element = document.getElementById("' . $replaceElementIdString . '_audio_element");
			if (!!' . $replaceElementIdString . '_video_element && !!' . $replaceElementIdString . '_audio_element) {
				' . $replaceElementIdString . '_audio_element.muted = true;
				VideoJS.addListener(' . $replaceElementIdString . '_video_element, "pause", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").pause(); });
				VideoJS.addListener(' . $replaceElementIdString . '_video_element, "play", function () { try {document.getElementById("' . $replaceElementIdString . '_audio_element").currentTime = document.getElementById("' . $replaceElementIdString . '_video_js").currentTime} catch(e) {}; document.getElementById("' . $replaceElementIdString . '_audio_element").play(); });
				VideoJS.addListener(' . $replaceElementIdString . '_video_element, "seeked", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").currentTime = document.getElementById("' . $replaceElementIdString . '_video_js").currentTime; });
				VideoJS.addListener(' . $replaceElementIdString . '_video_element, "volumechange", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").volume = document.getElementById("' . $replaceElementIdString . '_video_js").volume; });
			}';
            } else {
                $videoJsSetup = '
			var ' . $replaceElementIdString . '_video = VideoJS.setup("' . $replaceElementIdString . '_video_js", ' . $videoJsOptions . ');
			';
            }
            // Prefer Flash or fallback to Flash
            $videoSourcesEmbedding = '';
            // If we have a video file for Flash
            if (isset($conf['filename'])) {
                // If we prefer Flash
                if ($conf['preferFlashOverHtml5']) {
                    $videoTagAssembly = '';
                    // Create "source" elements
                    if (is_array($conf['sources']) && !empty($conf['sources'])) {
                        foreach ($conf['sources'] as $source) {
                            $fileinfo = GeneralUtility::split_fileref($source);
                            $mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
                            $videoTagAssembly .= '
			' . $replaceElementIdString . '_video_js.appendChild($f.extend(document.createElement("source"), {
				src: "' . $source . '",
				type: "' . $mimeType . '"
			}));';
                        }
                        // Create "track" elements
                        if (isset($conf['caption'])) {
                            // Assemble captions track tag
                            // It will take a while before the captions are loaded and parsed...
                            $videoTagAssembly .= '
			var track  = document.createElement("track");
			track.setAttribute("src", "' . $conf['caption'] . '");
			track.setAttribute("id", "' . $replaceElementIdString . '_captions_track");
			track.setAttribute("kind", "captions");
			track.setAttribute("default", "default");
			' . $replaceElementIdString . '_video_js.appendChild(track);';
                        }
                        $videoTagAssembly .= '
			$f.extend(' . $replaceElementIdString . '_video_js, {
				id: "' . $replaceElementIdString . '_video_js",
				className: "video-js",
				controls: "controls",
				mediagroup: "' . $replaceElementIdString . '",
				preload: "none",
				width: "' . $width . '",
				height: "' . $height . '"
			});
			' . $replaceElementIdString . '_video.appendChild(' . $replaceElementIdString . '_video_js);
			' . $replaceElementIdString . '_video.className = "video-js-box";';
                        $videoTagAssembly .= $videoJsSetup;
                    }
                    $videoSourcesEmbedding = '
		var ' . $replaceElementIdString . '_video = document.getElementById("' . $replaceElementIdString . '_video");
		var ' . $replaceElementIdString . '_video_js = document.createElement("video");
		if (flashembed.getVersion()[0] > 0) {
				// Flash is available
			var videoPlayer = flowplayer("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ', ' . $flowplayerVideoJsonConfig . ').load();
			videoPlayer.onBeforeUnload(function () { return false; });
		} else if (!!' . $replaceElementIdString . '_video_js.canPlayType) {
				// Flash is not available: fallback to videoJS if video tag is supported
			' . $videoTagAssembly . '
		} else {
				// Neither Flash nor video is available: offer to install Flash
			flashembed("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ');
		}';
                } elseif (is_array($conf['sources'])) {
                    // HTML5 is the preferred rendering method
                    // Test whether the browser supports any of types of the provided sources
                    $supported = array();
                    foreach ($conf['sources'] as $source) {
                        $fileinfo = GeneralUtility::split_fileref($source);
                        $mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
                        $supported[] = $replaceElementIdString . '_videoTag.canPlayType("' . $mimeType . '") != ""';
                    }
                    // Testing whether the browser supports the video tag with any of the provided source types
                    // If no support, embed flowplayer
                    $videoSourcesEmbedding = '
		var ' . $replaceElementIdString . '_videoTag = document.createElement(\'video\');
		var ' . $replaceElementIdString . '_video_box = document.getElementById("' . $replaceElementIdString . '_video");
		if (' . $replaceElementIdString . '_video_box) {
			if (!' . $replaceElementIdString . '_videoTag || !' . $replaceElementIdString . '_videoTag.canPlayType || !(' . (!empty($supported) ? implode(' || ', $supported) : 'false') . ')) {
					// Avoid showing an empty video element
				if (document.getElementById("' . $replaceElementIdString . '_video_js")) {
					document.getElementById("' . $replaceElementIdString . '_video_js").style.display = "none";
				}
				if (flashembed.getVersion()[0] > 0) {
						// Flash is available
					var videoPlayer = flowplayer("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ', ' . $flowplayerVideoJsonConfig . ').load();
					videoPlayer.onBeforeUnload(function () { return false; });
				} else {
						// Neither Flash nor video is available: offer to install Flash
					flashembed("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ');
				}
			} else {' . $videoJsSetup . '
			}
		}';
                }
            }
        }
        // Audio fallback to Flash
        $audioSourcesEmbedding = '';
        // If we have an audio file for Flash
        if (isset($conf['audioFallback'])) {
            // If we prefer Flash in
            if ($conf['preferFlashOverHtml5']) {
                $audioTagAssembly = '';
                // Create "source" elements
                if (is_array($conf['audioSources']) && !empty($conf['audioSources'])) {
                    foreach ($conf['audioSources'] as $source) {
                        $fileinfo = GeneralUtility::split_fileref($source);
                        $mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
                        $audioTagAssembly .= '
		' . $replaceElementIdString . '_audio_element.appendChild($f.extend(document.createElement("source"), {
			src: "' . $source . '",
			type: "' . $mimeType . '"
		}));';
                    }
                    $audioTagAssembly .= '
		$f.extend(' . $replaceElementIdString . '_audio_element, {
			id: "' . $replaceElementIdString . '_audio_element",
			className: "audio-element",
			controls: "' . ($conf['type'] === 'video' ? '' : 'controls') . '",
			mediagroup: "' . $replaceElementIdString . '",
			preload: "none",
			width: "' . ($conf['type'] === 'video' ? 0 : $width) . 'px",
			height: "' . ($conf['type'] === 'video' ? 0 : $height) . 'px"
		});
		' . $replaceElementIdString . '_audio_box.appendChild(' . $replaceElementIdString . '_audio_element);
		' . $replaceElementIdString . '_audio_box.className = "audio-box";';
                }
                $audioSourcesEmbedding = '
		var ' . $replaceElementIdString . '_audio_box = document.getElementById("' . $replaceElementIdString . '_audio_box");
		var ' . $replaceElementIdString . '_audio_element = document.createElement("audio");
		if (flashembed.getVersion()[0] > 0) {
				// Flash is available
			var audioPlayer = flowplayer("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ', ' . $flowplayerAudioJsonConfig . ').load();
			audioPlayer.onBeforeUnload(function () { return false; });
			' . ($conf['type'] === 'video' ? 'audioPlayer.mute();' : '') . '
		} else if (!!' . $replaceElementIdString . '_audio_element.canPlayType) {
				// Flash is not available: fallback to audio element if audio tag is supported
			' . $audioTagAssembly . '
		} else {
				// Neither Flash nor audio is available: offer to install Flash if this is not an audio description of a video
			' . ($conf['type'] === 'video' ? '' : 'flashembed("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ');') . '
		}';
            } elseif (is_array($conf['audioSources'])) {
                // HTML5 is the preferred rendering method
                // Test whether the browser supports any of types of the provided sources
                $supported = array();
                foreach ($conf['audioSources'] as $source) {
                    $fileinfo = GeneralUtility::split_fileref($source);
                    $mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
                    $supported[] = $replaceElementIdString . '_audioTag.canPlayType("' . $mimeType . '") != ""';
                }
                // Testing whether the browser supports the audio tag with any of the provided source types
                // If no support, embed flowplayer
                $audioSourcesEmbedding = '
		var ' . $replaceElementIdString . '_audioTag = document.createElement(\'audio\');
		var ' . $replaceElementIdString . '_audio_box = document.getElementById("' . $replaceElementIdString . '_audio_box");
		if (' . $replaceElementIdString . '_audio_box) {
			if (!' . $replaceElementIdString . '_audioTag || !' . $replaceElementIdString . '_audioTag.canPlayType || !(' . (!empty($supported) ? implode(' || ', $supported) : 'false') . ')) {
					// Avoid showing an empty audio element
				if (document.getElementById("' . $replaceElementIdString . '_audio_element")) {
					document.getElementById("' . $replaceElementIdString . '_audio_element").style.display = "none";
				}
				if (flashembed.getVersion()[0] > 0) {
					var audioPlayer = flowplayer("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ', ' . $flowplayerAudioJsonConfig . ').load();
					audioPlayer.onBeforeUnload(function () { return false; });
					' . ($conf['type'] === 'video' ? 'audioPlayer.mute()' : '') . '
				} else {
						// Neither Flash nor audio is available: offer to install Flash if this is not an audio description of a video
					' . ($conf['type'] === 'video' ? '' : 'flashembed("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ');') . '
				}
			}
		}';
            }
            // Flowplayer eventHandlers for audio description synchronisation
            $flowplayerHandlers = '';
            if ($conf['type'] === 'video') {
                $flowplayerHandlers = '
		if (flashembed.getVersion()[0] > 0) {
				// Flash is available
			var videoPlayer = flowplayer("' . $replaceElementIdString . '_video");
			if (videoPlayer) {
					// Control audio description through video control bar
				videoPlayer.onVolume(function (volume) { flowplayer("' . $replaceElementIdString . '_audio_box").setVolume(volume); });
				videoPlayer.onMute(function () { flowplayer("' . $replaceElementIdString . '_audio_box").mute(); });
				videoPlayer.onUnmute(function () { flowplayer("' . $replaceElementIdString . '_audio_box").unmute(); });
				videoPlayer.onPause(function () { flowplayer("' . $replaceElementIdString . '_audio_box").pause(); });
				videoPlayer.onResume(function () { flowplayer("' . $replaceElementIdString . '_audio_box").resume(); });
				videoPlayer.onStart(function () { flowplayer("' . $replaceElementIdString . '_audio_box").play(); });
				videoPlayer.onStop(function () { flowplayer("' . $replaceElementIdString . '_audio_box").stop(); });
				videoPlayer.onSeek(function (clip, seconds) { flowplayer("' . $replaceElementIdString . '_audio_box").seek(seconds); });
					// Mute audio description on start
				flowplayer("' . $replaceElementIdString . '_audio_box").onStart(function () { this.mute()});
					// Audio description toggle
				var videoContainer = document.getElementById("' . $replaceElementIdString . '_video");
				var buttonContainer = document.createElement("div");
				$f.extend(buttonContainer, {
					id: "' . $replaceElementIdString . '_audio_description_toggle",
					className: "vjs-audio-description-control"
				});
				var button = document.createElement("div");
				buttonContainer.appendChild(button);
				buttonContainer.style.position = "relative";
				buttonContainer.style.left = (parseInt(' . $width . ', 10)-27) + "px";
				videoContainer.parentNode.insertBefore(buttonContainer, videoContainer.nextSibling);
				VideoJS.addListener(buttonContainer, "click", function () {
					var buttonContainer = document.getElementById("' . $replaceElementIdString . '_audio_description_toggle");
					var state = buttonContainer.getAttribute("data-state");
					if (state == "enabled") {
						buttonContainer.setAttribute("data-state", "disabled");
						flowplayer("' . $replaceElementIdString . '_audio_box").mute();
					} else {
						buttonContainer.setAttribute("data-state", "enabled");
						flowplayer("' . $replaceElementIdString . '_audio_box").unmute();
					}
				});
			}
		}';
            }
        }
        // Wrap up inline JS code
        $jsInlineCode = $audioSourcesEmbedding . $videoSourcesEmbedding . $flowplayerHandlers;
        if ($jsInlineCode) {
            $jsInlineCode = 'VideoJS.DOMReady(function(){' . $jsInlineCode . LF . '});';
        }
        $this->getPageRenderer()->addJsInlineCode($replaceElementIdString, $jsInlineCode);
        if (isset($conf['stdWrap.'])) {
            $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
        }
        return $content;
    }
示例#29
0
 /**
  * Check if an update is possible at all
  *
  * @param string $version The target version number
  * @return bool TRUE on success
  * @throws \TYPO3\CMS\Install\Status\Exception
  */
 public function checkPreConditions($version)
 {
     $success = true;
     $messages = array();
     /** @var StatusUtility $statusUtility */
     $statusUtility = $this->objectManager->get(StatusUtility::class);
     // Folder structure test: Update can be done only if folder structure returns no errors
     /** @var $folderStructureFacade \TYPO3\CMS\Install\FolderStructure\StructureFacade */
     $folderStructureFacade = $this->objectManager->get(DefaultFactory::class)->getStructure();
     $folderStructureErrors = $statusUtility->filterBySeverity($folderStructureFacade->getStatus(), 'error');
     $folderStructureWarnings = $statusUtility->filterBySeverity($folderStructureFacade->getStatus(), 'warning');
     if (!empty($folderStructureErrors) || !empty($folderStructureWarnings)) {
         $success = false;
         /** @var $message StatusInterface */
         $message = $this->objectManager->get(ErrorStatus::class);
         $message->setTitle('Automatic TYPO3 CMS core update not possible: Folder structure has errors or warnings');
         $message->setMessage('To perform an update, the folder structure of this TYPO3 CMS instance must' . ' stick to the conventions, or the update process could lead to unexpected' . ' results and may be hazardous to your system');
         $messages[] = $message;
     }
     // No core update on windows
     if (TYPO3_OS === 'WIN') {
         $success = false;
         /** @var $message StatusInterface */
         $message = $this->objectManager->get(ErrorStatus::class);
         $message->setTitle('Automatic TYPO3 CMS core update not possible: Update not supported on Windows OS');
         $messages[] = $message;
     }
     if ($success) {
         // Explicit write check to document root
         $file = PATH_site . StringUtility::getUniqueId('install-core-update-test-');
         $result = @touch($file);
         if (!$result) {
             $success = false;
             /** @var $message StatusInterface */
             $message = $this->objectManager->get(ErrorStatus::class);
             $message->setTitle('Automatic TYPO3 CMS core update not possible: No write access to document root');
             $message->setMessage('Could not write a file in path "' . PATH_site . '"!');
             $messages[] = $message;
         } else {
             unlink($file);
         }
         if (!$this->checkCoreFilesAvailable($version)) {
             // Explicit write check to upper directory of current core location
             $coreLocation = @realPath($this->symlinkToCoreFiles . '/../');
             $file = $coreLocation . '/' . StringUtility::getUniqueId('install-core-update-test-');
             $result = @touch($file);
             if (!$result) {
                 $success = false;
                 /** @var $message StatusInterface */
                 $message = $this->objectManager->get(ErrorStatus::class);
                 $message->setTitle('Automatic TYPO3 CMS core update not possible: No write access to TYPO3 CMS core location');
                 $message->setMessage('New TYPO3 CMS core should be installed in "' . $coreLocation . '", but this directory is not writable!');
                 $messages[] = $message;
             } else {
                 unlink($file);
             }
         }
     }
     if ($success && !$this->coreVersionService->isInstalledVersionAReleasedVersion()) {
         $success = false;
         /** @var $message StatusInterface */
         $message = $this->objectManager->get(ErrorStatus::class);
         $message->setTitle('Automatic TYPO3 CMS core update not possible: You are running a development version of TYPO3');
         $message->setMessage('Your current version is specified as ' . $this->coreVersionService->getInstalledVersion() . '.' . ' This is a development version and can not be updated automatically. If this is a "git"' . ' checkout, please update using git directly.');
         $messages[] = $message;
     }
     $this->messages = $messages;
     return $success;
 }
示例#30
0
 /**
  * @param string $name the field name
  * @param int $timestamp the unix timestamp
  * @param string $type [datetime, date, time, timesec, year]
  *
  * @return string
  */
 protected function getDateTimePickerField($name, $timestamp, $type)
 {
     $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '%H:%M %m-%d-%Y' : '%H:%M %d-%m-%Y';
     $value = $timestamp > 0 ? strftime($dateFormat, $timestamp) : '';
     $id = StringUtility::getUniqueId('dt_');
     $html = array();
     $html[] = '<div class="input-group" id="' . $id . '-wrapper">';
     $html[] = '		<input data-formengine-input-name="' . htmlspecialchars($name) . '" value="' . $value . '" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="' . htmlspecialchars($type) . '" data-date-offset="0" type="text" id="' . $id . '">';
     $html[] = '		<input name="' . htmlspecialchars($name) . '" value="' . (int) $timestamp . '" type="hidden">';
     $html[] = '		<span class="input-group-btn">';
     $html[] = '			<label class="btn btn-default" for="' . $id . '">';
     $html[] = '				<span class="fa fa-calendar"></span>';
     $html[] = '			</label>';
     $html[] = ' 	</span>';
     $html[] = '</div>';
     return implode(LF, $html);
 }