diff --git a/.gitignore b/.gitignore index c53c4c4..7bab5ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea .phpunit.result.cache build composer.lock diff --git a/README.md b/README.md index f819d9b..20ccdc3 100644 --- a/README.md +++ b/README.md @@ -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, ]; ``` diff --git a/config/config.php b/config/config.php index 76ed05d..201d046 100644 --- a/config/config.php +++ b/config/config.php @@ -2,4 +2,5 @@ return [ 'column_name' => 'position', + 'initial_value' => 1, ]; diff --git a/src/Traits/Sequenceable.php b/src/Traits/Sequenceable.php index 247d086..067d187 100644 --- a/src/Traits/Sequenceable.php +++ b/src/Traits/Sequenceable.php @@ -27,7 +27,7 @@ public static function bootSequenceable(): void static::creating(function ($model) { $model->handleSequenceableCreate(); }); - + static::updating(function ($model) { $model->handleSequenceableUpdate(); }); @@ -81,7 +81,7 @@ protected function handleSequenceableUpdate(): void return; } - + $value = $this->getSequenceValue(); if (! $this->isDirty(static::getSequenceColumnName()) || is_null($value)) { @@ -107,12 +107,12 @@ protected function handleSequenceableDelete(): void return; } - + $columnName = static::getSequenceColumnName(); $objects = $this->getSequence() ->where($columnName, '>', $this->getSequenceValue()); - + static::decrementSequenceValues($objects); } @@ -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(); } @@ -180,7 +180,7 @@ public function getSequenceValue(): ?int return is_numeric($value) ? (int) $value : null; } - + /** * Get original sequence value. * @@ -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) { @@ -239,7 +236,7 @@ protected function isMovingUpInSequence(): bool protected function isMovingDownInSequence(): bool { $originalValue = $this->getOriginalSequenceValue(); - + return $originalValue && $originalValue > $this->getSequenceValue(); } @@ -286,7 +283,7 @@ public static function getSequenceColumnName(): string */ protected function getLastSequenceValue(): int { - return $this->getSequence()->count(); + return $this->getNextSequenceValue() - 1; } /** @@ -296,7 +293,7 @@ protected function getLastSequenceValue(): int */ public function getNextSequenceValue(): int { - return $this->getLastSequenceValue() + 1; + return static::getInitialSequenceValue() + $this->getSequence()->count(); } /** @@ -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); + } } diff --git a/tests/Unit/CreateObjectWithSequenceValueOutOfBoundsTest.php b/tests/Unit/CreateObjectWithSequenceValueOutOfBoundsTest.php index c1d03b9..ca59630 100644 --- a/tests/Unit/CreateObjectWithSequenceValueOutOfBoundsTest.php +++ b/tests/Unit/CreateObjectWithSequenceValueOutOfBoundsTest.php @@ -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, + ]); + } } diff --git a/tests/Unit/InitialSequenceValueTest.php b/tests/Unit/InitialSequenceValueTest.php new file mode 100644 index 0000000..a6e5096 --- /dev/null +++ b/tests/Unit/InitialSequenceValueTest.php @@ -0,0 +1,43 @@ + 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); + } +} diff --git a/tests/Unit/UpdateObjectWithSequenceValueOutOfBoundsTest.php b/tests/Unit/UpdateObjectWithSequenceValueOutOfBoundsTest.php index 8aff845..dec9e13 100644 --- a/tests/Unit/UpdateObjectWithSequenceValueOutOfBoundsTest.php +++ b/tests/Unit/UpdateObjectWithSequenceValueOutOfBoundsTest.php @@ -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]); + } }