public function __construct(Context $context, IMapper $targetMapper, PropertyMetadata $metadata) { $this->context = $context; $this->targetMapper = $targetMapper; $this->targetRepository = $targetMapper->getRepository(); $this->metadata = $metadata; $this->joinStorageKey = $targetMapper->getStorageReflection()->convertEntityToStorageKey($this->metadata->relationshipProperty); }
/** * @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; }; }
private function parseCondition(array $levels, IMapper $mapper) { /** @var IDbStorageReflection $reflection */ $reflection = $mapper->getStorageReflection(); $expression = ''; $column = array_pop($levels); $entityMD = $this->metadataStorage->get($mapper->getRepository()->getEntityClassNames()[0]); foreach ($levels as $level) { if (!$entityMD->hasProperty($level)) { throw new InvalidArgumentException("Undefined property {$entityMD->className}::\${$level}."); } $propertyMD = $entityMD->getProperty($level); if (!$propertyMD->relationshipRepository) { throw new InvalidArgumentException("Entity {$entityMD->className}::\${$level} does not contain a relationship."); } $targetMapper = $this->model->getRepository($propertyMD->relationshipRepository)->getMapper(); $targetReflection = $targetMapper->getStorageReflection(); if ($propertyMD->relationshipType === PropertyMetadata::RELATIONSHIP_ONE_HAS_MANY) { $table = $targetReflection->getStorageName(); $joinColumn = $targetReflection->convertEntityToStorageKey($propertyMD->relationshipProperty); $expression .= ":{$table}({$joinColumn})"; } elseif ($propertyMD->relationshipType === PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY) { if ($propertyMD->relationshipIsMain) { $expression .= ':' . $reflection->getManyHasManyStorageName($targetMapper); $expression .= '.' . $reflection->getManyHasManyStoragePrimaryKeys($targetMapper)[1]; } else { $expression .= ':' . $targetReflection->getManyHasManyStorageName($mapper); $expression .= '.' . $targetReflection->getManyHasManyStoragePrimaryKeys($mapper)[0]; } } else { $expression .= '.' . $reflection->convertEntityToStorageKey($level); } $mapper = $targetMapper; $reflection = $targetReflection; $entityMD = $this->metadataStorage->get($mapper->getRepository()->getEntityClassNames()[0]); } // check if property exists $entityMD->getProperty($column); $column = $reflection->convertEntityToStorageKey($column); return "{$expression}.{$column}"; }
/** * @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; }; }
public function __construct(Connection $connection, IMapper $targetMapper, PropertyMetadata $metadata) { $this->connection = $connection; $this->targetRepository = $targetMapper->getRepository(); $this->metadata = $metadata; }