Skip to content

Commit 61e39d8

Browse files
committed
Add voucher validation rule
1 parent 957e25d commit 61e39d8

File tree

5 files changed

+161
-0
lines changed

5 files changed

+161
-0
lines changed

src/Rules/Voucher.php

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace BeyondCode\Vouchers\Rules;
4+
5+
use Vouchers;
6+
use Illuminate\Contracts\Validation\Rule;
7+
use BeyondCode\Vouchers\Exceptions\VoucherExpired;
8+
use BeyondCode\Vouchers\Exceptions\VoucherIsInvalid;
9+
use BeyondCode\Vouchers\Exceptions\VoucherAlreadyRedeemed;
10+
11+
class Voucher implements Rule
12+
{
13+
protected $isInvalid = false;
14+
protected $isExpired = false;
15+
protected $wasRedeemd = false;
16+
17+
/**
18+
* Determine if the validation rule passes.
19+
*
20+
* @param string $attribute
21+
* @param mixed $value
22+
* @return bool
23+
*/
24+
public function passes($attribute, $value)
25+
{
26+
try {
27+
$voucher = Vouchers::check($value);
28+
29+
// Check if the voucher was already redeemed
30+
if (auth()->check() && $voucher->users()->wherePivot('user_id', auth()->id())->exists()) {
31+
throw VoucherAlreadyRedeemed::create($voucher);
32+
}
33+
} catch (VoucherIsInvalid $exception) {
34+
$this->isInvalid = true;
35+
return false;
36+
} catch (VoucherExpired $exception) {
37+
$this->isExpired = true;
38+
return false;
39+
} catch (VoucherAlreadyRedeemed $exception) {
40+
$this->wasRedeemd = true;
41+
return false;
42+
}
43+
44+
return true;
45+
}
46+
47+
/**
48+
* Get the validation error message.
49+
*
50+
* @return string
51+
*/
52+
public function message()
53+
{
54+
if ($this->wasRedeemd) {
55+
return trans('vouchers::validation.code_redeemed');
56+
}
57+
if ($this->isExpired) {
58+
return trans('vouchers::validation.code_expired');
59+
}
60+
return trans('vouchers::validation.code_invalid');
61+
}
62+
}

src/Vouchers.php

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace BeyondCode\Vouchers;
44

5+
use BeyondCode\Vouchers\Exceptions\VoucherExpired;
56
use BeyondCode\Vouchers\Exceptions\VoucherIsInvalid;
67
use BeyondCode\Vouchers\Models\Voucher;
78
use Illuminate\Database\Eloquent\Model;
@@ -61,6 +62,7 @@ public function create(Model $model, int $amount = 1, array $data = [], $expires
6162
/**
6263
* @param string $code
6364
* @throws VoucherIsInvalid
65+
* @throws VoucherExpired
6466
* @return Voucher
6567
*/
6668
public function check(string $code)
@@ -70,6 +72,9 @@ public function check(string $code)
7072
if ($voucher === null) {
7173
throw VoucherIsInvalid::withCode($code);
7274
}
75+
if ($voucher->isExpired()) {
76+
throw VoucherExpired::create($voucher);
77+
}
7378

7479
return $voucher;
7580
}

src/VouchersServiceProvider.php

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class VouchersServiceProvider extends ServiceProvider
1111
*/
1212
public function boot()
1313
{
14+
$this->loadTranslationsFrom(__DIR__.'/../translations', 'vouchers');
15+
1416
if ($this->app->runningInConsole()) {
1517
$this->publishes([
1618
__DIR__.'/../config/config.php' => config_path('vouchers.php'),
@@ -22,6 +24,10 @@ public function boot()
2224
__DIR__.'/../database/migrations/create_vouchers_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_vouchers_table.php'),
2325
], 'migrations');
2426
}
27+
28+
$this->publishes([
29+
__DIR__.'/../translations' => resource_path('lang/vendor/vouchers'),
30+
], 'translations');
2531
}
2632
}
2733

tests/VoucherRuleTest.php

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
namespace BeyondCode\Vouchers\Tests;
4+
5+
use Vouchers;
6+
use Validator;
7+
use BeyondCode\Vouchers\Rules\Voucher;
8+
use BeyondCode\Vouchers\Tests\Models\User;
9+
use BeyondCode\Vouchers\Tests\Models\Item;
10+
11+
class VoucherRuleTest extends TestCase
12+
{
13+
14+
/**
15+
* @return \Illuminate\Validation\Validator
16+
*/
17+
protected function validator($code)
18+
{
19+
return Validator::make(['code' => $code], ['code' => new Voucher()]);
20+
}
21+
22+
/** @test */
23+
public function it_validated_voucher_codes()
24+
{
25+
$item = Item::create(['name' => 'Foo']);
26+
27+
$vouchers = Vouchers::create($item);
28+
29+
$this->assertTrue($this->validator($vouchers[0]->code)->passes());
30+
$this->assertTrue($this->validator('invalid')->fails());
31+
}
32+
33+
/** @test */
34+
public function it_returns_correct_error_messages_for_invalid_vouchers()
35+
{
36+
$validator = $this->validator('invalid');
37+
$validator->passes();
38+
39+
$message = $validator->messages()->first('code');
40+
41+
$this->assertSame('The voucher code is invalid.', $message);
42+
}
43+
44+
/** @test */
45+
public function it_returns_correct_error_messages_for_redeemed_vouchers()
46+
{
47+
$item = Item::create(['name' => 'Foo']);
48+
$vouchers = Vouchers::create($item);
49+
50+
$user = User::first();
51+
$user->redeemCode($vouchers[0]->code);
52+
53+
auth()->login($user);
54+
55+
$validator = $this->validator($vouchers[0]->code);
56+
57+
$this->assertTrue($validator->fails());
58+
59+
$message = $validator->messages()->first('code');
60+
61+
$this->assertSame('The voucher code was already redeemed.', $message);
62+
}
63+
64+
/** @test */
65+
public function it_returns_correct_error_messages_for_expired_vouchers()
66+
{
67+
$item = Item::create(['name' => 'Foo']);
68+
$vouchers = Vouchers::create($item, 1, [], now()->subDay(1));
69+
70+
$validator = $this->validator($vouchers[0]->code);
71+
72+
$this->assertTrue($validator->fails());
73+
74+
$message = $validator->messages()->first('code');
75+
76+
$this->assertSame('The voucher code is already expired.', $message);
77+
}
78+
79+
}

translations/en/validation.php

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
return [
4+
5+
'code_invalid' => 'The voucher code is invalid.',
6+
'code_redeemed' => 'The voucher code was already redeemed.',
7+
'code_expired' => 'The voucher code is already expired.',
8+
9+
];

0 commit comments

Comments
 (0)