Ejemplo n.º 1
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;
    }
Ejemplo n.º 2
0
 /**
  * Type fetching method, based on the type that softRefParserObj returns
  *
  * @param array $value Reference properties
  * @param string $type Current type
  * @param string $key Validator hook name
  * @return string fetched type
  */
 public function fetchType($value, $type, $key)
 {
     if (StringUtility::beginswith(strtolower($value['tokenValue']), 'file:')) {
         $type = 'file';
     }
     return $type;
 }
Ejemplo n.º 3
0
 /**
  * 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;
 }
Ejemplo n.º 4
0
 /**
  * Unset all additional properties of test classes to help PHP
  * garbage collection. This reduces memory footprint with lots
  * of tests.
  *
  * If owerwriting tearDown() in test classes, please call
  * parent::tearDown() at the end. Unsetting of own properties
  * is not needed this way.
  *
  * @throws \RuntimeException
  * @return void
  */
 protected function tearDown()
 {
     // Unset properties of test classes to safe memory
     $reflection = new \ReflectionObject($this);
     foreach ($reflection->getProperties() as $property) {
         $declaringClass = $property->getDeclaringClass()->getName();
         if (!$property->isStatic() && $declaringClass !== \TYPO3\CMS\Core\Tests\UnitTestCase::class && $declaringClass !== \TYPO3\CMS\Core\Tests\BaseTestCase::class && strpos($property->getDeclaringClass()->getName(), 'PHPUnit_') !== 0) {
             $propertyName = $property->getName();
             unset($this->{$propertyName});
         }
     }
     unset($reflection);
     // Delete registered test files and directories
     foreach ($this->testFilesToDelete as $absoluteFileName) {
         $absoluteFileName = GeneralUtility::fixWindowsFilePath(PathUtility::getCanonicalPath($absoluteFileName));
         if (!GeneralUtility::validPathStr($absoluteFileName)) {
             throw new \RuntimeException('tearDown() cleanup: Filename contains illegal characters', 1410633087);
         }
         if (!StringUtility::beginsWith($absoluteFileName, PATH_site . 'typo3temp/')) {
             throw new \RuntimeException('tearDown() cleanup:  Files to delete must be within typo3temp/', 1410633412);
         }
         // file_exists returns false for links pointing to not existing targets, so handle links before next check.
         if (@is_link($absoluteFileName) || @is_file($absoluteFileName)) {
             unlink($absoluteFileName);
         } elseif (@is_dir($absoluteFileName)) {
             GeneralUtility::rmdir($absoluteFileName, true);
         } else {
             throw new \RuntimeException('tearDown() cleanup: File, link or directory does not exist', 1410633510);
         }
     }
     $this->testFilesToDelete = array();
 }
