Skip to content

Commit

Permalink
Add orderByNullsFirst method
Browse files Browse the repository at this point in the history
  • Loading branch information
bastien-phi committed Aug 21, 2024
1 parent 0d1a0f0 commit fec0f86
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ phpunit
vendor
.php-cs-fixer.php
.php-cs-fixer.cache
.phpunit.result.cache
.phpunit.cache
composer.lock
phpunit.xml
phpstan.neon
30 changes: 5 additions & 25 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ parameters:
count: 1
path: src/Mixins/CollectionMixin.php

-
message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<TModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\|Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:getAttributes\\(\\)\\.$#"
count: 4
path: src/Mixins/Creation.php

-
message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<TModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\|Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:newCollection\\(\\)\\.$#"
count: 1
path: src/Mixins/Creation.php

-
message: "#^Call to protected method addTimestampsToUpsertValues\\(\\) of class Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<TModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\.$#"
count: 2
Expand All @@ -31,7 +21,7 @@ parameters:
path: src/Mixins/Misc.php

-
message: "#^Call to protected method callScope\\(\\) of class Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\.$#"
message: "#^Call to protected method callScope\\(\\) of class Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<mixed\\>\\.$#"
count: 1
path: src/Mixins/Ordering.php

Expand Down Expand Up @@ -72,12 +62,7 @@ parameters:

-
message: "#^Method Soyhuce\\\\EloquentExtended\\\\Mixins\\\\Ordering\\:\\:preventInvalidDirection\\(\\) invoked with 1 parameter, 0 required\\.$#"
count: 2
path: src/Mixins/Ordering.php

-
message: "#^Offset 0 does not exist on array\\|null\\.$#"
count: 1
count: 3
path: src/Mixins/Ordering.php

-
Expand All @@ -91,7 +76,7 @@ parameters:
path: src/Mixins/Ordering.php

-
message: "#^Parameter \\#2 \\$parentQuery of method Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:getRelationExistenceQuery\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder, \\$this\\(Soyhuce\\\\EloquentExtended\\\\Mixins\\\\Ordering\\) given\\.$#"
message: "#^Parameter \\#2 \\$parentQuery of method Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\<\\*\\>\\:\\:getRelationExistenceQuery\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>, \\$this\\(Soyhuce\\\\EloquentExtended\\\\Mixins\\\\Ordering\\) given\\.$#"
count: 1
path: src/Mixins/Ordering.php

Expand All @@ -116,7 +101,7 @@ parameters:
path: src/Mixins/Select.php

-
message: "#^Call to protected method callScope\\(\\) of class Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\.$#"
message: "#^Call to protected method callScope\\(\\) of class Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<mixed\\>\\.$#"
count: 1
path: src/Mixins/Select.php

Expand All @@ -135,11 +120,6 @@ parameters:
count: 2
path: src/Mixins/Select.php

-
message: "#^Offset 0 does not exist on array\\|null\\.$#"
count: 1
path: src/Mixins/Select.php

-
message: "#^Parameter \\#1 \\$query of method Soyhuce\\\\EloquentExtended\\\\Aggregates\\\\Contracts\\\\AggregateFunction\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:apply\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>, \\$this\\(Soyhuce\\\\EloquentExtended\\\\Mixins\\\\Select\\<TModelClass of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\) given\\.$#"
count: 1
Expand All @@ -161,7 +141,7 @@ parameters:
path: src/Mixins/Select.php

-
message: "#^Parameter \\#2 \\$parentQuery of method Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:getRelationExistenceQuery\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder, \\$this\\(Soyhuce\\\\EloquentExtended\\\\Mixins\\\\Select\\<TModelClass of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\) given\\.$#"
message: "#^Parameter \\#2 \\$parentQuery of method Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\<\\*\\>\\:\\:getRelationExistenceQuery\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder\\<TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>, \\$this\\(Soyhuce\\\\EloquentExtended\\\\Mixins\\\\Select\\<TModelClass of Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\) given\\.$#"
count: 1
path: src/Mixins/Select.php

Expand Down
1 change: 1 addition & 0 deletions src/Aggregates/AnyExists.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Collection;
use Soyhuce\EloquentExtended\Aggregates\Contracts\MultiRelationAggregate;
use function sprintf;

