/** * @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()]); }
/** * @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; }
/** * @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]; }