Ejemplo n.º 5
0
 /**
  * @param array|NULL $backendUser
  * @param int $size
  * @param bool $showIcon
  * @return string
  */
 public function render(array $backendUser = NULL, $size = 32, $showIcon = FALSE)
 {
     $size = (int) $size;
     if (!is_array($backendUser)) {
         $backendUser = $this->getBackendUser()->user;
     }
     $image = parent::render($backendUser, $size, $showIcon);
     if (!StringUtility::beginsWith($image, '<span class="avatar"><span class="avatar-image"></span>') || empty($backendUser['email'])) {
         return $image;
     }
     $cachedFilePath = PATH_site . 'typo3temp/t3gravatar/';
     $cachedFileName = sha1($backendUser['email'] . $size) . '.jpg';
     if (!file_exists($cachedFilePath . $cachedFileName)) {
         $gravatar = 'https://www.gravatar.com/avatar/' . md5(strtolower($backendUser['email'])) . '?s=' . $size . '&d=404';
         $gravatarImage = GeneralUtility::getUrl($gravatar);
         if (empty($gravatarImage)) {
             return $image;
         }
         GeneralUtility::writeFileToTypo3tempDir($cachedFileName, $gravatarImage);
     }
     // Icon
     $icon = '';
     if ($showIcon) {
         $icon = '<span class="avatar-icon">' . IconUtility::getSpriteIconForRecord('be_users', $backendUser) . '</span>';
     }
     $relativeFilePath = PathUtility::getRelativePath(PATH_typo3, $cachedFilePath);
     return '<span class="avatar"><span class="avatar-image">' . '<img src="' . $relativeFilePath . $cachedFileName . '" width="' . $size . '" height="' . $size . '" /></span>' . $icon . '</span>';
 }
 /**
  * Resolve placeholders for input/text fields. Placeholders that are simple
  * strings will be returned unmodified. Placeholders beginning with __row are
  * being resolved, possibly traversing multiple tables.
  *
  * @param array $result
  * @return array
  */
 public function addData(array $result)
 {
     foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
         // Placeholders are only valid for input and text type fields
         if ($fieldConfig['config']['type'] !== 'input' && $fieldConfig['config']['type'] !== 'text' || !isset($fieldConfig['config']['placeholder'])) {
             continue;
         }
         // Resolve __row|field type placeholders
         if (StringUtility::beginsWith($fieldConfig['config']['placeholder'], '__row|')) {
             // split field names into array and remove the __row indicator
             $fieldNameArray = array_slice(GeneralUtility::trimExplode('|', $fieldConfig['config']['placeholder'], true), 1);
             $result['processedTca']['columns'][$fieldName]['config']['placeholder'] = $this->getPlaceholderValue($fieldNameArray, $result);
         }
         // Resolve placeholders from language files
         if (StringUtility::beginsWith($fieldConfig['config']['placeholder'], 'LLL:')) {
             $result['processedTca']['columns'][$fieldName]['config']['placeholder'] = $this->getLanguageService()->sl($fieldConfig['config']['placeholder']);
         }
         // Remove empty placeholders
         if (empty($fieldConfig['config']['placeholder'])) {
             unset($result['processedTca']['columns'][$fieldName]['config']['placeholder']);
             continue;
         }
     }
     return $result;
 }
    /**
     * 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;
    }
Ejemplo n.º 8
0
 /**
  * @param Icon $icon
  * @param array $options
  * @return string
  * @throws \InvalidArgumentException
  */
 protected function generateInlineMarkup(Icon $icon, array $options)
 {
     if (empty($options['source'])) {
         throw new \InvalidArgumentException('The option "source" is required and must not be empty', 1440754980);
     }
     $source = $options['source'];
     if (StringUtility::beginsWith($source, 'EXT:') || !StringUtility::beginsWith($source, '/')) {
         $source = GeneralUtility::getFileAbsFileName($source);
     }
     return $this->getInlineSvg($source);
 }
Ejemplo n.º 9
0
 /**
  * @param Icon $icon
  * @param array $options
  * @return string
  * @throws \InvalidArgumentException
  */
 protected function generateMarkup(Icon $icon, array $options)
 {
     if (empty($options['source'])) {
         throw new \InvalidArgumentException('[' . $icon->getIdentifier() . '] The option "source" is required and must not be empty', 1440754980);
     }
     $source = $options['source'];
     if (StringUtility::beginsWith($source, 'EXT:') || !StringUtility::beginsWith($source, '/')) {
         $source = GeneralUtility::getFileAbsFileName($source);
     }
     $source = PathUtility::getAbsoluteWebPath($source);
     return '<img src="' . htmlspecialchars($source) . '" width="' . $icon->getDimension()->getWidth() . '" height="' . $icon->getDimension()->getHeight() . '" />';
 }
 /**
  * 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;
 }
Ejemplo n.º 11
0
 /**
  * Add the given icon to the TCA table type
  *
  * @param string $table
  * @param string $type
  * @param string $icon
  */
 public static function addTcaTypeIcon($table, $type, $icon)
 {
     if (GeneralUtility::compat_version('7.0')) {
         $fullIconPath = substr(PathUtility::getAbsoluteWebPath($icon), 1);
         if (StringUtility::endsWith(strtolower($fullIconPath), 'svg')) {
             $iconProviderClass = 'TYPO3\\CMS\\Core\\Imaging\\IconProvider\\SvgIconProvider';
         } else {
             $iconProviderClass = 'TYPO3\\CMS\\Core\\Imaging\\IconProvider\\BitmapIconProvider';
         }
         /** @var IconRegistry $iconRegistry */
         $iconRegistry = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Imaging\\IconRegistry');
         $iconIdentifier = 'tcarecords-' . $table . '-' . $type;
         $iconRegistry->registerIcon($iconIdentifier, $iconProviderClass, ['source' => $fullIconPath]);
         $GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$type] = $iconIdentifier;
     } else {
         $fullIconPath = str_replace('../typo3/', '', $icon);
         SpriteManager::addTcaTypeIcon('tt_content', $type, $fullIconPath);
     }
 }
