Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] add modifyQuery parameter to setNewOrder method #167

Merged
merged 9 commits into from
Dec 11, 2023
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ Optionally you can pass the starting order number as the second argument.
MyModel::setNewOrder([3,1,2], 10);
```

You can modify the query that will be executed by passing a closure as the fourth argument.

```php
/**
* the record for model id 3 will have order_column value 11
* the record for model id 1 will have order_column value 12
* the record for model id 2 will have order_column value 13
*/
MyModel::setNewOrder([3,1,2], 10, null, function($query) {
$query->withoutGlobalScope(new ActiveScope);
});
```


To sort using a column other than the primary key, use the `setNewOrderByCustomColumn`-method.

```php
Expand Down
5 changes: 4 additions & 1 deletion src/SortableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function scopeOrdered(Builder $query, string $direction = 'asc')
return $query->orderBy($this->determineOrderColumnName(), $direction);
}

public static function setNewOrder($ids, int $startOrder = 1, string $primaryKeyColumn = null): void
public static function setNewOrder($ids, int $startOrder = 1, string $primaryKeyColumn = null, callable $modifyQuery = null): void
{
if (! is_array($ids) && ! $ids instanceof ArrayAccess) {
throw new InvalidArgumentException('You must pass an array or ArrayAccess object to setNewOrder');
Expand All @@ -56,6 +56,9 @@ public static function setNewOrder($ids, int $startOrder = 1, string $primaryKey

foreach ($ids as $id) {
static::withoutGlobalScope(SoftDeletingScope::class)
->when(is_callable($modifyQuery), function($query) use ($modifyQuery) {
return $modifyQuery($query);
})
->where($primaryKeyColumn, $id)
->update([$orderColumnName => $startOrder++]);
}
Expand Down
31 changes: 31 additions & 0 deletions tests/DummyWithGlobalScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Spatie\EloquentSortable\Test;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;

class DummyWithGlobalScope extends Model implements Sortable
{
use SortableTrait;

protected $table = 'dummies';
protected $guarded = [];
public $timestamps = false;

/**
* The "booting" method of the model.
*
* @return void
*/
protected static function boot()
{
parent::boot();

parent::addGlobalScope('ActiveScope', function(Builder $builder) {
$builder->where('is_active', true);
});
}
}
16 changes: 16 additions & 0 deletions tests/SortableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@ public function it_can_set_a_new_order_by_custom_column_from_collection()
}
}

/** @test */
public function it_can_set_new_order_without_global_scopes_models()
{
$this->setUpIsActiveFieldForGlobalScope();

$newOrder = Collection::make(Dummy::all()->pluck('id'))->shuffle()->toArray();

DummyWithGlobalScope::setNewOrder($newOrder, 1, null, function($query) {
$query->withoutGlobalScope('ActiveScope');
});

foreach (Dummy::orderBy('order_column')->get() as $i => $dummy) {
$this->assertEquals($newOrder[$i], $dummy->id);
}
}

/** @test */
public function it_can_set_a_new_order_with_trashed_models()
{
Expand Down
7 changes: 7 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,11 @@ protected function setUpSoftDeletes()
$table->softDeletes();
});
}

protected function setUpIsActiveFieldForGlobalScope()
{
$this->app['db']->connection()->getSchemaBuilder()->table('dummies', function (Blueprint $table) {
$table->boolean('is_active')->default(false);
});
}
}