Passed
Push — master ( b12120...7f2d87 )
by Valentin
04:10 queued 01:33
created

EntityCheckerTest::testExistsByField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Framework\Validation;
6
7
use Cycle\ORM\TransactionInterface;
8
use Spiral\App\TestApp;
9
use Spiral\App\User\User;
10
use Spiral\Database\Database;
11
use Spiral\Database\DatabaseInterface;
12
use Spiral\Framework\BaseTest;
13
use Spiral\Validation\ValidationInterface;
14
use Throwable;
15
16
class EntityCheckerTest extends BaseTest
17
{
18
    /** @var TestApp */
19
    private $app;
20
21
    public function setUp(): void
22
    {
23
        $this->app = $this->makeApp();
24
25
        /** @var Database $database */
26
        $database = $this->app->get(DatabaseInterface::class);
27
28
        $table = $database->table('users')->getSchema();
29
        $table->primary('id');
30
        $table->string('name');
31
        $table->save();
32
    }
33
34
    /**
35
     * @throws Throwable
36
     */
37
    public function testExistsByPK(): void
38
    {
39
        /** @var TransactionInterface $transaction */
40
        $transaction = $this->app->get(TransactionInterface::class);
41
        $transaction->persist(new User('Valentin'));
42
        $transaction->run();
43
44
        $this->assertFalse($this->exists(2));
45
        $this->assertTrue($this->exists(1));
46
    }
47
48
    /**
49
     * @throws Throwable
50
     */
51
    public function testExistsByField(): void
52
    {
53
        /** @var TransactionInterface $transaction */
54
        $transaction = $this->app->get(TransactionInterface::class);
55
        $transaction->persist(new User('Valentin'));
56
        $transaction->run();
57
58
        $this->assertFalse($this->exists('John', 'name'));
59
        $this->assertTrue($this->exists('Valentin', 'name'));
60
    }
61
62
    /**
63
     * @throws Throwable
64
     */
65
    public function testSimpleUnique(): void
66
    {
67
        /** @var TransactionInterface $transaction */
68
        $transaction = $this->app->get(TransactionInterface::class);
69
        $transaction->persist(new User('Valentin'));
70
        $transaction->persist(new User('Anton'));
71
        $transaction->run();
72
73
        $this->assertTrue($this->isUnique('John', 'name'));
74
        $this->assertFalse($this->isUnique('Valentin', 'name'));
75
    }
76
77
    /**
78
     * @throws Throwable
79
     */
80
    public function testContextualUnique(): void
81
    {
82
        $user1 = new User('Valentin');
83
        $user2 = new User('Anton');
84
        $user3 = new User('John');
85
86
        /** @var TransactionInterface $transaction */
87
        $transaction = $this->app->get(TransactionInterface::class);
88
        $transaction->persist($user1);
89
        $transaction->persist($user2);
90
        $transaction->persist($user3);
91
        $transaction->run();
92
93
        //context match
94
        $this->assertTrue($this->isUnique('Valentin', 'name', [], $user1));
95
        $this->assertTrue($this->isUnique('Valentin', 'name', [], $user1, ['id']));
96
        $this->assertTrue($this->isUnique('Valentin', 'name', ['id' => 1], $user1, ['id']));
97
98
        //context mismatch, unique in db
99
        $this->assertTrue($this->isUnique('Valentin', 'name', ['id' => 2], $user1, ['id']));
100
        $this->assertTrue($this->isUnique('Valentin', 'name', ['id' => 2], $user3, ['id']));
101
102
        //context mismatch, not unique in db
103
        $this->assertFalse($this->isUnique('Valentin', 'name', [], $user2));
104
        $this->assertFalse($this->isUnique('Valentin', 'name', [], $user2, ['id']));
105
    }
106
107
    /**
108
     * @param mixed       $value
109
     * @param string|null $field
110
     * @return bool
111
     */
112
    private function exists($value, ?string $field = null): bool
113
    {
114
        /** @var ValidationInterface $validator */
115
        $validator = $this->app->get(ValidationInterface::class);
116
        $validator = $validator->validate(
117
            ['value' => $value],
118
            ['value' => [['entity::exists', User::class, $field]]]
119
        );
120
121
        return $validator->isValid();
122
    }
123
124
    /**
125
     * @param string      $value
126
     * @param string      $field
127
     * @param array       $data
128
     * @param object|null $context
129
     * @param string[]    $fields
130
     * @return bool
131
     */
132
    private function isUnique(
133
        string $value,
134
        string $field,
135
        array $data = [],
136
        ?object $context = null,
137
        array $fields = []
138
    ): bool {
139
        /** @var ValidationInterface $validator */
140
        $validator = $this->app->get(ValidationInterface::class);
141
        $validator = $validator->validate(
142
            ['value' => $value] + $data,
143
            ['value' => [['entity::unique', User::class, $field, $fields]]]
144
        );
145
        if ($context !== null) {
146
            $validator = $validator->withContext($context);
147
        }
148
149
        return $validator->isValid();
150
    }
151
}
152