/** * Transforms orm order by expression and adds it to QueryBuilder. * @param string $expression * @param string $direction * @param QueryBuilder $builder */ public function processOrderByExpression($expression, $direction, QueryBuilder $builder) { list($chain, , $sourceEntity) = ConditionParserHelper::parseCondition($expression); $sqlExpression = $this->normalizeAndAddJoins($chain, $sourceEntity, $builder, $distinctNeeded); $builder->addOrderBy($sqlExpression . ($direction === ICollection::DESC ? ' DESC' : '')); if ($distinctNeeded) { throw new LogicException("Cannot order by '{$expression}' expression, includes has many relationship."); } }
/** * @param string $condition * @param string $direction * @return Closure */ public function createSorter(array $conditions) { $columns = []; foreach ($conditions as $pair) { list($column, , $sourceEntity) = ConditionParserHelper::parseCondition($pair[0]); $sourceEntityMeta = $this->metadataStorage->get($sourceEntity ?: $this->mapper->getRepository()->getEntityClassNames()[0]); $columns[] = [$column, $pair[1], $sourceEntityMeta]; } $getter = function ($element, $chain, EntityMetadata $sourceEntityMeta) use(&$getter) { $column = array_shift($chain); $propertyMeta = $sourceEntityMeta->getProperty($column); // check if property exists $value = $element->hasValue($column) ? $element->getValue($column) : NULL; if ($value instanceof IRelationshipCollection) { throw new InvalidStateException('You can not sort by hasMany relationship.'); } if (!$chain) { return $value; } else { $targetEntityMeta = $this->metadataStorage->get($propertyMeta->relationship->entity); return $getter($value, $chain, $targetEntityMeta); } }; return function ($a, $b) use($getter, $columns) { foreach ($columns as $pair) { $_a = $this->simplifyValue($getter($a, $pair[0], $pair[2])); $_b = $this->simplifyValue($getter($b, $pair[0], $pair[2])); $direction = $pair[1] === ICollection::ASC ? 1 : -1; if (is_int($_a) || is_float($_a)) { if ($_a < $_b) { return $direction * -1; } elseif ($_a > $_b) { return $direction; } } else { $res = strcmp((string) $_a, (string) $_b); if ($res < 0) { return $direction * -1; } elseif ($res > 0) { return $direction; } } } return 0; }; }
/** * @param string $condition * @param string $direction * @return Closure */ public function createSorter(array $conditions) { $columns = []; foreach ($conditions as $pair) { list($column, , $sourceEntity) = ConditionParserHelper::parseCondition($pair[0]); $sourceEntityMeta = $this->metadataStorage->get($sourceEntity ?: $this->mapper->getRepository()->getEntityClassNames()[0]); $columns[] = [$column, $pair[1], $sourceEntityMeta]; } return function ($a, $b) use($columns) { foreach ($columns as $pair) { $_a = $this->getter($a, $pair[0], $pair[2]); $_b = $this->getter($b, $pair[0], $pair[2]); $direction = $pair[1] === ICollection::ASC ? 1 : -1; if (is_int($_a) || is_float($_a)) { if ($_a < $_b) { return $direction * -1; } elseif ($_a > $_b) { return $direction; } } elseif ($_a instanceof \Datetime) { if ($_a < $_b) { return $direction * -1; } elseif ($_b > $_a) { return $direction; } } else { $res = strcmp((string) $_a, (string) $_b); if ($res < 0) { return $direction * -1; } elseif ($res > 0) { return $direction; } } } return 0; }; }