itemArray = []; $this->data = []; $theValue = ''; $tables = (string)$this->cObj->stdWrapValue('tables', $conf ?? []); if ($tables !== '') { $tablesArray = array_unique(GeneralUtility::trimExplode(',', $tables, true)); // Add tables which have a configuration (note that this may create duplicate entries) if (is_array($conf['conf.'] ?? false)) { foreach ($conf['conf.'] as $key => $value) { if (!str_ends_with($key, '.') && !in_array($key, $tablesArray)) { $tablesArray[] = $key; } } } // Get the data, depending on collection method. // Property "source" is considered more precise and thus takes precedence over "categories" $source = (string)$this->cObj->stdWrapValue('source', $conf ?? []); $categories = (string)$this->cObj->stdWrapValue('categories', $conf ?? []); if ($source !== '') { $this->collectRecordsFromSource($source, $tablesArray); } elseif ($categories !== '') { $relationField = (string)$this->cObj->stdWrapValue('relation', $conf['categories.'] ?? []); $this->collectRecordsFromCategories($categories, $tablesArray, $relationField); } if (!empty($this->itemArray)) { $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class); $cObj->setParent($this->cObj->data, $this->cObj->currentRecord); $pageRepository = $this->getPageRepository(); foreach ($this->itemArray as $val) { $row = $this->data[$val['table']][$val['id']] ?? null; if (!is_array($row)) { continue; } // Perform overlays if necessary (records coming from category collections are already overlaid) if ($source !== '') { // Versioning preview $pageRepository->versionOL($val['table'], $row); // Language overlay if (is_array($row)) { $row = $pageRepository->getLanguageOverlay($val['table'], $row); } } // Might be unset during the overlay process if (!is_array($row)) { continue; } if ($this->isRecordsPageAccessible($val['table'], $row, $conf)) { $renderObjName = ($conf['conf.'][$val['table']] ?? false) ? $conf['conf.'][$val['table']] : '<' . $val['table']; $renderObjKey = ($conf['conf.'][$val['table']] ?? false) ? 'conf.' . $val['table'] : ''; $renderObjConf = ($conf['conf.'][$val['table'] . '.'] ?? false) ? $conf['conf.'][$val['table'] . '.'] : []; $this->cObj->lastChanged($row['tstamp'] ?? 0); $cObj->setRequest($this->request); $cObj->start($row, $val['table']); $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey); $theValue .= $tmpValue; } } } } $wrap = $this->cObj->stdWrapValue('wrap', $conf); if ($wrap) { $theValue = $this->cObj->wrap($theValue, $wrap); } if (isset($conf['stdWrap.'])) { $theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']); } return $theValue; } /** * Checks if the records page is accessible */ protected function isRecordsPageAccessible(string $table, array $row, array $conf): bool { $pageId = (int)($table === 'pages' ? $row['uid'] : $row['pid']); if ($pageId === $this->request->getAttribute('frontend.page.information')->getId()) { // Access to current page has already been checked before rendering this content object. return true; } if ($this->cObj->stdWrapValue('dontCheckPid', $conf)) { return true; } $validPageId = $this->getPageRepository()->filterAccessiblePageIds([$pageId]); return $validPageId !== []; } /** * Collects records according to the configured source * * @param string $source Source of records * @param array $tables List of tables */ protected function collectRecordsFromSource($source, array $tables) { $loadDB = GeneralUtility::makeInstance(RelationHandler::class); $loadDB->start($source, implode(',', $tables)); foreach ($loadDB->tableArray as $table => $v) { $constraints = $this->getPageRepository()->getDefaultConstraints($table); if ($constraints !== []) { $loadDB->additionalWhere[$table] = implode(' AND ', $constraints); } } $this->data = $loadDB->getFromDB(); reset($loadDB->itemArray); $this->itemArray = $loadDB->itemArray; } /** * Collects records for all selected tables and categories. * * @param string $selectedCategories Comma-separated list of categories * @param array $tables List of tables * @param string $relationField Name of the field containing the categories relation */ protected function collectRecordsFromCategories($selectedCategories, array $tables, $relationField) { $selectedCategories = array_unique(GeneralUtility::intExplode(',', $selectedCategories, true)); // Loop on all selected tables foreach ($tables as $table) { // Get the records for each selected category $tableRecords = []; $categoriesPerRecord = []; foreach ($selectedCategories as $aCategory) { try { $collection = CategoryCollection::load( $aCategory, true, $table, $relationField ); if ($collection->count() > 0) { // Add items to the collection of records for the current table foreach ($collection as $item) { $tableRecords[$item['uid']] = $item; // Keep track of all categories a given item belongs to if (!isset($categoriesPerRecord[$item['uid']])) { $categoriesPerRecord[$item['uid']] = []; } $categoriesPerRecord[$item['uid']][] = $aCategory; } } } catch (\Exception $e) { $message = sprintf( 'Could not get records for category id %d. Error: %s (%d)', $aCategory, $e->getMessage(), $e->getCode() ); $this->timeTracker->setTSlogMessage($message, LogLevel::WARNING); } } // Store the resulting records into the itemArray and data results array if (!empty($tableRecords)) { $this->data[$table] = []; foreach ($tableRecords as $record) { $this->itemArray[] = [ 'id' => $record['uid'], 'table' => $table, ]; // Add to the record the categories it belongs to $record['_categories'] = implode(',', $categoriesPerRecord[$record['uid']]); $this->data[$table][$record['uid']] = $record; } } } } }