Ejemplo n.º 12
0
 /**
  * Return the default value of a field formatted to match the native MySQL SQL dialect
  *
  * @param array $fieldDefinition
  * @return mixed
  */
 protected function getNativeDefaultValue($fieldDefinition)
 {
     if (!$fieldDefinition['has_default']) {
         $returnValue = null;
     } elseif ($fieldDefinition['type'] === 'SERIAL' && substr($fieldDefinition['default_value'], 0, 7) === 'nextval') {
         $returnValue = null;
     } elseif ($fieldDefinition['type'] === 'varchar') {
         // Strip character class and unquote string
         if (StringUtility::beginsWith($fieldDefinition['default_value'], 'NULL::')) {
             $returnValue = null;
         } else {
             $returnValue = str_replace("\\'", "'", preg_replace('/\'(.*)\'(::(?:character\\svarying|varchar|character|char|text)(?:\\(\\d+\\))?)?\\z/', '\\1', $fieldDefinition['default_value']));
         }
     } elseif (substr($fieldDefinition['type'], 0, 3) === 'int') {
         $returnValue = (int) preg_replace('/^\\(?(\\-?\\d+)\\)?$/', '\\1', $fieldDefinition['default_value']);
     } else {
         $returnValue = $fieldDefinition['default_value'];
     }
     return $returnValue;
 }
Ejemplo n.º 13
0
 /**
  * @param array $data
  * @return array
  */
 protected function decryptDataArray(array $data)
 {
     foreach ($data as $key => $value) {
         if (empty($value)) {
             continue;
         }
         if (is_array($value)) {
             $data[$key] = $this->decryptDataArray($value);
             continue;
         }
         if (!StringUtility::beginsWith($value, 'rsa:')) {
             continue;
         }
         $decryptedValue = $this->getBackend()->decrypt($this->getKey(), substr($value, 4));
         if ($decryptedValue !== null) {
             $data[$key] = $decryptedValue;
         }
     }
     return $data;
 }
 /**
  * Determine which fields are required to render the placeholders and
  * add those to the list of columns that must be processed by the next
  * data providers.
  *
  * @param array $result
  * @return array
  */
 public function addData(array $result)
 {
     foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
         // Placeholders are only valid for input and text type fields
         if ($fieldConfig['config']['type'] !== 'input' && $fieldConfig['config']['type'] !== 'text' || !isset($fieldConfig['config']['placeholder'])) {
             continue;
         }
         // Process __row|field type placeholders
         if (StringUtility::beginsWith($fieldConfig['config']['placeholder'], '__row|')) {
             // split field names into array and remove the __row indicator
             $fieldNameArray = array_slice(GeneralUtility::trimExplode('|', $fieldConfig['config']['placeholder'], true), 1);
             // only the first field is required to be processed as it's the one referring to
             // the current record. All other columns will be resolved in a later pass through
             // the related records.
             if (!empty($fieldNameArray[0])) {
                 $result['columnsToProcess'][] = $fieldNameArray[0];
             }
         }
     }
     return $result;
 }
