Skip to content

Commit

Permalink
Merge pull request #10 from gurgentil/feature/initial-value
Browse files Browse the repository at this point in the history
Initial sequence value
  • Loading branch information
gurgentil authored Jul 4, 2020
2 parents fd0af32 + dae42a8 commit 373e71b
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
.phpunit.result.cache
build
composer.lock
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ php artisan vendor:publish --provider="Gurgentil\LaravelEloquentSequencer\Larave

### Configuration parameters

You can change the default colum name in `config/eloquentsequencer.php`:
You can change the default colum name and the initial value for the sequences in `config/eloquentsequencer.php`:

```php
return [
'column_name' => 'position',
'initial_value' => 1,
];
```

Expand Down
1 change: 1 addition & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

return [
'column_name' => 'position',
'initial_value' => 1,
];
31 changes: 19 additions & 12 deletions src/Traits/Sequenceable.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static function bootSequenceable(): void
static::creating(function ($model) {
$model->handleSequenceableCreate();
});

static::updating(function ($model) {
$model->handleSequenceableUpdate();
});
Expand Down Expand Up @@ -81,7 +81,7 @@ protected function handleSequenceableUpdate(): void

return;
}

$value = $this->getSequenceValue();

if (! $this->isDirty(static::getSequenceColumnName()) || is_null($value)) {
Expand All @@ -107,12 +107,12 @@ protected function handleSequenceableDelete(): void

return;
}

$columnName = static::getSequenceColumnName();

$objects = $this->getSequence()
->where($columnName, '>', $this->getSequenceValue());

static::decrementSequenceValues($objects);
}

Expand All @@ -138,7 +138,7 @@ protected function isUpdatedSequenceValueOutOfBounds(): bool
$newValue = $this->getSequenceValue();
$originalValue = $this->getOriginalSequenceValue();

return $newValue <= 0
return $newValue < static::getInitialSequenceValue()
|| ! is_null($originalValue) && $newValue > $this->getLastSequenceValue()
|| is_null($originalValue) && $newValue > $this->getNextSequenceValue();
}
Expand Down Expand Up @@ -180,7 +180,7 @@ public function getSequenceValue(): ?int

return is_numeric($value) ? (int) $value : null;
}

/**
* Get original sequence value.
*
Expand All @@ -202,9 +202,6 @@ protected function getOriginalSequenceValue(): ?int
protected static function updateSequenceablesAffectedBy(Model $model): void
{
DB::transaction(function () use ($model) {
$value = $model->getSequenceValue();
$originalValue = $model->getOriginalSequenceValue();

$modelsToUpdate = $model->getSequence()
->where('id', '!=', $model->id)
->filter(function ($sequenceModel) use ($model) {
Expand Down Expand Up @@ -239,7 +236,7 @@ protected function isMovingUpInSequence(): bool
protected function isMovingDownInSequence(): bool
{
$originalValue = $this->getOriginalSequenceValue();

return $originalValue && $originalValue > $this->getSequenceValue();
}

Expand Down Expand Up @@ -286,7 +283,7 @@ public static function getSequenceColumnName(): string
*/
protected function getLastSequenceValue(): int
{
return $this->getSequence()->count();
return $this->getNextSequenceValue() - 1;
}

/**
Expand All @@ -296,7 +293,7 @@ protected function getLastSequenceValue(): int
*/
public function getNextSequenceValue(): int
{
return $this->getLastSequenceValue() + 1;
return static::getInitialSequenceValue() + $this->getSequence()->count();
}

/**
Expand Down Expand Up @@ -375,4 +372,14 @@ protected function getSequenceKeys(): array
? static::$sequenceableKeys
: [];
}

/**
* Get the value that sequences should start at.
*
* @return int
*/
protected static function getInitialSequenceValue(): int
{
return (int) config('eloquentsequencer.initial_value', 1);
}
}
15 changes: 15 additions & 0 deletions tests/Unit/CreateObjectWithSequenceValueOutOfBoundsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,19 @@ public function it_throws_an_exception_when_the_object_created_has_a_sequence_va
'group_id' => $group->id,
]);
}

/** @test */
public function it_throws_an_exception_when_the_object_created_has_a_sequence_value_smaller_than_the_initial_value()
{
config(['eloquentsequencer.initial_vaue' => 10]);

$group = Factory::of('Group')->create();

$this->expectException(SequenceValueOutOfBoundsException::class);

Factory::of('Item')->create([
'position' => 9,
'group_id' => $group->id,
]);
}
}
43 changes: 43 additions & 0 deletions tests/Unit/InitialSequenceValueTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Gurgentil\LaravelEloquentSequencer\Tests\Unit;

use Facades\Gurgentil\LaravelEloquentSequencer\Tests\Factories\Factory;
use Gurgentil\LaravelEloquentSequencer\Tests\TestCase;

class InitialSequenceValueTest extends TestCase
{
/** @test */
public function it_starts_a_sequence_at_a_predefined_value()
{
config(['eloquentsequencer.initial_value' => 10]);

$group = Factory::of('Group')->create();

$firstItem = Factory::of('Item')->create(['group_id' => $group->id]);
$secondItem = Factory::of('Item')->create(['group_id' => $group->id]);
$thirdItem = Factory::of('Item')->create(['group_id' => $group->id]);

$this->assertEquals(10, $firstItem->position);
$this->assertEquals(11, $secondItem->position);
$this->assertEquals(12, $thirdItem->position);
}

/** @test */
public function when_a_sequence_is_updated_the_first_object_will_have_the_initial_value()
{
config(['eloquentsequencer.initial_value' => 10]);

$group = Factory::of('Group')->create();

$firstItem = Factory::of('Item')->create(['group_id' => $group->id]);
$secondItem = Factory::of('Item')->create(['group_id' => $group->id]);
$thirdItem = Factory::of('Item')->create(['group_id' => $group->id]);

$firstItem->update(['position' => 12]);

$this->assertEquals(10, $secondItem->refresh()->position);
$this->assertEquals(11, $thirdItem->refresh()->position);
$this->assertEquals(12, $firstItem->refresh()->position);
}
}
14 changes: 14 additions & 0 deletions tests/Unit/UpdateObjectWithSequenceValueOutOfBoundsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,18 @@ public function it_does_not_throw_an_exception_when_the_updated_object_has_a_seq

$this->assertEquals(2, $item->refresh()->position);
}

/** @test */
public function it_throws_an_exception_when_the_updated_object_has_a_sequence_value_smaller_than_the_initial_value()
{
config(['eloquentsequencer.initial_value' => 10]);

$group = Factory::of('Group')->create();

$item = Factory::of('Item')->create(['group_id' => $group->id]);

$this->expectException(SequenceValueOutOfBoundsException::class);

$item->update(['position' => 9]);
}
}

0 comments on commit 373e71b

Please sign in to comment.