Author: Vojtěch Kohout
Exemplo n.º 1
0
 public function addRepository(\Joseki\LeanMapper\Repository $repository)
 {
     $class = get_class($repository);
     $table = $this->mapper->getTableByRepositoryClass($class);
     $entity = $this->mapper->getEntityClass($table);
     $this->entities[] = new $entity();
 }
Exemplo n.º 2
0
 /**
  * @param string $definition
  * @param string $alias
  * @param string $type
  * @throws InvalidArgumentException
  */
 public function addJoinByType($definition, $alias, $type)
 {
     list($fromAlias, $viaProperty) = $this->parseDotNotation($definition);
     $entityReflection = $this->getReflection($fromEntity = $this->aliases->getEntityClass($fromAlias));
     $property = $entityReflection->getEntityProperty($viaProperty);
     if (!$property->hasRelationship()) {
         throw new InvalidArgumentException();
     }
     $relationship = $property->getRelationship();
     if ($relationship instanceof HasMany) {
         $this->clauses->join[] = array('type' => $type, 'joinParameters' => array($relationshipTable = $relationship->getRelationshipTable(), $relTableAlias = $relationshipTable . $this->indexer), 'onParameters' => array($fromAlias, $primaryKey = $this->mapper->getPrimaryKey($fromTable = $this->mapper->getTable($fromEntity)), $relTableAlias, $columnReferencingSourceTable = $relationship->getColumnReferencingSourceTable()));
         $this->hydratorMeta->addTablePrefix($relTableAlias, $relationshipTable);
         $this->hydratorMeta->addPrimaryKey($relationshipTable, $relTablePrimaryKey = $this->mapper->getPrimaryKey($relationshipTable));
         $this->hydratorMeta->addRelationship($alias, new Relationship($fromAlias, $fromTable, $columnReferencingSourceTable, Relationship::DIRECTION_REFERENCING, $relTableAlias, $relationshipTable, $primaryKey));
         $this->clauses->join[] = array('type' => $type, 'joinParameters' => array($targetTable = $relationship->getTargetTable(), $alias), 'onParameters' => array($relTableAlias, $columnReferencingTargetTable = $relationship->getColumnReferencingTargetTable(), $alias, $primaryKey = $this->mapper->getPrimaryKey($targetTable)));
         $this->aliases->addAlias($alias, $property->getType());
         $this->hydratorMeta->addTablePrefix($alias, $targetTable);
         $this->hydratorMeta->addPrimaryKey($targetTable, $primaryKey);
         $this->hydratorMeta->addRelationship($relTableAlias, new Relationship($relTableAlias, $relationshipTable, $columnReferencingTargetTable, Relationship::DIRECTION_REFERENCED, $alias, $targetTable, $primaryKey));
         $this->relationshipTables[$alias] = array($relTableAlias, $relTablePrimaryKey, $relTableAlias . QueryHelper::PREFIX_SEPARATOR . $relTablePrimaryKey, $relTableAlias, $columnReferencingSourceTable, $relTableAlias . QueryHelper::PREFIX_SEPARATOR . $columnReferencingSourceTable, $relTableAlias, $columnReferencingTargetTable, $relTableAlias . QueryHelper::PREFIX_SEPARATOR . $columnReferencingTargetTable);
         $this->indexer++;
     } else {
         $this->clauses->join[] = array('type' => $type, 'joinParameters' => array($targetTable = $relationship->getTargetTable(), $alias), 'onParameters' => $relationship instanceof HasOne ? array($fromAlias, $relationshipColumn = $relationship->getColumnReferencingTargetTable(), $alias, $primaryKey = $this->mapper->getPrimaryKey($targetTable)) : array($fromAlias, $primaryKey = $this->mapper->getPrimaryKey($fromTable = $this->mapper->getTable($fromEntity)), $alias, $columnReferencingSourceTable = $relationship->getColumnReferencingSourceTable()));
         $this->aliases->addAlias($alias, $property->getType());
         $this->hydratorMeta->addTablePrefix($alias, $targetTable);
         if ($relationship instanceof HasOne) {
             $this->hydratorMeta->addPrimaryKey($targetTable, $primaryKey);
             $this->hydratorMeta->addRelationship($alias, new Relationship($fromAlias, $this->mapper->getTable($fromEntity), $relationshipColumn, Relationship::DIRECTION_REFERENCED, $alias, $targetTable, $primaryKey));
         } else {
             $this->hydratorMeta->addPrimaryKey($targetTable, $targetTablePrimaryKey = $this->mapper->getPrimaryKey($targetTable));
             $this->hydratorMeta->addRelationship($fromAlias, new Relationship($fromAlias, $fromTable, $columnReferencingSourceTable, Relationship::DIRECTION_REFERENCING, $alias, $targetTable, $primaryKey));
         }
     }
 }