Ejemplo n.º 15
0
 /**
  * Generates the JumpURL for the given parameters.
  *
  * @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::processUrlModifiers()
  * @param string $context The context in which the URL is generated (e.g. "typolink").
  * @param string $url The URL that should be processed.
  * @param array $configuration The link configuration.
  * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObjectRenderer The calling content object renderer.
  * @param bool $keepProcessing If this is set to FALSE no further hooks will be processed after the current one.
  * @return string
  */
 public function process($context, $url, array $configuration, ContentObjectRenderer $contentObjectRenderer, &$keepProcessing)
 {
     if (!$this->isEnabled($context, $configuration)) {
         return $url;
     }
     $this->contentObjectRenderer = $contentObjectRenderer;
     // Strip the absRefPrefix from the URLs.
     $urlPrefix = (string) $this->getTypoScriptFrontendController()->absRefPrefix;
     if ($urlPrefix !== '' && StringUtility::beginsWith($url, $urlPrefix)) {
         $url = substr($url, strlen($urlPrefix));
     }
     // Make sure the slashes in the file URL are not encoded.
     if ($context === UrlProcessorInterface::CONTEXT_FILE) {
         $url = str_replace('%2F', '/', rawurlencode(rawurldecode($url)));
     }
     $url = $this->build($url, isset($configuration['jumpurl.']) ? $configuration['jumpurl.'] : array());
     // Now add the prefix again if it was not added by a typolink call already.
     if ($urlPrefix !== '' && !StringUtility::beginsWith($url, $urlPrefix)) {
         $url = $urlPrefix . $url;
     }
     return $url;
 }
 /**
  * @param string $status
  * @param string $table
  * @param int $id
  * @param array $fieldArray
  * @param DataHandler $parentObject
  */
 public function processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, $parentObject)
 {
     if ($table !== 'be_groups' || $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'] !== 'explicitAllow') {
         return;
     }
     $backendUserGroup = BackendUtility::getRecord($table, $id, 'explicit_allowdeny');
     $explicitAllowDenyFields = GeneralUtility::trimExplode(',', $backendUserGroup['explicit_allowdeny']);
     foreach ($explicitAllowDenyFields as $value) {
         if (StringUtility::beginsWith($value, 'tt_content:list_type:')) {
             if (!in_array('tt_content:CType:list:ALLOW', $explicitAllowDenyFields, true)) {
                 /** @var $flashMessage FlashMessage */
                 $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:error.backendUserGroupListTypeError.message'), $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:error.backendUserGroupListTypeError.header'), FlashMessage::WARNING, true);
                 /** @var $flashMessageService FlashMessageService */
                 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
                 /** @var $defaultFlashMessageQueue FlashMessageQueue */
                 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
                 $defaultFlashMessageQueue->enqueue($flashMessage);
             }
             return;
         }
     }
 }
Ejemplo n.º 17
0
 /**
  * Checks if this is the handler for the given link
  *
  * The handler may store this information locally for later usage.
  *
  * @param array $linkParts Link parts as returned from TypoLinkCodecService
  *
  * @return bool
  */
 public function canHandleLink(array $linkParts)
 {
     if (!$linkParts['url']) {
         return false;
     }
     $url = rawurldecode($linkParts['url']);
     if (StringUtility::beginsWith($url, 'file:') && !StringUtility::beginsWith($url, 'file://')) {
         $rel = substr($url, 5);
         try {
             // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
             $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel);
             if (is_a($fileOrFolderObject, $this->expectedClass)) {
                 $this->linkParts = $linkParts;
                 $this->linkParts['url'] = $rel;
                 $this->linkParts['name'] = $fileOrFolderObject->getName();
                 return true;
             }
         } catch (FileDoesNotExistException $e) {
         }
     }
     return false;
 }
Ejemplo n.º 18
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));
     }
 }
Ejemplo n.º 19
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;
 }
