Completed
Push — 2.0 ( e0fe81...4515bb )
by grégoire
02:55
created

WriteQueries   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 241
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 11
Bugs 0 Features 4
Metric Value
wmc 14
c 11
b 0
f 4
lcom 1
cbo 5
dl 0
loc 241
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
B insertOne() 0 24 1
A updateOne() 0 9 1
B updateByPk() 0 35 3
A deleteOne() 0 6 1
A deleteByPK() 0 9 1
A deleteWhere() 0 23 3
A createAndSave() 0 7 1
A getEscapedFieldList() 0 9 1
A getParametersList() 0 13 2
1
<?php
2
/*
3
 * This file is part of the PommProject/ModelManager package.
4
 *
5
 * (c) 2014 - 2015 Grégoire HUBERT <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PommProject\ModelManager\Model\ModelTrait;
11
12
use PommProject\Foundation\Where;
13
use PommProject\ModelManager\Exception\ModelException;
14
use PommProject\ModelManager\Model\CollectionIterator;
15
use PommProject\ModelManager\Model\FlexibleEntity\FlexibleEntityInterface;
16
use PommProject\ModelManager\Model\Model;
17
18
/**
19
 * WriteQueries
20
 *
21
 * Basic write queries for model instances.
22
 *
23
 * @package   ModelManager
24
 * @copyright 2014 - 2015 Grégoire HUBERT
25
 * @author    Grégoire HUBERT
26
 * @license   X11 {@link http://opensource.org/licenses/mit-license.php}
27
 */
