Skip to content

Instantly share code, notes, and snippets.

@rbqueo
Forked from birger-fuehne/MenuUtility.php
Last active January 15, 2023 11:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbqueo/1a6e4d0e80df4a371ea39a287b57650f to your computer and use it in GitHub Desktop.
Save rbqueo/1a6e4d0e80df4a371ea39a287b57650f to your computer and use it in GitHub Desktop.
Set USERDEF1 (or USERDEF2) in a language menu on record detail pages if the record is not translated. #TYPO3
<?php
namespace BGM\BgmTheme\Utility;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use TYPO3\CMS\Core\Context\LanguageAspect;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\Menu\TextMenuContentObject;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
/**
* Class MenuUtility
* @package BGM\BgmTheme\Utility
*/
class MenuUtility
{
/**
* Check if we are on the detail view of a record and if the record is translated.
* If the record is not translated, the ITEM_STATE of the language menu item is set to USERDEF1 or USERDEF2
* as it is also done for pages (see AbstractMenuContentObject::prepareMenuItemsForLanguageMenu() "Checking if the
* "disabled" state should be set.").
*
* TypoScript configuration example for EXT:news
*
* lib.languageSelector = HMENU
* lib.languageSelector {
* special = language
* [...]
* 1 = TMENU
* 1 {
* [...]
* itemArrayProcFunc = BGM\BgmTheme\Utility\MenuUtility->checkForRecordTranslations
* itemArrayProcFunc.getParameters {
* # GET.PARAMETER.WITH.RECORD.UID = TABLENAME
* tx_news_pi1.news = tx_news_domain_model_news
* }
* }
* }
*
* @see \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::prepareMenuItemsForLanguageMenu()
*
* @param $menuArr
* @param $conf
* @return array
* @throws AspectNotFoundException
*/
public function checkForRecordTranslations($menuArr, $conf): array
{
$check = $this->shouldCheck($conf['getParameters.'], GeneralUtility::_GET());
if (count($check) > 0) {
/** @var TextMenuContentObject $parentObject */
$parentObject = $conf['parentObj'];
$tsFe = $this->getTypoScriptFrontendController();
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($check['table']);
$context = GeneralUtility::makeInstance(Context::class);
/** @var LanguageAspect $languageAspect */
$languageAspect = $context->getAspect('language');
foreach ($menuArr as &$menuItem) {
/** current menu item language id */
$sUid = (int)$menuItem['_PAGES_OVERLAY_LANGUAGE'];
// Find overlay record:
if ($sUid) {
$currentRecord = $queryBuilder
->select('*')
->from($check['table'])
->where(
$queryBuilder->expr()->eq('uid', (int)$check['recordUid'])
)
->execute()
->fetch();
$overlayMode = $languageAspect->getOverlayType() === $languageAspect::OVERLAYS_MIXED ? '1' : 'hideNonTranslated';
$lRecs = $parentObject->__get('sys_page')->getRecordOverlay($check['table'], $currentRecord, $sUid, $overlayMode);
} else {
$lRecs = [];
}
// Checking if the "disabled" state should be set.
if (
(
!$parentObject->__get('conf')['special.']['special.']['normalWhenNoLanguage'] &&
$sUid &&
empty($lRecs)
)
||
(
GeneralUtility::hideIfNotTranslated($tsFe->page['l18n_cfg']) &&
$sUid &&
empty($lRecs)
)
||
(
GeneralUtility::hideIfDefaultLanguage($tsFe->page['l18n_cfg']) &&
(
!$sUid ||
empty($lRecs)
)
)
) {
$menuItem['ITEM_STATE'] = $languageAspect->getId() === $sUid ? 'USERDEF2' : 'USERDEF1';
}
}
}
return $menuArr;
}
/**
* Walk through GET-Parameters and TypoScript-Configuration to check if we should do something.
* If we should do something this function returns the tablename and uid of the record to check.
* Else it returns false.
*
* @param array $configuration
* @param array $getParameters
* @return array
*/
protected function shouldCheck(array $configuration, array $getParameters): array
{
$result = [];
foreach ($configuration as $key => $configuredParameter) {
$getParameterKey = $key;
if (is_array($configuredParameter)) {
$getParameterKey = rtrim($key, '.');
}
if (isset($getParameters[$getParameterKey])){
if (
is_array($getParameters[$getParameterKey]) &&
is_array($configuredParameter)
) {
$result = $this->shouldCheck($configuredParameter, $getParameters[$getParameterKey]);
} elseif (
is_string($configuredParameter) &&
$configuredParameter !== 0
) {
$result = [
'table' => $configuredParameter,
'recordUid' => $getParameters[$getParameterKey],
];
}
}
}
return $result;
}
/**
* @return TypoScriptFrontendController
*/
protected function getTypoScriptFrontendController(): TypoScriptFrontendController
{
return $GLOBALS['TSFE'];
}
}
@vicluber
Copy link

Hi, thanks for sharing this, it's exactly what I've been looking for.
If you have time can you tell me what is line 87 doing? Because I get errors with the __get function but I don't know how to fix them, don't know what are these "$parentObject->__get('conf')". That would really help me out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment