Completed
Push — master ( 0eeb04...4002ae )
by Oscar
02:31
created

SimpleCrud::getFieldFactory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
namespace SimpleCrud;
4
5
use Exception;
6
use PDO;
7
8
class SimpleCrud
9
{
10
    protected $connection;
11
    protected $scheme;
12
    protected $tables = [];
13
    protected $inTransaction = false;
14
    protected $attributes = [];
15
16
    protected $tableFactory;
17
    protected $queryFactory;
18
    protected $fieldFactory;
19
20
    /**
21
     * Set the connection and the tableFactory.
22
     *
23
     * @param PDO $connection
24
     */
25
    public function __construct(PDO $connection)
26
    {
27
        $this->connection = $connection;
28
        $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
29
    }
30
31
    /**
32
     * Set the database scheme.
33
     * 
34
     * @param array $scheme
35
     * 
36
     * @return self
37
     */
38
    public function setScheme(array $scheme)
39
    {
40
        $this->scheme = $scheme;
41
42
        return $this;
43
    }
44
45
    /**
46
     * Returns the database scheme.
47
     * 
48
     * @return array
49
     */
50
    public function getScheme()
51
    {
52
        if ($this->scheme === null) {
53
            $class = 'SimpleCrud\\Scheme\\'.ucfirst($this->getAttribute(PDO::ATTR_DRIVER_NAME));
54
55
            if (!class_exists($class)) {
56
                throw new SimpleCrudException(sprintf('Scheme class "%s" not found', $class));
57
            }
58
59
            $factory = new $class($this);
60
61
            $this->setScheme($factory());
62
        }
63
64
        return $this->scheme;
65
    }
66
67
    /**
68
     * Set the TableFactory instance used to create all tables.
69
     *
70
     * @param TableFactory $tableFactory
71
     * 
72
     * @return self
73
     */
74
    public function setTableFactory(TableFactory $tableFactory)
75
    {
76
        $this->tableFactory = $tableFactory;
77
78
        return $this;
79
    }
80
81
    /**
82
     * Returns the TableFactory instance used.
83
     *
84
     * @return TableFactory
85
     */
86
    public function getTableFactory()
87
    {
88
        if ($this->tableFactory === null) {
89
            return $this->tableFactory = (new TableFactory())->setAutocreate();
90
        }
91
92
        return $this->tableFactory;
93
    }
94
95
    /**
96
     * Set the QueryFactory instance used by the tables.
97
     *
98
     * @param QueryFactory $queryFactory
99
     *
100
     * @return self
101
     */
102
    public function setQueryFactory(QueryFactory $queryFactory)
103
    {
104
        $this->queryFactory = $queryFactory;
105
106
        return $this;
107
    }
108
109
    /**
110
     * Returns the QueryFactory instance used by the tables.
111
     *
112
     * @return QueryFactory
113
     */
114
    public function getQueryFactory()
115
    {
116
        if ($this->queryFactory === null) {
117
            $queryFactory = new QueryFactory();
118
            $queryFactory->addNamespace('SimpleCrud\\Queries\\'.ucfirst($this->getAttribute(PDO::ATTR_DRIVER_NAME)).'\\');
119
120
            return $this->queryFactory = $queryFactory;
121
        }
122
123
        return $this->queryFactory;
124
    }
125
126
    /**
127
     * Set the FieldFactory instance used by the tables.
128
     *
129
     * @param FieldFactory $fieldFactory
130
     *
131
     * @return self
132
     */
133
    public function setFieldFactory(FieldFactory $fieldFactory)
134
    {
135
        $this->fieldFactory = $fieldFactory;
136
137
        return $this;
138
    }
139
140
    /**
141
     * Returns the FieldFactory instance used by the tables.
142
     *
143
     * @return FieldFactory
144
     */
145
    public function getFieldFactory()
146
    {
147
        if ($this->fieldFactory === null) {
148
            return $this->fieldFactory = new FieldFactory();
149
        }
150
151
        return $this->fieldFactory;
152
    }
153
154
    /**
155
     * Magic method to initialize the tables in lazy mode.
156
     *
157
     * @param string $name The table name
158
     *
159
     * @throws SimpleCrudException If the table cannot be instantiated
160
     *
161
     * @return Table
162
     */
163
    public function __get($name)
164
    {
165
        if (isset($this->tables[$name])) {
166
            return $this->tables[$name];
167
        }
168
169
        return $this->tables[$name] = $this->getTableFactory()->get($this, $name);
170
    }
171
172
    /**
173
     * Magic method to check if a table exists or not.
174
     *
175
     * @param string $name
176
     *
177
     * @return bool
178
     */
179
    public function __isset($name)
180
    {
181
        return isset($this->getScheme()[$name]);
182
    }
183
184
    /**
185
     * Execute a query and returns the statement object with the result.
186
     *
187
     * @param string $query The Mysql query to execute
188
     * @param array  $marks The marks passed to the statement
189
     *
190
     * @throws Exception On error preparing or executing the statement
191
     *
192
     * @return PDOStatement The result
193
     */
194
    public function execute($query, array $marks = null)
195
    {
196
        $query = (string) $query;
197
198
        if (!empty($marks)) {
199
            foreach ($marks as $name => $mark) {
200
                if (is_array($mark)) {
201
                    foreach ($mark as &$val) {
202
                        $val = $this->connection->quote($val);
203
                    }
204
205
                    $query = str_replace($name, implode(', ', $mark), $query);
206
                    unset($marks[$name]);
207
                }
208
            }
209
210
            if (empty($marks)) {
211
                $marks = null;
212
            }
213
        }
214
215
        $statement = $this->connection->prepare($query);
216
        $statement->execute($marks);
217
218
        return $statement;
219
    }
220
221
    /**
222
     * Execute a callable inside a transaction.
223
     *
224
     * @param callable $callable The function with all operations
225
     *
226
     * @return mixed The callable returned value
227
     */
228
    public function executeTransaction(callable $callable)
229
    {
230
        try {
231
            $transaction = $this->beginTransaction();
232
233
            $return = $callable($this);
234
235
            if ($transaction) {
236
                $this->commit();
237
            }
238
        } catch (Exception $exception) {
239
            if ($transaction) {
240
                $this->rollBack();
241
            }
242
243
            throw $exception;
244
        }
245
246
        return $return;
247
    }
248
249
    /**
250
     * Returns the last insert id.
251
     *
252
     * @return string
253
     */
254
    public function lastInsertId()
255
    {
256
        return $this->connection->lastInsertId();
257
    }
258
259
    /**
260
     * Starts a transaction if it's not started yet.
261
     *
262
     * @return bool True if a the transaction is started or false if don't
263
     */
264
    public function beginTransaction()
265
    {
266
        if (!$this->inTransaction()) {
267
            $this->connection->beginTransaction();
268
269
            return $this->inTransaction = true;
270
        }
271
272
        return false;
273
    }
274
275
    /**
276
     * Commits the changes of the transaction to the database.
277
     */
278
    public function commit()
279
    {
280
        if ($this->inTransaction()) {
281
            $this->connection->commit();
282
            $this->inTransaction = false;
283
        }
284
    }
285
286
    /**
287
     * RollBack a transaction.
288
     */
289
    public function rollBack()
290
    {
291
        if ($this->inTransaction()) {
292
            $this->connection->rollBack();
293
            $this->inTransaction = false;
294
        }
295
    }
296
297
    /**
298
     * Check if there is a transaction opened currently in this adapter.
299
     */
300
    public function inTransaction()
301
    {
302
        return ($this->inTransaction === true) && ($this->connection->inTransaction() === true);
303
    }
304
305
    /**
306
     * Saves a new attribute.
307
     *
308
     * @param string $name
309
     * @param mixed  $value
310
     *
311
     * @return $this
312
     */
313
    public function setAttribute($name, $value)
314
    {
315
        $this->attributes[$name] = $value;
316
317
        return $this;
318
    }
319
320
    /**
321
     * Returns an attribute.
322
     *
323
     * @param string|int $name
324
     *
325
     * @return null|mixed
326
     */
327
    public function getAttribute($name)
328
    {
329
        if (is_int($name)) {
330
            return $this->connection->getAttribute($name);
331
        }
332
333
        return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
334
    }
335
}
336