Completed
Branch 2.0 (acba87)
by Vermeulen
02:20
created

Sql::createId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 17
nc 3
nop 2
dl 0
loc 32
rs 9.7
c 0
b 0
f 0
1
<?php
2
3
namespace BfwSql;
4
5
use \Exception;
6
7
/**
8
 * Class to access to query writer
9
 * 
10
 * @package bfw-sql
11
 * @author Vermeulen Maxime <[email protected]>
12
 * @version 2.0
13
 */
14
class Sql
15
{
16
    /**
17
     * @const ERR_QUERY_BAD_REQUEST Exception code if the request executed
18
     * on query method have an error.
19
     */
20
    const ERR_QUERY_BAD_REQUEST = 2103001;
21
    
22
    /**
23
     * @var \BfwSql\SqlConnect $sqlConnect SqlConnect object
24
     */
25
    protected $sqlConnect;
26
    
27
    /**
28
     * @var string $prefix Tables prefix
29
     */
30
    protected $prefix = '';
31
    
32
    /**
33
     * Constructor
34
     * 
35
     * @param \BfwSql\SqlConnect $sqlConnect SqlConnect instance
36
     * 
37
     * @throws \Exception
38
     */
39
    public function __construct(\BfwSql\SqlConnect $sqlConnect)
40
    {
41
        $this->sqlConnect = $sqlConnect;
42
        $this->prefix     = $sqlConnect->getConnectionInfos()->tablePrefix;
43
    }
44
    
45
    /**
46
     * Getter to the property sqlConnect
47
     * 
48
     * @return \BfwSql\SqlConnect
49
     */
50
    public function getSqlConnect(): \BfwSql\SqlConnect
51
    {
52
        return $this->sqlConnect;
53
    }
54
    
55
    /**
56
     * Getter to the property prefix
57
     * 
58
     * @return string
59
     */
60
    public function getPrefix(): string
61
    {
62
        return $this->prefix;
63
    }
64
    
65
    /**
66
     * Get the id for the last item has been insert in database
67
     * 
68
     * @param string|null $name (default: null) Name of the sequence for the id
69
     *  Used for SGDB like PostgreSQL. Not use it for mysql.
70
     * 
71
     * @return integer
72
     */
73
    public function obtainLastInsertedId($name = null): int
74
    {
75
        return (int) $this->sqlConnect->getPDO()->lastInsertId($name);
76
    }
77
    
78
    /**
79
     * Get the id for the last item has been insert in database for a table
80
     * without auto-increment
81
     * 
82
     * @param string       $table The table name
83
     * @param string       $colId The column name for the ID
84
     * @param array        $order Columns to sort table content
85
     * @param string|array $where All where instruction used for filter content
86
     * 
87
     * @return integer
88
     */
89
    public function obtainLastInsertedIdWithoutAI(
90
        string $table,
91
        string $colId,
92
        array $order,
93
        $where = ''
94
    ): int {
95
        $req = $this->select()
96
                    ->from($table, $colId)
0 ignored issues
show
Bug introduced by
The method from() does not exist on BfwSql\Queries\Select. Since you implemented __call, 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

96
                    ->/** @scrutinizer ignore-call */ from($table, $colId)
Loading history...
97
                    ->limit(1);
98
    
99
        if (is_array($where)) {
100
            foreach ($where as $val) {
101
                $req->where($val);
102
            }
103
        } elseif ($where != '') {
104
            $req->where($where);
105
        }
106
        
107
        if (is_array($order)) {
0 ignored issues
show
introduced by
The condition is_array($order) is always true.
Loading history...
108
            foreach ($order as $expr => $sort) {
109
                $req->order($expr, $sort);
110
            }
111
        }
112
        
113
        $res = $req->getExecuter()->fetchRow();
114
        $req->getExecuter()->closeCursor();
115
        
116
        if ($res) {
117
            return (int) $res[$colId];
118
        }
119
        
120
        return 0;
121
    }
122
    
123
    /**
124
     * Return a new instance of SqlSelect
125
     * 
126
     * @param string $type (default: "array") Return PHP type
127
     *  Possible value : "array" or "object"
128
     * 
129
     * @return \BfwSql\Queries\Select
130
     */
131
    public function select(string $type = 'array'): \BfwSql\Queries\Select
132
    {
133
        $usedClass       = \BfwSql\UsedClass::getInstance();
134
        $selectClassName = $usedClass->obtainClassNameToUse('QueriesSelect');
135
        
136
        return new $selectClassName($this->sqlConnect, $type);
137
    }
138
    
139
    /**
140
     * Return a new instance of SqlInsert
141
     * 
142
     * @param string $quoteStatus (default: QUOTE_ALL) Status to automatic
143
     *  quoted string value system.
144
     * 
145
     * @return \BfwSql\Queries\Insert
146
     */
147
    public function insert(
148
        string $quoteStatus = \BfwSql\Helpers\Quoting::QUOTE_ALL
149
    ): \BfwSql\Queries\Insert {
150
        $usedClass       = \BfwSql\UsedClass::getInstance();
151
        $insertClassName = $usedClass->obtainClassNameToUse('QueriesInsert');
152
        
153
        return new $insertClassName($this->sqlConnect, $quoteStatus);
154
    }
155
    
156
    /**
157
     * Return a new instance of SqlUpdate
158
     * 
159
     * @param string $quoteStatus (default: QUOTE_ALL) Status to automatic
160
     *  quoted string value system.
161
     * 
162
     * @return \BfwSql\Queries\Update
163
     */
164
    public function update(
165
        string $quoteStatus = \BfwSql\Helpers\Quoting::QUOTE_ALL
166
    ): \BfwSql\Queries\Update {
167
        $usedClass       = \BfwSql\UsedClass::getInstance();
168
        $updateClassName = $usedClass->obtainClassNameToUse('QueriesUpdate');
169
        
170
        return new $updateClassName($this->sqlConnect, $quoteStatus);
171
    }
172
    
173
    /**
174
     * Return a new instance of SqlDelete
175
     * 
176
     * @return \BfwSql\Queries\Delete
177
     */
178
    public function delete(): \BfwSql\Queries\Delete
179
    {
180
        $usedClass       = \BfwSql\UsedClass::getInstance();
181
        $deleteClassName = $usedClass->obtainClassNameToUse('QueriesDelete');
182
        
183
        return new $deleteClassName($this->sqlConnect);
184
    }
185
    
186
    /**
187
     * Find the first vacant id on a table and for a column
188
     * 
189
     * @param string $table  The table concerned by the request
190
     * @param string $column The id column. Must be an integer..
191
     * 
192
     * @throws \Exception If a error has been throw during the search
193
     * 
194
     * @return integer
195
     */
196
    public function createId(string $table, string $column): int
197
    {
198
        //Search the first line in the table
199
        $reqFirstLine = $this->select()
200
            ->from($table, $column)
201
            ->order($column, 'ASC')
202
            ->limit(1);
203
        
204
        $resFirstLine = $reqFirstLine->getExecuter()->fetchRow();
205
        $reqFirstLine->getExecuter()->closeCursor();
206
        
207
        // If nothing in the table. First AI is 1
208
        if (!$resFirstLine) {
209
            return 1;
210
        }
211
        
212
        // If the id for the first line is > 1
213
        if ($resFirstLine[$column] > 1) {
214
            return $resFirstLine[$column] - 1;
215
        }
216
        
217
        //First line have ID=1, we search from the end
218
        $reqLastLine = $this->select()
219
            ->from($table, $column)
220
            ->order($column, 'DESC')
221
            ->limit(1);
222
        
223
        $resLastLine = $reqLastLine->getExecuter()->fetchRow();
224
        $reqLastLine->getExecuter()->closeCursor();
225
226
        //Get the last ID and add 1
227
        return $resLastLine[$column] + 1;
228
    }
229
    
230
    /**
231
     * Run the query in parameter 
232
     * 
233
     * @param string $request The request to run
234
     * 
235
     * @throws \Exception If the request has failed
236
     * 
237
     * @return \PDOStatement
238
     */
239
    public function query(string $request): \PDOStatement
240
    {
241
        $this->sqlConnect->upNbQuery();
242
        
243
        $req   = $this->sqlConnect->getPDO()->query($request);
244
        $error = $this->sqlConnect->getPDO()->errorInfo();
245
        
246
        $app     = \BFW\Application::getInstance();
247
        $subject = $app->getSubjectList()->getSubjectByName('bfw-sql');
248
        $subject->addNotification(
249
            'user query',
250
            new class ($request, $error) {
251
                public $request = '';
252
                public $error = [];
253
                
254
                public function __construct($request, $error)
255
                {
256
                    $this->request = $request;
257
                    $this->error   = $error;
258
                }
259
            }
260
        );
261
        
262
        if (
263
            !$req
264
            && $error[0] !== null
265
            && $error[0] !== '00000'
266
            && isset($error[2])
267
        ) {
268
            throw new Exception(
269
                $error[2],
270
                self::ERR_QUERY_BAD_REQUEST
271
            );
272
        }
273
        
274
        return $req;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $req could return the type boolean which is incompatible with the type-hinted return PDOStatement. Consider adding an additional type-check to rule them out.
Loading history...
275
    }
276
}
277