/** * 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 === $record && NULL === $as) { $record = $this->renderChildren(); } if (NULL === $uid && NULL !== $record && TRUE === isset($record['uid'])) { $uid = $record['uid']; } if (TRUE === isset($GLOBALS['TCA'][$table]) && TRUE === isset($GLOBALS['TCA'][$table]['columns'][$field])) { if (NULL === $record) { $record = $this->recordService->getSingle($table, 'uid,' . $field, $uid); } if (NULL === $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 "record" attribute.', $table, $field, $uid), 1358679983); } $providers = $this->configurationService->resolveConfigurationProviders($table, $field, $record); $dataArray = $this->readDataArrayFromProvidersOrUsingDefaultMethod($providers, $record, $field); } 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; }
/** * Postprocesses a selected backend layout * * @param integer $pageUid Starting page UID in the rootline (this current page) * @param array $backendLayout The backend layout which was detected from page id * @return NULL|void */ public function postProcessBackendLayout(&$pageUid, &$backendLayout) { try { $record = $this->workspacesAwareRecordService->getSingle('pages', '*', $pageUid); // Stop processing if no fluidpages template configured in rootline if (NULL === $record) { return NULL; } $provider = $this->configurationService->resolvePrimaryConfigurationProvider('pages', 'tx_fed_page_flexform', $record); $action = $provider->getControllerActionFromRecord($record); if (TRUE === empty($action)) { $this->configurationService->message('No template selected - backend layout will not be rendered', GeneralUtility::SYSLOG_SEVERITY_INFO); return NULL; } $grid = $provider->getGrid($record)->build(); if (FALSE === is_array($grid) || 0 === count($grid['rows'])) { // no grid is defined; we use the "raw" BE layout as a default behavior $this->configurationService->message('The selected page template does not contain a grid but the template is itself valid.'); return NULL; } } catch (\RuntimeException $error) { $this->configurationService->debug($error); return NULL; } $config = array('backend_layout.' => array('colCount' => 0, 'rowCount' => 0, 'rows.' => array())); $colPosList = array(); $items = array(); $rowIndex = 0; foreach ($grid['rows'] as $row) { $index = 0; $colCount = 0; $rowKey = $rowIndex + 1 . '.'; $columns = array(); foreach ($row['columns'] as $column) { $key = $index + 1 . '.'; $columns[$key] = array('name' => $column['label'], 'colPos' => $column['colPos'] >= 0 ? $column['colPos'] : $config['backend_layout.']['colCount']); if ($column['colspan']) { $columns[$key]['colspan'] = $column['colspan']; } if ($column['rowspan']) { $columns[$key]['rowspan'] = $column['rowspan']; } array_push($colPosList, $columns[$key]['colPos']); array_push($items, array($columns[$key]['name'], $columns[$key]['colPos'], NULL)); $colCount += $column['colspan'] ? $column['colspan'] : 1; ++$index; } $config['backend_layout.']['colCount'] = max($config['backend_layout.']['colCount'], $colCount); $config['backend_layout.']['rowCount']++; $config['backend_layout.']['rows.'][$rowKey] = array('columns.' => $columns); ++$rowIndex; } unset($backendLayout['config']); $backendLayout['__config'] = $config; $backendLayout['__colPosList'] = $colPosList; $backendLayout['__items'] = $items; }
/** * @return PageLayoutView */ protected function getInitializePageLayoutView() { $row = $this->arguments['row']; $pageRecord = $this->recordService->getSingle('pages', '*', $row['pid']); // note: the following chained makeInstance is not an error; it is there to make the ViewHelper work on TYPO3 6.0 /** @var $dblist PageLayoutView */ $dblist = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager')->get('TYPO3\\CMS\\Backend\\View\\PageLayoutView'); $dblist->backPath = $GLOBALS['BACK_PATH']; $dblist->script = 'db_layout.php'; $dblist->showIcon = 1; $dblist->setLMargin = 0; $dblist->doEdit = 1; $dblist->no_noWrap = 1; $dblist->ext_CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($pageRecord); $dblist->id = $row['pid']; $dblist->nextThree = 1; $dblist->tt_contentConfig['showCommands'] = 1; $dblist->tt_contentConfig['showInfo'] = 1; $dblist->tt_contentConfig['single'] = 0; $dblist->CType_labels = array(); $dblist->pidSelect = "pid = '" . $row['pid'] . "'"; foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { $dblist->CType_labels[$val[1]] = $GLOBALS['LANG']->sL($val[0]); } $dblist->itemLabels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { $dblist->itemLabels[$name] = $GLOBALS['LANG']->sL($val['label']); } return $dblist; }
/** * @param array $row * @return PageLayoutView */ protected function getInitializedPageLayoutView(array $row) { $pageRecord = $this->workspacesAwareRecordService->getSingle('pages', '*', $row['pid']); /** @var $dblist PageLayoutView */ $dblist = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager')->get('TYPO3\\CMS\\Backend\\View\\PageLayoutView'); $dblist->backPath = $GLOBALS['BACK_PATH']; $dblist->script = 'db_layout.php'; $dblist->showIcon = 1; $dblist->setLMargin = 0; $dblist->doEdit = 1; $dblist->no_noWrap = 1; $dblist->ext_CALC_PERMS = $this->getBackendUser()->calcPerms($pageRecord); $dblist->id = $row['pid']; $dblist->nextThree = 1; $dblist->table = 'tt_content'; $dblist->tableList = 'tt_content'; $dblist->currentTable = 'tt_content'; $dblist->tt_contentConfig['showCommands'] = 1; $dblist->tt_contentConfig['showInfo'] = 1; $dblist->tt_contentConfig['single'] = 0; $dblist->tt_contentConfig['activeCols'] .= ',' . ContentService::COLPOS_FLUXCONTENT; $dblist->CType_labels = array(); $dblist->pidSelect = "pid = '" . $row['pid'] . "'"; $dblist->initializeLanguages(); foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { $dblist->CType_labels[$val[1]] = $this->getLanguageService()->sL($val[0]); } $dblist->itemLabels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { $dblist->itemLabels[$name] = $this->getLanguageService()->sL($val['label']); } return $dblist; }
/** * @param integer $pageUid Starting page UID in the rootline (this current page) * @return array */ protected function getBackendLayoutConfiguration($pageUid) { try { $record = $this->recordService->getSingle('pages', '*', $pageUid); // Stop processing if no fluidpages template configured in rootline if (NULL === $record) { return array(); } $provider = $this->configurationService->resolvePrimaryConfigurationProvider('pages', 'tx_fed_page_flexform', $record); $action = $provider->getControllerActionFromRecord($record); if (TRUE === empty($action)) { $this->configurationService->message('No template selected - backend layout will not be rendered', GeneralUtility::SYSLOG_SEVERITY_INFO); return array(); } $paths = $provider->getTemplatePaths($record); if (0 === count($paths)) { $this->configurationService->message('Unable to detect a configuration. If it is not intentional, check that you ' . 'have included the TypoScript for the desired template collection.', GeneralUtility::SYSLOG_SEVERITY_NOTICE); return array(); } $grid = $provider->getGrid($record)->build(); if (FALSE === is_array($grid) || 0 === count($grid['rows'])) { // no grid is defined; we use the "raw" BE layout as a default behavior $this->configurationService->message('The selected page template does not contain a grid but the template is itself valid.'); return array(); } } catch (\Exception $error) { $this->configurationService->debug($error); return array(); } $config = array('colCount' => 0, 'rowCount' => 0, 'rows.' => array()); $rowIndex = 0; foreach ($grid['rows'] as $row) { $index = 0; $colCount = 0; $rowKey = $rowIndex + 1 . '.'; $columns = array(); foreach ($row['columns'] as $column) { $key = $index + 1 . '.'; $columnName = $GLOBALS['LANG']->sL($column['label']); if (TRUE === empty($columnName)) { $columnName = $column['name']; } $columns[$key] = array('name' => $columnName, 'colPos' => $column['colPos'] >= 0 ? $column['colPos'] : $config['colCount']); if ($column['colspan']) { $columns[$key]['colspan'] = $column['colspan']; } if ($column['rowspan']) { $columns[$key]['rowspan'] = $column['rowspan']; } $colCount += $column['colspan'] ? $column['colspan'] : 1; ++$index; } $config['colCount'] = max($config['colCount'], $colCount); $config['rowCount']++; $config['rows.'][$rowKey] = array('columns.' => $columns); ++$rowIndex; } return $config; }
/** * @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 integer $pageUid Starting page UID in the rootline (this current page) * @return array */ protected function getBackendLayoutConfiguration($pageUid) { try { $record = $this->recordService->getSingle('pages', '*', $pageUid); // Stop processing if no fluidpages template configured in rootline if (null === $record) { return []; } $provider = $this->configurationService->resolvePageProvider($record); $action = $provider->getControllerActionFromRecord($record); if (true === empty($action)) { $this->configurationService->message('No template selected - backend layout will not be rendered', GeneralUtility::SYSLOG_SEVERITY_INFO); return []; } $grid = $provider->getGrid($record)->build(); if (false === is_array($grid) || 0 === count($grid['rows'])) { // no grid is defined; we use the "raw" BE layout as a default behavior $this->configurationService->message('The selected page template does not contain a grid but the template is itself valid.'); return []; } } catch (\Exception $error) { $this->configurationService->debug($error); return []; } $config = ['colCount' => 0, 'rowCount' => 0, 'rows.' => []]; $rowIndex = 0; foreach ($grid['rows'] as $row) { $index = 0; $colCount = 0; $rowKey = $rowIndex + 1 . '.'; $columns = []; foreach ($row['columns'] as $column) { $key = $index + 1 . '.'; $columns[$key] = ['name' => $column['label'], 'colPos' => $column['colPos'] >= 0 ? $column['colPos'] : null]; if ($column['colspan']) { $columns[$key]['colspan'] = $column['colspan']; } if ($column['rowspan']) { $columns[$key]['rowspan'] = $column['rowspan']; } $colCount += $column['colspan'] ? $column['colspan'] : 1; ++$index; } $config['colCount'] = max($config['colCount'], $colCount); $config['rowCount']++; $config['rows.'][$rowKey] = ['columns.' => $columns]; ++$rowIndex; } if (false === $this->isPageModuleLanguageView()) { $config['rows.'][$rowIndex + 1 . '.'] = ['columns.' => ['1.' => ['name' => LocalizationUtility::translate('fluidContentArea', 'fluidpages'), 'colPos' => ContentService::COLPOS_FLUXCONTENT]]]; } return $config; }
/** * @param integer $uid * @param integer $languageUid * @return array|NULL */ protected function loadRecordFromDatabase($uid, $languageUid = 0) { $uid = (int) $uid; $languageUid = (int) $languageUid; if (0 === $languageUid) { $record = BackendUtility::getRecord('tt_content', $uid); } else { $record = BackendUtility::getRecordLocalization('tt_content', $uid, $languageUid); } $record = $this->workspacesAwareRecordService->getSingle('tt_content', '*', $record['uid']); return $record; }
/** * Get a usable page configuration flexform from rootline * * @param integer $pageUid * @return string * @api */ public function getPageFlexFormSource($pageUid) { $pageUid = (int) $pageUid; if (1 > $pageUid) { return NULL; } $page = $this->workspacesAwareRecordService->getSingle('pages', '*', $pageUid); while (NULL !== $page && 0 !== (int) $page['uid'] && TRUE === empty($page['tx_fed_page_flexform'])) { $resolveParentPageUid = (int) (0 > $page['pid'] ? $page['t3ver_oid'] : $page['pid']); $page = $this->workspacesAwareRecordService->getSingle('pages', '*', $resolveParentPageUid); } return $page['tx_fed_page_flexform']; }
/** * 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 $relativeUid * @return array */ protected function getAreaNameAndParentFromRelativeRecordOrDefaults($relativeUid) { $fluxAreaName = NULL; $parentRecordUid = 0; $defaultValues = $this->getDefaultValues(); if (0 > $relativeUid) { // 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) $parentRecord = $this->recordService->getSingle('tt_content', '*', abs($relativeUid)); $fluxAreaName = (string) $parentRecord['tx_flux_column']; $parentRecordUid = (int) $parentRecord['tx_flux_parent']; } elseif (TRUE === isset($defaultValues['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 = (string) $defaultValues['tx_flux_column']; $parentRecordUid = (int) $defaultValues['tx_flux_parent']; } return array($parentRecordUid, $fluxAreaName); }
/** * @param integer $uid * @return array|NULL */ protected function loadRecordFromDatabase($uid) { $uid = intval($uid); $tableName = $this->tableName; return $this->recordService->getSingle($tableName, '*', $uid); }
/** * @param array $row * @return PageLayoutView */ protected function getInitializedPageLayoutView(array $row) { $pageRecord = $this->workspacesAwareRecordService->getSingle('pages', '*', $row['pid']); $moduleData = $GLOBALS['BE_USER']->getModuleData('web_layout', ''); // For all elements to be shown in draft workspaces & to also show hidden elements by default if user hasn't disabled the option // analog behavior to the PageLayoutController at the end of menuConfig() if ($this->getBackendUser()->workspace != 0 || FALSE === isset($this->moduleData['tt_content_showHidden']) || $this->moduleData['tt_content_showHidden'] !== '0') { $moduleData['tt_content_showHidden'] = 1; } /** @var $dblist PageLayoutView */ $dblist = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class)->get(\FluidTYPO3\Flux\View\PageLayoutView::class); $dblist->backPath = $GLOBALS['BACK_PATH']; $dblist->script = 'db_layout.php'; $dblist->showIcon = 1; $dblist->setLMargin = 0; $dblist->doEdit = 1; $dblist->no_noWrap = 1; $dblist->ext_CALC_PERMS = $this->getBackendUser()->calcPerms($pageRecord); $dblist->id = $row['pid']; $dblist->nextThree = 1; $dblist->table = 'tt_content'; $dblist->tableList = 'tt_content'; $dblist->currentTable = 'tt_content'; $dblist->tt_contentConfig['showCommands'] = 1; $dblist->tt_contentConfig['showInfo'] = 1; $dblist->tt_contentConfig['single'] = 0; $dblist->tt_contentConfig['showHidden'] = intval($moduleData['tt_content_showHidden']); $dblist->tt_contentConfig['activeCols'] .= ',' . ContentService::COLPOS_FLUXCONTENT; $dblist->CType_labels = array(); $dblist->pidSelect = "pid = '" . $row['pid'] . "'"; $dblist->setPageinfo(BackendUtility::readPageAccess($row['pid'], '')); $dblist->initializeLanguages(); foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { $dblist->CType_labels[$val[1]] = $this->getLanguageService()->sL($val[0]); } $dblist->itemLabels = array(); foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { $dblist->itemLabels[$name] = $this->getLanguageService()->sL($val['label']); } return $dblist; }
/** * @return array */ public static function resolveCurrentPageRecord() { self::initialize(); $recordUid = (int) (TRUE === isset($GLOBALS['TSFE']->page)) ? $GLOBALS['TSFE']->id : GeneralUtility::_GET('id'); return self::$recordService->getSingle('pages', '*', $recordUid); }