Completed
Push — develop ( 5b8818...63b33a )
by Mathieu
01:42
created

DBCollection::__sleep()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 0
dl 0
loc 11
ccs 0
cts 8
cp 0
crap 6
rs 10
c 0
b 0
f 0
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 (isset($this->loadedValues[$offset]) && $this->loadedValues[$offset]) {
110
            return $this->items[$offset];
111
        }
112
113
        $itemType = $this->itemsType;
114
        $itemToLoad = new $itemType;
115
        $itemToLoad->load($this->items[$offset]);
116
117
        $this->items[$offset] = $itemToLoad;
118
        $this->loadedValues[$offset] = true;
119
120
        return $this->items[$offset];
121
    }
122
123
    /**
124
     * Load entire table into collection
125
     * @return Collection Loaded collection
126
     */
127 1
    public static function loadAll()
128
    {
129 1
        $calledClass    = get_called_class();
130 1
        $collection     = new $calledClass;
131
132 1
        $sqlParams      = [];
133
134 1
        $sql  = "SELECT *";
135 1
        $sql .= "   FROM `" . $collection->getTableName() . "`";
136
137 1
        $collection->loadFromSql($sql, $sqlParams);
138
139 1
        return $collection;
140
    }
141
142
    /**
143
     * Static wrapper for loadFromSql
144
     * @param  string     $sql       SQL Statement
145
     * @param  array      $sqlParams SQL Parameters
146
     * @return Collection Loaded collection
147
     */
148 1
    public static function buildFromSql($sql, $sqlParams = [])
149
    {
150 1
        $calledClass = get_called_class();
151 1
        $collection = new $calledClass;
152
153 1
        $collection->loadFromSql($sql, $sqlParams);
154
155 1
        return $collection;
156
    }
157
158
    /**
159
     * Load collection from SQL query
160
     *
161
     * @param string $sql       SQL query
162
     * @param array  $sqlParams associative array of SQL params
163
     * @return DBCollection
164
     */
165 3
    public function loadFromSql($sql, $sqlParams = [])
166
    {
167 3
        if (!in_array(Interfaces\IDBObject::class, class_implements($this->itemsType))) {
168
            throw new \BadMethodCallException('Item type does not implement IDBObject interface');
169
        }
170
171 3
        $this->connectDB();
172 3
        $results = $this->dbLink->query($sql, $sqlParams)->fetchAll();
173
174 3
        if ($results !== false) {
175 3
            foreach ($results as $currentResult) {
176 3
                $itemName = $this->getItemsType();
177 3
                $this->addItem($itemName::instanciate($currentResult));
178
            }
179
        }
180
181 3
        return $this;
182
    }
183
184
    protected function addItemLink($linkId)
185
    {
186
         $this->items[$this->itemOffset] = $linkId;
187
         // add mapping between item->index and $position in items pool
188
         $this->mapping[$this->itemOffset] = $linkId;
189
         $this->loadedValues[$this->itemOffset] = false;
190
         $this->itemOffset++;
191
    }
192
193
    public function lazyLoadFromSql($sql, $sqlParams = [])
194
    {
195
        $this->connectDB();
196
        $results = $this->dbLink
197
            ->query($sql, $sqlParams)
198
            ->fetchAll();
199
200
        if ($results !== false) {
201
            foreach ($results as $currentResult) {
202
                $this->addItemLink(current($currentResult));
203
            }
204
        }
205
206
        return $this;
207
    }
208
209
    public function craftItem($itemData)
210
    {
211
        $itemName = $this->itemsType;
212
213
        foreach ($itemData as $data) {
214
            $newItem = new $itemName();
215
            $hasData = false;
216
            foreach ($data as $field => $value) {
217
                $newItem->$field = $value;
218
                if ($value != '') {
219
                    $hasData = true;
220
                }
221
            }
222
223
            // Only add item if there's data inside
224
            if ($hasData) {
225
                $this->addItem($newItem);
226
            }
227
        }
228
    }
229
230
    public function save()
231
    {
232
        foreach ($this->items as $currentItem) {
233
            $currentItem->save(true); // Force insert
234
        }
235
    }
236
237 3
    public function addItem(Interfaces\IDBObject $item)
238
    {
239 3
        $key = $item->getTableIndex();
240
        // Add item to items pool
241 3
        $this->items[$this->itemOffset] = $item;
242
243
        // add mapping between item->index and $position in items pool
244 3
        $this->mapping[$this->itemOffset] = $item->$key;
245
246 3
        $this->itemOffset++;
247
248 3
        return $this;
249
    }
250
251 3
    protected function connectDB()
252
    {
253 3
        if (!$this->dbLink) {
254
            $this->dbLink = Suricate::Database();
255
            if ($this->getDBConfig() !== '') {
256
                $this->dbLink->setConfig($this->getDBConfig());
257
            }
258
        }
259 3
    }
260
}
261