Skip to content

Commit

Permalink
Use new syntax for available validation rule.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikaeljorhult committed Jun 13, 2023
1 parent a3cca67 commit 2c991a1
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 39 deletions.
33 changes: 12 additions & 21 deletions app/Rules/Available.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

use App\Models\Booking;
use Carbon\Carbon;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class Available implements Rule
class Available implements ValidationRule
{
/**
* Start of time span to check.
Expand Down Expand Up @@ -38,12 +39,8 @@ class Available implements Rule

/**
* Create a new rule instance.
*
* @param mixed $startTime
* @param mixed $endTime
* @param string $column = ''
*/
public function __construct($startTime, $endTime, int $ignore = 0, string $column = '')
public function __construct(mixed $startTime, mixed $endTime, int $ignore = 0, string $column = '')
{
// Try to parse the supplied timestamps.
try {
Expand All @@ -59,29 +56,23 @@ public function __construct($startTime, $endTime, int $ignore = 0, string $colum
}

/**
* Determine if the validation rule passes.
*
* @param mixed $value
* Run the validation rule.
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
// Fail validation if timestamps is invalid.
// Fail validation if timestamps are invalid.
if ($this->startTime == null || $this->endTime == null) {
return false;
$fail('The :attribute timestamps are invalid.');
}

// Check if any bookings collide with requested resources within timestamps.
return ! Booking::where(! empty($this->column) ? $this->column : $attribute, $value)
$available = ! Booking::where(! empty($this->column) ? $this->column : $attribute, $value)
->where('id', '!=', $this->ignore)
->between($this->startTime, $this->endTime)
->exists();
}

/**
* Get the validation error message.
*/
public function message(): string
{
return 'The resource is not available during the given time frame.';
if (!$available) {
$fail('The resource is not available during the given time frame.');
}
}
}
51 changes: 33 additions & 18 deletions tests/Unit/Validation/AvailableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,30 @@ class AvailableTest extends TestCase
{
use RefreshDatabase;

private function ruleValidates(Available $rule, $attribute, $value)
{
$passes = true;

$this->app->call([$rule, 'validate'], [
'attribute' => $attribute,
'value' => $value,
'fail' => static function () use (&$passes): void {
$passes = false;
},
]);

return $passes;
}

/**
* Two bookings can't occupy the same resource and time.
*/
public function testSameResourceAndTime(): void
{
$booking = Booking::factory()->create();
$availableRule = new Available($booking->start_time, $booking->end_time);
$rule = new Available($booking->start_time, $booking->end_time);

$this->assertFalse($availableRule->passes('resource_id', $booking->resource_id));
$this->assertFalse($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -30,9 +45,9 @@ public function testSameResourceAndTime(): void
public function testSameTimeDifferentResources(): void
{
$booking = Booking::factory()->create();
$availableRule = new Available($booking->start_time, $booking->end_time);
$rule = new Available($booking->start_time, $booking->end_time);

$this->assertTrue($availableRule->passes('resource_id', Resource::factory()->create()->id));
$this->assertTrue($this->ruleValidates($rule, 'resource_id', Resource::factory()->create()->id));
}

/**
Expand All @@ -41,9 +56,9 @@ public function testSameTimeDifferentResources(): void
public function testOneBookingCanBeIgnored(): void
{
$booking = Booking::factory()->create();
$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertTrue($availableRule->passes('resource_id', $booking->resource_id));
$this->assertTrue($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -62,9 +77,9 @@ public function testBookingCanStartWhenAnotherEnds(): void
'end_time' => Carbon::parse('2017-01-01 14:00:00'),
]);

$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertTrue($availableRule->passes('resource_id', $booking->resource_id));
$this->assertTrue($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -83,9 +98,9 @@ public function testBookingCanEndWhenAnotherStart(): void
'end_time' => Carbon::parse('2017-01-01 13:00:00'),
]);

$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertTrue($availableRule->passes('resource_id', $booking->resource_id));
$this->assertTrue($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -104,9 +119,9 @@ public function testBookingCannotOverlapAWholeOtherBooking(): void
'end_time' => Carbon::parse('2017-01-01 15:00:00'),
]);

$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertFalse($availableRule->passes('resource_id', $booking->resource_id));
$this->assertFalse($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -125,9 +140,9 @@ public function testBookingCannotOverlapStartOfAnotherBooking(): void
'end_time' => Carbon::parse('2017-01-01 13:15:00'),
]);

$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertFalse($availableRule->passes('resource_id', $booking->resource_id));
$this->assertFalse($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -146,9 +161,9 @@ public function testBookingCannotOverlapEndOfAnotherBooking(): void
'end_time' => Carbon::parse('2017-01-01 14:00:00'),
]);

$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertFalse($availableRule->passes('resource_id', $booking->resource_id));
$this->assertFalse($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}

/**
Expand All @@ -167,8 +182,8 @@ public function testBookingCannotOverlapMiddleOfAnotherBooking(): void
'end_time' => Carbon::parse('2017-01-01 12:45:00'),
]);

$availableRule = new Available($booking->start_time, $booking->end_time, $booking->id);
$rule = new Available($booking->start_time, $booking->end_time, $booking->id);

$this->assertFalse($availableRule->passes('resource_id', $booking->resource_id));
$this->assertFalse($this->ruleValidates($rule, 'resource_id', $booking->resource_id));
}
}

0 comments on commit 2c991a1

Please sign in to comment.