Completed
Pull Request — master (#43)
by James
04:29
created

SqlStore::deleteRelationships()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 15
ccs 0
cts 12
cp 0
rs 9.4285
cc 2
eloc 9
nc 2
nop 3
crap 6
1
<?php
2
3
namespace Percy\Store;
4
5
use Aura\Filter\FilterFactory;
6
use Aura\SqlQuery\QueryFactory;
7
use Aura\Sql\ExtendedPdo;
8
use PDOException;
9
use Percy\Entity\Collection;
10
use Percy\Entity\EntityInterface;
11
12
class SqlStore extends AbstractStore
13
{
14
    /**
15
     * @var \Aura\Sql\ExtendedPdo
16
     */
17
    protected $dbal;
18
19
    /**
20
     * @var \Aura\SqlQuery\QueryFactory
21
     */
22
    protected $query;
23
24
    /**
25
     * Construct.
26
     *
27
     * @param \Aura\Sql\ExtendedPdo      $dbal
28
     * @param \Aura\Filter\FilterFactory $filter
29
     */
30
    public function __construct(ExtendedPdo $dbal, FilterFactory $filter)
31
    {
32
        $this->dbal  = $dbal;
33
        $this->query = new QueryFactory('mysql');
34
        parent::__construct($filter);
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40
    public function create(Collection $collection, array $scopes = [])
41
    {
42
        $this->decorate($collection, StoreInterface::ON_CREATE);
43
        $this->validate($collection);
44
        return $this->collectionIterator($collection, 'insertEntity', $scopes);
45
    }
46
47
    /**
48
     * Insert an entity to the database.
49
     *
50
     * @param \Percy\Entity\EntityInterface $entity
51
     * @param array                         $scopes
52
     *
53
     * @return void
54
     */
55
    protected function insertEntity(EntityInterface $entity, array $scopes = [])
56
    {
57
        $insert = $this->query->newInsert();
58
        $insert->into($entity->getDataSource());
59
        $insert->cols($entity->getData($scopes, true));
60
61
        $this->dbal->perform($insert->getStatement(), $insert->getBindValues());
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function read(Collection $collection, array $scopes = [])
68
    {
69
        // mysql need do nothing with the data on a read request
70
        return true;
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76
    public function update(Collection $collection, array $scopes = [])
77
    {
78
        $this->decorate($collection, StoreInterface::ON_UPDATE);
79
        $this->validate($collection);
80
        return $this->collectionIterator($collection, 'updateEntity', $scopes);
81
    }
82
83
    /**
84
     * Update an entity in the database.
85
     *
86
     * @param \Percy\Entity\EntityInterface $entity
87
     * @param array                         $scopes
88
     *
89
     * @return void
90
     */
91
    protected function updateEntity(EntityInterface $entity, array $scopes = [])
92
    {
93
        $update = $this->query->newUpdate();
94
        $update->table($entity->getDataSource());
95
        $update->cols($entity->getData($scopes, true));
96
        $update->where(sprintf('%s = ?', $entity->getPrimary()), $entity[$entity->getPrimary()]);
97
98
        $this->dbal->perform($update->getStatement(), $update->getBindValues());
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function delete(Collection $collection, array $scopes = [])
105
    {
106
        $this->decorate($collection, StoreInterface::ON_DELETE);
107
        return $this->collectionIterator($collection, 'deleteEntity', $scopes);
108
    }
109
110
    /**
111
     * Delete an entity from the database. Be aware, this handles hard deletes.
112
     * To handle soft deletes, extend this class and overload this method.
113
     *
114
     * @param \Percy\Entity\EntityInterface $entity
115
     * @param array                         $scopes
116
     *
117
     * @return void
118
     */
119
    protected function deleteEntity(EntityInterface $entity, array $scopes = [])
120
    {
121
        // ensure write scopes
122
        $entity->getData($scopes, true);
123
124
        $delete = $this->query->newDelete();
125
        $delete->from($entity->getDataSource());
126
        $delete->where(sprintf('%s = ?', $entity->getPrimary()), $entity[$entity->getPrimary()]);
127
128
        $this->dbal->perform($delete->getStatement(), $delete->getBindValues());
129
    }
130
131
    /**
132
     * Iterate a collection with the correct callback.
133
     *
134
     * @param \Percy\Entity\Collection $collection
135
     * @param string                   $callable
136
     *
137
     * @return boolean
138
     */
139
    protected function collectionIterator(Collection $collection, $callable, array $scopes = [])
140
    {
141
        $this->dbal->beginTransaction();
142
143
        try {
144
            foreach ($collection->getIterator() as $entity) {
145
                call_user_func_array([$this, $callable], [$entity, $scopes]);
146
            }
147
        } catch (PDOException $e) {
148
            $this->dbal->rollBack();
149
            return false;
150
        }
151
152
        $this->dbal->commit();
153
        return true;
154
    }
155
156
    /**
157
     * Persist relationships to data store.
158
     *
159
     * @param \Percy\Entity\EntityInterface $entity
160
     * @param array                         $rels
161
     * @param array                         $map
162
     *
163
     * @return void
164
     */
165
    public function relationships(EntityInterface $entity, array $rels, array $map)
166
    {
167
        $this->dbal->beginTransaction();
168
169
        foreach ($rels as $rel) {
170
            $data = [
171
                $map['defined_in']['primary']  => $entity[$map['defined_in']['entity']],
172
                $map['target']['relationship'] => $rel
173
            ];
174
175
            $insert = $this->query->newInsert();
176
            $insert->into($map['defined_in']['table']);
177
            $insert->cols($data);
178
179
            $this->dbal->perform($insert->getStatement(), $insert->getBindValues());
180
        }
181
182
        $this->dbal->commit();
183
    }
184
    
185
    /**
186
     * Remove relationships.
187
     *
188
     * @param \Percy\Entity\EntityInterface $entity
189
     * @param array                         $rels
190
     * @param array                         $map
191
     *
192
     * @return void
193
     */
194
    public function deleteRelationships(EntityInterface $entity, array $rels, array $map)
195
    {
196
        $this->dbal->beginTransaction();
197
198
        foreach ($rels as $rel) {
199
            $delete = $this->query->newDelete();
200
            $delete->from($map['defined_in']['table']);
201
            $delete->where(sprintf('%s = :%s', $map['defined_in']['primary'], $map['defined_in']['entity']));
202
            $delete->bindValue('uuid', $entity[$map['defined_in']['entity']]);
203
204
            $this->dbal->perform($delete->getStatement(), $delete->getBindValues());
205
        }
206
207
        $this->dbal->commit();
208
    }
209
}
210