Completed
Push — 2.0 ( acba87...b64ad2 )
by Vermeulen
06:14
created

Sql::obtainLastInsertedIdWithoutAI()   A

Complexity

Conditions 6
Paths 12

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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