Ejemplo n.º 20
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;
    }
 /**
  * Adds a module path to $GLOBALS['TBE_MODULES'] for used with the module dispatcher, index.php
  * Used only for modules that are not placed in the main/sub menu hierarchy by the traditional mechanism of addModule()
  * Examples for this is context menu functionality (like import/export) which runs as an independent module through index.php
  * FOR USE IN ext_tables.php FILES
  * Example:  \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath('xMOD_tximpexp', \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY).'app/');
  *
  * @param string $name The name of the module, refer to conf.php of the module.
  * @param string $path The absolute path to the module directory inside of which "index.php" and "conf.php" is found.
  * @return void
  * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use routeTarget or dispatched modules instead.
  */
 public static function addModulePath($name, $path)
 {
     GeneralUtility::logDeprecatedFunction();
     if (StringUtility::beginsWith($path, 'EXT:')) {
         list($extensionKey, $relativePath) = explode('/', substr($path, 4), 2);
         $path = ExtensionManagementUtility::extPath($extensionKey) . $relativePath;
     }
     $GLOBALS['TBE_MODULES']['_PATHS'][$name] = $path;
 }
Ejemplo n.º 22
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;
    }
Ejemplo n.º 23
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;
    }
Ejemplo n.º 24
0
 /**
  * Determines whether the URL is on the current host and belongs to the
  * current TYPO3 installation. The scheme part is ignored in the comparison.
  *
  * @param string $url URL to be checked
  * @return bool Whether the URL belongs to the current TYPO3 installation
  */
 protected function isInCurrentDomain($url)
 {
     $urlWithoutSchema = preg_replace('#^https?://#', '', $url);
     $siteUrlWithoutSchema = preg_replace('#^https?://#', '', GeneralUtility::getIndpEnv('TYPO3_SITE_URL'));
     return StringUtility::beginsWith($urlWithoutSchema . '/', GeneralUtility::getIndpEnv('HTTP_HOST') . '/') && StringUtility::beginsWith($urlWithoutSchema, $siteUrlWithoutSchema);
 }
