Completed
Push — master ( db7db7...b603ad )
by Mathieu
07:07 queued 05:18
created

DBCollection   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 262
Duplicated Lines 0 %

Test Coverage

Coverage 44.86%

Importance

Changes 17
Bugs 1 Features 1
Metric Value
eloc 95
c 17
b 1
f 1
dl 0
loc 262
ccs 48
cts 107
cp 0.4486
rs 9.68
wmc 34

18 Methods

Rating   Name   Duplication   Size   Complexity  
A purgeItems() 0 5 1
A getTableName() 0 3 1
A __wakeup() 0 3 1
A lazyLoadFromSql() 0 12 3
A getLazyLoad() 0 3 1
A getItemsType() 0 3 1
A __sleep() 0 11 2
A setLazyLoad() 0 5 1
A getDBConfig() 0 3 1
A addItem() 0 12 1
A buildFromSql() 0 8 1
A save() 0 4 2
A connectDB() 0 6 3
A loadFromSql() 0 26 4
A addItemLink() 0 7 1
A craftItem() 0 17 5
A loadAll() 0 13 1
A offsetGet() 0 21 4
1
<?php declare(strict_types=1);
2
3
namespace Suricate;
4
5
class DBCollection extends Collection
6
{
7
    /* @var string SQL table name */
8
    protected $tableName = '';
9
    /* @var string Item type stored in collection */
10
    protected $itemsType = '';
11
    /* @var string Database configuration identifier */
12
    protected $DBConfig = '';
13
14
    protected $mapping = [];
15
    protected $loadedValues = [];
16
    protected $lazyLoad = false;
17
18
    protected $dbLink = false;
19
    protected $itemOffset = 0;
20
21
    /**
22
     * Get table name
23
     *
24
     * @return string
25
     */
26 2
    public function getTableName(): string
27
    {
28 2
        return $this->tableName;
29
    }
30
31 4
    public function getItemsType(): string
32
    {
33 4
        return $this->itemsType;
34
    }
35
36 1
    public function getDBConfig(): string
37
    {
38 1
        return $this->DBConfig;
39
    }
40
41
    /**
42
     * __sleep magic method, permits an inherited DBObject class to be serialized
43
     * @return Array of properties to serialize
44
     */
45
    public function __sleep()
46
    {
47
        $discardedProps = ['dbLink'];
48
        $reflection = new \ReflectionClass($this);
49
        $props = $reflection->getProperties();
50
        $result = [];
51
        foreach ($props as $currentProperty) {
52
            $result[] = $currentProperty->name;
53
        }
54
55
        return array_diff($result, $discardedProps);
56
    }
57
58
    /**
59
     * Wake up magic method
60
     * restore dblink to initial value
61
     */
62
    public function __wakeup()
63
    {
64
        $this->dbLink = false;
65
    }
66
67
    /**
68
     * Set lazyload flag
69
     *
70
     * @param bool $lazyLoad
71
     * @return DBCollection
72
     */
73 1
    public function setLazyLoad($lazyLoad)
74
    {
75 1
        $this->lazyLoad = $lazyLoad;
76
77 1
        return $this;
78
    }
79
80
    /**
81
     * Get lazyload flag
82
     *
83
     * @return boolean
84
     */
85 1
    public function getLazyLoad(): bool
86
    {
87 1
        return $this->lazyLoad;
88
    }
89
90
    public function purgeItems()
91
    {
92
        $this->items = [];
93
        $this->mapping = [];
94
        $this->itemOffset = 0;
95
    }
96
97
    /**
98
     * Implementation of ArrayAccess Interface
99
     * override parent get to lazyLoad item
100
     * @param  mixed $offset Offset to get
101
     * @return mixed
102
     */
103 2
    public function offsetGet($offset)
104
    {
105 2
        if (!$this->lazyLoad) {
106 2
            return parent::offsetGet($offset);
107
        }
108
109
        if (
110
            isset($this->loadedValues[$offset]) &&
111
            $this->loadedValues[$offset]
112
        ) {
113
            return $this->items[$offset];
114
        }
115
116
        $itemType = $this->itemsType;
117
        $itemToLoad = new $itemType();
118
        $itemToLoad->load($this->items[$offset]);
119
120
        $this->items[$offset] = $itemToLoad;
121
        $this->loadedValues[$offset] = true;
122
123
        return $this->items[$offset];
124
    }
125
126
    /**
127
     * Load entire table into collection
128
     * @return DBCollection Loaded collection
129
     */
130 1
    public static function loadAll()
131
    {
132 1
        $calledClass = get_called_class();
133 1
        $collection = new $calledClass();
134
135 1
        $sqlParams = [];
136
137 1
        $sql = "SELECT *";
138 1
        $sql .= "   FROM `" . $collection->getTableName() . "`";
139
140 1
        $collection->loadFromSql($sql, $sqlParams);
141
142 1
        return $collection;
143
    }
144
145
    /**
146
     * Static wrapper for loadFromSql
147
     * @param  string     $sql       SQL Statement
148
     * @param  array      $sqlParams SQL Parameters
149
     * @return DBCollection Loaded collection
150
     */
151 1
    public static function buildFromSql($sql, $sqlParams = [])
152
    {
153 1
        $calledClass = get_called_class();
154 1
        $collection = new $calledClass();
155
156 1
        $collection->loadFromSql($sql, $sqlParams);
157
158 1
        return $collection;
159
    }
160
161
    /**
162
     * Load collection from SQL query
163
     *
164
     * @param string $sql       SQL query
165
     * @param array  $sqlParams associative array of SQL params
166
     * @return DBCollection
167
     */
168 3
    public function loadFromSql($sql, $sqlParams = [])
169
    {
170
        if (
171 3
            !in_array(
172 3
                Interfaces\IDBObject::class,
173 3
                class_implements($this->itemsType)
174
            )
175
        ) {
176
            throw new \BadMethodCallException(
177
                'Item type does not implement IDBObject interface'
178
            );
179
        }
180
181 3
        $this->connectDB();
182 3
        $results = $this->dbLink->query($sql, $sqlParams)->fetchAll();
183
184 3
        if ($results !== false) {
185 3
            foreach ($results as $currentResult) {
186 3
                $itemName = $this->getItemsType();
187 3
                $item = $itemName::instanciate($currentResult);
188 3
                $item->setLoaded();
189 3
                $this->addItem($item);
190
            }
191
        }
192
193 3
        return $this;
194
    }
195
196
    protected function addItemLink($linkId)
197
    {
198
        $this->items[$this->itemOffset] = $linkId;
199
        // add mapping between item->index and $position in items pool
200
        $this->mapping[$this->itemOffset] = $linkId;
201
        $this->loadedValues[$this->itemOffset] = false;
202
        $this->itemOffset++;
203
    }
204
205
    public function lazyLoadFromSql($sql, $sqlParams = [])
206
    {
207
        $this->connectDB();
208
        $results = $this->dbLink->query($sql, $sqlParams)->fetchAll();
209
210
        if ($results !== false) {
211
            foreach ($results as $currentResult) {
212
                $this->addItemLink(current($currentResult));
213
            }
214
        }
215
216
        return $this;
217
    }
218
219
    public function craftItem($itemData)
220
    {
221
        $itemName = $this->itemsType;
222
223
        foreach ($itemData as $data) {
224
            $newItem = new $itemName();
225
            $hasData = false;
226
            foreach ($data as $field => $value) {
227
                $newItem->$field = $value;
228
                if ($value != '') {
229
                    $hasData = true;
230
                }
231
            }
232
233
            // Only add item if there's data inside
234
            if ($hasData) {
235
                $this->addItem($newItem);
236
            }
237
        }
238
    }
239
240
    public function save()
241
    {
242
        foreach ($this->items as $currentItem) {
243
            $currentItem->save(true); // Force insert
244
        }
245
    }
246
247 3
    public function addItem(Interfaces\IDBObject $item)
248
    {
249 3
        $key = $item->getTableIndex();
250
        // Add item to items pool
251 3
        $this->items[$this->itemOffset] = $item;
252
253
        // add mapping between item->index and $position in items pool
254 3
        $this->mapping[$this->itemOffset] = $item->$key;
255
256 3
        $this->itemOffset++;
257
258 3
        return $this;
259
    }
260
261 3
    protected function connectDB()
262
    {
263 3
        if (!$this->dbLink) {
264
            $this->dbLink = Suricate::Database();
265
            if ($this->getDBConfig() !== '') {
266
                $this->dbLink->setConfig($this->getDBConfig());
267
            }
268
        }
269 3
    }
270
}
271