Exemplo n.º 3
0
 /**
  * Checks whether give entity is instance of required type
  *
  * @param Entity $entity
  * @throws InvalidArgumentException
  */
 protected function checkEntityType(Entity $entity)
 {
     $entityClass = $this->mapper->getEntityClass($this->getTable());
     if (!$entity instanceof $entityClass) {
         throw new InvalidArgumentException('Repository ' . get_called_class() . ' can only handle ' . $entityClass . ' entites. Use different repository to handle ' . get_class($entity) . '.');
     }
 }
Exemplo n.º 4
0
 /**
  * @param Result $referencingResult
  * @param string $table
  * @param string $viaColumn
  * @param string $strategy
  */
 public function setReferencingResult(self $referencingResult, $table, $viaColumn = null, $strategy = self::STRATEGY_IN)
 {
     $strategy = $this->translateStrategy($strategy);
     if ($viaColumn === null) {
         $viaColumn = $this->mapper->getRelationshipColumn($table, $this->table);
     }
     $this->referencing["{$table}({$viaColumn}){$strategy}#" . self::PRELOADED_KEY] = $referencingResult;
     unset($this->index[$referencingResult->getOriginKey()]);
 }
Exemplo n.º 5
0
 private function replaceEntitiesForItsPrimaryKeyValues(array $entities)
 {
     foreach ($entities as &$entity) {
         if ($entity instanceof LeanMapper\Entity) {
             $entityTable = $this->mapper->getTable(get_class($entity));
             // FIXME: Column name could be specified in the entity instead of mapper provided by 'getEntityField' function.
             $idField = $this->mapper->getEntityField($entityTable, $this->mapper->getPrimaryKey($entityTable));
             $entity = $entity->{$idField};
         }
     }
     return $entities;
 }
 /**
  * @param $table
  * @return Property
  * @throws \Exception
  */
 private function getRelationshipColumnProperty($table)
 {
     $class = $this->mapper->getEntityClass($table);
     if (!class_exists($class)) {
         throw new \Exception();
     }
     /** @var Entity $entity */
     $entity = new $class();
     $primaryKey = $this->mapper->getPrimaryKey($table);
     $primryKeyField = $this->mapper->getEntityField($table, $primaryKey);
     return $entity->getReflection($this->mapper)->getEntityProperty($primryKeyField);
 }
Exemplo n.º 7
0
 /**
  * @param Entity $entity
  * @return mixed
  */
 private function getIdValue(Entity $entity)
 {
     $table = $this->getTable();
     do {
         $primaryKey = $this->mapper->getPrimaryKey($table);
         $idField = $this->mapper->getEntityField($table, $primaryKey);
         $value = $entity->{$idField};
         if (!$value instanceof Entity) {
             return $value;
         }
         $entity = $value;
         $table = $this->mapper->getTable(get_class($entity));
     } while (true);
 }
Exemplo n.º 8
0
 /**
  * @return Entity[]
  */
 public function getEntities($limit = null, $offset = null)
 {
     if ($this->entities === NULL) {
         $entities = array();
         $entityClass = $this->clauses->from['entityClass'];
         $result = $this->getResult($this->clauses->from['alias'], $limit, $offset);
         $primaryKey = $this->mapper->getPrimaryKey($this->mapper->getTable($entityClass));
         foreach ($result as $key => $row) {
             $entity = $this->entityFactory->createEntity($entityClass, new Row($result, $key));
             $entities[$entity->{$primaryKey}] = $entity;
             $entity->makeAlive($this->entityFactory, $this->connection, $this->mapper);
             $entity->cleanReferencingRowsCache();
         }
         $this->entities = $this->entityFactory->createCollection($entities);
     }
     return $this->entities;
 }