Ejemplo n.º 25
0
    /**
     * Creating the module output.
     *
     * @throws \UnexpectedValueException
     * @return void
     */
    public function main()
    {
        $lang = $this->getLanguageService();
        $this->content .= '<form action="" name="editForm" id="NewContentElementController"><input type="hidden" name="defValues" value="" />';
        if ($this->id && $this->access) {
            // Init position map object:
            $posMap = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\ContentCreationPagePositionMap::class);
            $posMap->cur_sys_language = $this->sys_language;
            // If a column is pre-set:
            if (isset($this->colPos)) {
                if ($this->uid_pid < 0) {
                    $row = array();
                    $row['uid'] = abs($this->uid_pid);
                } else {
                    $row = '';
                }
                $this->onClickEvent = $posMap->onClickInsertRecord($row, $this->colPos, '', $this->uid_pid, $this->sys_language);
            } else {
                $this->onClickEvent = '';
            }
            // ***************************
            // Creating content
            // ***************************
            $this->content .= '<h1>' . $lang->getLL('newContentElement') . '</h1>';
            // Wizard
            $wizardItems = $this->wizardArray();
            // Wrapper for wizards
            $this->elementWrapper['section'] = array('', '');
            // Hook for manipulating wizardItems, wrapper, onClickEvent etc.
            if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'])) {
                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'] as $classData) {
                    $hookObject = GeneralUtility::getUserObj($classData);
                    if (!$hookObject instanceof NewContentElementWizardHookInterface) {
                        throw new \UnexpectedValueException('$hookObject must implement interface ' . NewContentElementWizardHookInterface::class, 1227834741);
                    }
                    $hookObject->manipulateWizardItems($wizardItems, $this);
                }
            }
            // Add document inline javascript
            $this->moduleTemplate->addJavaScriptCode('NewContentElementWizardInlineJavascript', '
				function goToalt_doc() {	//
					' . $this->onClickEvent . '
				}

				if(top.refreshMenu) {
					top.refreshMenu();
				} else {
					top.TYPO3ModuleMenu.refreshMenu();
				}');
            $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
            // Traverse items for the wizard.
            // An item is either a header or an item rendered with a radio button and title/description and icon:
            $cc = $key = 0;
            $menuItems = array();
            foreach ($wizardItems as $k => $wInfo) {
                if ($wInfo['header']) {
                    $menuItems[] = array('label' => htmlspecialchars($wInfo['header']), 'content' => $this->elementWrapper['section'][0]);
                    $key = count($menuItems) - 1;
                } else {
                    $content = '';
                    if (!$this->onClickEvent) {
                        // Radio button:
                        $oC = 'document.editForm.defValues.value=unescape(' . GeneralUtility::quoteJSvalue(rawurlencode($wInfo['params'])) . ');goToalt_doc();' . (!$this->onClickEvent ? 'window.location.hash=\'#sel2\';' : '');
                        $content .= '<div class="media-left"><input type="radio" name="tempB" value="' . htmlspecialchars($k) . '" onclick="' . htmlspecialchars($oC) . '" /></div>';
                        // Onclick action for icon/title:
                        $aOnClick = 'document.getElementsByName(\'tempB\')[' . $cc . '].checked=1;' . $oC . 'return false;';
                    } else {
                        $aOnClick = "document.editForm.defValues.value=unescape('" . rawurlencode($wInfo['params']) . "');goToalt_doc();" . (!$this->onClickEvent ? "window.location.hash='#sel2';" : '');
                    }
                    if (isset($wInfo['icon'])) {
                        GeneralUtility::deprecationLog('The PageTS-Config: mod.wizards.newContentElement.wizardItems.*.elements.*.icon' . ' is deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8.' . ' Register your icon in IconRegistry::registerIcon and use the new setting:' . ' mod.wizards.newContentElement.wizardItems.*.elements.*.iconIdentifier');
                        $wInfo['iconIdentifier'] = 'content-' . $k;
                        $icon = $wInfo['icon'];
                        if (StringUtility::beginsWith($icon, '../typo3conf/ext/')) {
                            $icon = str_replace('../typo3conf/ext/', 'EXT:', $icon);
                        }
                        if (!StringUtility::beginsWith($icon, 'EXT:') && strpos($icon, '/') !== false) {
                            $icon = TYPO3_mainDir . GeneralUtility::resolveBackPath($wInfo['icon']);
                        }
                        $iconRegistry->registerIcon($wInfo['iconIdentifier'], BitmapIconProvider::class, array('source' => $icon));
                    }
                    $icon = $this->moduleTemplate->getIconFactory()->getIcon($wInfo['iconIdentifier'])->render();
                    $menuItems[$key]['content'] .= '
						<div class="media">
							<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">
								' . $content . '
								<div class="media-left">
									' . $icon . '
								</div>
								<div class="media-body">
									<strong>' . htmlspecialchars($wInfo['title']) . '</strong>' . '<br />' . nl2br(htmlspecialchars(trim($wInfo['description']))) . '</div>
							</a>
						</div>';
                    $cc++;
                }
            }
            // Add closing section-tag
            foreach ($menuItems as $key => $val) {
                $menuItems[$key]['content'] .= $this->elementWrapper['section'][1];
            }
            // Add the wizard table to the content, wrapped in tabs
            $code = '<p>' . $lang->getLL('sel1', 1) . '</p>' . $this->moduleTemplate->getDynamicTabMenu($menuItems, 'new-content-element-wizard');
            $this->content .= !$this->onClickEvent ? '<h2>' . $lang->getLL('1_selectType', true) . '</h2>' : '';
            $this->content .= '<div>' . $code . '</div>';
            // If the user must also select a column:
            if (!$this->onClickEvent) {
                // Add anchor "sel2"
                $this->content .= '<div><a name="sel2"></a></div>';
                // Select position
                $code = '<p>' . $lang->getLL('sel2', 1) . '</p>';
                // Load SHARED page-TSconfig settings and retrieve column list from there, if applicable:
                $colPosArray = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getColPosListItemsParsed', $this->id, $this);
                $colPosIds = array_column($colPosArray, 1);
                // Removing duplicates, if any
                $colPosList = implode(',', array_unique(array_map('intval', $colPosIds)));
                // Finally, add the content of the column selector to the content:
                $code .= $posMap->printContentElementColumns($this->id, 0, $colPosList, 1, $this->R_URI);
                $this->content .= '<h2>' . $lang->getLL('2_selectPosition', true) . '</h2><div>' . $code . '</div>';
            }
        } else {
            // In case of no access:
            $this->content = '';
            $this->content .= '<h1>' . $lang->getLL('newContentElement') . '</h1>';
        }
        $this->content .= '</form>';
        // Setting up the buttons and markers for docheader
        $this->getButtons();
    }
