Kami Yang Kami Yang - 17 days ago 7
PHP Question

Get Record Localization within backend module

I'm struggling with the TYPO3 l10n and the modifying of localized records.

Short Question:
How can I get the localized record from my extbase model?

In more detail:
I am using a backend module to modify multiple records at the same time. At the moment it only works for origin records. But the customer wants to use this module to edit localized records also.

This is what I tryed so far:

An array is passing the origin uid's to the repository class. Depending on the SysLanguageUid I am doing a findByUid if its an origin record and if the SysLanguageUid is anything higher than 0 I do the following query:

protected function findByUidAndSysLanguageUid($uid, $sysLanguageUid) {
$query = $this->createQuery();
$query->matching(
$query->equals('l10n_parent', $uid),
$query->equals('sys_language_uid', $sysLanguageUid)
);

return $query->execute();
}


This query works fine for the first record. But what really confuses me is, ongoing from the second entry the query returns the origin records (even while the sys_language_uid in the query is set to >0).

Any ideas how to handle this?

PS: If you need some more information then let me know it.

UPDATE:
So far I managed it to get the raw query from the above constraint:

Query of the first record:

SELECT tx_extkey_domain_model_mymodel.*
FROM tx_extkey_domain_model_mymodel
WHERE (tx_extkey_domain_model_mymodel.l10n_parent = '133' AND tx_extkey_domain_model_mymodel.sys_language_uid = '1') AND
(tx_extkey_domain_model_mymodel.sys_language_uid IN (1, -1) OR
(tx_extkey_domain_model_mymodel.sys_language_uid = 0 AND
tx_extkey_domain_model_mymodel.uid NOT IN (SELECT tx_extkey_domain_model_mymodel.l10n_parent
FROM tx_extkey_domain_model_mymodel
WHERE tx_extkey_domain_model_mymodel.l10n_parent > 0 AND
tx_extkey_domain_model_mymodel.sys_language_uid = 1 AND
tx_extkey_domain_model_mymodel.deleted = 0))) AND
tx_extkey_domain_model_mymodel.hidden = 0 AND (tx_extkey_domain_model_mymodel.starttime 1479390060) AND
tx_extkey_domain_model_mymodel.deleted = 0
ORDER BY tx_extkey_domain_model_mymodel.name ASC
LIMIT 1;


Query of the second record:

SELECT tx_extkey_domain_model_mymodel.*
FROM tx_extkey_domain_model_mymodel
WHERE (tx_extkey_domain_model_mymodel.l10n_parent = '134' AND tx_extkey_domain_model_mymodel.sys_language_uid = '1') AND
(tx_extkey_domain_model_mymodel.sys_language_uid IN (1, -1) OR
(tx_extkey_domain_model_mymodel.sys_language_uid = 0 AND
tx_extkey_domain_model_mymodel.uid NOT IN (SELECT tx_extkey_domain_model_mymodel.l10n_parent
FROM tx_extkey_domain_model_mymodel
WHERE tx_extkey_domain_model_mymodel.l10n_parent > 0 AND
tx_extkey_domain_model_mymodel.sys_language_uid = 1 AND
tx_extkey_domain_model_mymodel.deleted = 0))) AND
tx_extkey_domain_model_mymodel.hidden = 0 AND (tx_extkey_domain_model_mymodel.starttime 1479390360) AND
tx_extkey_domain_model_mymodel.deleted = 0
ORDER BY tx_extkey_domain_model_mymodel.name ASC
LIMIT 1;


UPDATE 2
This now confuses me even more...
I put both of the sql queries into heidisql and run them manually. They work perfectly!

So it seems like there is no problem with the query itself.

UPDATE 3

This is the method of the repository which gets called by the controller.

/**
* @param array $parentUidCollection
* @param int $L
*/
protected function updateByCollection(array $parentUidCollection, $L = 0) {
//$L is the language $_GET parameter. cant use TSFE because of inside of a backend module
if($L > 0) {
$this->setTempQuerySettings($L);
}
foreach ($parentUidCollection as $parentUid){
$myModel = $this->findTranslatedByParentId($parentUid)->getFirst();
$myModel->setDescription('foo');
$this->update($myModel);
}
}


My defaultQuerySettings are overwritten in the third line if the actual language is not the default language.

/**
* @param $sysLanguageUid
*/
protected function setTempQuerySettings($sysLanguageUid) {
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings $tempQuerySettings */
$this->originalQuerySettings = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Typo3QuerySettings');
$tempQuerySettings = clone $this->originalQuerySettings;
$tempQuerySettings->setRespectStoragePage(false);
$tempQuerySettings->setRespectSysLanguage(true);
$tempQuerySettings->setLanguageUid($sysLanguageUid);
$tempQuerySettings->setLanguageMode(false);
$tempQuerySettings->setLanguageOverlayMode(false);
$this->setDefaultQuerySettings($tempQuerySettings);
}


And now with the function suggessted by Toke Herkild but without the query settings inside. they are set in the above snipped.

/**
* @param int|string $parentUid
* @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findTranslatedByParentId($parentUid)
{
$query = $this->createQuery();
$query->matching($query->equals('l10n_parent', $parentUid));
return $query->execute();
}


UPDATE 4:

After executing the code the database looks like this:

database snipped

The 100 uid's are the origin and the 200 are the localized records in this picture.

Answer

NOTICE: Below solution would work except for this bug: https://forge.typo3.org/issues/47192

Maybe just make it simple, inside your ModelRepository do something like:

public function findTranslatedByParentId($parentUid) {
   $query = $this->createQuery()
   $qrySettings = $query->getQuerySettings();
   $qrySettings->setLanguageMode('ignore');
   $qrySettings->setLanguageOverlay(FALSE);
   $query->setDefaultQuerySettings($qrySettings);
   return $query->matching($query->equals('l18n_parent', $parentUid))->execute();
}

You need to disable the persistence layers language handling or it believes you try to fetch the localized version of the record for your current sys_language.

Comments