Completed
Push — develop ( e5d75d...f9f106 )
by Mathieu
01:40
created

DBCollection::offsetGet()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 10.1554

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 3
nop 1
dl 0
loc 18
ccs 3
cts 11
cp 0.2727
crap 10.1554
rs 9.9332
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
     * Set lazyload flag
43
     *
44
     * @param bool $lazyLoad
45
     * @return DBCollection
46
     */
47 1
    public function setLazyLoad($lazyLoad)
48
    {
49 1
        $this->lazyLoad = $lazyLoad;
50
51 1
        return $this;
52
    }
53
54
    /**
55
     * Get lazyload flag
56
     *
57
     * @return boolean
58
     */
59 1
    public function getLazyLoad(): bool
60
    {
61 1
        return $this->lazyLoad;
62
    }
63
64
    public function purgeItems()
65
    {
66
        $this->items        = [];
67
        $this->mapping      = [];
68
        $this->itemOffset   = 0;
69
    }
70
71
    /**
72
     * Implementation of ArrayAccess Interface
73
     * override parent get to lazyLoad item
74
     * @param  mixed $offset Offset to get
75
     * @return mixed
76
     */
77 2
    public function offsetGet($offset)
78
    {
79 2
        if (!$this->lazyLoad) {
80 2
            return parent::offsetGet($offset);
81
        }
82
83
        if (isset($this->loadedValues[$offset]) && $this->loadedValues[$offset]) {
84
            return $this->items[$offset];
85
        }
86
87
        $itemType = $this::ITEM_TYPE;
0 ignored issues
show
Bug introduced by
The constant Suricate\DBCollection::ITEM_TYPE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
88
        $itemToLoad = new $itemType;
89
        $itemToLoad->load($this->items[$offset]);
90
91
        $this->items[$offset] = $itemToLoad;
92
        $this->loadedValues[$offset] = true;
93
94
        return $this->items[$offset];
95
    }
96
97
    /**
98
     * Load entire table into collection
99
     * @return Collection Loaded collection
100
     */
101 1
    public static function loadAll()
102
    {
103 1
        $calledClass    = get_called_class();
104 1
        $collection     = new $calledClass;
105
106 1
        $sqlParams      = [];
107
108 1
        $sql  = "SELECT *";
109 1
        $sql .= "   FROM `" . $collection->getTableName() . "`";
110
111 1
        $collection->loadFromSql($sql, $sqlParams);
112
113 1
        return $collection;
114
    }
115
116
    /**
117
     * Static wrapper for loadFromSql
118
     * @param  string     $sql       SQL Statement
119
     * @param  array      $sqlParams SQL Parameters
120
     * @return Collection Loaded collection
121
     */
122 1
    public static function buildFromSql($sql, $sqlParams = [])
123
    {
124 1
        $calledClass = get_called_class();
125 1
        $collection = new $calledClass;
126
127 1
        $collection->loadFromSql($sql, $sqlParams);
128
129 1
        return $collection;
130
    }
131
132
    /**
133
     * Load collection from SQL query
134
     *
135
     * @param string $sql       SQL query
136
     * @param array  $sqlParams associative array of SQL params
137
     * @return DBCollection
138
     */
139 3
    public function loadFromSql($sql, $sqlParams = [])
140
    {
141 3
        if (!in_array(Interfaces\IDBObject::class, class_implements($this->itemsType))) {
142
            throw new \BadMethodCallException('Item type does not implement IDBObject interface');
143
        }
144
145 3
        $this->connectDB();
146 3
        $results = $this->dbLink->query($sql, $sqlParams)->fetchAll();
147
148 3
        if ($results !== false) {
149 3
            foreach ($results as $currentResult) {
150 3
                $itemName = $this->getItemsType();
151 3
                $this->addItem($itemName::instanciate($currentResult));
152
            }
153
        }
154
155 3
        return $this;
156
    }
157
158
    protected function addItemLink($linkId)
159
    {
160
         $this->items[$this->itemOffset] = $linkId;
161
         // add mapping between item->index and $position in items pool
162
         $this->mapping[$this->itemOffset] = $linkId;
163
         $this->loadedValues[$this->itemOffset] = false;
164
         $this->itemOffset++;
165
    }
166
167
    public function lazyLoadFromSql($sql, $sqlParams = array())
168
    {
169
        $this->connectDB();
170
        $results = $this->dbLink
171
            ->query($sql, $sqlParams)
172
            ->fetchAll();
173
174
        if ($results !== false) {
175
            foreach ($results as $currentResult) {
176
                $this->addItemLink(current($currentResult));
177
            }
178
        }
179
180
        return $this;
181
    }
182
183
    public function craftItem($itemData)
184
    {
185
        $itemName = $this->itemsType;
186
187
        foreach ($itemData as $data) {
188
            $newItem = new $itemName();
189
            $hasData = false;
190
            foreach ($data as $field => $value) {
191
                $newItem->$field = $value;
192
                if ($value != '') {
193
                    $hasData = true;
194
                }
195
            }
196
197
            // Only add item if there's data inside
198
            if ($hasData) {
199
                $this->addItem($newItem);
200
            }
201
        }
202
    }
203
204
    public function save()
205
    {
206
        foreach ($this->items as $currentItem) {
207
            $currentItem->save(true); // Force insert
208
        }
209
    }
210
211 3
    public function addItem(Interfaces\IDBObject $item)
212
    {
213 3
        $key = $item->getTableIndex();
214
        // Add item to items pool
215 3
        $this->items[$this->itemOffset] = $item;
216
217
        // add mapping between item->index and $position in items pool
218 3
        $this->mapping[$this->itemOffset] = $item->$key;
219
220 3
        $this->itemOffset++;
221
222 3
        return $this;
223
    }
224
225 3
    protected function connectDB()
226
    {
227 3
        if (!$this->dbLink) {
228
            $this->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

228
            /** @scrutinizer ignore-call */ 
229
            $this->dbLink = Suricate::Database();
Loading history...
229
            if ($this->getDBConfig() !== '') {
230
                $this->dbLink->setConfig($this->getDBConfig());
231
            }
232
        }
233 3
    }
234
}
235