Completed
Push — master ( 5b5abc...10afaf )
by Phil
02:13
created

SqlStore   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 0%

Importance

Changes 8
Bugs 2 Features 1
Metric Value
wmc 13
c 8
b 2
f 1
lcom 1
cbo 4
dl 0
loc 167
ccs 0
cts 78
cp 0
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A create() 0 6 1
A insertEntity() 0 8 1
A read() 0 5 1
A update() 0 6 1
A updateEntity() 0 9 1
A delete() 0 5 1
A deleteEntity() 0 8 1
A collectionIterator() 0 16 3
A relationships() 0 19 2
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');
45
    }
46
47
    /**
48
     * Insert an entity to the database.
49
     *
50
     * @param \Percy\Entity\EntityInterface $entity
51
     *
52
     * @return void
53
     */
54
    protected function insertEntity(EntityInterface $entity)
55
    {
56
        $insert = $this->query->newInsert();
57
        $insert->into($entity->getDataSource());
58
        $insert->cols($entity->getData([]));
59
60
        $this->dbal->perform($insert->getStatement(), $insert->getBindValues());
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66
    public function read(Collection $collection, array $scopes = [])
67
    {
68
        // mysql need do nothing with the data on a read request
69
        return true;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function update(Collection $collection, array $scopes = [])
76
    {
77
        $this->decorate($collection, StoreInterface::ON_UPDATE);
78
        $this->validate($collection);
79
        return $this->collectionIterator($collection, 'updateEntity');
80
    }
81
82
    /**
83
     * Update an entity in the database.
84
     *
85
     * @param \Percy\Entity\EntityInterface $entity
86
     *
87
     * @return void
88
     */
89
    protected function updateEntity(EntityInterface $entity)
90
    {
91
        $update = $this->query->newUpdate();
92
        $update->table($entity->getDataSource());
93
        $update->cols($entity->getData([]));
94
        $update->where(sprintf('%s = ?', $entity->getPrimary()), $entity[$entity->getPrimary()]);
95
96
        $this->dbal->perform($update->getStatement(), $update->getBindValues());
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function delete(Collection $collection, array $scopes = [])
103
    {
104
        $this->decorate($collection, StoreInterface::ON_DELETE);
105
        return $this->collectionIterator($collection, 'deleteEntity');
106
    }
107
108
    /**
109
     * Delete an entity from the database. Be aware, this handles hard deletes.
110
     * To handle soft deletes, extend this class and overload this method.
111
     *
112
     * @param \Percy\Entity\EntityInterface $entity
113
     *
114
     * @return void
115
     */
116
    protected function deleteEntity(EntityInterface $entity)
117
    {
118
        $delete = $this->query->newDelete();
119
        $delete->from($entity->getDataSource());
120
        $delete->where(sprintf('%s = ?', $entity->getPrimary()), $entity[$entity->getPrimary()]);
121
122
        $this->dbal->perform($delete->getStatement(), $delete->getBindValues());
123
    }
124
125
    /**
126
     * Iterate a collection with the correct callback.
127
     *
128
     * @param \Percy\Entity\Collection $collection
129
     * @param string                   $callable
130
     *
131
     * @return boolean
132
     */
133
    protected function collectionIterator(Collection $collection, $callable)
134
    {
135
        $this->dbal->beginTransaction();
136
137
        try {
138
            foreach ($collection->getIterator() as $entity) {
139
                call_user_func_array([$this, $callable], [$entity]);
140
            }
141
        } catch (PDOException $e) {
142
            $this->dbal->rollBack();
143
            return false;
144
        }
145
146
        $this->dbal->commit();
147
        return true;
148
    }
149
    
150
    /**
151
     * Persist relationships to data store.
152
     *
153
     * @param \Percy\Entity\EntityInterface $entity
154
     * @param array                         $rels
155
     * @param array                         $map
156
     *
157
     * @return void
158
     */
159
    public function relationships(EntityInterface $entity, array $rels, array $map)
160
    {
161
        $this->dbal->beginTransaction();
162
163
        foreach ($rels as $rel) {
164
            $data = [
165
                $map['defined_in']['primary']  => $entity[$map['defined_in']['entity']],
166
                $map['target']['relationship'] => $rel
167
            ];
168
169
            $insert = $this->query->newInsert();
170
            $insert->into($map['defined_in']['table']);
171
            $insert->cols($data);
172
173
            $this->dbal->perform($insert->getStatement(), $insert->getBindValues());
174
        }
175
176
        $this->dbal->commit();
177
    }
178
}
179