Passed
Push — develop ( 59c81d...575dfb )
by Mathieu
01:46
created

DBCollection::getDBConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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
    protected $dbLink               = false;
24
    protected $itemOffset           = 0;
25
26
    /**
27
     * Get table name
28
     *
29
     * @return string
30
     */
31 2
    public function getTableName(): string
32
    {
33 2
        return $this->tableName;
34
    }
35
36 4
    public function getItemsType(): string
37
    {
38 4
        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 1
    public function getParentId()
57
    {
58 1
        return $this->parentId;
59
    }
60
61
    /**
62
     * Set lazyload flag
63
     *
64
     * @param bool $lazyLoad
65
     * @return DBCollection
66
     */
67 1
    public function setLazyLoad($lazyLoad)
68
    {
69 1
        $this->lazyLoad = $lazyLoad;
70
71 1
        return $this;
72
    }
73
74
    /**
75
     * Get lazyload flag
76
     *
77
     * @return boolean
78
     */
79 1
    public function getLazyLoad(): bool
80
    {
81 1
        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 1
    public static function loadAll()
96
    {
97 1
        $calledClass    = get_called_class();
98 1
        $collection     = new $calledClass;
99
100 1
        $sqlParams      = [];
101
102 1
        $sql  = "SELECT *";
103 1
        $sql .= "   FROM `" . $collection->getTableName() . "`";
104
105 1
        if ($collection->parentFilterType !== '' && $collection->parentFilterType != null) {
106
            $sql .= "WHERE " . $collection->parentFilterName . "=:type";
107
            $sqlParams['type'] = $collection->parentFilterType;
108
        }
109
110 1
        $collection->loadFromSql($sql, $sqlParams);
111
112 1
        return $collection;
113
    }
114
115
    /**
116
     * Static wrapper for loadFromSql
117
     * @param  string     $sql       SQL Statement
118
     * @param  array      $sqlParams SQL Parameters
119
     * @return Collection Loaded collection
120
     */
121 1
    public static function buildFromSql($sql, $sqlParams = [])
122
    {
123 1
        $calledClass = get_called_class();
124 1
        $collection = new $calledClass;
125
126 1
        $collection->loadFromSql($sql, $sqlParams);
127
128 1
        return $collection;
129
    }
130
131
    /**
132
     * Load collection from SQL query
133
     *
134
     * @param string $sql       SQL query
135
     * @param array  $sqlParams associative array of SQL params
136
     * @return DBCollection
137
     */
138 3
    public function loadFromSql($sql, $sqlParams = [])
139
    {
140 3
        if (!in_array(Interfaces\IDBObject::class, class_implements($this->itemsType))) {
141
            throw new \BadMethodCallException('Item type does not implement IDBObject interface');
142
        }
143
144 3
        $this->connectDB();
145 3
        $results = $this->dbLink->query($sql, $sqlParams)->fetchAll();
146
147 3
        if ($results !== false) {
148 3
            foreach ($results as $currentResult) {
149 3
                $itemName = $this->getItemsType();
150 3
                $this->addItem($itemName::instanciate($currentResult));
151
            }
152
        }
153
154 3
        return $this;
155
    }
156
157
    public function addItemLink($linkId)
158
    {
159
         $this->items[$this->itemOffset] = $linkId;
160
         // add mapping between item->index and $position in items pool
161
         $this->mapping[$this->itemOffset] = $linkId;
162
         $this->itemOffset++;
163
    }
164
165
    public function lazyLoadFromSql($sql, $sqlParams = array())
166
    {
167
        $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

167
        /** @scrutinizer ignore-call */ 
168
        $dbLink = Suricate::Database();
Loading history...
168
        if ($this->DBConfig !== '') {
169
            $dbLink->setConfig($this->DBConfig);
170
        }
171
172
        $results = $dbLink
173
            ->query($sql, $sqlParams)
174
            ->fetchAll();
175
176
        if ($results !== false) {
177
            foreach ($results as $currentResult) {
178
                $this->addItemLink(current($currentResult));
179
            }
180
        }
181
182
        return $this;
183
    }
184
185
    /**
186
     * Load items linked to a parentId
187
     * @param mixed        $parentId       Parent id description
188
     * @param string       $parentIdField  Name of parent id referencing field
189
     * @param \Closure|null $validate       Callback use to validate add to items collection
190
     */
191
    public static function loadForParentId($parentId, $parentIdField = null, $validate = null)
192
    {
193
        $calledClass   = get_called_class();
194
        $collection     = new $calledClass;
195
196
        if ($parentId != '') {
197
            $sqlParams     = [];
198
            $dbHandler     = Suricate::Database(true);
199
200
            if ($collection->getDBConfig() !== '') {
201
                $dbHandler->setConfig($collection->getDBConfig());
202
            }
203
204
            $sql  = "SELECT *";
205
            $sql .= " FROM `" . $collection->getTableName() . "`";
206
            $sql .= " WHERE";
207
            if ($parentIdField !== null) {
208
                $sql .= "`" . $parentIdField . "`=:parent_id";
209
            } else {
210
                $sql .= "`" . $collection->getParentIdField() . "`=:parent_id";
211
            }
212
213
            if ($collection->parentFilterType !== null) {
214
                $sql .= "   AND " . $collection->parentFilterName . "=:parent_type";
215
                $sqlParams['parent_type'] = $collection->parentFilterType;
216
            }
217
218
            $sqlParams['parent_id'] = $parentId;
219
            $results = $dbHandler->query($sql, $sqlParams)->fetchAll();
220
221
            if ($results !== false) {
222
                foreach ($results as $currentResult) {
223
                    $itemName = $collection->getItemsType();
224
                    $item = $itemName::instanciate($currentResult);
225
                    if ($validate === null || $validate($item)) {
226
                        $collection->addItem($item);
227
                    }
228
                }
229
            }
230
231
            $collection->parentId = $parentId;
232
        }
233
234
        return $collection;
235
    }
236
237
    public function setParentIdForAll($parentId)
238
    {
239
        if ($this->parentIdField !== null) {
240
            $this->parentId = $parentId;
241
            foreach (array_keys($this->items) as $key) {
242
                $this->items[$key]->{$this->parentIdField} = $parentId;
243
            }
244
            return $this;
245
        }
246
247
        throw new \BadMethodCallException('Collection does not have a parentId field');
248
    }
249
250
    /**
251
     * Load Parent Item, if item type is defined
252
     */
253
    public function loadParent()
254
    {
255
        if ($this->parentType !== '' && $this->parentId != '') {
256
            $parentObjectType = $this->parentType;
257
            $parent = new $parentObjectType();
258
            if (method_exists($parent, 'load')) {
259
                $parent->load($this->parentId);
260
261
                return $parent;
262
            } else {
263
                throw new \BadMethodCallException('Parent object does not have a load($id) method');
264
            }
265
        } else {
266
            throw new \BadMethodCallException('self::$parentType is not defined');
267
        }
268
    }
269
270
    public function craftItem($itemData)
271
    {
272
        $itemName = $this->itemsType;
273
274
        foreach ($itemData as $data) {
275
            $newItem = new $itemName();
276
            $newItem->{$this->parentIdField} = $this->parentId;
277
            $hasData = false;
278
            foreach ($data as $field => $value) {
279
                $newItem->$field = $value;
280
                if ($value != '') {
281
                    $hasData = true;
282
                }
283
            }
284
285
            // Only add item if there's data inside
286
            if ($hasData) {
287
                $this->addItem($newItem);
288
            }
289
        }
290
    }
291
292
    public function save()
293
    {
294
        // 1st step : delete all records for current parentId
295
        $sql  = "DELETE FROM `" . $this->tableName . "`";
296
        if ($this->parentIdField !== '') {
297
            $sql .= " WHERE";
298
            $sql .= "   `" . $this->parentIdField . "`=:parent_id";
299
300
            $sqlParams = array('parent_id' => $this->parentId);
301
        } else {
302
            $sqlParams = array();
303
        }
304
305
        $dbLink = Suricate::Database();
306
        if ($this->DBConfig !== '') {
307
            $dbLink->setConfig($this->DBConfig);
308
        }
309
        
310
        $dbLink->query($sql, $sqlParams);
311
312
        // 2nd step : save all current items
313
        foreach ($this->items as $currentItem) {
314
            $currentItem->save(true); // Force insert
315
        }
316
    }
317
318 3
    public function addItem(Interfaces\IDBObject $item)
319
    {
320 3
        $key = $item->getTableIndex();
321
        // Add item to items pool
322 3
        $this->items[$this->itemOffset] = $item;
323
324
        // add mapping between item->index and $position in items pool
325 3
        $this->mapping[$this->itemOffset] = $item->$key;
326
327 3
        $this->itemOffset++;
328
329 3
        return $this;
330
    }
331
332 3
    protected function connectDB()
333
    {
334 3
        if (!$this->dbLink) {
335
            $this->dbLink = Suricate::Database();
336
            if ($this->getDBConfig() !== '') {
337
                $this->dbLink->setConfig($this->getDBConfig());
338
            }
339
        }
340 3
    }
341
}
342