246 lines
9.3 KiB
PHP
246 lines
9.3 KiB
PHP
<?php
|
|
|
|
namespace Query;
|
|
|
|
use KupShop\I18nBundle\Translations\ITranslation;
|
|
use KupShop\KupShopBundle\Context\LanguageContext;
|
|
use KupShop\KupShopBundle\Util\ArrayUtil;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use KupShop\KupShopBundle\Util\Contexts;
|
|
|
|
class Translation
|
|
{
|
|
public const COALESCE_STYLE_INHERITANCE = 'inheritance';
|
|
public const COALESCE_STYLE_NONE = 'none';
|
|
|
|
/**
|
|
* @return \Closure
|
|
*/
|
|
public static function adminAlwaysVisible($spec)
|
|
{
|
|
if (!getAdminUser()) {
|
|
return $spec;
|
|
}
|
|
|
|
return function (QueryBuilder $qb) use ($spec) {
|
|
$dbcfg = \Settings::getDefault();
|
|
|
|
$tmp = $dbcfg->hide_not_translated_objects ?? null;
|
|
$dbcfg->hide_not_translated_objects = 'N';
|
|
|
|
$qb->andWhere($spec);
|
|
|
|
$dbcfg->hide_not_translated_objects = $tmp;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param array|callable|null $columns list of column names ['name', 'title', ...]
|
|
*/
|
|
public static function withTranslatedFields(
|
|
array $languages,
|
|
ITranslation $translation,
|
|
$columns = null,
|
|
bool $frontend = false,
|
|
string $coalesceStyle = self::COALESCE_STYLE_NONE,
|
|
): callable {
|
|
// TODO: Hack
|
|
$first = false;
|
|
|
|
return self::joinTranslations($languages, $translation, function (QueryBuilder $qb, $columnName, $translatedColumn, $langID) use (&$first, $translation, $frontend, $coalesceStyle) {
|
|
$translationAlias = $translation->getTableAlias().'_'.$langID;
|
|
if (!$frontend && $coalesceStyle == self::COALESCE_STYLE_NONE) {
|
|
$qb->addSelect("{$translationAlias}.{$columnName} AS {$langID}_{$columnName}");
|
|
|
|
// TODO: Rozdelit na specku pouze pro admin
|
|
if ($first == false) {
|
|
$qb->leftJoin($translationAlias, 'admins', "{$translationAlias}_a", "{$translationAlias}_a.id = {$translationAlias}.id_admin");
|
|
$qb->addSelect("{$translationAlias}.created AS {$langID}_created")
|
|
->addSelect("{$translationAlias}.updated AS {$langID}_updated")
|
|
->addSelect("{$translationAlias}_a.id AS {$langID}_admin_id")
|
|
->addSelect("{$translationAlias}_a.email AS {$langID}_admin_email");
|
|
$first = true;
|
|
}
|
|
|
|
return false;
|
|
} elseif ($coalesceStyle == self::COALESCE_STYLE_INHERITANCE) {
|
|
$qb->addSelect("{$translatedColumn} AS {$langID}_{$columnName}");
|
|
|
|
return false;
|
|
}
|
|
}, $columns);
|
|
}
|
|
|
|
/**
|
|
* @param array|callable|null $columns list of column names ['name', 'title', ...]
|
|
*/
|
|
public static function joinTranslations(
|
|
array $languages,
|
|
ITranslation $translation,
|
|
callable $fieldsCallback,
|
|
$columns = null,
|
|
): callable {
|
|
return function (QueryBuilder $qb) use ($fieldsCallback, $languages, $translation, $columns) {
|
|
if (!findModule(\Modules::TRANSLATIONS)) {
|
|
return '1';
|
|
}
|
|
|
|
if (!$languages) {
|
|
return '1';
|
|
}
|
|
|
|
$tableAlias = $translation->getTableAlias();
|
|
$foreignKeyColumn = $translation->getForeignKeyColumn();
|
|
$keyColumn = $translation->getKeyColumn();
|
|
|
|
if (is_callable($columns)) {
|
|
$columnsToSelect = array_keys($translation->getColumns());
|
|
$columns = $columns(array_combine($columnsToSelect, $columnsToSelect));
|
|
}
|
|
|
|
if (!is_array($columns)) {
|
|
$columns = array_keys($translation->getColumns());
|
|
}
|
|
|
|
if (!ArrayUtil::isDictionary($columns)) {
|
|
// convert to assoc
|
|
$columns = array_combine($columns, $columns);
|
|
}
|
|
|
|
$inheritedLanguages = static::getInheritedLanguages($languages);
|
|
|
|
// Pokud je getJoinType join a máme více jazyků, tak použijeme leftJoin a následně použijeme inNotNul v proměnné $whereOr.
|
|
// Upraveno kvůli skrývání nepřeložených objektů
|
|
$useLeftJoin = count($inheritedLanguages) > 1 && $translation->getJoinType() == 'join';
|
|
$join = $useLeftJoin ? 'leftJoin' : $translation->getJoinType();
|
|
$whereOr = [];
|
|
|
|
// join translation tables
|
|
foreach ($inheritedLanguages as $langID) {
|
|
$translationAlias = $translation->getTableAlias().'_'.$langID;
|
|
$qb->setParameter("translation_language_{$langID}", $langID);
|
|
$qb->{$join}(
|
|
$tableAlias,
|
|
$translation->getTableName().'_translations',
|
|
$translationAlias,
|
|
"{$translationAlias}.{$foreignKeyColumn} = {$tableAlias}.{$keyColumn} AND {$translationAlias}.id_language = :translation_language_{$langID}"
|
|
);
|
|
$translation->customizeJoinQueryBuilder($qb, $langID);
|
|
if ($useLeftJoin) {
|
|
$whereOr[] = Operator::isNotNull("{$translationAlias}.{$foreignKeyColumn}");
|
|
}
|
|
}
|
|
if (!empty($whereOr)) {
|
|
$qb->andWhere(Operator::orX($whereOr));
|
|
}
|
|
// add columns
|
|
foreach ($languages as $langID) {
|
|
foreach ($columns as $columnName => $alias) {
|
|
$coalesce = [];
|
|
// add translation fields to $coalesce
|
|
foreach (static::getInheritedLanguages($langID) as $inheritedLanguageId) {
|
|
$translationAlias = $translation->getTableAlias().'_'.$inheritedLanguageId;
|
|
$coalesce[] = "{$translationAlias}.{$columnName}";
|
|
}
|
|
|
|
$coalesceField = Operator::coalesce(...$coalesce);
|
|
// add select with coalesce to default field
|
|
if ($fieldsCallback($qb, $columnName, $coalesceField, $langID) !== false) {
|
|
$qb->addSelect("COALESCE({$coalesceField}, {$tableAlias}.{$columnName}) as `{$alias}`");
|
|
}
|
|
}
|
|
}
|
|
|
|
return '1';
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param array|callable|null $columns list of column names ['name', 'title', ...]
|
|
*/
|
|
public static function coalesceTranslatedFields(
|
|
string $translationClass,
|
|
$columns = null,
|
|
?string $languageID = null,
|
|
) {
|
|
if (!findModule(\Modules::TRANSLATIONS)) {
|
|
if ($columns) {
|
|
// Emulate selected columns
|
|
$class = new $translationClass();
|
|
|
|
if (is_callable($columns)) {
|
|
$columnsToSelect = array_keys($class->getColumns());
|
|
$columns = $columns(array_combine($columnsToSelect, $columnsToSelect));
|
|
}
|
|
|
|
if (!ArrayUtil::isDictionary($columns)) {
|
|
// convert to assoc
|
|
$columns = array_combine($columns, $columns);
|
|
}
|
|
|
|
return function (QueryBuilder $qb) use ($columns, $class) {
|
|
foreach ($columns as $columnName => $translatedField) {
|
|
$qb->addSelect("{$class->getTableAlias()}.{$columnName} AS `{$translatedField}`");
|
|
}
|
|
|
|
return '1';
|
|
};
|
|
}
|
|
|
|
return '1';
|
|
}
|
|
|
|
/** @var $translation ITranslation */
|
|
$translation = ServiceContainer::getService($translationClass);
|
|
if (!isset($languageID)) {
|
|
$language = ServiceContainer::getService(LanguageContext::class)->getActive();
|
|
$languageID = $language->getId();
|
|
}
|
|
|
|
return self::withTranslatedFields([$languageID], $translation, $columns, true);
|
|
}
|
|
|
|
public static function joinTranslatedFields(
|
|
string $translationClass,
|
|
callable $fieldsCallback,
|
|
array $columns,
|
|
) {
|
|
if (!findModule(\Modules::TRANSLATIONS)) {
|
|
if (!ArrayUtil::isDictionary($columns)) {
|
|
// convert to assoc
|
|
$columns = array_combine($columns, $columns);
|
|
}
|
|
|
|
return function (QueryBuilder $qb) use ($columns, $fieldsCallback, $translationClass) {
|
|
$class = new $translationClass();
|
|
foreach ($columns as $columnName => $translatedField) {
|
|
if ($fieldsCallback($qb, $columnName, null, null) !== false) {
|
|
$qb->addSelect("{$class->getTableAlias()}.{$columnName} AS `{$translatedField}`");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
$translation = ServiceContainer::getService($translationClass);
|
|
$language = ServiceContainer::getService(LanguageContext::class)->getActive();
|
|
|
|
return self::joinTranslations([$language->getId()], $translation, $fieldsCallback, $columns);
|
|
}
|
|
|
|
public static function getInheritedLanguages(array|string $languages): array
|
|
{
|
|
$languageContext = Contexts::get(LanguageContext::class);
|
|
|
|
if (is_string($languages)) {
|
|
$languages = [$languages];
|
|
}
|
|
|
|
$inheritedLanguages = [];
|
|
foreach ($languages as $language) {
|
|
$inheritedLanguages = array_unique(array_merge($inheritedLanguages, $languageContext->getInheritance($language)));
|
|
}
|
|
|
|
return $inheritedLanguages;
|
|
}
|
|
}
|