public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { // Get locale and translation zone to use $locale = $dataQuery->getQueryParam('Fluent.Locale') ?: Fluent::current_locale(); // Get all tables to translate fields for, and their respective field names $includedTables = $this->getTranslatedTables(); // Iterate through each select clause, replacing each with the translated version foreach ($query->getSelect() as $alias => $select) { // Skip fields without table context if (!preg_match('/^"(?<class>\\w+)"\\."(?<field>\\w+)"$/i', $select, $matches)) { continue; } $class = $matches['class']; $field = $matches['field']; // If this table doesn't have translated fields then skip if (empty($includedTables[$class])) { continue; } // If this field shouldn't be translated, skip if (!in_array($field, $includedTables[$class])) { continue; } // Select visible field from translated fields (Title_fr_FR || Title => Title) $translatedField = Fluent::db_field_for_locale($field, $locale); $expression = $this->localiseSelect($class, $translatedField, $field); $query->selectField($expression, $alias); } // Rewrite where conditions $where = $query->getWhere(); foreach ($where as $index => $condition) { // determine the table/column this condition is against $filterColumn = $this->detectFilterColumn($condition, $includedTables, $locale); if (empty($filterColumn)) { continue; } // Duplicate the condition with all localisable fields replaced $localisedCondition = $this->localiseFilterCondition($condition, $includedTables, $locale); if ($localisedCondition === $condition) { continue; } // Generate new condition that conditionally executes one of the two conditions // depending on field nullability. // If the filterColumn is null or empty, then it's considered untranslated, and // thus the query should continue running on the default column unimpeded. $where[$index] = "\n\t\t\t\t({$filterColumn} IS NOT NULL AND {$filterColumn} != '' AND ({$localisedCondition}))\n\t\t\t\tOR (\n\t\t\t\t\t({$filterColumn} IS NULL OR {$filterColumn} = '') AND ({$condition})\n\t\t\t\t)"; } $query->setWhere($where); // Augment search if applicable if ($adapter = Fluent::search_adapter()) { $adapter->augmentSearch($query, $dataQuery); } }
public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { // Get locale and translation zone to use $default = Fluent::default_locale(); $locale = $dataQuery->getQueryParam('Fluent.Locale') ?: Fluent::current_locale(); // Get all tables to translate fields for, and their respective field names $includedTables = $this->getTranslatedTables(); // Iterate through each select clause, replacing each with the translated version foreach ($query->getSelect() as $alias => $select) { // Skip fields without table context if (!preg_match('/^"(?<class>\\w+)"\\."(?<field>\\w+)"$/i', $select, $matches)) { continue; } $class = $matches['class']; $field = $matches['field']; // If this table doesn't have translated fields then skip if (empty($includedTables[$class])) { continue; } // If this field shouldn't be translated, skip if (!in_array($field, $includedTables[$class])) { continue; } // Select visible field from translated fields (Title_fr_FR || Title => Title) $translatedField = Fluent::db_field_for_locale($field, $locale); $expression = $this->localiseSelect($class, $translatedField, $field); $query->selectField($expression, $alias); // At the same time, rewrite the selector for the default field to make sure that // (in the case it is blank, which happens if installing fluent for the first time) // that it also populated from the root field. $defaultField = Fluent::db_field_for_locale($field, $default); $defaultExpression = $this->localiseSelect($class, $defaultField, $field); $query->selectField($defaultExpression, $defaultField); } // Rewrite where conditions with parameterised query (3.2 +) $where = $query->toAppropriateExpression()->getWhere(); foreach ($where as $index => $condition) { // Extract parameters from condition if ($condition instanceof SQLConditionGroup) { $parameters = array(); $predicate = $condition->conditionSQL($parameters); } else { $parameters = array_values(reset($condition)); $predicate = key($condition); } // determine the table/column this condition is against $filterColumn = $this->detectFilterColumn($predicate, $includedTables, $locale); if (empty($filterColumn)) { continue; } // Duplicate the condition with all localisable fields replaced $localisedPredicate = $this->localiseFilterCondition($predicate, $includedTables, $locale); if ($localisedPredicate === $predicate) { continue; } // Generate new condition that conditionally executes one of the two conditions // depending on field nullability. // If the filterColumn is null or empty, then it's considered untranslated, and // thus the query should continue running on the default column unimpeded. $castColumn = "COALESCE(CAST({$filterColumn} AS CHAR), '')"; $newPredicate = "\n\t\t\t\t({$castColumn} != '' AND {$castColumn} != '0' AND ({$localisedPredicate}))\n\t\t\t\tOR (\n\t\t\t\t\t({$castColumn} = '' OR {$castColumn} = '0') AND ({$predicate})\n\t\t\t\t)"; // Duplicate this condition with parameters duplicated $where[$index] = array($newPredicate => array_merge($parameters, $parameters)); } $query->setWhere($where); // Augment search if applicable if ($adapter = Fluent::search_adapter()) { $adapter->augmentSearch($query, $dataQuery); } }