Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented a file cache for labels to avoid multiple db requests #48

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Classes/Domain/Model/Translation.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ class Translation extends AbstractEntity
*/
protected $l10n_parent = 0;

/**
* @var int
*/
protected $starttime = 0;

/**
* @var int
*/
protected $endtime = 0;

/**
* Returns the labelkey
*
Expand Down Expand Up @@ -135,4 +145,24 @@ public function setL10nParent($l10nParent)
{
$this->l10n_parent = $l10nParent;
}

public function getStarttime(): int
{
return $this->starttime;
}

public function setStarttime(int $starttime): void
{
$this->starttime = $starttime;
}

public function getEndtime(): int
{
return $this->endtime;
}

public function setEndtime(int $endtime): void
{
$this->endtime = $endtime;
}
}
22 changes: 22 additions & 0 deletions Classes/Domain/Repository/TranslationRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,26 @@ public function findOneByLabelKeyInPid(string $label, int $pid)
$result = $query->matching($constraints)->execute();
return $result->getFirst();
}

public function findAllByPid(int $pid)
{
$query = $this->createQuery();

$query->getQuerySettings()
->setRespectSysLanguage(false)
->setLanguageOverlayMode(false)
->setIgnoreEnableFields(true)
->setEnableFieldsToBeIgnored(['starttime', 'endtime'])
->setRespectStoragePage(false);

$constraints = $query->logicalAnd(
[
$query->equals('pid', $pid),
$query->equals('hidden', false)
]
);

$result = $query->matching($constraints)->execute();
return $result;
}
}
24 changes: 24 additions & 0 deletions Classes/Hooks/UpdateLabelsHook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Sitegeist\Translatelabels\Hooks;


use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Sitegeist\Translatelabels\Renderer\FrontendRenderer;
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use Sitegeist\Translatelabels\Exception\LabelReplaceException;
use Sitegeist\Translatelabels\Utility\TranslationLabelUtility;
use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;


class UpdateLabelsHook
{
public function processDatamap_afterDatabaseOperations($status, $table, $id, array $fieldArray, DataHandler $dataHandler)
{
if ($table === 'tx_translatelabels_domain_model_translation') {
$cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('translatelabels_cache');
$cache->flush();
}
}
}
51 changes: 47 additions & 4 deletions Classes/Utility/TranslationLabelUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
* LICENSE file that was distributed with this source code.
*
*/

use phpDocumentor\Reflection\Types\This;
use TYPO3\CMS\Core\Cache\Backend\BackendInterface;
use TYPO3\CMS\Core\Cache\Backend\FileBackend;
use TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use TYPO3\CMS\Core\Http\ApplicationType;
Expand All @@ -25,6 +31,8 @@

class TranslationLabelUtility
{
protected static ?array $labelCache = null;
protected static int $languageUid = 0;
/**
* returns storagePid where to store translation records
*
Expand Down Expand Up @@ -52,11 +60,47 @@ public static function getStoragePid()
* @throws Exception
* @throws \TYPO3\CMS\Extbase\Object\Exception
*/
public static function readLabelFromDatabase(string $labelKey, string $fallBackTranslation = null)
public static function readLabelFromDatabase(string $labelKey, string $fallBackTranslation = null, int $pid = null, int $languageUid = null)
{
$translation = self::getLabelFromDatabase($labelKey, self::getStoragePid());
if (!self::$labelCache) {
$cache ??= GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('translatelabels_cache');
$cacheIdentifier = $pid ?? self::getStoragePid();

$cacheValue = $cache->require($cacheIdentifier);
if ($cacheValue === false) {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var $translationRepository TranslationRepository */
$translationRepository = $objectManager->get(TranslationRepository::class);
$cacheLifetime = PHP_INT_MAX;
$result = $translationRepository->findAllByPid($cacheIdentifier)->toArray();
$cacheValue = [];
/** @var Translation $translation */
foreach ($result as $translation) {
if ($translation->getStarttime() > $GLOBALS['EXEC_TIME']) {
$cacheLifetime = min($cacheLifetime, $translation->getStarttime());
}
if ($translation->getEndtime() > $GLOBALS['EXEC_TIME']) {
$cacheLifetime = min($cacheLifetime, $translation->getEndtime());
}
if (($translation->getEndtime() > 0 && $translation->getEndtime() < $GLOBALS['EXEC_TIME']) || $translation->getStarttime() > $GLOBALS['EXEC_TIME']) {
continue;
}
$cacheValue[$translation->getLabelkey()][$translation->getLanguageUid()] = $translation->getTranslation();
}
$lifetime = $cacheLifetime !== PHP_INT_MAX ? ($cacheLifetime - $GLOBALS['EXEC_TIME']) : 0;
$cache->set($cacheIdentifier,'return ' . var_export($cacheValue, true) . ';', [], $cacheLifetime !== PHP_INT_MAX ? ($cacheLifetime - $GLOBALS['EXEC_TIME']) : 0);
}
self::$labelCache = $cacheValue;
}

if (!self::$languageUid && !$languageUid) {
$context = GeneralUtility::makeInstance(Context::class);
self::$languageUid = $context->getPropertyFromAspect('language', 'id');
}

$translation = self::$labelCache[$labelKey][$languageUid ?? self::$languageUid] ?? self::$labelCache[$labelKey][-1] ?? null;
if ($translation !== null) {
$fallBackTranslation = $translation->getTranslation();
$fallBackTranslation = $translation;
}
return $fallBackTranslation;
}
Expand All @@ -65,7 +109,6 @@ public static function readLabelFromDatabase(string $labelKey, string $fallBackT
* @param string $labelKey Translation Key
* @param int $pid pid of sysfolder where to search for translation records (needed for calls from BE)
* @param int | null $languageUid uid of language of translation label, null means current language

* @return object translation from database or null if it doesn't exist
* @throws \TYPO3\CMS\Extbase\Object\Exception
*/
Expand Down
7 changes: 7 additions & 0 deletions ext_localconf.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,11 @@

$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['translatelabels_translate']
= \Sitegeist\Translatelabels\Controller\AjaxController::class . '::saveDataAction';


$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['translatelabels_cache'] ??= [];
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['translatelabels_cache']['backend'] ??= \TYPO3\CMS\Core\Cache\Backend\FileBackend::class;
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['translatelabels_cache']['frontend'] ??= \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend::class;

$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = \Sitegeist\Translatelabels\Hooks\UpdateLabelsHook::class;
});