/** * Creates a left join list for translations * on used query components * * @todo: make it cleaner * @return string */ private function prepareTranslatedComponents() { $q = $this->getQuery(); $locale = $q->getHint(TranslatableListener::HINT_TRANSLATABLE_LOCALE); if (!$locale) { // use from listener $locale = $this->listener->getListenerLocale(); } $defaultLocale = $this->listener->getDefaultLocale(); if ($locale === $defaultLocale && !$this->listener->getPersistDefaultLocaleTranslation()) { // Skip preparation as there's no need to translate anything return; } $em = $this->getEntityManager(); $ea = new TranslatableEventAdapter(); $ea->setEntityManager($em); $joinStrategy = $q->getHint(TranslatableListener::HINT_INNER_JOIN) ? 'INNER' : 'LEFT'; foreach ($this->translatedComponents as $dqlAlias => $comp) { $meta = $comp['metadata']; $config = $this->listener->getConfiguration($em, $meta->name); $transClass = $this->listener->getTranslationClass($ea, $meta->name); $transMeta = $em->getClassMetadata($transClass); $transTable = $transMeta->getQuotedTableName($this->platform); foreach ($config['fields'] as $field) { $compTblAlias = $this->walkIdentificationVariable($dqlAlias, $field); $tblAlias = $this->getSQLTableAlias('trans' . $compTblAlias . $field); $sql = " {$joinStrategy} JOIN " . $transTable . ' ' . $tblAlias; $sql .= ' ON ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('locale', $this->platform) . ' = ' . $this->conn->quote($locale); $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('field', $this->platform) . ' = ' . $this->conn->quote($field); $identifier = $meta->getSingleIdentifierFieldName(); $idColName = $meta->getQuotedColumnName($identifier, $this->platform); if ($ea->usesPersonalTranslation($transClass)) { $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getSingleAssociationJoinColumnName('object') . ' = ' . $compTblAlias . '.' . $idColName; } else { $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('objectClass', $this->platform) . ' = ' . $this->conn->quote($meta->name); $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('foreignKey', $this->platform) . ' = ' . $compTblAlias . '.' . $idColName; } isset($this->components[$dqlAlias]) ? $this->components[$dqlAlias] .= $sql : ($this->components[$dqlAlias] = $sql); $originalField = $compTblAlias . '.' . $meta->getQuotedColumnName($field, $this->platform); $substituteField = $tblAlias . '.' . $transMeta->getQuotedColumnName('content', $this->platform); // If original field is integer - treat translation as integer (for ORDER BY, WHERE, etc) $fieldMapping = $meta->getFieldMapping($field); if (in_array($fieldMapping["type"], array("integer", "bigint", "tinyint", "int"))) { $substituteField = 'CAST(' . $substituteField . ' AS SIGNED)'; } // Fallback to original if was asked for if ($this->needsFallback() && (!isset($config['fallback'][$field]) || $config['fallback'][$field]) || !$this->needsFallback() && isset($config['fallback'][$field]) && $config['fallback'][$field]) { $substituteField = 'COALESCE(' . $substituteField . ', ' . $originalField . ')'; } $this->replacements[$originalField] = $substituteField; } } }
/** * {@inheritDoc} */ public function setTranslationValue($object, $field, $value) { return $this->ea->setTranslationValue($object, $field, $value); }
/** * Creates a left join list for translations * on used query components * * @todo: make it cleaner * @return string */ private function prepareTranslatedComponents() { $q = $this->getQuery(); $locale = $q->getHint(TranslatableListener::HINT_TRANSLATABLE_LOCALE); if (!$locale) { // use from listener $locale = $this->listener->getListenerLocale(); } $defaultLocale = $this->listener->getDefaultLocale(); if ($locale === $defaultLocale && !$this->listener->getPersistDefaultLocaleTranslation()) { // Skip preparation as there's no need to translate anything return; } $em = $this->getEntityManager(); $ea = new TranslatableEventAdapter(); $ea->setEntityManager($em); $joinStrategy = $q->getHint(TranslatableListener::HINT_INNER_JOIN) ? 'INNER' : 'LEFT'; foreach ($this->translatedComponents as $dqlAlias => $comp) { $meta = $comp['metadata']; $config = $this->listener->getConfiguration($em, $meta->name); $transClass = $this->listener->getTranslationClass($ea, $meta->name); $transMeta = $em->getClassMetadata($transClass); $transTable = $em->getConfiguration()->getQuoteStrategy()->getTableName($transMeta, $this->platform); foreach ($config['fields'] as $field) { $compTblAlias = $this->walkIdentificationVariable($dqlAlias, $field); $tblAlias = $this->getSQLTableAlias('trans' . $compTblAlias . $field); $sql = " {$joinStrategy} JOIN " . $transTable . ' ' . $tblAlias; $sql .= ' ON ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('locale', $this->platform) . ' = ' . $this->conn->quote($locale); $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('field', $this->platform) . ' = ' . $this->conn->quote($field); $identifier = $meta->getSingleIdentifierFieldName(); $idColName = $meta->getQuotedColumnName($identifier, $this->platform); if ($ea->usesPersonalTranslation($transClass)) { $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getSingleAssociationJoinColumnName('object') . ' = ' . $compTblAlias . '.' . $idColName; } else { $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('objectClass', $this->platform) . ' = ' . $this->conn->quote($config['useObjectClass']); $mappingFK = $transMeta->getFieldMapping('foreignKey'); $mappingPK = $meta->getFieldMapping($identifier); $fkColName = $this->getCastedForeignKey($compTblAlias . '.' . $idColName, $mappingFK['type'], $mappingPK['type']); $sql .= ' AND ' . $tblAlias . '.' . $transMeta->getQuotedColumnName('foreignKey', $this->platform) . ' = ' . $fkColName; } isset($this->components[$dqlAlias]) ? $this->components[$dqlAlias] .= $sql : ($this->components[$dqlAlias] = $sql); $originalField = $compTblAlias . '.' . $meta->getQuotedColumnName($field, $this->platform); $substituteField = $tblAlias . '.' . $transMeta->getQuotedColumnName('content', $this->platform); // Treat translation as original field type $fieldMapping = $meta->getFieldMapping($field); if ($this->platform instanceof MySqlPlatform && in_array($fieldMapping["type"], array("decimal")) || !$this->platform instanceof MySqlPlatform && !in_array($fieldMapping["type"], array("datetime", "datetimetz", "date", "time"))) { $type = Type::getType($fieldMapping["type"]); $castType = $type->getSQLDeclaration($fieldMapping, $this->platform); if ($this->platform instanceof \Doctrine\DBAL\Platforms\MySqlPlatform && in_array($fieldMapping["type"], array("decimal"))) { $castType = preg_replace("/NUMERIC/", "DECIMAL", $castType); } $substituteField = 'CAST(' . $substituteField . ' AS ' . $castType . ')'; } // Fallback to original if was asked for if ($this->needsFallback() && (!isset($config['fallback'][$field]) || $config['fallback'][$field]) || !$this->needsFallback() && isset($config['fallback'][$field]) && $config['fallback'][$field]) { $substituteField = 'COALESCE(' . $substituteField . ', ' . $originalField . ')'; } $this->replacements[$originalField] = $substituteField; } } }