Completed
Pull Request — master (#73)
by San
01:41
created

WriteQueries::deleteOne()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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("insert into :relation (:fields) values (:values) returning :projection", [
51
            ':relation'   => $this->getStructure()->getRelation(),
52
            ':fields'     => $this->getEscapedFieldList(array_keys($values)),
53
            ':projection' => $this->createProjection()->formatFieldsWithFieldAlias(),
54
            ':values'     => join(',', $this->getParametersList($values))
55
        ]);
56
57
        $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...
58
            ->query($sql, array_values($values))
59
            ->current()
60
            ->status(FlexibleEntityInterface::STATUS_EXIST);
61
62
        return $this;
63
    }
64
65
    /**
66
     * updateOne
67
     *
68
     * Update the entity. ONLY the fields indicated in the $fields array are
69
     * updated. The entity is passed by reference and its values are updated
70
     * with the values from the database. This means all changes not updated
71
     * are lost. The update is made upon a condition on the primary key. If the
72
     * primary key is not fully set, an exception is thrown.
73
     *
74
     * @access public
75
     * @param  FlexibleEntityInterface  $entity
76
     * @param  array                    $fields
77
     * @return Model                    $this
78
     */
79
    public function updateOne(FlexibleEntityInterface &$entity, array $fields = [])
80
    {
81
        if (empty($fields)) {
82
            $fields = $entity->getModifiedColumns();
83
        }
84
85
        $entity = $this->updateByPk(
86
            $entity->fields($this->getStructure()->getPrimaryKey()),
87
            $entity->fields($fields)
88
        );
89
90
        return $this;
91
    }
92
93
    /**
94
     * updateByPk
95
     *
96
     * Update a record and fetch it with its new values. If no records match
97
     * the given key, null is returned.
98
     *
99
     * @access public
100
     * @param  array          $primary_key
101
     * @param  array          $updates
102
     * @throws ModelException
103
     * @return FlexibleEntityInterface
104
     */
105
    public function updateByPk(array $primary_key, array $updates)
106
    {
107
        $where = $this
108
            ->checkPrimaryKey($primary_key)
109
            ->getWhereFrom($primary_key)
110
            ;
111
        $parameters = $this->getParametersList($updates);
112
        $update_strings = [];
113
114
        foreach ($updates as $field_name => $new_value) {
115
            $update_strings[] = sprintf(
116
                "%s = %s",
117
                $this->escapeIdentifier($field_name),
118
                $parameters[$field_name]
119
            );
120
        }
121
122
        $sql = strtr("update :relation set :update where :condition returning :projection", [
123
            ':relation'   => $this->getStructure()->getRelation(),
124
            ':update'     => join(', ', $update_strings),
125
            ':condition'  => (string) $where,
126
            ':projection' => $this->createProjection()->formatFieldsWithFieldAlias(),
127
        ]);
128
129
        $iterator = $this->query($sql, array_merge(array_values($updates), $where->getValues()));
130
131
        if ($iterator->isEmpty()) {
132
            return null;
133
        }
134
135
        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...
136
    }
137
138
    /**
139
     * deleteOne
140
     *
141
     * Delete an entity from a table. Entity is passed by reference and is
142
     * updated with the values fetched from the deleted record.
143
     *
144
     * @access public
145
     * @param  FlexibleEntityInterface  $entity
146
     * @return Model                    $this
147
     */
148
    public function deleteOne(FlexibleEntityInterface &$entity)
149
    {
150
        $entity = $this->deleteByPK($entity->fields($this->getStructure()->getPrimaryKey()));
151
152
        return $this;
153
    }
154
155
    /**
156
     * deleteByPK
157
     *
158
     * Delete a record from its primary key. The deleted entity is returned or
159
     * null if not found.
160
     *
161
     * @access public
162
     * @param  array          $primary_key
163
     * @throws ModelException
164
     * @return FlexibleEntityInterface
165
     */
166
    public function deleteByPK(array $primary_key)
167
    {
168
        $where = $this
169
            ->checkPrimaryKey($primary_key)
170
            ->getWhereFrom($primary_key)
171
        ;
172
173
        return $this->deleteWhere($where)->current();
174
    }
175
176
    /**
177
     * deleteWhere
178
     *
179
     * Delete records by a given condition. A collection of all deleted entries is returned.
180
     *
181
     * @param        $where
182
     * @param  array $values
183
     * @return CollectionIterator
184
     */
185
    public function deleteWhere($where, array $values = [])
186
    {
187
        if (!$where instanceof Where) {
188
            $where = new Where($where, $values);
189
        }
190
191
        $sql = strtr(
192
            "delete from :relation where :condition returning :projection",
193
            [
194
                ':relation'   => $this->getStructure()->getRelation(),
195
                ':condition'  => (string) $where,
196
                ':projection' => $this->createProjection()->formatFieldsWithFieldAlias(),
197
            ]
198
        );
199
200
        $collection = $this->query($sql, $where->getValues());
201
        foreach ($collection as $entity) {
202
            $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...
203
        }
204
        $collection->rewind();
205
206
        return $collection;
207
    }
208
209
    /**
210
     * createAndSave
211
     *
212
     * Create a new entity from given values and save it in the database.
213
     *
214
     * @access public
215
     * @param  array          $values
216
     * @return FlexibleEntityInterface
217
     */
218
    public function createAndSave(array $values)
219
    {
220
        $entity = $this->createEntity($values);
221
        $this->insertOne($entity);
222
223
        return $entity;
224
    }
225
226
    /**
227
     * getEscapedFieldList
228
     *
229
     * Return a comma separated list with the given escaped field names.
230
     *
231
     * @access protected
232
     * @param  array  $fields
233
     * @return string
234
     */
235
    public function getEscapedFieldList(array $fields)
236
    {
237
        return join(
238
            ', ',
239
            array_map(function ($field) {
240
                return $this->escapeIdentifier($field);
241
            }, $fields)
242
        );
243
    }
244
245
    /**
246
     * getParametersList
247
     *
248
     * Create a parameters list from values.
249
     *
250
     * @access protected
251
     * @param  array    $values
252
     * @return array    $escape codes
253
     */
254
    protected function getParametersList(array $values)
255
    {
256
        $parameters = [];
257
258
        foreach ($values as $name => $value) {
259
            $parameters[$name] = sprintf(
260
                "$*::%s",
261
                $this->getStructure()->getTypeFor($name)
262
            );
263
        }
264
265
        return $parameters;
266
    }
267
}
268