Skip to content

Commit

Permalink
[FIX] Translation handling by delegating requered context objects/values
Browse files Browse the repository at this point in the history
This change fixes the context losts by TSFE/ContentObjectRenderer stack for translations.
Now is the language delegated directly or via reques object, instead of previously core context object.

Relates: #3995
  • Loading branch information
dkd-kaehm committed Sep 17, 2024
1 parent 2323fef commit 8c1bc4c
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 74 deletions.
53 changes: 41 additions & 12 deletions Classes/ContentObject/Relation.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Result;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use TYPO3\CMS\Core\Context\LanguageAspectFactory;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\RelationHandler;
Expand Down Expand Up @@ -70,6 +72,7 @@ public function __construct(
*
* @throws ContentRenderingException
* @throws DBALException
* @throws AspectNotFoundException
*
* @noinspection PhpMissingReturnTypeInspection, because foreign source inheritance See {@link AbstractContentObject::render()}
*/
Expand Down Expand Up @@ -104,6 +107,7 @@ public function render($conf = [])
*
* @throws ContentRenderingException
* @throws DBALException
* @throws AspectNotFoundException
*/
protected function getRelatedItems(ContentObjectRenderer $parentContentObject): array
{
Expand All @@ -115,11 +119,16 @@ protected function getRelatedItems(ContentObjectRenderer $parentContentObject):
return [];
}

$overlayUid = $this->getFrontendOverlayService()->getUidOfOverlay($table, $field, $uid);
$overlayUid = $this->getFrontendOverlayService($parentContentObject)->getUidOfOverlay($table, $field, $uid);
$fieldTCA = $this->tcaService->getConfigurationForField($table, $field);

if (isset($fieldTCA['config']['MM']) && trim($fieldTCA['config']['MM']) !== '') {
$relatedItems = $this->getRelatedItemsFromMMTable($table, $overlayUid, $fieldTCA);
$relatedItems = $this->getRelatedItemsFromMMTable(
$table,
$overlayUid,
$fieldTCA,
$parentContentObject,
);
} else {
$relatedItems = $this->getRelatedItemsFromForeignTable($table, $overlayUid, $fieldTCA, $parentContentObject);
}
Expand All @@ -138,9 +147,14 @@ protected function getRelatedItems(ContentObjectRenderer $parentContentObject):
*
* @throws ContentRenderingException
* @throws DBALException
* @throws AspectNotFoundException
*/
protected function getRelatedItemsFromMMTable(string $localTableName, int $localRecordUid, array $localFieldTca): array
{
protected function getRelatedItemsFromMMTable(
string $localTableName,
int $localRecordUid,
array $localFieldTca,
ContentObjectRenderer $parentContentObject,
): array {
$relatedItems = [];
$foreignTableName = $localFieldTca['config']['foreign_table'];
$foreignTableTca = $this->tcaService->getTableConfiguration($foreignTableName);
Expand All @@ -161,7 +175,9 @@ protected function getRelatedItemsFromMMTable(string $localTableName, int $local
return $relatedItems;
}

/** @var ContentObjectRenderer $contentObject */
$contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$contentObject->setRequest($parentContentObject->getRequest());
$relatedRecords = $this->getRelatedRecords($foreignTableName, ...$selectUids);
foreach ($relatedRecords as $record) {
$contentObject->start($record, $foreignTableName);
Expand All @@ -181,8 +197,9 @@ protected function getRelatedItemsFromMMTable(string $localTableName, int $local
$relatedItems = array_merge($relatedItems, $this->getRelatedItems($contentObject));
continue;
}
if ($this->getLanguageUid() > 0) {
$record = $this->getFrontendOverlayService()->getOverlay($foreignTableName, $record);
if ($this->getLanguageUid($parentContentObject) > 0) {
$record = $this->getFrontendOverlayService($parentContentObject)
->getOverlay($foreignTableName, $record);
}

$relatedItems[] = $contentObject->stdWrap($record[$foreignTableLabelField] ?? '', $this->configuration) ?? '';
Expand Down Expand Up @@ -303,8 +320,8 @@ protected function resolveRelatedValue(
ContentObjectRenderer $parentContentObject,
string $foreignTableName = ''
): array {
if ($this->getLanguageUid() > 0 && !empty($foreignTableName)) {
$relatedRecord = $this->getFrontendOverlayService()->getOverlay($foreignTableName, $relatedRecord);
if ($this->getLanguageUid($parentContentObject) > 0 && !empty($foreignTableName)) {
$relatedRecord = $this->getFrontendOverlayService($parentContentObject)->getOverlay($foreignTableName, $relatedRecord);
}

$contentObject = clone $parentContentObject;
Expand Down Expand Up @@ -396,25 +413,37 @@ protected function sortByKeyInIN(Result $statement, string $columnName, ...$arra

/**
* Returns current language id fetched from the Context
*
* @throws ContentRenderingException
*/
protected function getLanguageUid(): int
protected function getLanguageUid(ContentObjectRenderer $parentContentObject): int
{
return GeneralUtility::makeInstance(Context::class)->getAspect('language')->get('id');
return $parentContentObject
->getRequest()
->getAttribute('language')
->getLanguageId();
}

/**
* Returns and sets FrontendOverlayService instance to this object.
*
* @throws ContentRenderingException
*/
protected function getFrontendOverlayService(): FrontendOverlayService
protected function getFrontendOverlayService(ContentObjectRenderer $parentContentObject): FrontendOverlayService
{
if ($this->frontendOverlayService !== null) {
return $this->frontendOverlayService;
}

$siteLanguage = $parentContentObject->getRequest()->getAttribute('language');

/** @var Context $coreContext */
$coreContext = clone GeneralUtility::makeInstance(Context::class);
$coreContext->setAspect('language', LanguageAspectFactory::createFromSiteLanguage($siteLanguage));
return $this->frontendOverlayService = GeneralUtility::makeInstance(
FrontendOverlayService::class,
$this->tcaService,
GeneralUtility::makeInstance(Context::class)
$coreContext,
);
}
}
9 changes: 7 additions & 2 deletions Classes/FrontendEnvironment.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager;
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
use Doctrine\DBAL\Exception as DBALException;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

Expand All @@ -37,7 +37,7 @@ class FrontendEnvironment implements SingletonInterface
* Check whether the page record is within the configured allowed pages types(doktype) for indexing.
* Uses TypoScript: plugin.tx_solr.index.queue.<queue name>.allowedPageTypes
*
* @throws DBALException
* @throws SiteNotFoundException
*/
public function isAllowedPageType(
array $pageRecord,
Expand Down Expand Up @@ -74,7 +74,12 @@ public function isAllowedPageType(
/**
* Returns TypoScriptConfiguration for desired page ID and language id.
*
* @throws SiteNotFoundException
*
* @todo: check when to use $rootPageId and if it can be removed.
* Most probably that belongs to mounted pages or to plugin.tx_solr.index.queue.[indexConfig].additionalPageIds
* For both cases, the indexing configuration must be used from desired/current root page given by `tx_solr_indexqueue_item`.`root`.
* Note about Site-config languages mismatch troubles: https://github.com/TYPO3-Solr/ext-solr/issues/3325#issuecomment-1900091020
*/
public function getSolrConfigurationFromPageId(
int $pageId,
Expand Down
44 changes: 39 additions & 5 deletions Classes/IndexQueue/AbstractIndexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@
use ApacheSolrForTypo3\Solr\ContentObject\Classification;
use ApacheSolrForTypo3\Solr\ContentObject\Multivalue;
use ApacheSolrForTypo3\Solr\ContentObject\Relation;
use ApacheSolrForTypo3\Solr\FrontendEnvironment\Exception\Exception as FrontendEnvironmentException;
use ApacheSolrForTypo3\Solr\FrontendEnvironment\Tsfe;
use ApacheSolrForTypo3\Solr\System\Solr\Document\Document;
use ApacheSolrForTypo3\Solr\System\Util\ArrayAccessor;
use Doctrine\DBAL\Exception as DBALException;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\TypoScript\FrontendTypoScript;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\Exception\ContentRenderingException;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use UnexpectedValueException;

Expand Down Expand Up @@ -60,8 +65,13 @@ public static function isAllowedToOverrideField(string $solrFieldName): bool
* @param array $data Record data
* @return Document Modified document with added fields
*/
protected function addDocumentFieldsFromTyposcript(Document $document, array $indexingConfiguration, array $data, TypoScriptFrontendController $tsfe): Document
{
protected function addDocumentFieldsFromTyposcript(
Document $document,
array $indexingConfiguration,
array $data,
TypoScriptFrontendController $tsfe,
int|SiteLanguage $language,
): Document {
$data = static::addVirtualContentFieldToRecord($document, $data);

// mapping of record fields => solr document fields, resolving cObj
Expand All @@ -78,7 +88,13 @@ protected function addDocumentFieldsFromTyposcript(Document $document, array $in
);
}

$fieldValue = $this->resolveFieldValue($indexingConfiguration, $solrFieldName, $data, $tsfe);
$fieldValue = $this->resolveFieldValue(
$indexingConfiguration,
$solrFieldName,
$data,
$tsfe,
$language,
);
if ($fieldValue === null
|| $fieldValue === ''
|| (is_array($fieldValue) && empty($fieldValue))
Expand Down Expand Up @@ -115,13 +131,23 @@ public static function addVirtualContentFieldToRecord(Document $document, array
* @param array $indexingConfiguration Indexing configuration as defined in plugin.tx_solr_index.queue.[indexingConfigurationName].fields
* @param string $solrFieldName A Solr field name that is configured in the indexing configuration
* @param array $data A record or item's data
* @param TypoScriptFrontendController $tsfe
* @param int|SiteLanguage $language The language to use in TSFE stack
*
* @return array|float|int|string|null The resolved string value to be indexed; null if value could not be resolved
*
*
* @throws FrontendEnvironmentException
* @throws DBALException
* @throws SiteNotFoundException
* @throws ContentRenderingException
*/
protected function resolveFieldValue(
array $indexingConfiguration,
string $solrFieldName,
array $data,
TypoScriptFrontendController $tsfe,
int|SiteLanguage $language,
): mixed {
if (isset($indexingConfiguration[$solrFieldName . '.'])) {
// configuration found => need to resolve a cObj
Expand All @@ -132,7 +158,11 @@ protected function resolveFieldValue(
chdir(Environment::getPublicPath() . '/');

$cObject = GeneralUtility::makeInstance(ContentObjectRenderer::class, $tsfe);
$request = $GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(Tsfe::class)->getServerRequestForTsfeByPageIdAndLanguageId($tsfe->id);
$request = $GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(Tsfe::class)
->getServerRequestForTsfeByPageIdAndLanguageId(
$tsfe->id,
$language instanceof SiteLanguage ? $language->getLanguageId() : $language
);
$cObject->setRequest($request);
$cObject->start($data, $this->type);
$fieldValue = $cObject->cObjGetSingle(
Expand Down Expand Up @@ -170,7 +200,11 @@ protected function resolveFieldValue(
chdir(Environment::getPublicPath() . '/');

$cObject = GeneralUtility::makeInstance(ContentObjectRenderer::class, $tsfe);
$request = $GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(Tsfe::class)->getServerRequestForTsfeByPageIdAndLanguageId($tsfe->id);
$request = $GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(Tsfe::class)
->getServerRequestForTsfeByPageIdAndLanguageId(
$tsfe->id,
$language instanceof SiteLanguage ? $language->getLanguageId() : $language
);
$cObject->setRequest($request);
$cObject->start($data, $this->type);
$fieldValue = $cObject->cObjGetSingle($name, $conf);
Expand Down
8 changes: 7 additions & 1 deletion Classes/IndexQueue/Indexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,13 @@ protected function itemToDocument(Item $item, int $language = 0): ?Document
$itemIndexingConfiguration = $this->getItemTypeConfiguration($item, $language);
$document = $this->getBaseDocument($item, $itemRecord);
$tsfe = $this->getTsfeByItemAndLanguageId($item, $language);
$document = $this->addDocumentFieldsFromTyposcript($document, $itemIndexingConfiguration, $itemRecord, $tsfe);
$document = $this->addDocumentFieldsFromTyposcript(
$document,
$itemIndexingConfiguration,
$itemRecord,
$tsfe,
$language,
);
}

return $document;
Expand Down
Loading

0 comments on commit 8c1bc4c

Please sign in to comment.