Exemplo n.º 9
0
 /**
  * @param string $action
  * @param string $name
  * @param mixed $arg
  * @throws InvalidMethodCallException
  * @throws InvalidArgumentException
  * @throws InvalidValueException
  */
 private function addToOrRemoveFrom($action, $name, $arg)
 {
     if ($this->isDetached()) {
         throw new InvalidMethodCallException('Cannot add or remove related entity to detached entity.');
     }
     if ($arg === null) {
         throw new InvalidArgumentException('Invalid argument given in entity ' . get_called_class() . '.');
     }
     if (is_array($arg) or $arg instanceof Traversable and !$arg instanceof Entity) {
         foreach ($arg as $value) {
             $this->addToOrRemoveFrom($action, $name, $value);
         }
     } else {
         $method = $action === self::ACTION_ADD ? 'addTo' : 'removeFrom';
         $property = $this->getCurrentReflection()->getEntityProperty($name);
         if ($property === null or !$property->hasRelationship() or !$property->getRelationship() instanceof Relationship\HasMany) {
             throw new InvalidMethodCallException("Cannot call {$method} method with '{$name}' property in entity " . get_called_class() . '. Only properties with m:hasMany relationship can be managed this way.');
         }
         if ($property->getFilters()) {
             throw new InvalidMethodCallException("Cannot call {$method} method with '{$name}' property in entity " . get_called_class() . '. Only properties without filters can be managed this way.');
             // deliberate restriction
         }
         $relationship = $property->getRelationship();
         if ($arg instanceof Entity) {
             if ($arg->isDetached()) {
                 throw new InvalidArgumentException('Cannot add or remove detached entity ' . get_class($arg) . " to {$name} in entity " . get_called_class() . '.');
             }
             $type = $property->getType();
             if (!$arg instanceof $type) {
                 $type = gettype($arg) !== 'object' ? gettype($arg) : 'instance of ' . get_class($arg);
                 throw new InvalidValueException("Unexpected value type given in property '{$property->getName()}' in entity " . get_called_class() . ", {$property->getType()} expected, {$type} given.");
             }
             $data = $arg->getRowData();
             $arg = $data[$this->mapper->getPrimaryKey($relationship->getTargetTable())];
         }
         $table = $this->mapper->getTable($this->getCurrentReflection()->getName());
         $values = [$relationship->getColumnReferencingSourceTable() => $this->row->{$this->mapper->getPrimaryKey($table)}, $relationship->getColumnReferencingTargetTable() => $arg];
         $method .= 'Referencing';
         $this->row->{$method}($values, $relationship->getRelationshipTable(), $relationship->getColumnReferencingSourceTable(), null, $relationship->getStrategy());
     }
 }
Exemplo n.º 10
0
 /**
  * @param string $sourceClass
  * @param PropertyType $propertyType
  * @param string $relationshipType
  * @param string|null $definition
  * @param IMapper|null $mapper
  * @return mixed
  * @throws InvalidAnnotationException
  */
 private static function createRelationship($sourceClass, PropertyType $propertyType, $relationshipType, $definition = null, IMapper $mapper = null)
 {
     if ($relationshipType !== 'hasOne') {
         $strategy = Result::STRATEGY_IN;
         // default strategy
         if ($definition !== null and substr($definition, -6) === '#union') {
             $strategy = Result::STRATEGY_UNION;
             $definition = substr($definition, 0, -6);
         }
     }
     $pieces = array_replace(array_fill(0, 6, ''), $definition !== null ? explode(':', $definition) : []);
     $sourceTable = $mapper !== null ? $mapper->getTable($sourceClass) : null;
     $targetTable = $mapper !== null ? $mapper->getTable($propertyType->getType()) : null;
     switch ($relationshipType) {
         case 'hasOne':
             $relationshipColumn = $mapper !== null ? $mapper->getRelationshipColumn($sourceTable, $targetTable) : self::getSurrogateRelationshipColumn($propertyType);
             return new Relationship\HasOne($pieces[0] ?: $relationshipColumn, $pieces[1] ?: $targetTable);
         case 'hasMany':
             return new Relationship\HasMany($pieces[0] ?: ($mapper !== null ? $mapper->getRelationshipColumn($mapper->getRelationshipTable($sourceTable, $targetTable), $sourceTable) : null), $pieces[1] ?: ($mapper !== null ? $mapper->getRelationshipTable($sourceTable, $targetTable) : null), $pieces[2] ?: ($mapper !== null ? $mapper->getRelationshipColumn($mapper->getRelationshipTable($sourceTable, $targetTable), $targetTable) : null), $pieces[3] ?: $targetTable, $strategy);
         case 'belongsToOne':
             $relationshipColumn = $mapper !== null ? $mapper->getRelationshipColumn($targetTable, $sourceTable) : $sourceTable;
             return new Relationship\BelongsToOne($pieces[0] ?: $relationshipColumn, $pieces[1] ?: $targetTable, $strategy);
         case 'belongsToMany':
             $relationshipColumn = $mapper !== null ? $mapper->getRelationshipColumn($targetTable, $sourceTable) : $sourceTable;
             return new Relationship\BelongsToMany($pieces[0] ?: $relationshipColumn, $pieces[1] ?: $targetTable, $strategy);
     }
     return null;
 }