Ejemplo n.º 26
0
 /**
  * Detects if a control button (up/down/around/delete) has been pressed for an item and accordingly it will
  * manipulate the internal TABLECFG array
  *
  * @return void
  * @internal
  */
 public function changeFunc()
 {
     if ($this->TABLECFG['col_remove']) {
         $kk = key($this->TABLECFG['col_remove']);
         $cmd = 'col_remove';
     } elseif ($this->TABLECFG['col_add']) {
         $kk = key($this->TABLECFG['col_add']);
         $cmd = 'col_add';
     } elseif ($this->TABLECFG['col_start']) {
         $kk = key($this->TABLECFG['col_start']);
         $cmd = 'col_start';
     } elseif ($this->TABLECFG['col_end']) {
         $kk = key($this->TABLECFG['col_end']);
         $cmd = 'col_end';
     } elseif ($this->TABLECFG['col_left']) {
         $kk = key($this->TABLECFG['col_left']);
         $cmd = 'col_left';
     } elseif ($this->TABLECFG['col_right']) {
         $kk = key($this->TABLECFG['col_right']);
         $cmd = 'col_right';
     } elseif ($this->TABLECFG['row_remove']) {
         $kk = key($this->TABLECFG['row_remove']);
         $cmd = 'row_remove';
     } elseif ($this->TABLECFG['row_add']) {
         $kk = key($this->TABLECFG['row_add']);
         $cmd = 'row_add';
     } elseif ($this->TABLECFG['row_top']) {
         $kk = key($this->TABLECFG['row_top']);
         $cmd = 'row_top';
     } elseif ($this->TABLECFG['row_bottom']) {
         $kk = key($this->TABLECFG['row_bottom']);
         $cmd = 'row_bottom';
     } elseif ($this->TABLECFG['row_up']) {
         $kk = key($this->TABLECFG['row_up']);
         $cmd = 'row_up';
     } elseif ($this->TABLECFG['row_down']) {
         $kk = key($this->TABLECFG['row_down']);
         $cmd = 'row_down';
     } else {
         $kk = '';
         $cmd = '';
     }
     if ($cmd && MathUtility::canBeInterpretedAsInteger($kk)) {
         if (StringUtility::beginsWith($cmd, 'row_')) {
             switch ($cmd) {
                 case 'row_remove':
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_add':
                     for ($a = 1; $a <= $this->numNewRows; $a++) {
                         // Checking if set: The point is that any new row between existing rows
                         // will be TRUE after one row is added while if rows are added in the bottom
                         // of the table there will be no existing rows to stop the addition of new rows
                         // which means it will add up to $this->numNewRows rows then.
                         if (!isset($this->TABLECFG['c'][$kk + $a])) {
                             $this->TABLECFG['c'][$kk + $a] = array();
                         } else {
                             break;
                         }
                     }
                     break;
                 case 'row_top':
                     $this->TABLECFG['c'][1] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_bottom':
                     $this->TABLECFG['c'][10000000] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_up':
                     $this->TABLECFG['c'][$kk - 3] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_down':
                     $this->TABLECFG['c'][$kk + 3] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
             }
             ksort($this->TABLECFG['c']);
         }
         if (StringUtility::beginsWith($cmd, 'col_')) {
             foreach ($this->TABLECFG['c'] as $cAK => $value) {
                 switch ($cmd) {
                     case 'col_remove':
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_add':
                         $this->TABLECFG['c'][$cAK][$kk + 1] = '';
                         break;
                     case 'col_start':
                         $this->TABLECFG['c'][$cAK][1] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_end':
                         $this->TABLECFG['c'][$cAK][1000000] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_left':
                         $this->TABLECFG['c'][$cAK][$kk - 3] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_right':
                         $this->TABLECFG['c'][$cAK][$kk + 3] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                 }
                 ksort($this->TABLECFG['c'][$cAK]);
             }
         }
     }
     // Convert line breaks to <br /> tags:
     foreach ($this->TABLECFG['c'] as $a => $value) {
         foreach ($this->TABLECFG['c'][$a] as $b => $value2) {
             $this->TABLECFG['c'][$a][$b] = str_replace(LF, '<br />', str_replace(CR, '', $this->TABLECFG['c'][$a][$b]));
         }
     }
 }
