diff --git a/system/MagiQL/Builder/Syntax/Adapt/MSSQL/SelectWriter.php b/system/MagiQL/Builder/Syntax/Adapt/MSSQL/SelectWriter.php new file mode 100644 index 0000000..2c8551d --- /dev/null +++ b/system/MagiQL/Builder/Syntax/Adapt/MSSQL/SelectWriter.php @@ -0,0 +1,45 @@ +getStartingLimit($select) . $this->getLimitCount($select); + + $limit = ''; + + if ($mask !== '00') { + $start = $this->placeholderWriter->add($select->getLimitStart()); + $count = $this->placeholderWriter->add($select->getLimitCount()); + + + //$limit = "LIMIT {$start}, {$count}"; + $limit = "OFFSET {$start} ROWS FETCH NEXT {$count} ROWS ONLY"; + + if (\count($select->getAllOrderBy()) < 1) { + $limit = "ORDER BY 1 ASC " . $limit; + } + } + + $parts = \array_merge($parts, [$limit]); + + return $this; + } +} diff --git a/system/MagiQL/Builder/Syntax/Adapt/Oracle/SelectWriter.php b/system/MagiQL/Builder/Syntax/Adapt/Oracle/SelectWriter.php new file mode 100644 index 0000000..ac99900 --- /dev/null +++ b/system/MagiQL/Builder/Syntax/Adapt/Oracle/SelectWriter.php @@ -0,0 +1,41 @@ +getStartingLimit($select) . $this->getLimitCount($select); + + $limit = ''; + + if ($mask !== '00') { + $start = $this->placeholderWriter->add($select->getLimitStart()); + $count = $this->placeholderWriter->add($select->getLimitCount()); + + + //$limit = "LIMIT {$start}, {$count}"; + $limit = "OFFSET {$start} ROWS FETCH NEXT {$count} ROWS ONLY"; + } + + $parts = \array_merge($parts, [$limit]); + + return $this; + } +} diff --git a/system/MagiQL/Builder/Syntax/Adapt/PostgreSQL/SelectWriter.php b/system/MagiQL/Builder/Syntax/Adapt/PostgreSQL/SelectWriter.php new file mode 100644 index 0000000..3cfd817 --- /dev/null +++ b/system/MagiQL/Builder/Syntax/Adapt/PostgreSQL/SelectWriter.php @@ -0,0 +1,39 @@ +getStartingLimit($select) . $this->getLimitCount($select); + + $limit = ''; + + if ($mask !== '00') { + $start = $this->placeholderWriter->add($select->getLimitStart()); + $count = $this->placeholderWriter->add($select->getLimitCount()); + + $limit = "LIMIT {$count} OFFSET {$start}"; + } + + $parts = \array_merge($parts, [$limit]); + + return $this; + } +} diff --git a/system/MagiQL/Builder/Syntax/Adapt/PostgreSQL/UpdateWriter.php b/system/MagiQL/Builder/Syntax/Adapt/PostgreSQL/UpdateWriter.php new file mode 100644 index 0000000..e583c07 --- /dev/null +++ b/system/MagiQL/Builder/Syntax/Adapt/PostgreSQL/UpdateWriter.php @@ -0,0 +1,56 @@ +getValues() as $column => $value) { + $value = $this->writer->writePlaceholderValue($value); + + $assigns[] = "$column = $value"; + } + + return \implode(', ', $assigns); + } + + /** + * Creates a Column object. + * + * @param array $argument + * @param null|Table $table + * + * @return Column + */ + public static function createColumn(array &$argument, $table = null) + { + $columnName = \array_values($argument); + $columnName = $columnName[0]; + + $columnAlias = \array_keys($argument); + $columnAlias = $columnAlias[0]; + + if (\is_numeric($columnAlias) || \strpos($columnName, '*') !== false) { + $columnAlias = null; + } + + return new Column($columnName, (string) $table, $columnAlias); + } +} diff --git a/system/MagiQL/Builder/Syntax/WriterFactory.php b/system/MagiQL/Builder/Syntax/WriterFactory.php index 99cf6dc..c398009 100644 --- a/system/MagiQL/Builder/Syntax/WriterFactory.php +++ b/system/MagiQL/Builder/Syntax/WriterFactory.php @@ -10,6 +10,7 @@ namespace Phacil\Framework\MagiQL\Builder\Syntax; use Phacil\Framework\MagiQL\Api\BuilderInterface; +use Phacil\Framework\Databases\Api\DriverInterface as DatabaseDriverInterface; /** * Class WriterFactory. @@ -46,6 +47,30 @@ final class WriterFactory */ public static function createSelectWriter(BuilderInterface $writer, PlaceholderWriter $placeholderWriter) { + /** @var \Phacil\Framework\MagiQL $writer */ + + switch ($writer->getDb()->getDBTypeId()) { + case DatabaseDriverInterface::LIST_DB_TYPE_ID['MYSQL']: + case DatabaseDriverInterface::LIST_DB_TYPE_ID['SQLLITE3']: + return new SelectWriter($writer, $placeholderWriter); + break; + + case DatabaseDriverInterface::LIST_DB_TYPE_ID['MSSQL']: + return new \Phacil\Framework\MagiQL\Builder\Syntax\Adapt\MSSQL\SelectWriter($writer, $placeholderWriter); + break; + + case DatabaseDriverInterface::LIST_DB_TYPE_ID['POSTGRE']: + return new \Phacil\Framework\MagiQL\Builder\Syntax\Adapt\PostgreSQL\SelectWriter($writer, $placeholderWriter); + break; + + case DatabaseDriverInterface::LIST_DB_TYPE_ID['ORACLE']: + return new \Phacil\Framework\MagiQL\Builder\Syntax\Adapt\Oracle\SelectWriter($writer, $placeholderWriter); + break; + + default: + return new SelectWriter($writer, $placeholderWriter); + break; + } return new SelectWriter($writer, $placeholderWriter); } @@ -68,6 +93,23 @@ final class WriterFactory */ public static function createUpdateWriter(BuilderInterface $writer, PlaceholderWriter $placeholderWriter) { + /** @var \Phacil\Framework\MagiQL $writer */ + switch ($writer->getDb()->getDBTypeId()) { + case DatabaseDriverInterface::LIST_DB_TYPE_ID['MYSQL']: + case DatabaseDriverInterface::LIST_DB_TYPE_ID['SQLLITE3']: + case DatabaseDriverInterface::LIST_DB_TYPE_ID['MSSQL']: + case DatabaseDriverInterface::LIST_DB_TYPE_ID['ORACLE']: + return new UpdateWriter($writer, $placeholderWriter); + break; + + case DatabaseDriverInterface::LIST_DB_TYPE_ID['POSTGRE']: + return new \Phacil\Framework\MagiQL\Builder\Syntax\Adapt\PostgreSQL\UpdateWriter($writer, $placeholderWriter); + break; + + default: + return new UpdateWriter($writer, $placeholderWriter); + break; + } return new UpdateWriter($writer, $placeholderWriter); } diff --git a/system/MagiQL/MagiQL.php b/system/MagiQL/MagiQL.php index 243e76c..3324dbc 100644 --- a/system/MagiQL/MagiQL.php +++ b/system/MagiQL/MagiQL.php @@ -22,7 +22,7 @@ class MagiQL extends Builder { /** * - * @var \Phacil\Framework\Database + * @var \Phacil\Framework\Api\Database */ private $db; @@ -54,6 +54,14 @@ class MagiQL extends Builder { return $this->db->execute($query, $values); } + /** + * + * @return \Phacil\Framework\Api\Database + */ + public function getDb() { + return $this->db; + } + /** * @param string $tableName * @return bool diff --git a/system/database/Databases/Driver/MySQL_PDO.php b/system/database/Databases/Driver/MySQL_PDO.php index 473c780..bed2556 100644 --- a/system/database/Databases/Driver/MySQL_PDO.php +++ b/system/database/Databases/Driver/MySQL_PDO.php @@ -6,7 +6,7 @@ * Phacil PHP Framework - https://github.com/exacti/phacil-framework */ -namespace Phacil\Framework\Databases\Driver\Driver; +namespace Phacil\Framework\Databases\Driver; use Phacil\Framework\Databases\Api\DriverInterface as DatabasesDriver; diff --git a/system/database/Databases/Driver/Oracle.php b/system/database/Databases/Driver/Oracle.php index d71c675..36b7919 100644 --- a/system/database/Databases/Driver/Oracle.php +++ b/system/database/Databases/Driver/Oracle.php @@ -100,7 +100,7 @@ class Oracle implements Databases { { // Verificar se há parâmetros e fazer o bind if (!empty($params)) { - $sql = $this->replacePlaceholders($sql, array_keys($params)); + //$sql = $this->replacePlaceholders($sql, array_keys($params)); $stid = \oci_parse($this->connection, $sql); @@ -140,8 +140,8 @@ class Oracle implements Databases { */ private function replacePlaceholders($sql, $placeholders) { - foreach ($placeholders as $placeholder) { - $sql = str_replace($placeholder, ':' . $placeholder, $sql); + foreach ($placeholders as $key => $placeholder) { + $sql = str_replace($placeholder, ':' . ($key + 1), $sql); } return $sql; diff --git a/system/database/Databases/Driver/Postgre.php b/system/database/Databases/Driver/Postgre.php index f003773..ce873d0 100644 --- a/system/database/Databases/Driver/Postgre.php +++ b/system/database/Databases/Driver/Postgre.php @@ -98,28 +98,27 @@ class Postgre implements DriverInterface { if (!empty($params)) { $sql = $this->replacePlaceholders($sql, array_keys($params)); $result = pg_query_params($this->link, $sql, array_values($params)); + } else { + $result = pg_query($this->link, $sql); + } - if ($result === false) { - throw new \Phacil\Framework\Exception('Error executing query: ' . pg_last_error($this->link)); - } + if ($result === false) { + throw new \Phacil\Framework\Exception('Error executing query: ' . pg_last_error($this->link)); + } - // Processar resultados se for um SELECT - $i = 0; - $data = []; - while ($row = pg_fetch_assoc($result)) { - $data[$i] = $row; - $i++; - } + // Processar resultados se for um SELECT + $data = pg_fetch_all($result); + + if(!empty($data)) { /** @var \Phacil\Framework\Databases\Object\ResultInterface */ $resultObj = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); - $resultObj->setNumRows($i); + $resultObj->setNumRows(count($data)); return $resultObj; - } else { - // Se não há parâmetros, executar diretamente sem consulta preparada - return $this->query($sql); } + + return true; } /** @@ -131,8 +130,8 @@ class Postgre implements DriverInterface { */ private function replacePlaceholders($sql, $placeholders) { - foreach ($placeholders as $placeholder) { - $sql = str_replace($placeholder, '$' . ($placeholders[$placeholder] + 1), $sql); + foreach ($placeholders as $key => $placeholder) { + $sql = str_replace($placeholder, '$' . ($key + 1), $sql); } return $sql; diff --git a/system/database/Databases/Driver/SQLSRV.php b/system/database/Databases/Driver/SQLSRV.php index d275310..9e409cf 100644 --- a/system/database/Databases/Driver/SQLSRV.php +++ b/system/database/Databases/Driver/SQLSRV.php @@ -124,39 +124,48 @@ class SQLSRV implements DriverInterface { public function execute($sql, array $params = []) { if (!empty($params)) { - // Bind parameters if there are any - $stmt = \sqlsrv_prepare($this->link, $sql, $params); - - if ($stmt === false) { - throw new \Phacil\Framework\Exception('Error preparing query: ' . \sqlsrv_errors()); - } + foreach ($params as $placeholder => &$param) { - $result = \sqlsrv_execute($stmt); + //$stmt->bind_param($this->getParamType($param), $param); + $bindParams[] = &$param; - if ($result === false) { - throw new \Phacil\Framework\Exception('Error executing query: ' . \sqlsrv_errors()); + if (is_string($placeholder)) + $sql = str_replace($placeholder, '?', $sql); } + // Bind parameters if there are any + $stmt = \sqlsrv_prepare($this->link, $sql, $bindParams); + } else { + $stmt = \sqlsrv_prepare($this->link, $sql); + } - // Processar resultados se for um SELECT - if (\sqlsrv_has_rows($stmt)) { - $data = []; - while ($row = \sqlsrv_fetch_array($stmt, \SQLSRV_FETCH_ASSOC)) { - $data[] = $row; - } + if ($stmt === false) { + throw new \Phacil\Framework\Exception('Error preparing query: ' . \sqlsrv_errors()); + } - /** @var \Phacil\Framework\Databases\Object\ResultInterface */ - $resultObj = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Object\ResultInterface::class, [$data]); - $resultObj->setNumRows(\sqlsrv_num_rows($stmt)); + $result = \sqlsrv_execute($stmt); + + if ($result === false) { + $errors = \sqlsrv_errors(); + throw new \Phacil\Framework\Exception('Error executing query: ' . json_encode($errors)); + } - return $resultObj; + // Processar resultados se for um SELECT + if (\sqlsrv_has_rows($stmt)) { + $data = []; + while ($row = \sqlsrv_fetch_array($stmt, \SQLSRV_FETCH_ASSOC)) { + $data[] = $row; } - // Se não for um SELECT, apenas retornar verdadeiro - return true; - } else { - // Se não há parâmetros, executar diretamente sem consulta preparada - return $this->query($sql); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Object\ResultInterface::class, [$data]); + $resultObj->setNumRows(\sqlsrv_num_rows($stmt)); + + return $resultObj; } + + // Se não for um SELECT, apenas retornar verdadeiro + return $result; + } /** diff --git a/system/database/Databases/Driver/SQLite3.php b/system/database/Databases/Driver/SQLite3.php index d181e5a..29041e4 100644 --- a/system/database/Databases/Driver/SQLite3.php +++ b/system/database/Databases/Driver/SQLite3.php @@ -96,11 +96,6 @@ class SQLite3 implements DriverInterface { public function execute($sql, array $params = []) { if (!empty($params)) { - // Bind parameters if there are any - foreach ($params as $placeholder => &$param) { - $sql = str_replace($placeholder, ':' . $placeholder, $sql); - } - $stmt = $this->connection->prepare($sql); if ($stmt === false) { @@ -108,37 +103,37 @@ class SQLite3 implements DriverInterface { } foreach ($params as $placeholder => &$param) { - $stmt->bindValue(':' . $placeholder, $param); + $stmt->bindValue($placeholder, $param, $this->getParamType($param)); } + } else { + $stmt = $this->connection->prepare($sql); + } - $result = $stmt->execute(); - - if ($result === false) { - throw new \Phacil\Framework\Exception('Error executing query: ' . $this->connection->lastErrorMsg()); - } + $result = $stmt->execute(); - // Processar resultados se for um SELECT - if ($result instanceof \SQLite3Result) { - $data = []; - while ($row = $result->fetchArray(SQLITE3_ASSOC)) { - $data[] = $row; - } + if ($result === false) { + throw new \Phacil\Framework\Exception('Error executing query: ' . $this->connection->lastErrorMsg()); + } - /** @var \Phacil\Framework\Databases\Object\ResultInterface */ - $resultObj = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Object\ResultInterface::class, [$data]); - $resultObj->setNumRows(count($data)); + // Processar resultados se for um SELECT + if ($result instanceof \SQLite3Result) { + $data = []; + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $data[] = $row; + } - $result->finalize(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Object\ResultInterface::class, [$data]); + $resultObj->setNumRows(count($data)); - return $resultObj; - } + $result->finalize(); - // Se não for um SELECT, apenas retornar verdadeiro - return true; - } else { - // Se não há parâmetros, executar diretamente sem consulta preparada - return $this->query($sql); + return $resultObj; } + + // Se não for um SELECT, apenas retornar verdadeiro + return true; + } /** @@ -154,4 +149,28 @@ class SQLite3 implements DriverInterface { public function getDBTypeId() { return self::DB_TYPE_ID; } + + private function getParamType(&$param) + { + $paramType = gettype($param); + + switch ($paramType) { + case 'boolean': + case 'integer': + $paramType = SQLITE3_INTEGER; + break; + case 'double': + case 'float': + $paramType = SQLITE3_FLOAT; + break; + case 'NULL': + $paramType = SQLITE3_NULL; + break; + default: + $paramType = SQLITE3_TEXT; + break; + } + + return $paramType; + } } \ No newline at end of file diff --git a/system/encryption/autoload.php b/system/encryption/autoload.php index 4c644e2..f35a6cd 100644 --- a/system/encryption/autoload.php +++ b/system/encryption/autoload.php @@ -72,7 +72,7 @@ class Encryption { */ public function setHashAlgorithm($hashAlgorithm) { if (!in_array($hashAlgorithm, hash_algos())) { - throw new \Phacil\Framework\Exception\InvalidArgumentException("The hash algorithm '${hashAlgorithm}' is not available."); + throw new \Phacil\Framework\Exception\InvalidArgumentException("The hash algorithm '{$hashAlgorithm}' is not available."); } $this->hash_algo = $hashAlgorithm; return $this; diff --git a/system/engine/registry.php b/system/engine/registry.php index 3106e7e..04f0c3d 100644 --- a/system/engine/registry.php +++ b/system/engine/registry.php @@ -120,7 +120,7 @@ final class Registry { * @param array $args (optional) * @param bool $onlyCheckInstances (Optional) if true, don't create an auto-instance * - * @return \Phacil\Framework\Registry + * @return \Phacil\Framework\Registry|object|null * @since 2.0.0 */ static public function getInstance($class = null, $args = [], $onlyCheckInstances = false) { @@ -134,7 +134,7 @@ final class Registry { if (isset(self::$autoInstances[($classObj)])) return self::$autoInstances[($classObj)]; - foreach ($registry->instances as $key => $value) { + foreach ($registry->instances as $value) { if(!is_object($value)) continue; if(get_class($value) == $classObj) {$return = $value; break; } @@ -157,11 +157,12 @@ final class Registry { } /** - * @param string $class - * @param array $args + * Force the creation of an instance of a class, even if it already exists. + * + * @param string $class Class full qualified name + * @param array $args (Optional) An array with the arguments to pass to the constructor * @return mixed - * @throws \ReflectionException - * @throws \Exception + * @throws \Phacil\Framework\Exception\ReflectionException * @throws \Phacil\Framework\Exception */ public function create($class, $args = array()) { diff --git a/system/system.php b/system/system.php index d6e73f0..462263b 100644 --- a/system/system.php +++ b/system/system.php @@ -524,6 +524,9 @@ set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$engine){ return true; }); +// Session +$engine->session = $engine->getRegistry()->create(\Phacil\Framework\Session::class); + /** * Caches * @var Caches @@ -544,9 +547,6 @@ $engine->response->addHeader('Content-Type: text/html; charset=utf-8'); if($engine->config->get('config_compression')) $engine->response->setCompression($engine->config->get('config_compression')); -// Session -$engine->session = $engine->getRegistry()->create(\Phacil\Framework\Session::class); - // Custom registrations $engine->extraRegistrations();