Completed
Push — develop ( 64da83...d844ac )
by Mathieu
01:46
created

DBCollection::save()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 8
nop 0
dl 0
loc 23
ccs 0
cts 13
cp 0
crap 20
rs 9.8333
c 0
b 0
f 0
1
<?php
2
namespace Suricate;
3
4
class DBCollection extends Collection
5
{
6
    /* @var string SQL table name */
7
    protected $tableName        = '';
8
    /* @var string Item type stored in collection */
9
    protected $itemsType        = '';
10
    /* @var string Database configuration identifier */
11
    protected $DBConfig         = '';
12
    /* @var string Name of parent identifier field */
13
    protected $parentIdField    = 'parent_id';
14
    /** @var string Parent Object type */
15
    protected $parentType       = '';
16
17
    protected $mapping          = [];
18
    protected $lazyLoad = false;
19
    protected $parentId;                       // Id of the parent
20
    protected $parentFilterName;                // Name of field used for filtering
21
    protected $parentFilterType;                // Value of filter
22
23
24
    protected $itemOffset        = 0;
25
26
    /**
27
     * Get table name
28
     *
29
     * @return string
30
     */
31 1
    public function getTableName(): string
32
    {
33 1
        return $this->tableName;
34
    }
35
36 1
    public function getItemsType(): string
37
    {
38 1
        return $this->itemsType;
39
    }
40
41 1
    public function getDBConfig(): string
42
    {
43 1
        return $this->DBConfig;
44
    }
45
46 1
    public function getParentIdField(): string
47
    {
48 1
        return $this->parentIdField;
49
    }
50
51
    public function getParentType()
52
    {
53
        return $this->parentType;
54
    }
55
56
    public function getParentId()
57
    {
58
        return $this->parentId;
59
    }
60
61
    /**
62
     * Set lazyload flag
63
     *
64
     * @param bool $lazyLoad
65
     * @return DBCollection
66
     */
67
    public function setLazyLoad($lazyLoad)
68
    {
69
        $this->lazyLoad = $lazyLoad;
70
71
        return $this;
72
    }
73
74
    /**
75
     * Get lazyload flag
76
     *
77
     * @return boolean
78
     */
79
    public function getLazyLoad(): bool
80
    {
81
        return $this->lazyLoad;
82
    }
83
84
    public function purgeItems()
85
    {
86
        $this->items        = [];
87
        $this->mapping      = [];
88
        $this->itemOffset   = 0;
89
    }
90
91
    /**
92
     * Load entire table into collection
93
     * @return Collection Loaded collection
94
     */
95
    public static function loadAll()
96
    {
97
        $calledClass    = get_called_class();
98
        $collection     = new $calledClass;
99
100
        $sqlParams      = [];
101
102
        $sql  = "SELECT *";
103
        $sql .= "   FROM `" . $collection::getTableName() . "`";
104
105
        if ($collection->parentFilterType !== '' && $collection->parentFilterType != null) {
106
            $sql .= "WHERE " . $collection->parentFilterName . "=:type";
107
            $sqlParams['type'] = $collection->parentFilterType;
108
        }
109
        $dbLink = Suricate::Database();
0 ignored issues
show
Bug introduced by
The method Database() does not exist on Suricate\Suricate. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

109
        /** @scrutinizer ignore-call */ 
110
        $dbLink = Suricate::Database();
Loading history...
110
        if ($collection->getDBConfig() !== '') {
111
            $dbLink->setConfig($collection->getDBConfig());
112
        }
113
        $results = $dbLink->query($sql, $sqlParams)->fetchAll();
114
115
        if ($results !== false) {
116
            foreach ($results as $currentResult) {
117
                $itemName = $collection->getItemsType();
118
                $collection->addItem($itemName::instanciate($currentResult));
119
            }
120
        }
121
122
        return $collection;
123
    }
124
125
    /**
126
     * Static wrapper for loadFromSql
127
     * @param  string     $sql       SQL Statement
128
     * @param  array      $sqlParams SQL Parameters
129
     * @return Collection Loaded collection
130
     */
131
    public static function buildFromSql($sql, $sqlParams = [])
132
    {
133
        $calledClass = get_called_class();
134
        $collection = new $calledClass;
135
136
        $collection->loadFromSql($sql, $sqlParams);
137
138
        return $collection;
139
    }
140
141
    public function loadFromSql($sql, $sqlParams = [])
142
    {
143
        $dbLink = Suricate::Database();
144
        if ($this->DBConfig !== '') {
145
            $dbLink->setConfig($this->DBConfig);
146
        }
147
148
        $results = Suricate::Database()->query($sql, $sqlParams)->fetchAll();
149
150
        if ($results !== false) {
151
            foreach ($results as $currentResult) {
152
                $itemName = $this->getItemsType();
153
                $this->addItem($itemName::instanciate($currentResult));
154
            }
155
        }
156
157
        return $this;
158
    }
159
160
    public function addItemLink($linkId)
161
    {
162
         $this->items[$this->itemOffset] = $linkId;
163
         // add mapping between item->index and $position in items pool
164
         $this->mapping[$this->itemOffset] = $linkId;
165
         $this->itemOffset++;
166
    }
167
168
    public function lazyLoadFromSql($sql, $sqlParams = array())
169
    {
170
        $dbLink = Suricate::Database();
171
        if ($this->DBConfig !== '') {
172
            $dbLink->setConfig($this->DBConfig);
173
        }
174
175
        $results = $dbLink
176
            ->query($sql, $sqlParams)
177
            ->fetchAll();
178
179
        if ($results !== false) {
180
            foreach ($results as $currentResult) {
181
                $this->addItemLink(current($currentResult));
182
            }
183
        }
184
185
        return $this;
186
    }
187
188
    /**
189
     * Load items linked to a parentId
190
     * @param mixed        $parentId       Parent id description
191
     * @param string       $parentIdField  Name of parent id referencing field
192
     * @param \Closure|null $validate       Callback use to validate add to items collection
193
     */
194
    public static function loadForParentId($parentId, $parentIdField = null, $validate = null)
195
    {
196
        $calledClass   = get_called_class();
197
        $collection     = new $calledClass;
198
199
        if ($parentId != '') {
200
            $sqlParams     = [];
201
            $dbHandler     = Suricate::Database(true);
202
203
            if ($collection->getDBConfig() !== '') {
204
                $dbHandler->setConfig($collection->getDBConfig());
205
            }
206
207
            $sql  = "SELECT *";
208
            $sql .= " FROM `" . $collection->getTableName() . "`";
209
            $sql .= " WHERE";
210
            if ($parentIdField !== null) {
211
                $sql .= "`" . $parentIdField . "`=:parent_id";
212
            } else {
213
                $sql .= "`" . $collection->getParentIdField() . "`=:parent_id";
214
            }
215
216
            if ($collection->parentFilterType !== null) {
217
                $sql .= "   AND " . $collection->parentFilterName . "=:parent_type";
218
                $sqlParams['parent_type'] = $collection->parentFilterType;
219
            }
220
221
            $sqlParams['parent_id'] = $parentId;
222
            $results = $dbHandler->query($sql, $sqlParams)->fetchAll();
223
224
            if ($results !== false) {
225
                foreach ($results as $currentResult) {
226
                    $itemName = $collection->getItemsType();
227
                    $item = $itemName::instanciate($currentResult);
228
                    if ($validate === null || $validate($item)) {
229
                        $collection->addItem($item);
230
                    }
231
                }
232
            }
233
234
            $collection->parentId = $parentId;
235
        }
236
237
        return $collection;
238
    }
239
240
    public function setParentIdForAll($parentId)
241
    {
242
        $this->parentId = $parentId;
243
        foreach (array_keys($this->items) as $key) {
244
            $this->items[$key]->{$this->parentIdField} = $parentId;
245
        }
246
    }
247
248
    /**
249
     * Load Parent Item, if item type is defined
250
     */
251
    public function loadParent()
252
    {
253
        if ($this->parentType !== '' && $this->parentId != '') {
254
            $parentObjectType = $this->parentType;
255
            $parent = new $parentObjectType();
256
            if (method_exists($parent, 'load')) {
257
                $parent->load($this->parentId);
258
259
                return $parent;
260
            } else {
261
                throw new \BadMethodCallException('Parent object does not have a load($id) method');
262
            }
263
        } else {
264
            throw new \BadMethodCallException('self::$parentType is not defined');
265
        }
266
    }
267
268
    public function craftItem($itemData)
269
    {
270
        $itemName = $this->itemsType;
271
272
        foreach ($itemData as $data) {
273
            $newItem = new $itemName();
274
            $newItem->{$this->parentIdField} = $this->parentId;
275
            $hasData = false;
276
            foreach ($data as $field => $value) {
277
                $newItem->$field = $value;
278
                if ($value != '') {
279
                    $hasData = true;
280
                }
281
            }
282
283
            // Only add item if there's data inside
284
            if ($hasData) {
285
                $this->addItem($newItem);
286
            }
287
        }
288
    }
289
290
    public function save()
291
    {
292
        // 1st step : delete all records for current parentId
293
        $sql  = "DELETE FROM `" . $this->tableName . "`";
294
        if ($this->parentIdField !== '') {
295
            $sql .= " WHERE";
296
            $sql .= "   `" . $this->parentIdField . "`=:parent_id";
297
298
            $sqlParams = array('parent_id' => $this->parentId);
299
        } else {
300
            $sqlParams = array();
301
        }
302
303
        $dbLink = Suricate::Database();
304
        if ($this->DBConfig !== '') {
305
            $dbLink->setConfig($this->DBConfig);
306
        }
307
        
308
        $dbLink->query($sql, $sqlParams);
309
310
        // 2nd step : save all current items
311
        foreach ($this->items as $currentItem) {
312
            $currentItem->save(true); // Force insert
313
        }
314
    }
315
316
    public function addItem(Interfaces\IDBObject $item)
317
    {
318
        $key = $item->getTableIndex();
319
        // Add item to items pool
320
        $this->items[$this->itemOffset] = $item;
321
322
        // add mapping between item->index and $position in items pool
323
        $this->mapping[$this->itemOffset] = $item->$key;
324
325
        $this->itemOffset++;
326
327
        return $this;
328
    }
329
}
330