Ejemplo n.º 27
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;
 }
Ejemplo n.º 28
0
 /**
  * called from the typoLink() function
  *
  * does the magic to split the full "typolink" string like "15,13 _blank myclass &more=1"
  * into separate parts
  *
  * @param string $linkText The string (text) to link
  * @param string $mixedLinkParameter destination data like "15,13 _blank myclass &more=1" used to create the link
  * @param array $configuration TypoScript configuration
  * @return array | string
  * @see typoLink()
  */
 protected function resolveMixedLinkParameter($linkText, $mixedLinkParameter, &$configuration = array())
 {
     $linkParameter = null;
     // Link parameter value = first part
     $linkParameterParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($mixedLinkParameter);
     // Check for link-handler keyword:
     list($linkHandlerKeyword, $linkHandlerValue) = explode(':', $linkParameterParts['url'], 2);
     if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword] && (string) $linkHandlerValue !== '') {
         $linkHandlerObj = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]);
         if (method_exists($linkHandlerObj, 'main')) {
             return $linkHandlerObj->main($linkText, $configuration, $linkHandlerKeyword, $linkHandlerValue, $mixedLinkParameter, $this);
         }
     }
     // Resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
     if ($linkHandlerKeyword === 'file' && !StringUtility::beginsWith($linkParameterParts['url'], 'file://')) {
         try {
             $fileOrFolderObject = $this->getResourceFactory()->retrieveFileOrFolderObject($linkHandlerValue);
             // Link to a folder or file
             if ($fileOrFolderObject instanceof File || $fileOrFolderObject instanceof Folder) {
                 $linkParameter = $fileOrFolderObject->getPublicUrl();
             } else {
                 $linkParameter = null;
             }
         } catch (\RuntimeException $e) {
             // Element wasn't found
             $linkParameter = null;
         } catch (ResourceDoesNotExistException $e) {
             // Resource was not found
             return $linkText;
         }
         // Disallow direct javascript: links
     } elseif (strtolower(trim($linkHandlerKeyword)) === 'javascript') {
         return $linkText;
     } else {
         $linkParameter = $linkParameterParts['url'];
     }
     // additional parameters that need to be set
     if ($linkParameterParts['additionalParams'] !== '') {
         $forceParams = $linkParameterParts['additionalParams'];
         // params value
         $configuration['additionalParams'] .= $forceParams[0] === '&' ? $forceParams : '&' . $forceParams;
     }
     return array('href' => $linkParameter, 'target' => $linkParameterParts['target'], 'class' => $linkParameterParts['class'], 'title' => $linkParameterParts['title']);
 }
Ejemplo n.º 29
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;
 }
Ejemplo n.º 30
0
 /**
  * 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);
 }