diff --git a/system/database/Databases/Conectors/Oracle/ORDS/Api/HandleInterface.php b/system/database/Databases/Conectors/Oracle/ORDS/Api/HandleInterface.php new file mode 100644 index 0000000..7ba9229 --- /dev/null +++ b/system/database/Databases/Conectors/Oracle/ORDS/Api/HandleInterface.php @@ -0,0 +1,24 @@ + + */ + +namespace Phacil\Framework\Databases\Conectors\Oracle\ORDS\Api; + +interface HandleInterface { + public function __construct(\Phacil\Framework\Databases\Conectors\Oracle\ORDS\Conector $conector); + + public function setOption($option, $value); + + public function exec(); + + public function error(); + + public function close(); + + public function execute($sql); +} \ No newline at end of file diff --git a/system/database/Databases/Conectors/Oracle/ORDS/Conector.php b/system/database/Databases/Conectors/Oracle/ORDS/Conector.php new file mode 100644 index 0000000..5d78e66 --- /dev/null +++ b/system/database/Databases/Conectors/Oracle/ORDS/Conector.php @@ -0,0 +1,80 @@ + + */ + +namespace Phacil\Framework\Databases\Conectors\Oracle\ORDS; + +class Conector { + + private $host; + + private $port; + + private $user; + + private $pass; + + public function __construct($url = 'localhost', $port = 8181, $user = null, $pass = null){ + $this->host = $url; + + $this->port = $port; + + $this->user = $user; + + $this->pass = $pass; + + return $this; + } + + public function getHost(){ + return $this->host; + } + + public function getPort(){ + return $this->port; + } + + public function getUser(){ + return $this->user; + } + + public function getPass(){ + return $this->pass; + } + + public function escape($value) + { + $formattedValue = null; + + switch (gettype($value)) { + case 'integer': + $formattedValue = $value; // Números inteiros não precisam de formatação + break; + case 'double': + $formattedValue = sprintf('%F', $value); // Formata números decimais + break; + case 'boolean': + $formattedValue = $value ? 'TRUE' : 'FALSE'; // Converte booleanos para strings 'TRUE' ou 'FALSE' + break; + case 'NULL': + $formattedValue = 'NULL'; // Valores nulos + break; + case 'object': + $formattedValue = "'" . serialize($value) . "'"; // Valores nulos + break; + case 'array': + $formattedValue = "'" . \Phacil\Framework\Json::encode($value) . "'"; // Valores nulos + break; + default: + // Escapa as aspas simples e adiciona aspas simples ao redor de strings + $formattedValue = "'" . str_replace("'", "''", $value) . "'"; + } + + return $formattedValue; + } +} \ No newline at end of file diff --git a/system/database/Databases/Conectors/Oracle/ORDS/Model/Handler/Curl.php b/system/database/Databases/Conectors/Oracle/ORDS/Model/Handler/Curl.php new file mode 100644 index 0000000..7195264 --- /dev/null +++ b/system/database/Databases/Conectors/Oracle/ORDS/Model/Handler/Curl.php @@ -0,0 +1,78 @@ + + */ + +namespace Phacil\Framework\Databases\Conectors\Oracle\ORDS\Model\Handler; + +use Phacil\Framework\Databases\Conectors\Oracle\ORDS\Api\HandleInterface; +use Phacil\Framework\Databases\Conectors\Oracle\ORDS\Conector; + +class Curl implements HandleInterface { + /** + * + * @var resource|false + */ + private $curl; + + /** + * @var \Phacil\Framework\Databases\Conectors\Oracle\ORDS\Conector + */ + private $conector; + + public function __construct( + Conector $conector + ) + { + $this->curl = curl_init(); + $this->conector = $conector; + + $generatedAuth = base64_encode($this->conector->getUser().":".$this->conector->getPass()); + + $this->setOption(CURLOPT_PORT, $this->conector->getPort()); + $this->setOption(CURLOPT_URL, $this->conector->getHost()."/_/sql"); + $this->setOption(CURLOPT_RETURNTRANSFER, true); + $this->setOption(CURLOPT_MAXREDIRS, 10); + $this->setOption(CURLOPT_TIMEOUT, 30); + $this->setOption(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + $this->setOption(CURLOPT_CUSTOMREQUEST, 'POST'); + $this->setOption(CURLOPT_HTTPHEADER, [ + "Accept: */*", + sprintf("Authorization: Basic %s", $generatedAuth), + "Content-Type: application/sql" + ]); + } + + public function setOption($option, $value) + { + curl_setopt($this->curl, $option, $value); + } + + public function exec() + { + return curl_exec($this->curl); + } + + public function error() + { + return curl_error($this->curl); + } + + public function close() + { + curl_close($this->curl); + } + + public function execute($sql) { + $post = [ + '$' => $sql + ]; + $this->setOption(CURLOPT_POSTFIELDS, $post); + + return $this->exec(); + } +} \ No newline at end of file diff --git a/system/database/Databases/Conectors/Oracle/ORDS/Model/Query.php b/system/database/Databases/Conectors/Oracle/ORDS/Model/Query.php new file mode 100644 index 0000000..ab07e98 --- /dev/null +++ b/system/database/Databases/Conectors/Oracle/ORDS/Model/Query.php @@ -0,0 +1,110 @@ + + */ + +namespace Phacil\Framework\Databases\Conectors\Oracle\ORDS\Model; + +use Phacil\Framework\Databases\Conectors\Oracle\ORDS\Conector; +use Phacil\Framework\Databases\Conectors\Oracle\ORDS\Api\HandleInterface; + +class Query { + + /** + * + * @var \Phacil\Framework\Databases\Conectors\Oracle\ORDS\Conector + */ + private $conector; + + private $handle; + + private $sql; + + private $num_rows = 0; + + private $items = []; + + public function __construct( + Conector $conector, + HandleInterface $handle + ) { + $this->conector = $conector; + $this->handle = $handle; + } + + private function curlPLQ() { + + } + + /** + * @param string $sql + * @param array $bindParams + * @return $this + * @throws \Phacil\Framework\Exception\InvalidArgumentException + */ + public function prepareSQL($sql, $bindParams = []) + { + // Percorre os parâmetros a serem vinculados + foreach ($bindParams as $key => $value) { + // Detecta o tipo do valor e formata conforme necessário + $formattedValue = $this->conector->escape($value); + + if(!is_string($key)) + $sql = preg_replace('/\?/', $formattedValue, $sql, 1); + else { + $sql = str_replace($key, $formattedValue, $sql); + } + } + + $this->sql = $sql; + + return $this; + } + + public function execute() { + if(empty($this->sql)){ + throw new \Phacil\Framework\Exception\RuntimeException('Query is empty'); + } + + $executed = $this->handle->execute($this->sql); + + if($executed){ + $executed = \Phacil\Framework\Json::decode($executed); + + $resultEnd = isset($executed['items']) ? end($executed ['items']) : null; + + $resultSet = isset($resultEnd['resultSet']) ? $resultEnd['resultSet'] : null; + + if($resultSet) { + $this->num_rows = $resultSet["count"]; + + $this->items = $resultSet["items"]; + } elseif (isset($resultEnd["result"])) { + $this->num_rows = $resultEnd["result"]; + } + + return $this; + } else { + throw new \Phacil\Framework\Exception\RuntimeException($this->handle->error()); + } + } + + public function getNumRows() { + return $this->num_rows; + } + + public function getItems() { + return $this->items; + } + + public function close() { + $this->handle->close(); + + unset($this->handle); + $this->handle = \Phacil\Framework\Registry::getInstance()->create(HandleInterface::class); + } +} \ No newline at end of file diff --git a/system/database/Databases/Driver/OracleORDS.php b/system/database/Databases/Driver/OracleORDS.php new file mode 100644 index 0000000..1a7070d --- /dev/null +++ b/system/database/Databases/Driver/OracleORDS.php @@ -0,0 +1,176 @@ +connection = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Conectors\Oracle\ORDS\Conector::class, [ + $hostname.$database, + \Phacil\Framework\Config::DB_PORT() ?: $port, + $username, + $password + ]); + + } catch (\PDOException $e) { + throw new \Phacil\Framework\Exception('Failed to connect to database. Reason: \'' . $e->getMessage() . '\''); + } + } + + /** {@inheritdoc} */ + public function query($sql, $params = array()) + { + $this->createStatement(); + $result = false; + try { + $data = $this->statement->prepareSQL($sql, $params); + if ($this->statement && $this->statement->execute($params)) { + $data = array(); + $this->rowCount = $this->statement->rowCount(); + if ($this->rowCount > 0) { + try { + $data = $this->statement->fetchAll(\PDO::FETCH_ASSOC); + } catch (\Exception $ex) { + } + } + // free up resources + $this->statement->closeCursor(); + $this->statement = null; + + /** @var \Phacil\Framework\Databases\Api\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Api\Object\ResultInterface::class, [$data]); + $result->setNumRows($this->rowCount); + } + } catch (\PDOException $e) { + throw new \Phacil\Framework\Exception('Error: ' . $e->getMessage() . ' Error Code : ' . $e->getCode() . '
' . $sql); + } + if ($result) { + return $result; + } else { + $result = new \Phacil\Framework\Databases\Object\Result(); + $result->row = array(); + $result->rows = array(); + $result->num_rows = 0; + return $result; + } + } + + public function createStatement() { + $this->rowCount = 0; + + /** @var \Phacil\Framework\Databases\Conectors\Oracle\ORDS\Model\Query */ + $this->statement = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Conectors\Oracle\ORDS\Model\Query::class); + } + + /** {@inheritdoc} */ + public function escape($value) + { + return str_replace(array("\\", "\0", "\n", "\r", "\x1a", "'", '"'), array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'), $value); + } + + /** {@inheritdoc} */ + public function countAffected() + { + return $this->rowCount; + } + + /** {@inheritdoc} */ + public function getLastId() + { + return $this->connection->lastInsertId(); + } + + /** {@inheritdoc} */ + public function isConnected() + { + if ($this->connection) { + return true; + } else { + return false; + } + } + + /** + * {@inheritdoc} + */ + public function execute($sql, array $params = []) + { + $this->createStatement(); + try { + $stmt = $this->statement->prepareSQL($sql, $params)->execute(); + + if (!$stmt) { + throw new \Phacil\Framework\Exception('Error preparing query: ' . implode(', ', $this->connection->errorInfo())); + } + + if ($stmt->getNumRows() && !empty($stmt->getItems())) { + /** @var \Phacil\Framework\Databases\Api\Object\ResultInterface */ + $data = \Phacil\Framework\Registry::getInstance()->create(\Phacil\Framework\Databases\Api\Object\ResultInterface::class, [$stmt->getItems()]); + $data->setNumRows($stmt->getNumRows()); + + $this->rowCount = $stmt->getNumRows(); + + $stmt->close(); + + return $data; + } else { + $this->rowCount = $stmt->getNumRows(); + $stmt->close(); + return true; + } + } catch (\PDOException $exception) { + throw new \Phacil\Framework\Exception($exception->getMessage()); + } + } +}