Exemplo n.º 11
0
 /**
  * @param string $table
  * @param string $viaColumn
  * @param Filtering|null $filtering
  * @param string $strategy
  * @throws InvalidArgumentException
  * @throws InvalidStateException
  * @return self
  */
 private function getReferencingResult($table, $viaColumn = null, Filtering $filtering = null, $strategy = self::STRATEGY_IN)
 {
     $strategy = $this->translateStrategy($strategy);
     if ($this->isDetached) {
         throw new InvalidStateException('Cannot get referencing Result for detached Result.');
     }
     if ($viaColumn === null) {
         $viaColumn = $this->mapper->getRelationshipColumn($table, $this->table);
     }
     $key = "{$table}({$viaColumn}){$strategy}";
     if (isset($this->referencing[$forcedKey = $key . '#' . self::KEY_FORCED])) {
         $ids = $this->extractIds($this->mapper->getPrimaryKey($this->table));
         foreach ($this->referencing[$forcedKey] as $filteringResult) {
             if ($filteringResult->isValidFor($ids, $filtering->getArgs())) {
                 return $filteringResult->getResult();
             }
         }
     }
     if (isset($this->referencing[$preloadedKey = $key . '#' . self::KEY_PRELOADED])) {
         return $this->referencing[$preloadedKey];
     }
     if ($strategy === self::STRATEGY_IN) {
         if ($filtering === null) {
             if (!isset($this->referencing[$key])) {
                 isset($ids) or $ids = $this->extractIds($this->mapper->getPrimaryKey($this->table));
                 $statement = $this->createTableSelection($table, $ids);
                 if ($this->isAlias($viaColumn)) {
                     $statement->where('%n IN %in', $this->trimAlias($viaColumn), $ids);
                 } else {
                     $statement->where('%n.%n IN %in', $table, $viaColumn, $ids);
                 }
                 $data = $statement->execute()->setRowClass(null)->fetchAll();
                 $this->referencing[$key] = self::createInstance($data, $table, $this->connection, $this->mapper);
             }
         } else {
             isset($ids) or $ids = $this->extractIds($this->mapper->getPrimaryKey($this->table));
             $statement = $this->createTableSelection($table, $ids);
             if ($this->isAlias($viaColumn)) {
                 $statement->where('%n IN %in', $this->trimAlias($viaColumn), $ids);
             } else {
                 $statement->where('%n.%n IN %in', $table, $viaColumn, $ids);
             }
             $filteringResult = $this->applyFiltering($statement, $filtering);
             if ($filteringResult instanceof FilteringResultDecorator) {
                 if (!isset($this->referencing[$forcedKey])) {
                     $this->referencing[$forcedKey] = [];
                 }
                 $this->referencing[$forcedKey][] = $filteringResult;
                 return $filteringResult->getResult();
             }
             $args = $statement->_export();
             $key .= '#' . $this->calculateArgumentsHash($args);
             if (!isset($this->referencing[$key])) {
                 $data = $this->connection->query($args)->setRowClass(null)->fetchAll();
                 $this->referencing[$key] = self::createInstance($data, $table, $this->connection, $this->mapper);
             }
         }
         return $this->referencing[$key];
     }
     // $strategy === self::STRATEGY_UNION
     if ($filtering === null) {
         if (!isset($this->referencing[$key])) {
             isset($ids) or $ids = $this->extractIds($this->mapper->getPrimaryKey($this->table));
             if (count($ids) === 0) {
                 $data = [];
             } else {
                 $data = $this->connection->query($this->buildUnionStrategySql($ids, $table, $viaColumn))->setRowClass(null)->fetchAll();
             }
             $this->referencing[$key] = self::createInstance($data, $table, $this->connection, $this->mapper);
         }
     } else {
         isset($ids) or $ids = $this->extractIds($this->mapper->getPrimaryKey($this->table));
         if (count($ids) === 0) {
             $this->referencing[$key] = self::createInstance([], $table, $this->connection, $this->mapper);
         } else {
             $firstStatement = $this->createTableSelection($table, [reset($ids)]);
             if ($this->isAlias($viaColumn)) {
                 $firstStatement->where('%n = ?', $this->trimAlias($viaColumn), reset($ids));
             } else {
                 $firstStatement->where('%n.%n = ?', $table, $viaColumn, reset($ids));
             }
             $filteringResult = $this->applyFiltering($firstStatement, $filtering);
             if ($filteringResult instanceof FilteringResultDecorator) {
                 if (!isset($this->referencing[$forcedKey])) {
                     $this->referencing[$forcedKey] = [];
                 }
                 $this->referencing[$forcedKey][] = $filteringResult;
                 return $filteringResult->getResult();
             }
             $args = $firstStatement->_export();
             $key .= '#' . $this->calculateArgumentsHash($args);
             if (!isset($this->referencing[$key])) {
                 $sql = $this->buildUnionStrategySql($ids, $table, $viaColumn, $filtering);
                 $data = $this->connection->query($sql)->setRowClass(null)->fetchAll();
                 $result = self::createInstance($data, $table, $this->connection, $this->mapper);
                 $this->referencing[$key] = $result;
             }
         }
     }
     return $this->referencing[$key];
 }