getSiteByPageId($pid); } catch (\Exception $e) { return FALSE; } $language = $site->getLanguageById($languageUid); if (!$language instanceof SiteLanguage) { return FALSE; } $elementfactory = GeneralUtility::makeInstance(ElementFactory::class); try { $element = $elementfactory->getElementForTable($table, $row); } catch (Exception $e) { return FALSE; } $visibility = GeneralUtility::makeInstance(VisibilityService::class); self::$cache_isVisible[$cacheKey] = $visibility->isVisible($language, $element); } return self::$cache_isVisible[$cacheKey]; } /** * Helper function to check if a record from a given table in an overlayrecord * * @param array $row * @param string $table * @return bool */ public static function isOverlayRecord(array $row, string $table): bool { $result = FALSE; if (in_array($table, VisibilityService::getSupportedTables(), TRUE)) { $translationIdField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; if ($translationIdField !== '') { // if the field which points to the original of the translation is // not 0 a translation exists and we have an overlay record if (is_array($row[$translationIdField])) { // somehow the sys_language_uid field could contain 0 => 0 $result = (int) $row[$translationIdField][0] !== 0; } else { $result = (int) $row[$translationIdField] !== 0; } } } return $result; } /** * checks if the current BE_USER has access to the page record: * that is the case if: * a) new page created -> always because then the languagevisibility is set to never for all languages where the user has no access * b) edit page record: only if the record is only visible in languages where the user has access to * b.1) also if the languages that are visible and falls back to allowed languages * c) delete: same as for edit (only if user has access to all visible languages) * * @param array $row * @param string $cmd * @return bool * @throws Exception */ public static function hasUserAccessToPageRecord(array $row, string $cmd = 'edit'): bool { if ($cmd === 'new') { return TRUE; } $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); try { $site = $siteFinder->getSiteByPageId($row['uid']); } catch (\Exception $e) { return FALSE; } $availableLanguages = $site->getAllLanguages(); foreach ($availableLanguages as $language) { if (self::isVisible($row, 'pages', $language->getLanguageId())) { if (!$GLOBALS['BE_USER']->checkLanguageAccess($language->getLanguageId())) { //no access to a visible language: check fallbacks $isInFallback = FALSE; $fallbacks = $language->getFallbackLanguageIds(); foreach ($fallbacks as $lId) { if ($GLOBALS['BE_USER']->checkLanguageAccess($lId)) { $isInFallback = TRUE; continue; } } if (!$isInFallback) { return FALSE; } } } } return TRUE; } /** * checks if the current BE_USER has access to a record: * that is the case if: * a) new page created -> always because then the languagevisibility is set to never for all languages where the user has no access * b) edit page record: only if the record is only visible in languages where the user has access to * * @param string $table * @param array $row * @return bool * @throws Exception */ public static function hasUserAccessToEditRecord(string $table, array $row): bool { if (!self::isSupportedTable($table)) { return TRUE; } if (self::isOverlayRecord($row, $table)) { if ($GLOBALS['BE_USER']->checkLanguageAccess($row['sys_language_uid'])) { return TRUE; } return FALSE; } $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); if ($table === 'pages') { $pid = $row['uid']; } else { $pid = $row['pid']; } try { $site = $siteFinder->getSiteByPageId($pid); } catch (\Exception $e) { return FALSE; } $availableLanguages = $site->getAllLanguages(); foreach ($availableLanguages as $language) { if (self::isVisible($row, $table, $language->getLanguageId())) { if (!$GLOBALS['BE_USER']->checkLanguageAccess($language->getLanguageId())) { // no access to a visible language: check fallbacks $isInFallback = FALSE; $fallbacks = $language->getFallbackLanguageIds(); foreach ($fallbacks as $lId) { if ($GLOBALS['BE_USER']->checkLanguageAccess($lId)) { // TODO - write testcase - this can't be right $isInFallback = TRUE; continue; } } if (!$isInFallback) { return FALSE; } } } } return TRUE; } /** * Method to check if the translatedAsDefaultEnabled is enabled or not * * @return boolean */ protected static function isTranslatedAsDefaultEnabled(): bool { $confArr = ExtensionUtility::getExtensionConfiguration(); if (is_array($confArr)) { return (bool) $confArr['translatedAsDefaultEnabled']; } return FALSE; } /** * returns array with the visibility options that are allowed for the current user. * * @param SiteLanguage $language * @param bool $isOverlay * @param Element $element * @return array */ public static function getAvailableOptionsForLanguage( SiteLanguage $language, bool $isOverlay = FALSE, Element $element = NULL ): array { $uid = $language->getLanguageId(); $select = []; if (!$isOverlay) { if ($uid === 0) { $select['active'] = 'active'; $select['enforce'] = 'enforce'; $select['inactive'] = 'inactive'; } else { $select['active'] = 'active'; $select['enforce'] = 'enforce'; $select['translated'] = 'translated'; $select['fallback'] = 'fallback'; $select['inactive'] = 'inactive'; } //check permissions, if user has no permission only no for the language is allowed // if the user has permissions for languages that act as fallback language: then the languages that falls back can have "-" in the options! if (!$GLOBALS['BE_USER']->checkLanguageAccess($uid)) { //check if the language falls back to one of the languages the user has permissions: $isInFallback = FALSE; $fallbacks = $language->getFallbackLanguageIds(); foreach ($fallbacks as $lId) { if ($GLOBALS['BE_USER']->checkLanguageAccess($lId)) { $isInFallback = TRUE; continue; } } $select = []; if ($isInFallback) { $select['active'] = 'active'; } if ($uid !== 0 && self::isTranslatedAsDefaultEnabled()) { $select['translated'] = 'translated'; } $select['inactive'] = 'inactive'; } } else { //overlays elements can only have "force to no" $select['active'] = 'active'; $select['inactive'] = 'inactive'; } /** * Get translations of labels from the locallang file */ foreach ($select as $k => $v) { $select[$k] = LocalizationUtility::translate( 'LLL:EXT:languagevisibility/Resources/Private/Language/locallang_db.xlf:tx_languagevisibility_visibility.I.' . $v, 'languagevisibility' ); } return $select; } }