Skip to content

Commit

Permalink
phpstan: introduce literal-string (BC break!)
Browse files Browse the repository at this point in the history
  • Loading branch information
hrach committed Dec 2, 2021
1 parent 445352b commit d88eb6e
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 55 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"marc-mabe/php-enum": "~3.0",
"mockery/mockery": "~1.2",
"phpstan/extension-installer": "1.1.0",
"phpstan/phpstan": "1.0.2",
"phpstan/phpstan": "1.2.0",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-nette": "1.0.0",
"phpstan/phpstan-mockery": "1.0.0",
Expand Down
4 changes: 2 additions & 2 deletions src/Collection/DbalCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ public function findBy(array $conds): ICollection
}

if ($expression->isHavingClause) {
$collection->queryBuilder->andHaving(...$expression->args);
$collection->queryBuilder->andHaving($expression->expression, ...$expression->args);
} else {
$collection->queryBuilder->andWhere(...$expression->args);
$collection->queryBuilder->andWhere($expression->expression, ...$expression->args);
}
return $collection;
}
Expand Down
10 changes: 7 additions & 3 deletions src/Collection/Functions/BaseAggregateFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@

abstract class BaseAggregateFunction implements IArrayFunction, IQueryBuilderFunction
{
/** @var string */
/** @var literal-string */
private $sqlFunction;


/**
* @param literal-string $sqlFunction
*/
protected function __construct(string $sqlFunction)
{
$this->sqlFunction = $sqlFunction;
Expand Down Expand Up @@ -70,7 +73,7 @@ public function processQueryBuilderExpression(
}

$aggregator = new class implements IDbalAggregator {
/** @var string */
/** @var literal-string */
public $sqlFunction;


Expand All @@ -80,7 +83,8 @@ public function aggregate(
): DbalExpressionResult
{
return new DbalExpressionResult(
["{$this->sqlFunction}(%ex)", $expression->args],
"{$this->sqlFunction}($expression->expression)",
$expression->args,
$expression->joins,
null,
true,
Expand Down
6 changes: 3 additions & 3 deletions src/Collection/Functions/CompareEqualsFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function evaluateInDb(DbalExpressionResult $expression, $value): DbalE
if (count($value) > 0) {
// extract column names for multiOr simplification
// array{%column, array<string>}
$args = $expression->args;
$args = $expression->getExpansionArguments();
if (count($args) === 2 && $args[0] === '%column' && is_array($args[1])) {
$columns = $args[1];
$value = array_map(function ($value) use ($columns): array {
Expand All @@ -45,12 +45,12 @@ protected function evaluateInDb(DbalExpressionResult $expression, $value): DbalE
}
return $combined;
}, $value);
return $expression->withArgs(['%multiOr', $value]);
return $expression->withArgs('%multiOr', [$value]);
} else {
return $expression->append('IN %any', $value);
}
} else {
return $expression->withArgs(['1=0']);
return $expression->withArgs('1=0', []);
}
} elseif ($value === null) {
return $expression->append('IS NULL');
Expand Down
6 changes: 3 additions & 3 deletions src/Collection/Functions/CompareNotEqualsFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function evaluateInDb(DbalExpressionResult $expression, $value): DbalE
if (count($value) > 0) {
// extract column names for multiOr simplification
// array{%column, array<string>}
$args = $expression->args;
$args = $expression->getExpansionArguments();
if (count($args) === 2 && $args[0] === '%column' && is_array($args[1])) {
$columns = $args[1];
$value = array_map(function ($value) use ($columns): array {
Expand All @@ -45,12 +45,12 @@ protected function evaluateInDb(DbalExpressionResult $expression, $value): DbalE
}
return $combined;
}, $value);
return $expression->withArgs(['NOT (%multiOr)', $value]);
return $expression->withArgs('NOT (%multiOr)', [$value]);
} else {
return $expression->append('NOT IN %any', $value);
}
} else {
return $expression->withArgs(['1=1']);
return $expression->withArgs('1=1', []);
}
} elseif ($value === null) {
return $expression->append('IS NOT NULL');
Expand Down
5 changes: 3 additions & 2 deletions src/Collection/Functions/ConjunctionOperatorFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ public function processQueryBuilderExpression(
foreach ($this->normalizeFunctions($args) as $collectionFunctionArgs) {
$expression = $helper->processFilterFunction($builder, $collectionFunctionArgs, $aggregator);
$expression = $expression->applyAggregator($builder);
$processedArgs[] = $expression->args;
$processedArgs[] = $expression->getExpansionArguments();
$joins = array_merge($joins, $expression->joins);
$isHavingClause = $isHavingClause || $expression->isHavingClause;
}

return new DbalExpressionResult(
['%and', $processedArgs],
'%and',
[$processedArgs],
$joins,
null,
$isHavingClause,
Expand Down
5 changes: 3 additions & 2 deletions src/Collection/Functions/DisjunctionOperatorFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ public function processQueryBuilderExpression(
foreach ($this->normalizeFunctions($args) as $collectionFunctionArgs) {
$expression = $helper->processFilterFunction($builder, $collectionFunctionArgs, $aggregator);
$expression = $expression->applyAggregator($builder);
$processedArgs[] = $expression->args;
$processedArgs[] = $expression->getExpansionArguments();
$joins = array_merge($joins, $expression->joins);
$isHavingClause = $isHavingClause || $expression->isHavingClause;
}

return new DbalExpressionResult(
['%or', $processedArgs],
'%or',
[$processedArgs],
$joins,
null,
$isHavingClause,
Expand Down
5 changes: 3 additions & 2 deletions src/Collection/Helpers/DbalAnyAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function aggregate(
DbalExpressionResult $expression
): DbalExpressionResult
{
$joinExpression = array_shift($expression->args);
$joinExpression = $expression->expression;

$joinArgs = $expression->args;
$joins = $expression->joins;
Expand All @@ -38,7 +38,8 @@ public function aggregate(
$queryBuilder->addGroupBy('%table.%column', $join->alias, $primaryKey);

return new DbalExpressionResult(
['COUNT(%table.%column) > 0', $join->alias, $primaryKey],
'COUNT(%table.%column) > 0',
[$join->alias, $primaryKey],
$joins,
null,
true,
Expand Down
45 changes: 38 additions & 7 deletions src/Collection/Helpers/DbalExpressionResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Nextras\Orm\Collection\Helpers;


use MongoDB\Driver\Query;
use Nextras\Dbal\QueryBuilder\QueryBuilder;
use Nextras\Orm\Entity\Reflection\PropertyMetadata;
use Nextras\Orm\Exception\InvalidArgumentException;
Expand All @@ -18,7 +17,14 @@
class DbalExpressionResult
{
/**
* Holds expression as the first argument and then all its arguments.
* Holds expression separately from its arguments.
* @var string
* @phpstan-var literal-string
*/
public $expression;

/**
* Expression's arguments.
* @var mixed[]
* @phpstan-var list<mixed>
*/
Expand Down Expand Up @@ -56,12 +62,14 @@ class DbalExpressionResult


/**
* @phpstan-param literal-string $expression
* @param mixed[] $args
* @param DbalJoinEntry[] $joins
* @phpstan-param list<mixed> $args
* @param bool $isHavingClause
*/
public function __construct(
string $expression,
array $args,
array $joins = [],
?IDbalAggregator $aggregator = null,
Expand All @@ -70,6 +78,7 @@ public function __construct(
?callable $valueNormalizer = null
)
{
$this->expression = $expression;
$this->args = $args;
$this->aggregator = $aggregator;
$this->joins = $joins;
Expand All @@ -86,24 +95,46 @@ public function __construct(
/**
* Appends SQL expression to the original expression.
* If you need prepend or other complex expression, create new instance of DbalExpressionResult.
* @phpstan-param literal-string $expression
* @phpstan-param list<mixed> $args
*/
public function append(string $expression, ...$args): DbalExpressionResult
{
array_unshift($args, $this->args);
array_unshift($args, "%ex $expression");
return $this->withArgs($args);
$args = array_merge($this->args, $args);
return $this->withArgs("{$this->expression} $expression", $args);
}


/**
* Returns all arguments including the expression.
* Suitable as an `%ex` modifier argument.
* @return array<mixed>
*/
public function getExpansionArguments(): array
{
$args = $this->args;
array_unshift($args, $this->expression);
return $args;
}


/**
* Creates a new DbalExpression from the passed $args and keeps the original expression
* properties (joins, aggregator, ...).
* @phpstan-param literal-string $expression
* @param array<mixed> $args
*/
public function withArgs(array $args): DbalExpressionResult
public function withArgs(string $expression, array $args): DbalExpressionResult
{
return new DbalExpressionResult($args, $this->joins, $this->aggregator, $this->isHavingClause, null, null);
return new DbalExpressionResult(
$expression,
$args,
$this->joins,
$this->aggregator,
$this->isHavingClause,
null,
null
);
}


Expand Down
18 changes: 15 additions & 3 deletions src/Collection/Helpers/DbalJoinEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@
*/
class DbalJoinEntry
{
/** @var string */
/**
* @var string
* @phpstan-var literal-string
*/
public $toExpression;

/** @var string */
/**
* @var string
* @phpstan-var literal-string
*/
public $alias;

/** @var string */
/**
* @var string
* @phpstan-var literal-string
*/
public $onExpression;

/** @var array<mixed> */
Expand All @@ -29,6 +38,9 @@ class DbalJoinEntry


/**
* @phpstan-param literal-string $toExpression
* @phpstan-param literal-string $toAlias
* @phpstan-param literal-string $onExpression
* @param array<mixed> $args
*/
public function __construct(
Expand Down
5 changes: 3 additions & 2 deletions src/Collection/Helpers/DbalNoneAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function aggregate(
DbalExpressionResult $expression
): DbalExpressionResult
{
$joinExpression = array_shift($expression->args);
$joinExpression = $expression->expression;

$joinArgs = $expression->args;
$joins = $expression->joins;
Expand All @@ -38,7 +38,8 @@ public function aggregate(
$queryBuilder->addGroupBy('%table.%column', $join->alias, $primaryKey);

return new DbalExpressionResult(
['COUNT(%table.%column) = 0', $join->alias, $primaryKey],
'COUNT(%table.%column) = 0',
[$join->alias, $primaryKey],
$joins,
null,
true,
Expand Down
36 changes: 20 additions & 16 deletions src/Collection/Helpers/DbalQueryBuilderHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,35 +143,36 @@ public function processOrder(QueryBuilder $builder, $expr, string $direction): v
*/
private function processOrderDirection(DbalExpressionResult $expression, string $direction): array
{
$args = $expression->getExpansionArguments();
if ($this->platformName === 'mysql') {
if ($direction === ICollection::ASC || $direction === ICollection::ASC_NULLS_FIRST) {
return ['%ex ASC', $expression->args];
return ['%ex ASC', $args];
} elseif ($direction === ICollection::DESC || $direction === ICollection::DESC_NULLS_LAST) {
return ['%ex DESC', $expression->args];
return ['%ex DESC', $args];
} elseif ($direction === ICollection::ASC_NULLS_LAST) {
return ['%ex IS NULL, %ex ASC', $expression->args, $expression->args];
return ['%ex IS NULL, %ex ASC', $args, $args];
} elseif ($direction === ICollection::DESC_NULLS_FIRST) {
return ['%ex IS NOT NULL, %ex DESC', $expression->args, $expression->args];
return ['%ex IS NOT NULL, %ex DESC', $args, $args];
}
} elseif ($this->platformName === 'mssql') {
if ($direction === ICollection::ASC || $direction === ICollection::ASC_NULLS_FIRST) {
return ['%ex ASC', $expression->args];
return ['%ex ASC', $args];
} elseif ($direction === ICollection::DESC || $direction === ICollection::DESC_NULLS_LAST) {
return ['%ex DESC', $expression->args];
return ['%ex DESC', $args];
} elseif ($direction === ICollection::ASC_NULLS_LAST) {
return ['CASE WHEN %ex IS NULL THEN 1 ELSE 0 END, %ex ASC', $expression->args, $expression->args];
return ['CASE WHEN %ex IS NULL THEN 1 ELSE 0 END, %ex ASC', $args, $args];
} elseif ($direction === ICollection::DESC_NULLS_FIRST) {
return ['CASE WHEN %ex IS NOT NULL THEN 1 ELSE 0 END, %ex DESC', $expression->args, $expression->args];
return ['CASE WHEN %ex IS NOT NULL THEN 1 ELSE 0 END, %ex DESC', $args, $args];
}
} elseif ($this->platformName === 'pgsql') {
if ($direction === ICollection::ASC || $direction === ICollection::ASC_NULLS_LAST) {
return ['%ex ASC', $expression->args];
return ['%ex ASC', $args];
} elseif ($direction === ICollection::DESC || $direction === ICollection::DESC_NULLS_FIRST) {
return ['%ex DESC', $expression->args];
return ['%ex DESC', $args];
} elseif ($direction === ICollection::ASC_NULLS_FIRST) {
return ['%ex ASC NULLS FIRST', $expression->args];
return ['%ex ASC NULLS FIRST', $args];
} elseif ($direction === ICollection::DESC_NULLS_LAST) {
return ['%ex DESC NULLS LAST', $expression->args];
return ['%ex DESC NULLS LAST', $args];
}
}

Expand Down Expand Up @@ -301,7 +302,8 @@ private function processTokens(
);

return new DbalExpressionResult(
['%column', $column],
'%column',
[$column],
$joins,
$makeDistinct ? ($aggregator ?? new DbalAnyAggregator()) : null,
$makeDistinct,
Expand Down Expand Up @@ -373,11 +375,12 @@ private function processRelationship(
$targetMapper->getManyHasManyParameters($sourceProperty, $currentMapper);
}

/** @phpstan-var literal-string $joinAlias */
$joinAlias = self::getAlias($joinTable, array_slice($tokens, 0, $tokenIndex));
$joins[] = new DbalJoinEntry(
"[$joinTable]",
"[$joinTable]", // @phpstan-ignore-line TODO: fix after JOINs refactoring
$joinAlias,
"[$currentAlias.$fromColumn] = %table.[$inColumn]",
"[$currentAlias.$fromColumn] = %table.[$inColumn]", // @phpstan-ignore-line TODO: fix after JOINs refactoring
[],
$currentConventions
);
Expand All @@ -390,11 +393,12 @@ private function processRelationship(
}

$targetTable = $targetMapper->getTableName();
/** @phpstan-var literal-string $targetAlias */
$targetAlias = self::getAlias($tokens[$tokenIndex], array_slice($tokens, 0, $tokenIndex));
$joins[] = new DbalJoinEntry(
"[$targetTable]",
$targetAlias,
"[$currentAlias.$fromColumn] = %table.[$toColumn]",
"[$currentAlias.$fromColumn] = %table.[$toColumn]", // @phpstan-ignore-line TODO: fix after JOINs refactoring
[],
$targetConventions
);
Expand Down
Loading

0 comments on commit d88eb6e

Please sign in to comment.