/**
* @template TModelClass of \Illuminate\Database\Eloquent\Model
Expand Down
23 changes: 23 additions & 0 deletions src/Mixins/Ordering.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use InvalidArgumentException;
use function count;
use function in_array;
use function sprintf;

/**
* @mixin \Illuminate\Database\Eloquent\Builder
Expand Down Expand Up @@ -44,6 +45,28 @@ public function orderByRawNullsLast(): Closure
};
}

public function orderByNullsFirst(): Closure
{
return function (string $column, string $direction = 'asc'): self {
$this->preventInvalidDirection($direction);

$column = $this->getGrammar()->wrap($column);

$this->orderByRaw("{$column} {$direction} nulls first");

return $this;
};
}

public function orderByRawNullsFirst(): Closure
{
return function (string $sql): self {
$this->orderByRaw("{$sql} nulls first");

return $this;
};
}

public function orderByAggregate(): Closure
{
return function (
Expand Down
2 changes: 2 additions & 0 deletions src/NextIdeHelper/Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public function execute(Model $model): void
"{$builderClass} withImplode(array|string \$relations, string \$column, string \$glue, ?string \$orderBy = null, string \$direction = 'asc')",
"{$builderClass} orderByNullsLast(string \$column, string \$direction = 'asc')",
"{$builderClass} orderByRawNullsLast(string \$sql)",
"{$builderClass} orderByNullsFirst(string \$column, string \$direction = 'asc')",
"{$builderClass} orderByRawNullsFirst(string \$sql)",
"{$builderClass} orderByAggregate(string \$relationName, string \$column, string \$direction = 'asc', ?string \$function = null, ?\\Closure \$constraints = null)",
"{$builderClass} orderByExists(string \$relation, ?\\Closure \$constraints = null, string \$direction = 'asc')",
"{$builderClass} orderByExistsDesc(string \$relation, ?\\Closure \$constraints = null)",
Expand Down
56 changes: 55 additions & 1 deletion tests/OrderingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function otherDirectionIsInvalid(): void
* @test
* @covers ::orderByNullsLast
*/
public function orderByNullLast(): void
public function orderByNullsLast(): void
{
$sqliteVersion = User::query()->getConnection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

Expand Down Expand Up @@ -90,6 +90,60 @@ public function orderByRawNullsLast(): void
);
}

/**
* @test
* @covers ::orderByNullsLast
*/
public function orderByNullsFirst(): void
{
$sqliteVersion = User::query()->getConnection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

if (version_compare($sqliteVersion, '3.31', '<')) {
$this->markTestSkipped('Sqlite < 3.31 does not support nulls last');
}

$admin = User::factory()->createOne(['role' => 'admin']);
$user = User::factory()->createOne(['role' => 'user']);
$none = User::factory()->createOne(['role' => null]);

$this->assertEquals(
[$none->id, $admin->id, $user->id],
User::query()->orderByNullsFirst('role')->pluck('id')->all()
);

$this->assertEquals(
[$none->id, $user->id, $admin->id],
User::query()->orderByNullsFirst('role', 'desc')->pluck('id')->all()
);
}

/**
* @test
* @covers ::orderByRawNullsLast
*/
public function orderByRawNullsFirst(): void
{
$sqliteVersion = User::query()->getConnection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

if (version_compare($sqliteVersion, '3.31', '<')) {
$this->markTestSkipped('Sqlite < 3.31 does not support nulls last');
}

$admin = User::factory()->createOne(['role' => 'admin']);
$user = User::factory()->createOne(['role' => 'user']);
$none = User::factory()->createOne(['role' => null]);

$this->assertEquals(
[$none->id, $admin->id, $user->id],
User::query()->orderByRawNullsFirst('UPPER("role")')->pluck('id')->all()
);

$this->assertEquals(
[$none->id, $user->id, $admin->id],
User::query()->orderByRawNullsFirst('UPPER("role") desc')->pluck('id')->all()
);
}

/**
* @test
* @covers ::orderByExists
Expand Down

0 comments on commit fec0f86

Please sign in to comment.