Skip to content

Commit

Permalink
Dispatch event after performing a sort (#178)
Browse files Browse the repository at this point in the history
* Bump dependabot/fetch-metadata from 1.6.0 to 2.1.0

Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 1.6.0 to 2.1.0.
- [Release notes](https://github.com/dependabot/fetch-metadata/releases)
- [Commits](dependabot/fetch-metadata@v1.6.0...v2.1.0)

---
updated-dependencies:
- dependency-name: dependabot/fetch-metadata
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

* Dispatch event on sortable update

* Changed to Event::dispatch()
Added convenience helper to event

* Updated README docs

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
chrispage1 and dependabot[bot] authored Jun 4, 2024
1 parent 545d096 commit a8d09f5
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v1.6.0
uses: dependabot/fetch-metadata@v2.1.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
compat-lookup: true
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,29 @@ public function buildSortQuery()
```
This will restrict the calculations to fields value of the model instance.

### Dispatched events

Once a sort has been completed, an event (`Spatie\EloquentSortable\EloquentModelSortedEvent`) is dispatched that you
can listen for. This can be useful for running post-sorting logic such as clearing caches or other actions that
need to be taken after a sort.

The event has an `isFor` helper which allows you to conveniently check the Eloquent class that has been sorted.

Below is an example of how you can listen for this event:

```php
use Spatie\EloquentSortable\EloquentModelSortedEvent as SortEvent;

class SortingListener
{
public function handle(SortEvent $event): void {
if ($event->isFor(MyClass::class)) {
// ToDo: flush our cache
}
}
}
```

## Tests

The package contains some integration/smoke tests, set up with Orchestra. The tests can be run via phpunit.
Expand Down
24 changes: 24 additions & 0 deletions src/EloquentModelSortedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Spatie\EloquentSortable;

use Illuminate\Database\Eloquent\Model;

class EloquentModelSortedEvent
{
public string $model;

public function __construct(string $model)
{
$this->model = $model;
}

public function isFor(Model|string $model): bool
{
if (is_string($model)) {
return $model === $this->model;
}

return get_class($model) === $this->model;
}
}
25 changes: 17 additions & 8 deletions src/SortableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use ArrayAccess;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Facades\Event;
use InvalidArgumentException;

trait SortableTrait
Expand All @@ -27,22 +28,26 @@ public function setHighestOrderNumber(): void

public function getHighestOrderNumber(): int
{
return (int) $this->buildSortQuery()->max($this->determineOrderColumnName());
return (int)$this->buildSortQuery()->max($this->determineOrderColumnName());
}

public function getLowestOrderNumber(): int
{
return (int) $this->buildSortQuery()->min($this->determineOrderColumnName());
return (int)$this->buildSortQuery()->min($this->determineOrderColumnName());
}

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, callable $modifyQuery = null): void
{
if (! is_array($ids) && ! $ids instanceof ArrayAccess) {
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 @@ -67,6 +72,8 @@ public static function setNewOrder($ids, int $startOrder = 1, string $primaryKey
->update([$orderColumnName => $startOrder++]);
}

Event::dispatch(new EloquentModelSortedEvent(static::class));

if (config('eloquent-sortable.ignore_timestamps', false)) {
static::$ignoreTimestampsOn = array_values(array_diff(static::$ignoreTimestampsOn, [static::class]));
}
Expand Down Expand Up @@ -99,7 +106,7 @@ public function moveOrderDown(): static
->where($orderColumnName, '>', $this->$orderColumnName)
->first();

if (! $swapWithModel) {
if (!$swapWithModel) {
return $this;
}

Expand All @@ -115,7 +122,7 @@ public function moveOrderUp(): static
->where($orderColumnName, '<', $this->$orderColumnName)
->first();

if (! $swapWithModel) {
if (!$swapWithModel) {
return $this;
}

Expand Down Expand Up @@ -157,7 +164,9 @@ public function moveToStart(): static
$this->$orderColumnName = $firstModel->$orderColumnName;
$this->save();

$this->buildSortQuery()->where($this->getQualifiedKeyName(), '!=', $this->getKey())->increment($orderColumnName);
$this->buildSortQuery()->where($this->getQualifiedKeyName(), '!=', $this->getKey())->increment(
$orderColumnName
);

return $this;
}
Expand Down
9 changes: 9 additions & 0 deletions tests/SortableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Spatie\EloquentSortable\Test;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Event;
use Spatie\EloquentSortable\EloquentModelSortedEvent;

class SortableTest extends TestCase
{
Expand Down Expand Up @@ -33,13 +35,20 @@ public function it_can_get_the_highest_order_number_with_trashed_models()
/** @test */
public function it_can_set_a_new_order()
{

Event::fake(EloquentModelSortedEvent::class);

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

Dummy::setNewOrder($newOrder);

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

Event::assertDispatched(EloquentModelSortedEvent::class, function (EloquentModelSortedEvent $event) {
return $event->isFor(Dummy::class);
});
}

/** @test */
Expand Down

0 comments on commit a8d09f5

Please sign in to comment.