/** * @param string $headerContent * @param string $itemContent * @param array $row * @param boolean $drawItem * @return NULL */ public function renderPreview(&$headerContent, &$itemContent, array &$row, &$drawItem) { $fieldName = NULL; // every provider for tt_content will be asked to get a preview if ('shortcut' === $row['CType'] && FALSE === strpos($row['records'], ',')) { $itemContent = $this->createShortcutIcon($row) . $itemContent; } else { $itemContent = '<a name="c' . $row['uid'] . '"></a>' . $itemContent; } $providers = $this->configurationService->resolveConfigurationProviders('tt_content', $fieldName, $row); foreach ($providers as $provider) { /** @var ProviderInterface $provider */ list($previewHeader, $previewContent, $continueDrawing) = $provider->getPreview($row); if (FALSE === empty($previewHeader)) { $headerContent = $previewHeader . (FALSE === empty($headerContent) ? ': ' . $headerContent : ''); $drawItem = FALSE; } if (FALSE === empty($previewContent)) { $itemContent .= $previewContent; $drawItem = FALSE; } if (FALSE === $continueDrawing) { break; } } $this->attachAssets(); return NULL; }
/** * @return string */ public function indexAction() { $this->view->assign('grid', $this->grid); $this->view->assign('row', $this->row); $paths = $this->configurationService->getViewConfigurationForExtensionName('flux'); $templateRootPath = TRUE === isset($paths['templateRootPath']) ? $paths['templateRootPath'] : NULL; $templatePathAndFilename = ResolveUtility::resolveWidgetTemplateFileBasedOnTemplateRootPathAndEnvironment($templateRootPath); $this->view->setTemplatePathAndFilename($templatePathAndFilename); }
/** * Hook for generating dynamic FlexForm source code * * @param array $dataStructArray * @param array $conf * @param array $row * @param string $table * @param string $fieldName * @return void */ public function getFlexFormDS_postProcessDS(&$dataStructArray, $conf, &$row, $table, $fieldName) { if (empty($fieldName) === TRUE) { // Cast NULL if an empty but not-NULL field name was passed. This has significance to the Flux internals in // respect to which ConfigurationProvider(s) are returned. $fieldName = NULL; } $providers = $this->configurationService->resolveConfigurationProviders($table, $fieldName, $row); foreach ($providers as $provider) { $provider->postProcessDataStructure($row, $dataStructArray, $conf); } }
/** * @param string $sectionName * @param string $formName * @return Form|NULL */ public function getForm($sectionName = 'Configuration', $formName = 'form') { /** @var Form $form */ $form = $this->getStoredVariable(AbstractFormViewHelper::SCOPE, $formName, $sectionName); if (NULL !== $form && TRUE === isset($this->templatePathAndFilename)) { $form->setOption(Form::OPTION_TEMPLATEFILE, $this->templatePathAndFilename); $signature = ExtensionNamingUtility::getExtensionSignature($this->controllerContext->getRequest()->getControllerExtensionName()); $overrides = (array) $this->configurationService->getTypoScriptByPath('plugin.tx_' . $signature . '.forms.' . $form->getName()); $form->modify($overrides); } return $form; }
/** * @param integer $pageUid * @param integer $columnPosition * @param integer $relativeUid * @return array */ protected function getWhiteAndBlackListsFromPageAndContentColumn($pageUid, $columnPosition, $relativeUid) { $whitelist = array(); $blacklist = array(); // if a Provider is registered for the "pages" table, try to get a Grid from it. If the Grid // returned contains a Column which matches the desired colPos value, attempt to read a list // of allowed/denied content element types from it. $pageRecord = (array) $this->recordService->getSingle('pages', '*', $pageUid); $pageProviders = $this->configurationService->resolveConfigurationProviders('pages', NULL, $pageRecord); $this->appendToWhiteAndBlacklistFromProviders($pageProviders, $pageRecord, $whitelist, $blacklist, $columnPosition); // Detect what was clicked in order to create the new content element; decide restrictions // based on this. Returned parent UID and area name is either non-zero and string, or zero // and NULL when record is NOT inserted as child. list($parentRecordUid, $fluxAreaName) = $this->getAreaNameAndParentFromRelativeRecordOrDefaults($relativeUid); // if these variables now indicate that we are inserting content elements into a Flux-enabled content // area inside another content element, attempt to read allowed/denied content types from the // Grid returned by the Provider that applies to the parent element's type and configuration // (admitted, that's quite a mouthful - but it's not that different from reading the values from // a page template like above; it's the same principle). if (0 < $parentRecordUid && FALSE === empty($fluxAreaName)) { $parentRecord = (array) $this->recordService->getSingle('tt_content', '*', $parentRecordUid); $contentProviders = $this->configurationService->resolveConfigurationProviders('tt_content', NULL, $parentRecord); $this->appendToWhiteAndBlacklistFromProviders($contentProviders, $parentRecord, $whitelist, $blacklist, NULL, $fluxAreaName); } // White/blacklist filtering. If whitelist contains elements, filter the list // of possible types by whitelist first. Then apply the blacklist, removing // any element types recorded herein. $whitelist = array_unique($whitelist); $blacklist = array_unique($blacklist); return array($whitelist, $blacklist); }
/** * @param ProviderInterface $provider * @param array $row * @param Form $form * @return string|NULL */ protected function renderPreviewSection(ProviderInterface $provider, array $row, Form $form = NULL) { $templatePathAndFilename = $provider->getTemplatePathAndFilename($row); if (NULL === $templatePathAndFilename) { return NULL; } $extensionKey = $provider->getExtensionKey($row); $paths = $provider->getTemplatePaths($row); $flexformVariables = $provider->getFlexFormValues($row); $templateVariables = $provider->getTemplateVariables($row); $variables = RecursiveArrayUtility::merge($templateVariables, $flexformVariables); $variables['row'] = $row; $variables['record'] = $row; if (TRUE === is_object($form)) { $formLabel = $form->getLabel(); $label = LocalizationUtility::translate($formLabel, $extensionKey); $variables['label'] = $label; } $templatePaths = new TemplatePaths($paths); $viewContext = new ViewContext($templatePathAndFilename, $extensionKey, self::CONTROLLER_NAME); $viewContext->setTemplatePaths($templatePaths); $viewContext->setVariables($variables); $view = $this->configurationService->getPreparedExposedTemplateView($viewContext); $existingContentObject = $this->configurationManager->getContentObject(); $contentObject = new ContentObjectRenderer(); $contentObject->start($row, $provider->getTableName($row)); $this->configurationManager->setContentObject($contentObject); $previewContent = $view->renderStandaloneSection(self::PREVIEW_SECTION, $variables, TRUE); $this->configurationManager->setContentObject($existingContentObject); $previewContent = trim($previewContent); return $previewContent; }
/** * @param string $pattern Pattern to be resolved * @param boolean $bubbleControllerAndSubpackage if TRUE, then we successively split off parts from "@controller" and "@subpackage" until both are empty. * @param boolean $formatIsOptional if TRUE, then half of the resulting strings will have ."@format" stripped off, and the other half will have it. * @return array unix style path */ protected function expandGenericPathPattern($pattern, $bubbleControllerAndSubpackage, $formatIsOptional) { $extensionKey = $this->controllerContext->getRequest()->getControllerExtensionKey(); $configurations = $this->configurationService->getViewConfigurationForExtensionName($extensionKey); $pathOverlayConfigurations = $this->buildPathOverlayConfigurations($configurations); $paths = parent::expandGenericPathPattern($pattern, $bubbleControllerAndSubpackage, $formatIsOptional); foreach ($pathOverlayConfigurations as $overlayPaths) { if (FALSE === empty($overlayPaths['templateRootPath'])) { $templateRootPath = $overlayPaths['templateRootPath']; $this->setTemplateRootPath($templateRootPath); } if (FALSE === empty($overlayPaths['partialRootPath'])) { $partialRootPath = $overlayPaths['partialRootPath']; $this->setPartialRootPath($partialRootPath); } if (FALSE === empty($overlayPaths['layoutRootPath'])) { $layoutRootPath = $overlayPaths['layoutRootPath']; $this->setLayoutRootPath($layoutRootPath); } $subset = parent::expandGenericPathPattern($pattern, $bubbleControllerAndSubpackage, $formatIsOptional); $paths = array_merge($paths, $subset); } $paths = array_unique($paths); $paths = array_reverse($paths); $paths = $this->trimPathStringRecursive($paths); return $paths; }
/** * @param string $extensionName * @param string $controllerName * @param string $actionName * @return boolean */ protected function hasSubControllerActionOnForeignController($extensionName, $controllerName, $actionName) { $potentialControllerClassName = $this->configurationService->getResolver()->resolveFluxControllerClassNameByExtensionKeyAndAction($extensionName, $actionName, $controllerName); $isForeign = $extensionName !== $this->extensionName; $isValidController = class_exists($potentialControllerClassName); return TRUE === $isForeign && TRUE === $isValidController; }
/** * Render method * @param string $table * @param string $field * @param integer $uid * @param array $record * @param string $as * @return array * @throws Exception */ public function render($table, $field, $uid = NULL, $record = NULL, $as = NULL) { if (NULL === $uid && NULL !== $record && TRUE === isset($record['uid'])) { $uid = $record['uid']; } if (TRUE === isset(self::$dataCache[$uid . $table . $field])) { $dataArray = self::$dataCache[$uid . $table . $field]; } elseif (TRUE === isset($GLOBALS['TCA'][$table]) && TRUE === isset($GLOBALS['TCA'][$table]['columns'][$field])) { if (NULL === $record) { $record = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid,' . $field, $table, sprintf('uid=%d', $uid)); } if (FALSE === $record) { throw new Exception(sprintf('Either table "%s", field "%s" or record with uid %d do not exist and you did not manually ' . 'provide the "row" attribute.', $table, $field, $uid), 1358679983); } $providers = $this->configurationService->resolveConfigurationProviders($table, $field, $record); if (0 === count($providers)) { $dataArray = $this->configurationService->convertFlexFormContentToArray($record[$field]); } else { $dataArray = array(); foreach ($providers as $provider) { $data = (array) $provider->getFlexFormValues($record); $dataArray = RecursiveArrayUtility::merge($dataArray, $data); } } self::$dataCache[$uid . $table . $field] = $dataArray; } else { throw new Exception('Invalid table:field "' . $table . ':' . $field . '" - does not exist in TYPO3 TCA.', 1387049117); } if (NULL !== $as) { if ($this->templateVariableContainer->exists($as)) { $backupVariable = $this->templateVariableContainer->get($as); $this->templateVariableContainer->remove($as); } $this->templateVariableContainer->add($as, $dataArray); $content = $this->renderChildren(); $this->templateVariableContainer->remove($as); if (TRUE === isset($backupVariable)) { $this->templateVariableContainer->add($as, $backupVariable); } return $content; } return $dataArray; }
/** * @return string */ public function indexAction() { $workspaceVersionOfRecord = $this->workspacesAwareRecordService->getSingle('tt_content', '*', $this->row['uid']); $this->view->assign('grid', $this->grid); $this->view->assign('row', $workspaceVersionOfRecord); $this->view->assign('colPosFluxContent', ContentService::COLPOS_FLUXCONTENT); $paths = $this->configurationService->getViewConfigurationForExtensionName('flux'); $templateRootPath = TRUE === isset($paths['templateRootPath']) ? $paths['templateRootPath'] : NULL; $templatePathAndFilename = ResolveUtility::resolveWidgetTemplateFileBasedOnTemplateRootPathAndEnvironment($templateRootPath); $this->view->setTemplatePathAndFilename($templatePathAndFilename); }
/** * @param array $providers * @param array $record * @param string $field * @return array */ protected function readDataArrayFromProvidersOrUsingDefaultMethod(array $providers, $record, $field) { if (0 === count($providers)) { $dataArray = $this->configurationService->convertFlexFormContentToArray($record[$field]); } else { $dataArray = array(); foreach ($providers as $provider) { $data = (array) $provider->getFlexFormValues($record); $dataArray = RecursiveArrayUtility::merge($dataArray, $data); } } return $dataArray; }
/** * @return void */ protected function initializeViewObject() { $row = $this->getRecord(); $templatePathAndFilename = $this->provider->getTemplatePathAndFilename($row); $extensionKey = $this->provider->getExtensionKey($row); $extensionName = ExtensionNamingUtility::getExtensionName($extensionKey); $controller = $this->request->getControllerName(); $this->view = $this->configurationService->getPreparedExposedTemplateView($extensionKey, $controller, $this->setup, $this->data); $this->request->setControllerExtensionName($extensionName); $this->view->setControllerContext($this->controllerContext); if (FALSE === empty($templatePathAndFilename)) { $this->view->setTemplatePathAndFilename($templatePathAndFilename); } }
/** * Perform various cleanup operations upon clearing cache * * @param string $command * @return void */ public function clearCacheCommand($command) { if (TRUE === self::$cachesCleared) { return; } $tables = array_keys($GLOBALS['TCA']); foreach ($tables as $table) { $providers = $this->configurationService->resolveConfigurationProviders($table, NULL); foreach ($providers as $provider) { /** @var $provider ProviderInterface */ $provider->clearCacheCommand($command); } } self::$cachesCleared = TRUE; }
/** * @param array $providers * @param array $record * @param string $field * @return array */ protected static function readDataArrayFromProvidersOrUsingDefaultMethod(array $providers, $record, $field) { if (0 === count($providers)) { $lang = static::getCurrentLanguageName(); $pointer = static::getCurrentValuePointerName(); $dataArray = static::$configurationService->convertFlexFormContentToArray($record[$field], NULL, $lang, $pointer); } else { $dataArray = array(); /** @var ProviderInterface $provider */ foreach ($providers as $provider) { $data = (array) $provider->getFlexFormValues($record); $dataArray = RecursiveArrayUtility::merge($dataArray, $data); } } return $dataArray; }
/** * @return ProviderInterface[] */ public function loadTypoScriptConfigurationProviderInstances() { $providerConfigurations = (array) $this->configurationService->getTypoScriptByPath('plugin.tx_flux.providers'); $providers = array(); foreach ($providerConfigurations as $name => $providerSettings) { $className = 'FluidTYPO3\\Flux\\Provider\\Provider'; if (TRUE === isset($providerSettings['className']) && TRUE === class_exists($providerSettings['className'])) { $className = $providerSettings['className']; } /** @var ProviderInterface $provider */ $provider = $this->objectManager->get($className); $provider->setName($name); $provider->loadSettings($providerSettings); $providers[$name] = $provider; } return $providers; }
/** * Hook for generating dynamic FlexForm source code. * * NOTE: patches data structure resolving in a way that solves * a regression in the TYPO3 core when dealing with IRRE AJAX * requests (in which the database record is no longer fetched * by the controller). This patches not only data structure * resolving for Flux data structures but indeed any data * structure built using hooks or involving user functions which * require the entire record (but when using hooks, supports * only extensions which are loaded AFTER or depend on Flux). * * @param array $dataStructArray * @param array $conf * @param array $row * @param string $table * @param string $fieldName * @return void */ public function getFlexFormDS_postProcessDS(&$dataStructArray, $conf, &$row, $table, $fieldName) { if (empty($fieldName) === TRUE) { // Cast NULL if an empty but not-NULL field name was passed. This has significance to the Flux internals in // respect to which ConfigurationProvider(s) are returned. $fieldName = NULL; } if (!empty($fieldName) && !isset($row[$fieldName])) { // Patch required (possibly temporary). Due to changes in TYPO3 in the new FormEngine we must fetch the // database record at this point when the record is incomplete, which happens when attempting to render // IRRE records. The reason is that the controller that creates the HTML does not fetch the record any // more - and that the AJAX request contains only the UID. So, we fetch the record here to ensure it // contains the necessary fields. DOES NOT WORK FOR NEW RECORDS - SEE COMMENTS BELOW. $row = $this->recordService->getSingle($table, '*', $row['uid']); } $defaultDataSourceCacheIdentifier = $table . '_' . $fieldName . '_' . sha1(serialize($conf)); if (!$row) { // In the case that the database record cannot be fetched we are dealing with a new or otherwise deleted // or unidentifiable record. This happens primarily when AJAX requests are made to render IRRE records // without the parent record having been saved first. To accommodate this case we have to be slightly // creative and store a "default" data source definition which is identified based on a checksum of the // configuration provided. Whenever we are then unable to fetch a record, we can at least attempt to // locate a default data source in previously cached content. NB: we enforce a VERY high cache lifetime // and continually refresh it every time it is possible to render a new DS that can serve as default. $dataStructArray = (array) $this->cache->get($defaultDataSourceCacheIdentifier); } else { if (FALSE === is_array($dataStructArray)) { $dataStructArray = array(); } $providers = $this->configurationService->resolveConfigurationProviders($table, $fieldName, $row); foreach ($providers as $provider) { $provider->postProcessDataStructure($row, $dataStructArray, $conf); } if (empty($dataStructArray)) { $dataStructArray = array('ROOT' => array('el' => array())); } $evaluationParameters = array(); $this->cache->set($defaultDataSourceCacheIdentifier, $this->recursivelyEvaluateClosures($dataStructArray, $evaluationParameters), array(), time() + 31536000); } // Trigger TCEforms dimension patching only if required by TYPO3 version according to CompatibilityRegistry. if (CompatibilityRegistry::get('FluidTYPO3\\Flux\\Backend\\DynamicFlexForm::NEEDS_TCEFORMS_WRAPPER')) { $dataStructArray = $this->patchTceformsWrapper($dataStructArray); } }
/** * @param integer $relativeRecordUid * @param string $fluxAreaName * @param array $whitelist * @param array $blacklist * @return array */ protected function readWhitelistAndBlacklistFromColumn($relativeRecordUid, $fluxAreaName, $whitelist, $blacklist) { $relativeRecord = $this->recordService->getSingle('tt_content', '*', (int) $relativeRecordUid); $contentProviders = $this->configurationService->resolveConfigurationProviders('tt_content', NULL, $relativeRecord); foreach ($contentProviders as $contentProvider) { $grid = $contentProvider->getGrid($relativeRecord); if (NULL === $grid) { continue; } foreach ($grid->getRows() as $row) { foreach ($row->getColumns() as $column) { if ($column->getName() === $fluxAreaName) { list($whitelist, $blacklist) = $this->appendToWhiteAndBlacklistFromComponent($column, $whitelist, $blacklist); } } } } return array($whitelist, $blacklist); }
/** * @param string $headerContent * @param string $itemContent * @param array $row * @param boolean $drawItem * @return NULL */ public function renderPreview(&$headerContent, &$itemContent, array &$row, &$drawItem) { $children = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,tx_flux_column', 'tt_content', "tx_flux_parent = '" . $row['uid'] . "'"); $checksum = sha1(json_encode($row)) . '-' . sha1(json_encode($children)); $cacheFilePathAndfilenameHeader = GeneralUtility::getFileAbsFileName('typo3temp/flux-preview-' . $checksum . '-header.tmp'); $cacheFilePathAndfilenameContent = GeneralUtility::getFileAbsFileName('typo3temp/flux-preview-' . $checksum . '-content.tmp'); $drawItem = TRUE; if (TRUE === file_exists($cacheFilePathAndfilenameHeader) && TRUE === file_exists($cacheFilePathAndfilenameContent)) { $itemContent = file_get_contents($cacheFilePathAndfilenameContent); $headerContent = file_get_contents($cacheFilePathAndfilenameHeader); $drawItem = FALSE; $this->attachStyle(); return NULL; } $fieldName = NULL; // every provider for tt_content will be asked to get a preview if ('shortcut' === $row['CType'] && FALSE === strpos($row['records'], ',')) { $itemContent = $this->createShortcutIcon($row) . $itemContent; } else { $itemContent = '<a name="c' . $row['uid'] . '"></a>' . $itemContent; } $providers = $this->configurationService->resolveConfigurationProviders('tt_content', $fieldName, $row); foreach ($providers as $provider) { /** @var ProviderInterface $provider */ list($previewHeader, $previewContent, $continueDrawing) = $provider->getPreview($row); if (FALSE === empty($previewHeader)) { $headerContent = $previewHeader . (FALSE === empty($headerContent) ? ': ' . $headerContent : ''); $drawItem = FALSE; GeneralUtility::writeFile($cacheFilePathAndfilenameHeader, $headerContent); } if (FALSE === empty($previewContent)) { $itemContent .= $previewContent; $drawItem = FALSE; GeneralUtility::writeFile($cacheFilePathAndfilenameContent, $itemContent); } if (FALSE === $continueDrawing) { break; } } $this->attachStyle(); return NULL; }
/** * @param integer $uid * @return array */ public function getContentAreasDefinedInContentElement($uid) { $uid = (int) $uid; $record = $this->recordService->getSingle('tt_content', '*', $uid); /** @var $providers ProviderInterface[] */ $providers = $this->fluxService->resolveConfigurationProviders('tt_content', NULL, $record); $columns = array(); foreach ($providers as $provider) { $grid = $provider->getGrid($record); if (TRUE === empty($grid)) { continue; } $gridConfiguration = $grid->build(); foreach ($gridConfiguration['rows'] as $row) { foreach ($row['columns'] as $column) { array_push($columns, array($column['label'] . ' (' . $column['name'] . ')', $column['name'])); } } } return array_unique($columns, SORT_REGULAR); }
/** * @param integer $uid * @return array */ public function getContentAreasDefinedInContentElement($uid) { $uid = (int) $uid; $record = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'tt_content', "uid = '" . $uid . "'"); /** @var $providers ProviderInterface[] */ $providers = $this->fluxService->resolveConfigurationProviders('tt_content', NULL, $record); $columns = array(); foreach ($providers as $provider) { $grid = $provider->getGrid($record); if (TRUE === empty($grid)) { continue; } $gridConfiguration = $grid->build(); foreach ($gridConfiguration['rows'] as $row) { foreach ($row['columns'] as $column) { foreach ($column['areas'] as $area) { array_push($columns, array($area['label'] . ' (' . $area['name'] . ')', $area['name'])); } } } } return array_unique($columns); }
/** * @param array $parameters * @param PageLayoutView|DatabaseRecordList $caller * @return string */ public function addSubIcon(array $parameters, $caller = NULL) { $this->attachAssets(); list($table, $uid, $record) = $parameters; $icon = NULL; if (NULL !== $caller) { $record = NULL === $record && 0 < $uid ? BackendUtility::getRecord($table, $uid) : $record; $cacheIdentity = $table . $uid . sha1(serialize($record)); // filter 1: icon must not already be cached and both record and caller must be provided. if (TRUE === $this->cache->has($cacheIdentity)) { $icon = $this->cache->get($cacheIdentity); } elseif (NULL !== $record) { $field = $this->detectFirstFlexTypeFieldInTableFromPossibilities($table, array_keys($record)); // filter 2: table must have one field defined as "flex" and record must include it. if (NULL !== $field && TRUE === isset($record[$field])) { // we check the cache here because at this point, the cache key is decidedly // unique and we have not yet consulted the (potentially costly) Provider. $provider = $this->fluxService->resolvePrimaryConfigurationProvider($table, $field, $record); // filter 3: a Provider must be resolved for the record. if (NULL !== $provider) { $form = $provider->getForm((array) $record); if (NULL !== $form) { $icon = MiscellaneousUtility::getIconForTemplate($form); if (NULL !== $icon) { $label = trim($form->getLabel()); $icon = '<img width="16" height="16" src="' . $icon . '" alt="' . $label . '" title="' . $label . '" class="" />'; $icon = sprintf($this->templates['iconWrapper'], $icon); } } } } $this->cache->set($cacheIdentity, $icon); } } return $icon; }
/** * @param array $items * @param \TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController * @return void */ public function manipulateWizardItems(&$items, &$parentObject) { $whitelist = array(); $blacklist = array(); // if a Provider is registered for the "pages" table, try to get a Grid from it. If the Grid // returned contains a Column which matches the desired colPos value, attempt to read a list // of allowed/denied content element types from it. $pageRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'pages', "uid = '" . $parentObject->id . "'"); $pageProviders = $this->configurationService->resolveConfigurationProviders('pages', NULL, $pageRecord); foreach ($pageProviders as $pageProvider) { $grid = $pageProvider->getGrid($pageRecord); if (NULL === $grid) { continue; } foreach ($grid->getRows() as $row) { foreach ($row->getColumns() as $column) { if ($column->getColumnPosition() === $parentObject->colPos) { list($whitelist, $blacklist) = $this->appendToWhiteAndBlacklistFromComponent($column, $whitelist, $blacklist); } } } } // Detect what was clicked in order to create the new content element; decide restrictions // based on this. $defaultValues = GeneralUtility::_GET('defVals'); if (0 > $parentObject->uid_pid) { // pasting after another element means we should try to resolve the Flux content relation // from that element instead of GET parameters (clicked: "create new" icon after other element) $relativeRecordUid = abs($parentObject->uid_pid); $relativeRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'tt_content', "uid = '" . $relativeRecordUid . "'"); $fluxAreaName = $relativeRecord['tx_flux_column']; } elseif (TRUE === isset($defaultValues['tt_content']['tx_flux_column'])) { // attempt to read the target Flux content area from GET parameters (clicked: "create new" icon // in top of nested Flux content area $fluxAreaName = $defaultValues['tt_content']['tx_flux_column']; $relativeRecordUid = $defaultValues['tt_content']['tx_flux_parent']; } // if these variables now indicate that we are inserting content elements into a Flux-enabled content // area inside another content element, attempt to read allowed/denied content types from the // Grid returned by the Provider that applies to the parent element's type and configuration // (admitted, that's quite a mouthful - but it's not that different from reading the values from // a page template like above; it's the same principle). if (0 < $relativeRecordUid && FALSE === empty($fluxAreaName)) { $relativeRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'tt_content', "uid = '" . $relativeRecordUid . "'"); $contentProviders = $this->configurationService->resolveConfigurationProviders('tt_content', NULL, $relativeRecord); foreach ($contentProviders as $contentProvider) { $grid = $contentProvider->getGrid($relativeRecord); if (NULL === $grid) { continue; } foreach ($grid->getRows() as $row) { foreach ($row->getColumns() as $column) { foreach ($column->getAreas() as $area) { if ($area->getName() === $fluxAreaName) { list($whitelist, $blacklist) = $this->appendToWhiteAndBlacklistFromComponent($area, $whitelist, $blacklist); } } } } } } // White/blacklist filtering. If whitelist contains elements, filter the list // of possible types by whitelist first. Then apply the blacklist, removing // any element types recorded herein. $whitelist = array_unique($whitelist); $blacklist = array_unique($blacklist); if (0 < count($whitelist)) { foreach ($items as $name => $item) { if (FALSE !== strpos($name, '_') && FALSE === in_array($item['tt_content_defValues']['CType'], $whitelist)) { unset($items[$name]); } } } if (0 < count($blacklist)) { foreach ($blacklist as $contentElementType) { foreach ($items as $name => $item) { if ($item['tt_content_defValues']['CType'] === $contentElementType) { unset($items[$name]); } } } } // Finally, loop through the items list and clean up any tabs with zero element types inside. $preserveHeaders = array(); foreach ($items as $name => $item) { if (FALSE !== strpos($name, '_')) { array_push($preserveHeaders, reset(explode('_', $name))); } } foreach ($items as $name => $item) { if (FALSE === strpos($name, '_') && FALSE === in_array($name, $preserveHeaders)) { unset($items[$name]); } } }
/** * @test * @dataProvider getSortObjectsTestValues * @param array $input * @param string $sortBy * @param string $direction * @param array $expectedOutput */ public function testSortObjectsByProperty($input, $sortBy, $direction, $expectedOutput) { $service = new FluxService(); $sorted = $service->sortObjectsByProperty($input, $sortBy, $direction); $this->assertEquals($expectedOutput, $sorted); }
/** * Get preview chunks - header and content - as * array(string $headerContent, string $previewContent, boolean $continueRendering) * * Default implementation renders the Preview section from the template * file that the actual Provider returns for $row, using paths also * determined by $row. Example: fluidcontent's Provider returns files * and paths based on selected "Fluid Content type" and inherits and * uses this method to render a Preview from the template file in the * specific path. This default implementation expects the TYPO3 core * to render the default header, so it returns NULL as $headerContent. * * @param array $row The record data to be analysed for variables to use in a rendered preview * @return array */ public function getPreview(array $row) { $templateSource = $this->getTemplateSource($row); if (TRUE === empty($templateSource)) { return array(NULL, NULL, TRUE); } $extensionKey = $this->getExtensionKey($row); $flexformVariables = $this->getFlexFormValues($row); $templateVariables = $this->getTemplateVariables($row); $variables = RecursiveArrayUtility::merge($templateVariables, $flexformVariables); $paths = $this->getTemplatePaths($row); $form = $this->getForm($row); $formLabel = $form->getLabel(); $label = LocalizationUtility::translate($formLabel, $extensionKey); $variables['label'] = $label; $variables['row'] = $row; $variables['record'] = $row; $view = $this->configurationService->getPreparedExposedTemplateView($extensionKey, 'Content', $paths, $variables); $view->setTemplateSource($templateSource); $existingContentObject = $this->configurationManager->getContentObject(); $contentObject = new ContentObjectRenderer(); $contentObject->start($row, $this->getTableName($row)); $this->configurationManager->setContentObject($contentObject); $previewContent = $view->renderStandaloneSection('Preview', $variables); $this->configurationManager->setContentObject($existingContentObject); $previewContent = trim($previewContent); $headerContent = NULL; return array($headerContent, $previewContent, empty($previewContent)); }
/** * @param string $extension * @param string $contentType * @param string $version * @return string */ public function getIconFromVersion($extension, $contentType, $version = NULL) { $extensionKey = ExtensionNamingUtility::getExtensionKey($extension); $templatePathAndFilename = $this->resolveTemplateFileForVariant($extensionKey, $contentType, $extension, $version); $paths = $this->getViewConfigurationForExtensionName($extensionKey); $templatePaths = new TemplatePaths($paths); $viewContext = new ViewContext($templatePathAndFilename, $extensionKey); $viewContext->setTemplatePaths($templatePaths); $viewContext->setSectionName('Configuration'); $form = FluxService::getFormFromTemplateFile($viewContext); if (FALSE === $form instanceof Form) { return ''; } else { return MiscellaneousUtility::getIconForTemplate($form); } }
/** * @param array $row * @return array */ public function getTemplatePaths(array $row) { $paths = $this->templatePaths; if (FALSE === is_array($paths)) { $extensionKey = $this->getExtensionKey($row); $extensionKey = ExtensionNamingUtility::getExtensionKey($extensionKey); if (FALSE === empty($extensionKey)) { $paths = $this->configurationService->getViewConfigurationForExtensionName($extensionKey); } } if (TRUE === is_array($paths)) { $paths = PathUtility::translatePath($paths); } return $paths; }