From 3135e75086f502fde09e8f6f047549ba1691c322 Mon Sep 17 00:00:00 2001 From: Franck DAKIA Date: Tue, 7 Apr 2026 16:40:07 +0000 Subject: [PATCH 1/2] Resolve confict --- src/Database/Barry/Model.php | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Database/Barry/Model.php b/src/Database/Barry/Model.php index 39af76cd..86f71c82 100644 --- a/src/Database/Barry/Model.php +++ b/src/Database/Barry/Model.php @@ -1017,12 +1017,7 @@ private function executeDataCasting(string $name): mixed if (is_object($value)) { return (object) $value; } - return json_decode( - $value, - false, - 512, - JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE - ); + return $this->parseToJson($value); } if ($type === "array") { @@ -1032,14 +1027,25 @@ private function executeDataCasting(string $name): mixed if (is_object($value)) { return (array) $value; } - return json_decode( - $value, - true, - 512, - JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE - ); + return $this->parseToJson($value); } return $this->attributes[$name]; } + + /** + * Parse value to json + * + * @param string $value + * @return void + */ + private function parseToJson($value) + { + return json_decode( + $value, + false, + 512, + JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_IGNORE + ); + } } From c6932c9bf3d1d8f9f6e1b520732c8303e8b91a46 Mon Sep 17 00:00:00 2001 From: Franck DAKIA Date: Tue, 7 Apr 2026 16:44:54 +0000 Subject: [PATCH 2/2] Fix many bugs --- .../Exception/QueryBuilderException.php | 14 +- src/Database/QueryBuilder.php | 142 ++++++++++-------- src/Http/Request.php | 4 + src/Http/UploadedFile.php | 22 ++- 4 files changed, 118 insertions(+), 64 deletions(-) diff --git a/src/Database/Exception/QueryBuilderException.php b/src/Database/Exception/QueryBuilderException.php index ea11365e..658bb306 100644 --- a/src/Database/Exception/QueryBuilderException.php +++ b/src/Database/Exception/QueryBuilderException.php @@ -8,5 +8,17 @@ class QueryBuilderException extends ErrorException { - // Empty + protected string $query; + + public function __construct( + string $message, + string $query = '', + int $code = 0, + int $severity = E_ERROR, + ?string $filename = null, + ?int $line = null + ) { + parent::__construct($message, $code, $severity, $filename, $line); + $this->query = $query; + } } diff --git a/src/Database/QueryBuilder.php b/src/Database/QueryBuilder.php index e2e657a3..562705df 100644 --- a/src/Database/QueryBuilder.php +++ b/src/Database/QueryBuilder.php @@ -10,6 +10,7 @@ use Bow\Support\Str; use JsonSerializable; use PDO; +use PDOException; use PDOStatement; class QueryBuilder implements JsonSerializable @@ -112,6 +113,13 @@ class QueryBuilder implements JsonSerializable */ protected string $adapter = ''; + /** + * Determine the last sql query + * + * @var string|null + */ + protected ?string $last_query = null; + /** * QueryBuilder Constructor * @@ -170,9 +178,10 @@ public function as(string $as): QueryBuilder * WHERE column1 $comparator $value|column * * @param string $where + * @param array $data * @return QueryBuilder */ - public function whereRaw(string $where): QueryBuilder + public function whereRaw(string $where, array $data = []): QueryBuilder { if ($this->where == null) { $this->where = $where; @@ -180,6 +189,10 @@ public function whereRaw(string $where): QueryBuilder $this->where .= ' and ' . $where; } + if (!empty($data)) { + $this->where_data_binding = array_merge(array_values($data), $this->where_data_binding); + } + return $this; } @@ -189,9 +202,10 @@ public function whereRaw(string $where): QueryBuilder * WHERE column1 $comparator $value|column * * @param string $where + * @param array $data * @return QueryBuilder */ - public function orWhereRaw(string $where): QueryBuilder + public function orWhereRaw(string $where, array $data = []): QueryBuilder { if ($this->where == null) { $this->where = $where; @@ -199,6 +213,10 @@ public function orWhereRaw(string $where): QueryBuilder $this->where .= ' or ' . $where; } + if (!empty($data)) { + $this->where_data_binding = array_merge(array_values($data), $this->where_data_binding); + } + return $this; } @@ -217,8 +235,7 @@ public function orWhere(string $column, mixed $comparator = '=', mixed $value = { if (is_null($this->where)) { throw new QueryBuilderException( - 'This function can not be used without a where before.', - E_ERROR + 'This function can not be used without a where before.' ); } @@ -252,13 +269,12 @@ public function where( } if ($value === null) { - throw new QueryBuilderException('Unresolved comparison value', E_ERROR); + throw new QueryBuilderException('Unresolved comparison value'); } if (!in_array(Str::lower($boolean), ['and', 'or'])) { throw new QueryBuilderException( - 'The bool ' . $boolean . ' not accepted', - E_ERROR + 'The bool ' . $boolean . ' not accepted' ); } @@ -719,8 +735,7 @@ public function andOn(string $first, $comparator = '=', $second = null): QueryBu { if (is_null($this->join)) { throw new QueryBuilderException( - 'The inner join clause is already initialized.', - E_ERROR + 'The inner join clause is already initialized.' ); } @@ -750,7 +765,6 @@ public function orOn(string $first, $comparator = '=', $second = null): QueryBui if (is_null($this->join)) { throw new QueryBuilderException( 'The inner join clause is already initialized.', - E_ERROR ); } @@ -889,13 +903,8 @@ private function aggregate($aggregate, $column): mixed } } - $statement = $this->connection->prepare($sql); - - $this->bind($statement, $this->where_data_binding); + $statement = $this->execute($sql, $this->where_data_binding); - $statement->execute(); - - $this->triggerQueryEvent($sql, $this->where_data_binding); $this->where_data_binding = []; if ($statement->rowCount() > 1) { @@ -926,7 +935,9 @@ private function bind(PDOStatement $pdo_statement, array $bindings = []): void // Named placeholders foreach ($bindings as $key => $value) { $param = PDO::PARAM_STR; - if (is_null($value) || strtolower((string) $value) === 'null') { + if (is_array($value) || is_object($value)) { + $value = json_encode($value); + } elseif (is_null($value) || strtolower((string) $value) === 'null') { $param = PDO::PARAM_NULL; } elseif (is_int($value)) { $param = PDO::PARAM_INT; @@ -945,7 +956,9 @@ private function bind(PDOStatement $pdo_statement, array $bindings = []): void $i = 1; foreach ($bindings as $value) { $param = PDO::PARAM_STR; - if (is_null($value) || strtolower((string) $value) === 'null') { + if (is_array($value) || is_object($value)) { + $value = json_encode($value); + } elseif (is_null($value) || strtolower((string) $value) === 'null') { $param = PDO::PARAM_NULL; } elseif (is_int($value)) { $param = PDO::PARAM_INT; @@ -1110,17 +1123,12 @@ public function get(array $columns = []): array|object|null // Execution of request. $sql = $this->toSql(); - $statement = $this->connection->prepare($sql); - - $this->bind($statement, $this->where_data_binding); - - $statement->execute(); + $statement = $this->execute($sql, $this->where_data_binding); $data = $statement->fetchAll(); $statement->closeCursor(); - $this->triggerQueryEvent($sql, $this->where_data_binding); $this->where_data_binding = []; if (!$this->first) { @@ -1215,20 +1223,14 @@ public function update(array $data = []): int $sql .= ' where ' . $this->where; $this->where = null; - - $this->where_data_binding = array_merge(array_values($data), $this->where_data_binding); } - $statement = $this->connection->prepare($sql); + $this->where_data_binding = array_merge(array_values($data), $this->where_data_binding); - $this->bind($statement, $this->where_data_binding); - - // Execution of the request - $statement->execute(); + $statement = $this->execute($sql, $this->where_data_binding); $result = $statement->rowCount(); - $this->triggerQueryEvent($sql, $this->where_data_binding); $this->where_data_binding = []; return (int) $result; @@ -1265,15 +1267,10 @@ public function delete(): int $this->where = null; } - $statement = $this->connection->prepare($sql); - - $this->bind($statement, $this->where_data_binding); - - $statement->execute(); + $statement = $this->execute($sql, $this->where_data_binding); $result = $statement->rowCount(); - $this->triggerQueryEvent($sql, $this->where_data_binding); $this->where_data_binding = []; return (int) $result; @@ -1292,6 +1289,18 @@ public function increment(string $column, int $step = 1): int return $this->incrementAction($column, $step); } + /** + * Decrement column + * + * @param string $column + * @param int $step + * @return int + */ + public function decrement(string $column, int $step = 1): int + { + return $this->incrementAction($column, $step, '-'); + } + /** * Method to customize the increment and decrement methods * @@ -1310,27 +1319,11 @@ private function incrementAction(string $column, int $step = 1, string $directio $this->where = null; } - $statement = $this->connection->prepare($sql); - - $this->bind($statement, $this->where_data_binding); - - $statement->execute(); + $statement = $this->execute($sql, $this->where_data_binding); return (int)$statement->rowCount(); } - /** - * Decrement column - * - * @param string $column - * @param int $step - * @return int - */ - public function decrement(string $column, int $step = 1): int - { - return $this->incrementAction($column, $step, '-'); - } - /** * Allows a query with the DISTINCT clause * @@ -1371,10 +1364,14 @@ public function truncate(): bool $sql = 'truncate table ' . $this->table . ';'; } + $this->last_query = $sql; + $result = (bool) $this->connection->exec($sql); $this->triggerQueryEvent($sql, []); + $this->last_query = $sql; + return $result; } @@ -1422,7 +1419,6 @@ public function insert(array $values): int if ($single_item_structure_detected && $mixture_item_structure_detected) { throw new QueryBuilderException( 'Mixed structure detected in insert data. Cannot mix single and multiple row inserts.', - E_ERROR ); } @@ -1455,15 +1451,39 @@ private function insertOne(array $values): int $sql .= '(' . implode(', ', $this->add2points($fields, true)) . ');'; + $statement = $this->execute($sql, $values); + + return (int) $statement->rowCount(); + } + + /** + * Execute statement + * + * @param string $sql + * @param array $bindings + * @return PDOStatement + */ + private function execute(string $sql, array $bindings = []): PDOStatement + { + $this->last_query = $sql; + $statement = $this->connection->prepare($sql); - $this->bind($statement, $values); + $this->bind($statement, $bindings); - $statement->execute(); + try { + $statement->execute(); - $this->triggerQueryEvent($sql, $values); + $this->triggerQueryEvent($sql, $bindings); + } catch (\Exception $e) { + throw new QueryBuilderException( + 'Error executing query: ' . $e->getMessage(), + $this->last_query, + E_ERROR, + ); + } - return (int) $statement->rowCount(); + return $statement; } /** @@ -1475,6 +1495,8 @@ public function drop(): bool { $sql = 'drop table ' . $this->table; + $this->last_query = $sql; + $result = (bool) $this->connection->exec($sql); $this->triggerQueryEvent($sql, []); diff --git a/src/Http/Request.php b/src/Http/Request.php index 97813caa..d581aa50 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -402,6 +402,10 @@ public function file(string $key): UploadedFile|Collection|null return null; } + if (!is_uploaded_file($_FILES[$key]['tmp_name']) === UPLOAD_ERR_OK) { + return null; + } + if (!is_array($_FILES[$key]['name'])) { return new UploadedFile($_FILES[$key]); } diff --git a/src/Http/UploadedFile.php b/src/Http/UploadedFile.php index 01a59546..4ebfdcc4 100644 --- a/src/Http/UploadedFile.php +++ b/src/Http/UploadedFile.php @@ -38,6 +38,10 @@ public function extension(): string */ public function getExtension(): ?string { + if (!$this->isUploaded()) { + return null; + } + if (!isset($this->file['name'])) { return null; } @@ -71,7 +75,7 @@ public function getFilesize(): ?int } /** - * Check if the file is uploader + * Check if the file is uploaded * * @return bool */ @@ -91,6 +95,10 @@ public function isUploaded(): bool */ public function getFilename(): ?string { + if (!$this->isUploaded()) { + return null; + } + return $this->file['name'] ?? null; } @@ -101,6 +109,10 @@ public function getFilename(): ?string */ public function getContent(): ?string { + if (!$this->isUploaded()) { + return null; + } + if (!isset($this->file['tmp_name'])) { return null; } @@ -109,15 +121,19 @@ public function getContent(): ?string } /** - * Move the uploader file to a directory. + * Move the uploaded file to a directory. * * @param string $to * @param ?string $filename * @return bool - * @throws + * @throws \RuntimeException */ public function moveTo(string $to, ?string $filename = null): bool { + if (!$this->isUploaded()) { + return false; + } + if (!isset($this->file['tmp_name'])) { return false; }