28
trait WriteQueries
29
{
30
    use ReadQueries;
31
32
    /**
33
     * insertOne
34
     *
35
     * Insert a new entity in the database. The entity is passed by reference.
36
     * It is updated with values returned by the database (ie, default values).
37
     *
38
     * @access public
39
     * @param  FlexibleEntityInterface  $entity
40
     * @return Model                    $this
41
     */
42
    public function insertOne(FlexibleEntityInterface &$entity)
43
    {
44
        $values = $entity->fields(
45
            array_intersect(
46
                array_keys($this->getStructure()->getDefinition()),
47
                array_keys($entity->extract())
48
            )
49
        );
50
        $sql = strtr(
51
            "insert into :relation (:fields) values (:values) returning :projection",
52
            [
53
                ':relation'   => $this->getStructure()->getRelation(),
54
                ':fields'     => $this->getEscapedFieldList(array_keys($values)),
55
                ':projection' => $this->createProjection()->formatFieldsWithFieldAlias(),
56
                ':values'     => join(',', $this->getParametersList($values))
57
            ]);
58
59
        $entity = $this
0 ignored issues
show
Bug introduced by
The method status cannot be called on $this->query($sql, array...es($values))->current() (of type array|null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
60
            ->query($sql, array_values($values))
61
            ->current()
62
            ->status(FlexibleEntityInterface::STATUS_EXIST);
63
64
        return $this;
65
    }
66
67
    /**
68
     * updateOne
69
     *
70
     * Update the entity. ONLY the fields indicated in the $fields array are
71
     * updated. The entity is passed by reference and its values are updated
72
     * with the values from the database. This means all changes not updated
73
     * are lost. The update is made upon a condition on the primary key. If the
74
     * primary key is not fully set, an exception is thrown.
75
     *
76
     * @access public
77
     * @param  FlexibleEntityInterface  $entity
78
     * @param  array                    $fields
79
     * @return Model                    $this
80
     */
81
    public function updateOne(FlexibleEntityInterface &$entity, array $fields)
82
    {
83
        $entity = $this->updateByPk(
84
            $entity->fields($this->getStructure()->getPrimaryKey()),
85
            $entity->fields($fields)
86
        );
87
88
        return $this;
89
    }
90
91
    /**
92
     * updateByPk
93
     *
94
     * Update a record and fetch it with its new values. If no records match
95
     * the given key, null is returned.
96
     *
97
     * @access public
98
     * @param  array          $primary_key
99
     * @param  array          $updates
100
     * @throws ModelException
101
     * @return FlexibleEntityInterface
102
     */
103
    public function updateByPk(array $primary_key, array $updates)
104
    {
105
        $where = $this
106
            ->checkPrimaryKey($primary_key)
107
            ->getWhereFrom($primary_key)
108
            ;
109
        $parameters = $this->getParametersList($updates);
110
        $update_strings = [];
111
112
        foreach ($updates as $field_name => $new_value) {
113
            $update_strings[] = sprintf(
114
                "%s = %s",
115
                $this->escapeIdentifier($field_name),
116
                $parameters[$field_name]
117
            );
118
        }
119
120
        $sql = strtr(
121
            "update :relation set :update where :condition returning :projection",
122
            [
123
                ':relation'   => $this->getStructure()->getRelation(),
124
                ':update'     => join(', ', $update_strings),
125
                ':condition'  => (string) $where,
126
                ':projection' => $this->createProjection()->formatFieldsWithFieldAlias(),
127
            ]
128
        );
129
130
        $iterator = $this->query($sql, array_merge(array_values($updates), $where->getValues()));
131
132
        if ($iterator->isEmpty()) {
133
            return null;
134
        }
135
136
        return $iterator->current()->status(FlexibleEntityInterface::STATUS_EXIST);
0 ignored issues
show
Bug introduced by
The method status cannot be called on $iterator->current() (of type array|null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
137
    }
138
139
    /**
140
     * deleteOne
141
     *
142
     * Delete an entity from a table. Entity is passed by reference and is
143
     * updated with the values fetched from the deleted record.
144
     *
145
     * @access public
146
     * @param  FlexibleEntityInterface  $entity
147
     * @return Model                    $this
148
     */
149
    public function deleteOne(FlexibleEntityInterface &$entity)
150
    {
151
        $entity = $this->deleteByPK($entity->fields($this->getStructure()->getPrimaryKey()));
152
153
        return $this;
154
    }
155
156
    /**
157
     * deleteByPK
158
     *
159
     * Delete a record from its primary key. The deleted entity is returned or
160
     * null if not found.
161
     *
162
     * @access public
163
     * @param  array          $primary_key
164
     * @throws ModelException
165
     * @return FlexibleEntityInterface
166
     */
167
    public function deleteByPK(array $primary_key)
168
    {
169
        $where = $this
170
            ->checkPrimaryKey($primary_key)
171
            ->getWhereFrom($primary_key)
172
        ;
173
174
        return $this->deleteWhere($where)->current();
175
    }
176
177
    /**
178
     * deleteWhere
179
     *
180
     * Delete records by a given condition. A collection of all deleted entries is returned.
181
     *
182
     * @param        $where
183
     * @param  array $values
184
     * @return CollectionIterator
185
     */
186
    public function deleteWhere($where, array $values = [])
187
    {
188
        if (!$where instanceof Where) {
189
            $where = new Where($where, $values);
190
        }
191
192
        $sql = strtr(
193
            "delete from :relation where :condition returning :projection",
194
            [
195
                ':relation'   => $this->getStructure()->getRelation(),
196
                ':condition'  => (string) $where,
197
                ':projection' => $this->createProjection()->formatFieldsWithFieldAlias(),
198
            ]
199
        );
200
201
        $collection = $this->query($sql, $where->getValues());
202
        foreach ($collection as $entity) {
203
            $entity->status(FlexibleEntityInterface::STATUS_NONE);
0 ignored issues
show
Bug introduced by
The method status cannot be called on $entity (of type array|null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
204
        }
205
        $collection->rewind();
206
207
        return $collection;
208
    }
209
210
    /**
211
     * createAndSave
212
     *
213
     * Create a new entity from given values and save it in the database.
214
     *
215
     * @access public
216
     * @param  array          $values
217
     * @return FlexibleEntityInterface
218
     */
219
    public function createAndSave(array $values)
220
    {
221
        $entity = $this->createEntity($values);
222
        $this->insertOne($entity);
223
224
        return $entity;
225
    }
226
227
    /**
228
     * getEscapedFieldList
229
     *
230
     * Return a comma separated list with the given escaped field names.
231
     *
232
     * @access protected
233
     * @param  array  $fields
234
     * @return string
235
     */
236
    public function getEscapedFieldList(array $fields)
237
    {
238
        return join(
239
            ', ',
240
            array_map(
241
                function ($field) { return $this->escapeIdentifier($field); },
242
                $fields
243
            ));
244
    }
245
246
    /**
247
     * getParametersList
248
     *
249
     * Create a parameters list from values.
250
     *
251
     * @access protected
252
     * @param  array    $values
253
     * @return array    $escape codes
254
     */
255
    protected function getParametersList(array $values)
256
    {
257
        $parameters = [];
258
259
        foreach ($values as $name => $value) {
260
            $parameters[$name] = sprintf(
261
                "$*::%s",
262
                $this->getStructure()->getTypeFor($name)
263
            );
264
        }
265
266
        return $parameters;
267
    }
268
}
269