From e2575a93bb755c07100b726fc51e59b21d6670f2 Mon Sep 17 00:00:00 2001 From: "Bruno O. Notario" Date: Sat, 3 Feb 2024 21:26:40 -0300 Subject: [PATCH] Preferences on DI injector, new database results objects, refactoring some codes Also changes in db drivers to optimized results object --- composer.json | 2 +- system/database/Databases/MSSQL.php | 7 +- system/database/Databases/MySQL_PDO.php | 16 +- system/database/Databases/MySQL_legacy.php | 9 +- system/database/Databases/MySQLi.php | 20 +- .../Databases/Object/Aux/ComplementResult.php | 32 --- .../Object/Aux/ComplementResultLegacy.php | 33 --- system/database/Databases/Object/Item.php | 9 - system/database/Databases/Object/Result.php | 104 +++++---- .../Databases/Object/ResultCacheIterator.php | 189 +++++++++++++++++ .../Databases/Object/ResultInterface.php | 16 +- .../Databases/Object/ResultIterator.php | 30 --- system/database/Databases/Oracle.php | 10 +- system/database/Databases/Oracle_PDO.php | 14 +- system/database/Databases/Postgre.php | 12 +- system/database/Databases/SQLSRV.php | 12 +- system/database/Databases/SQLite3.php | 12 +- system/database/Databases/mPDO.php | 14 +- system/database/Databases/sqlsrvPDO.php | 10 +- system/engine/autoload.php | 1 + system/engine/front.php | 56 +---- system/engine/interfaces/url.php | 40 ++++ system/engine/registry.php | 198 +++++++++++++----- system/etc/preferences.json | 7 + system/system.php | 11 +- system/url/autoload.php | 3 +- 26 files changed, 538 insertions(+), 329 deletions(-) delete mode 100644 system/database/Databases/Object/Aux/ComplementResult.php delete mode 100644 system/database/Databases/Object/Aux/ComplementResultLegacy.php create mode 100644 system/database/Databases/Object/ResultCacheIterator.php delete mode 100644 system/database/Databases/Object/ResultIterator.php create mode 100644 system/engine/interfaces/url.php create mode 100644 system/etc/preferences.json diff --git a/composer.json b/composer.json index 6871003..5f89ba5 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "platform-check": false }, "require": { - "php": ">=5.4.20", + "php": ">=5.6.20", "colinmollenhour/credis": "^1.11.1", "twig/twig": "^3.0", "mustache/mustache": "^2.0", diff --git a/system/database/Databases/MSSQL.php b/system/database/Databases/MSSQL.php index eb84ef9..748892d 100644 --- a/system/database/Databases/MSSQL.php +++ b/system/database/Databases/MSSQL.php @@ -57,10 +57,9 @@ class MSSQL implements \Phacil\Framework\Interfaces\Databases \mssql_free_result($resource); - $query = new \Phacil\Framework\Databases\Object\Result(); - $query->row = isset($data[0]) ? $data[0] : array(); - $query->rows = $data; - $query->num_rows = $i; + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $query = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); + $query->setNumRows($i); unset($data); diff --git a/system/database/Databases/MySQL_PDO.php b/system/database/Databases/MySQL_PDO.php index 31c3d9d..c9e8b02 100644 --- a/system/database/Databases/MySQL_PDO.php +++ b/system/database/Databases/MySQL_PDO.php @@ -98,16 +98,14 @@ class MySQL_PDO implements Databases */ public function query($sql) { - if ($this->dbh) { - $data = new \Phacil\Framework\Databases\Object\Result(); - + if ($this->dbh) { $sth=$this->dbh->prepare($sql); $sth->execute(); //$sth= $this->dbh->query($sql); $this->affectedRows = $sth->rowCount(); - $data->rows = $sth ? $sth->fetchAll(\PDO::FETCH_ASSOC) : array(); - $data->row = isset($data->rows[0]) ? $data->rows[0] : null; - $data->num_rows = $this->affectedRows; + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $data = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$sth ? $sth->fetchAll(\PDO::FETCH_ASSOC) : array()]); + $data->setNumRows($this->affectedRows); return $data; } return null; @@ -197,10 +195,10 @@ class MySQL_PDO implements Databases $stmt->execute(); if ($stmt->columnCount()) { - $data = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $data = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$stmt->fetchAll(\PDO::FETCH_ASSOC)]); $data->setNumRows($stmt->rowCount()); - $data->setRows($stmt->fetchAll(\PDO::FETCH_ASSOC)); - //$data->setRow(isset($data->rows[0]) ? $data->rows[0] : null); + $stmt->closeCursor(); return $data; diff --git a/system/database/Databases/MySQL_legacy.php b/system/database/Databases/MySQL_legacy.php index b500c30..7ccf476 100644 --- a/system/database/Databases/MySQL_legacy.php +++ b/system/database/Databases/MySQL_legacy.php @@ -64,10 +64,11 @@ class MySQL_legacy implements \Phacil\Framework\Interfaces\Databases { \mysql_free_result($resource); - $query = new \Phacil\Framework\Databases\Object\Result(); - $query->row = isset($data[0]) ? $data[0] : array(); - $query->rows = $data; - $query->num_rows = $i; + /** + * @var \Phacil\Framework\Databases\Object\ResultInterface + */ + $query = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); + $query->setNumRows($i); unset($data); diff --git a/system/database/Databases/MySQLi.php b/system/database/Databases/MySQLi.php index ffb800d..8181ad9 100644 --- a/system/database/Databases/MySQLi.php +++ b/system/database/Databases/MySQLi.php @@ -90,14 +90,9 @@ class MySQLi implements Databases { $query = $this->connection->query($sql); if (!$this->connection->errno) { if ($query instanceof \mysqli_result) { - $data = array(); - while ($row = $query->fetch_assoc()) { - $data[] = $row; - } - $result = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$query->fetch_all(MYSQLI_ASSOC)]); $result->setNumRows($query->num_rows); - $result->setRow(isset($data[0]) ? $data[0] : []); - $result->setRows($data); $query->close(); return $result; } else { @@ -194,15 +189,10 @@ class MySQLi implements Databases { // Processar resultados se for um SELECT if ($result instanceof \mysqli_result) { - $data = []; - while ($row = $result->fetch_assoc()) { - $data[] = $row; - } - - $resultObj = new \Phacil\Framework\Databases\Object\Result(); + //$resultObj = new \Phacil\Framework\Databases\Object\Result($result->fetch_all(MYSQLI_ASSOC)); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$result->fetch_all(MYSQLI_ASSOC)]); $resultObj->setNumRows($result->num_rows); - $resultObj->setRow(isset($data[0]) ? $data[0] : []); - $resultObj->setRows($data); $result->close(); diff --git a/system/database/Databases/Object/Aux/ComplementResult.php b/system/database/Databases/Object/Aux/ComplementResult.php deleted file mode 100644 index 53a6b0f..0000000 --- a/system/database/Databases/Object/Aux/ComplementResult.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ - public function count(): int - { - return (int) $this->getNumRows(); - } - - /** - * {@inheritdoc} - */ - public function getIterator(): \Traversable - { - $this->customStorage = new \Phacil\Framework\Databases\Object\ResultIterator($this->rows); - return $this->customStorage; - //return new \ArrayIterator($this->loop($this->rows)); - } -} \ No newline at end of file diff --git a/system/database/Databases/Object/Aux/ComplementResultLegacy.php b/system/database/Databases/Object/Aux/ComplementResultLegacy.php deleted file mode 100644 index 68cfa78..0000000 --- a/system/database/Databases/Object/Aux/ComplementResultLegacy.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ - public function count() - { - return (int) $this->getNumRows(); - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - $this->customStorage = new \Phacil\Framework\Databases\Object\ResultIterator($this->rows); - return $this->customStorage; - //return new \ArrayIterator($this->loop($this->rows)); - } -} \ No newline at end of file diff --git a/system/database/Databases/Object/Item.php b/system/database/Databases/Object/Item.php index 341d1e8..e42fbed 100644 --- a/system/database/Databases/Object/Item.php +++ b/system/database/Databases/Object/Item.php @@ -46,15 +46,6 @@ class Item extends ComplementItem implements ObjectInterface { */ public function setData(array $data) { $this->__data = $data; - //$this->__data = new SplObjectStorage(); - - /* foreach($data as $key => $val) { - $keyForA = new self([$key => $val]); - $this->__data[$keyForA] = [$key => $val]; - } */ - - //$this->__data->attach(new self($data)); - //$this->__data->attach(json_decode(json_encode($data))); return $this; } diff --git a/system/database/Databases/Object/Result.php b/system/database/Databases/Object/Result.php index dfa5397..4f54cf4 100644 --- a/system/database/Databases/Object/Result.php +++ b/system/database/Databases/Object/Result.php @@ -9,50 +9,60 @@ namespace Phacil\Framework\Databases\Object; use Phacil\Framework\Databases\Object\ResultInterface; -use SplObjectStorage; -use Traversable; +use Phacil\Framework\Databases\Object\ResultCacheIterator; -if (version_compare(phpversion(), "7.1.0", ">=")) { - class ComplementResult extends \Phacil\Framework\Databases\Object\Aux\ComplementResult - { - - } - -} else { - class ComplementResult extends \Phacil\Framework\Databases\Object\Aux\ComplementResultLegacy{ - - } -} - -class Result extends ComplementResult implements ResultInterface { +/** + * @since 2.0.0 + * @package Phacil\Framework\Databases\Object + */ +class Result extends \ArrayIterator implements ResultInterface { /** * - * @var array + * @var int */ - public $rows; + public $num_rows; /** * - * @var array + * @var ResultCacheIterator */ - public $row; + private $cachedIterator; /** * - * @var int + * @var \Phacil\Framework\Databases\Object\Item[]|\Iterator|null */ - public $num_rows; + public $data = null; + + public function __construct(array $results = []) { + parent::__construct($results); + //$this->num_rows = $this->count(); + return $this; + } /** * - * @var \Phacil\Framework\Databases\Object\Item[]|\SplObjectStorage|\Iterator|null + * @param string $name + * @return \Phacil\Framework\Databases\Object\ItemInterface[]|\Phacil\Framework\Databases\Object\ItemInterface|null + * @throws \Phacil\Framework\Exception\RuntimeException */ - public $data = null; - - public function __construct(array $array = []) { - //return parent::__construct($array, 0, "\Phacil\Framework\Databases\Object\ResultIterator"); - } + public function __get($name) { + + switch ($name) { + case 'rows': + return $this; + break; + + case 'row': + return $this->offsetGet(0); + break; + + default: + throw new \Phacil\Framework\Exception\RuntimeException("Undefined property: $name"); + break; + } + } /** * @@ -97,9 +107,7 @@ class Result extends ComplementResult implements ResultInterface { * {@inheritdoc} */ public function getRow($numRow = false){ - $obj = new \Phacil\Framework\Databases\Object\Item(); - $this->data->attach($obj->setData($numRow ? (isset($this->rows[$numRow + 1]) ? $this->rows[$numRow + 1] : null) : $this->row)); - return $obj; + return ($numRow ? ($this->offsetGet($numRow - 1) ? : null) : $this->row); } /** @@ -122,7 +130,19 @@ class Result extends ComplementResult implements ResultInterface { * {@inheritdoc} */ public function __toObject() { - return $this->data ? $this->data : $this->loop($this->rows); + return $this; + } + + /** + * {@inheritdoc} + */ + public function __toArray() { + return iterator_to_array($this); + $this->cachedIterator = new ResultCacheIterator($this); + foreach ($this->cachedIterator as $val) { + # nothing + } + return $this->cachedIterator->getCache(); } /** @@ -134,11 +154,9 @@ class Result extends ComplementResult implements ResultInterface { { if($this->data) return $this->data; - $this->data = new SplObjectStorage(); + $this->data = []; foreach ($array as $key => $value) { - //$this->data[] = new \Phacil\Framework\Databases\Object\Item($value); - $obj = new \Phacil\Framework\Databases\Object\Item(); - $this->data->attach($obj->setData($value)); + $this->data[] = $value; } return $this->data; @@ -149,9 +167,21 @@ class Result extends ComplementResult implements ResultInterface { */ public function offsetGet($index) { + if(!$this->offsetExists($index)) return null; + $data = parent::offsetGet($index); - $item = new \Phacil\Framework\Databases\Object\Item(); - $item->setData($data); + + $item = new \Phacil\Framework\Databases\Object\Item($data); + return $item; + } + + /** + * {@inheritdoc} + */ + public function current() + { + $item = new \Phacil\Framework\Databases\Object\Item(parent::current()); + //$item->setData(parent::current()); return $item; } diff --git a/system/database/Databases/Object/ResultCacheIterator.php b/system/database/Databases/Object/ResultCacheIterator.php new file mode 100644 index 0000000..d0ab0b6 --- /dev/null +++ b/system/database/Databases/Object/ResultCacheIterator.php @@ -0,0 +1,189 @@ +Iterator = new \Phacil\Framework\Databases\Object\Result($results); + elseif($results instanceof \Phacil\Framework\Databases\Object\ResultInterface) + $this->Iterator = $results; + + parent::__construct($this->Iterator, $flags); + //$this->num_rows = $this->count(); + return $this; + } + + /** + * + * @param string $name + * @return \Phacil\Framework\Databases\Object\ItemInterface[]|\Phacil\Framework\Databases\Object\ItemInterface|null + * @throws \Phacil\Framework\Exception\RuntimeException + */ + public function __get($name) + { + + switch ($name) { + case 'rows': + return $this->__toArray(); + break; + + case 'row': + return $this->offsetGet(0); + break; + + default: + throw new \Phacil\Framework\Exception\RuntimeException("Undefined property: $name"); + break; + } + } + + /** + * + * {@inheritdoc} + */ + public function getData($numRow = false) + { + return $numRow ? $this->getRow($numRow) : $this->getRows(); + } + + /** + * {@inheritdoc} + */ + public function getItems() + { + return $this->__toObject(); + } + + /** + * {@inheritdoc} + */ + public function setRows($rows) + { + $this->rows = $rows; + $this->row = isset($rows[0]) ? $this->rows[0] : null; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRows() + { + return $this->rows; + } + + /** + * {@inheritdoc} + */ + public function setRow($row) + { + $this->row = $row; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRow($numRow = false) + { + return ($numRow ? ($this->offsetGet($numRow - 1) ?: null) : $this->row); + } + + /** + * + * {@inheritdoc} + */ + public function setNumRows($num) + { + $this->num_rows = $num; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNumRows() + { + return $this->num_rows; + } + + /** + * {@inheritdoc} + */ + public function __toObject() + { + return $this; + } + + /** + * {@inheritdoc} + */ + public function __toArray() + { + //return iterator_to_array($this); + foreach ($this as $val) { + # nothing + } + return $this->getCache(); + } + + /** + * {@inheritdoc} + */ + public function offsetGet($index) + { + $data = null; + if ($this->offsetExists($index)) { + $data = parent::offsetGet($index); + } elseif ($this->Iterator->offsetExists($index)){ + $data = $this->Iterator->offsetGet($index); + } + + if(!$data) return null; + + $item = new \Phacil\Framework\Databases\Object\Item($data); + return $item; + } + +} \ No newline at end of file diff --git a/system/database/Databases/Object/ResultInterface.php b/system/database/Databases/Object/ResultInterface.php index 200d617..83eba34 100644 --- a/system/database/Databases/Object/ResultInterface.php +++ b/system/database/Databases/Object/ResultInterface.php @@ -10,12 +10,14 @@ namespace Phacil\Framework\Databases\Object; /** + * A Database result object with all stored data + * @since 2.0.0 * @property int $num_rows - * @property array $row - * @property array $rows + * @property \Phacil\Framework\Databases\Object\Item $row + * @property \Phacil\Framework\Databases\Object\Item[] $rows * @package Phacil\Framework\Databases\Object */ -interface ResultInterface extends \Countable, \IteratorAggregate { +interface ResultInterface extends \Countable, \ArrayAccess, \Traversable { /** * * @param array $rows @@ -65,10 +67,16 @@ interface ResultInterface extends \Countable, \IteratorAggregate { /** * - * @return \Phacil\Framework\Databases\Object\Item[] + * @return \Phacil\Framework\Databases\Object\ResultInterface */ public function __toObject(); + /** + * + * @return \Phacil\Framework\Databases\Object\Item[] + */ + public function __toArray(); + /** * * @return \Phacil\Framework\Databases\Object\Item[] diff --git a/system/database/Databases/Object/ResultIterator.php b/system/database/Databases/Object/ResultIterator.php deleted file mode 100644 index c1ef7fe..0000000 --- a/system/database/Databases/Object/ResultIterator.php +++ /dev/null @@ -1,30 +0,0 @@ -setData($data); - return $item; - } - - public function current() - { - $item = new \Phacil\Framework\Databases\Object\Item(); - $item->setData(parent::current()); - return $item; - } -} \ No newline at end of file diff --git a/system/database/Databases/Oracle.php b/system/database/Databases/Oracle.php index 34eee3d..6a5950f 100644 --- a/system/database/Databases/Oracle.php +++ b/system/database/Databases/Oracle.php @@ -69,10 +69,9 @@ class Oracle implements Databases { if (!$this->connection) { \oci_fetch_all($stid, $res); - $result = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$res]); $result->setNumRows(\oci_num_rows($stid)); - $result->setRow(isset($res[0]) ? $res[0] : []); - $result->setRows($res); return $result; @@ -132,10 +131,9 @@ class Oracle implements Databases { $res = []; \oci_fetch_all($stid, $res); - $resultObj = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$res]); $resultObj->setNumRows(\oci_num_rows($stid)); - $resultObj->setRow(isset($res[0]) ? $res[0] : []); - $resultObj->setRows($res); return $resultObj; } else { diff --git a/system/database/Databases/Oracle_PDO.php b/system/database/Databases/Oracle_PDO.php index 7a26e7e..4dd504b 100644 --- a/system/database/Databases/Oracle_PDO.php +++ b/system/database/Databases/Oracle_PDO.php @@ -102,10 +102,10 @@ class Oracle_PDO implements Databases // free up resources $this->statement->closeCursor(); $this->statement = null; - $result = new \Phacil\Framework\Databases\Object\Result(); - $result->row = (isset($data[0]) ? $data[0] : array()); - $result->rows = $data; - $result->num_rows = $this->rowCount; + + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); + $result->setNumRows($this->rowCount); } } catch (\PDOException $e) { throw new \Phacil\Framework\Exception('Error: ' . $e->getMessage() . ' Error Code : ' . $e->getCode() . '
' . $sql); @@ -178,10 +178,10 @@ class Oracle_PDO implements Databases $stmt->execute(); if ($stmt->columnCount()) { - $data = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $data = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$stmt->fetchAll(\PDO::FETCH_ASSOC)]); $data->setNumRows($stmt->rowCount()); - $data->setRows($stmt->fetchAll(\PDO::FETCH_ASSOC)); - //$data->setRow(isset($data->rows[0]) ? $data->rows[0] : null); + $stmt->closeCursor(); return $data; diff --git a/system/database/Databases/Postgre.php b/system/database/Databases/Postgre.php index befc26e..0f3c761 100644 --- a/system/database/Databases/Postgre.php +++ b/system/database/Databases/Postgre.php @@ -64,10 +64,11 @@ class Postgre implements Databases { $i++; } pg_free_result($resource); - $query = new \Phacil\Framework\Databases\Object\Result(); - $query->setRow(isset($data[0]) ? $data[0] : array()); - $query->setRows($data); + + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $query = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); $query->setNumRows($i); + unset($data); return $query; } else { @@ -133,10 +134,9 @@ class Postgre implements Databases { $i++; } - $resultObj = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); $resultObj->setNumRows($i); - $resultObj->setRow(isset($data[0]) ? $data[0] : []); - $resultObj->setRows($data); return $resultObj; } else { diff --git a/system/database/Databases/SQLSRV.php b/system/database/Databases/SQLSRV.php index 72782a5..e928a5e 100644 --- a/system/database/Databases/SQLSRV.php +++ b/system/database/Databases/SQLSRV.php @@ -82,10 +82,9 @@ class SQLSRV implements Databases { \sqlsrv_free_stmt($resource); - $query = new \Phacil\Framework\Databases\Object\Result(); - $query->row = isset($data[0]) ? $data[0] : array(); - $query->rows = $data; - $query->num_rows = $i; + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $query = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); + $query->setNumRows($i); unset($data); @@ -164,10 +163,9 @@ class SQLSRV implements Databases { $data[] = $row; } - $resultObj = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); $resultObj->setNumRows(\sqlsrv_num_rows($stmt)); - $resultObj->setRow(isset($data[0]) ? $data[0] : []); - $resultObj->setRows($data); return $resultObj; } diff --git a/system/database/Databases/SQLite3.php b/system/database/Databases/SQLite3.php index ef2a995..aad8d90 100644 --- a/system/database/Databases/SQLite3.php +++ b/system/database/Databases/SQLite3.php @@ -65,10 +65,11 @@ class SQLite3 implements Databases { while ($row = $query->fetchArray(SQLITE3_ASSOC)) { $data[] = $row; } - $result = new \Phacil\Framework\Databases\Object\Result(); + + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); $result->setNumRows((!empty($data)) ? count($data) : 0); - $result->setRow(isset($data[0]) ? $data[0] : array()); - $result->setRows($data); + $query->finalize(); return $result; @@ -146,10 +147,9 @@ class SQLite3 implements Databases { $data[] = $row; } - $resultObj = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $resultObj = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); $resultObj->setNumRows(count($data)); - $resultObj->setRow(isset($data[0]) ? $data[0] : []); - $resultObj->setRows($data); $result->finalize(); diff --git a/system/database/Databases/mPDO.php b/system/database/Databases/mPDO.php index 187caa5..49d54f2 100644 --- a/system/database/Databases/mPDO.php +++ b/system/database/Databases/mPDO.php @@ -85,10 +85,10 @@ class mPDO implements Databases { // free up resources $this->statement->closeCursor(); $this->statement = null; - $result = new \Phacil\Framework\Databases\Object\Result(); - $result->row = (isset($data[0]) ? $data[0] : array()); - $result->rows = $data; - $result->num_rows = $this->rowCount; + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); + $result->setNumRows($this->rowCount); + } } catch (\PDOException $e) { throw new \Phacil\Framework\Exception('Error: ' . $e->getMessage() . ' Error Code : ' . $e->getCode() . '
' . $sql); @@ -156,10 +156,10 @@ class mPDO implements Databases { $stmt->execute(); if ($stmt->columnCount()) { - $data = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $data = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$stmt->fetchAll(\PDO::FETCH_ASSOC)]); $data->setNumRows($stmt->rowCount()); - $data->setRows($stmt->fetchAll(\PDO::FETCH_ASSOC)); - //$data->setRow(isset($data->rows[0]) ? $data->rows[0] : null); + $stmt->closeCursor(); return $data; diff --git a/system/database/Databases/sqlsrvPDO.php b/system/database/Databases/sqlsrvPDO.php index 59eda3b..846b46c 100644 --- a/system/database/Databases/sqlsrvPDO.php +++ b/system/database/Databases/sqlsrvPDO.php @@ -99,9 +99,8 @@ class sqlsrvPDO implements Databases { $data[] = $row; } - $result = new \Phacil\Framework\Databases\Object\Result(); - $result->setRow((isset($data[0])) ? $data[0] : array()); - $result->setRows($data); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $result = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$data]); $result->setNumRows($this->statement->rowCount()); } } catch (\PDOException $e) { @@ -182,9 +181,10 @@ class sqlsrvPDO implements Databases { $this->statement->execute(); if ($this->statement->columnCount()) { - $data = new \Phacil\Framework\Databases\Object\Result(); + /** @var \Phacil\Framework\Databases\Object\ResultInterface */ + $data = \Phacil\Framework\Registry::getInstance()->create("Phacil\Framework\Databases\Object\ResultInterface", [$this->statement->fetchAll(\PDO::FETCH_ASSOC)]); $data->setNumRows($this->statement->rowCount()); - $data->setRows($this->statement->fetchAll(\PDO::FETCH_ASSOC)); + $this->statement->closeCursor(); return $data; diff --git a/system/engine/autoload.php b/system/engine/autoload.php index 1119a87..032dffd 100644 --- a/system/engine/autoload.php +++ b/system/engine/autoload.php @@ -92,6 +92,7 @@ 'Interfaces\\Controller', 'Interfaces\\Helper', 'Interfaces\\Model', + 'Interfaces\\Url', 'Exception', 'Render', 'Debug', diff --git a/system/engine/front.php b/system/engine/front.php index 045cf4d..815e85a 100644 --- a/system/engine/front.php +++ b/system/engine/front.php @@ -10,7 +10,10 @@ namespace Phacil\Framework; use Phacil\Framework\Interfaces\Front as frontInterface; -/** @package Phacil\Framework */ +/** + * @package Phacil\Framework + * @since 1.0.0 + **/ final class Front implements frontInterface { /** @@ -105,43 +108,10 @@ final class Front implements frontInterface { } } - /* try { - if (is_callable(array($controller, $method))) { - $action = call_user_func_array(array($controller, $method), $args); - } else { - $action = new Action($this->error); - - $this->error = ''; - throw new Exception("The controller can't be loaded", 1); - } - } catch (\Phacil\Framework\Exception\Throwable $th) { - //throw $th; - $action = new Action($this->error); - - $this->error = ''; - - throw new Exception("The controller can't be loaded: ".$th->getMessage(), $th->getCode(), $th); - - } */ - } elseif(!$file && isset($classAlt['class'])) { try { $this->injectionClass($classController); $action = $this->callController(new $classAlt['class']($this->registry), $method, $args); - - /* if (!is_subclass_of($controller, 'Phacil\Framework\Controller')) { - throw new Exception('PHACIL ERROR: Controller ' . get_class($controller) . ' doesn\'t have Phacil\Framework\Controller implemented'); - } - - if(!is_callable(array($controller, $method))) { - $action = new Action($this->error); - - $this->error = ''; - - new Exception("PHACIL ERROR: Controller class " . get_class($controller) . "->".$method."() is not a callable function"); - } else { - $action = call_user_func_array(array($controller, $method), $args); - } */ } catch (\Phacil\Framework\Exception\Throwable $th) { throw ($th); } @@ -180,24 +150,6 @@ final class Front implements frontInterface { } protected function injectionClass($class){ - /* $refClass = new ReflectionClass($class); - - if(!$refClass->getConstructor()){ - if($refClass->hasMethod('getInstance') && $refClass->getMethod('getInstance')->isStatic()){ - return $refClass->getMethod('getInstance')->invoke(null); - } - - return $refClass->newInstanceWithoutConstructor(); - } - - try { - if ($autoInstance = $this->registry->getInstance($class)) - return $autoInstance; - } catch (\Throwable $th) { - //throw $th; - } */ - - return $this->registry->injectionClass($class); } } diff --git a/system/engine/interfaces/url.php b/system/engine/interfaces/url.php new file mode 100644 index 0000000..eae425a --- /dev/null +++ b/system/engine/interfaces/url.php @@ -0,0 +1,40 @@ +instances as $key => $value) { - # code... if(!is_object($value)) continue; if(get_class($value) == $classObj) {$return = $value; break; } @@ -130,8 +136,9 @@ final class Registry { if($onlyCheckInstances) return $return; if(is_string($class)) { - $reflector = new ReflectionClass($class); - return self::setAutoInstance($reflector->newInstanceArgs($args)); + $classCreate = self::checkPreference($class); + $reflector = new ReflectionClass($classCreate); + return self::setAutoInstance($reflector->newInstanceArgs($args), $class); } if (is_object($class)) { @@ -142,16 +149,82 @@ final class Registry { } /** - * - * @param object $class - * @return object + * @param string $class + * @param array $args + * @return mixed + * @throws \ReflectionException + * @throws \Exception * @throws \Phacil\Framework\Exception + */ + public function create($class, $args = array()) { + if(is_string($class)) { + return $this->injectionClass($class, $args, true); + /* $classCreate = self::checkPreference($class); + $reflector = new ReflectionClass($classCreate); + return self::setAutoInstance($reflector->newInstanceArgs($args), $class); */ + } + return null; + } + + /** + * Adds DI preferences from a JSON file. + * + * This method reads a JSON file containing preferences and merges them into the existing preferences array. + * + * @param string $jsonFilePath The path to the JSON file containing preferences. + * @return void + * @throws \Phacil\Framework\Exception If there is an error reading the JSON file or if the JSON data is invalid. + */ + static public function addPreference($jsonFilePath) { + if (file_exists($jsonFilePath)) { + $jsonData = file_get_contents($jsonFilePath); + + $dataArray = json_decode($jsonData, true); + + // Verifica se a conversão foi bem-sucedida + if ($dataArray === null && json_last_error() !== JSON_ERROR_NONE) { + // Se houver um erro na conversão, trata o erro + $error = new \Phacil\Framework\Exception(json_last_error_msg()); + return; + } + } + if (isset($dataArray['preferences'])) + self::$preferences = array_merge(self::$preferences, $dataArray['preferences']); + } + + /** + * Checks if a preference has been set for the specified class and returns it if found. + * + * This method checks if a preference has been set for the specified class. If a preference + * is found, it returns the class name defined as the preference; otherwise, it returns the + * original class name. + * + * @param string $class The class name to check for a preference. + * @return string The class name defined as the preference, if found; otherwise, the original class name. + */ + static public function checkPreference($class) { + if(isset(self::$preferences[$class])) { + return self::$preferences[$class]; + } + return $class; + } + + /** + * Sets an auto-instantiated object to be used as a dependency. + * + * This method allows you to set an object to be automatically instantiated and used as a dependency + * when resolving other dependencies that require an instance of the specified class. + * + * @param object $class The object instance to be set as an auto-instantiated dependency. + * @param string|null (Optional) $original The original class name of the object being set. + * @return object The object instance that was set as an auto-instantiated dependency. + * @throws \Phacil\Framework\Exception If the provided parameter is not an object. * @since 2.0.0 */ - static public function setAutoInstance($class) { + static public function setAutoInstance($class, $original = null) { if(!is_object($class)) throw new Exception('Object type is required!'); - self::$autoInstances[get_class($class)] = $class; + self::$autoInstances[$original ?: get_class($class)] = $class; return $class; } @@ -169,68 +242,91 @@ final class Registry { } - public function injectionClass($class) + /** + * Resolves and instantiates a class with optional constructor arguments and creation control. + * + * This method resolves a class by its name, instantiates it with optional constructor arguments, + * and provides control over the creation process. + * + * @param string $class The fully qualified name of the class to instantiate. + * @param array $args (Optional) Arguments for the class constructor. Default is an empty array. + * If empty, constructor arguments will be automatically detected and injected. + * @param bool $forceCreate (Optional) Whether to force creation. Default is false. + * @return mixed + * @throws \ReflectionException + * @throws \Exception + * @throws \Phacil\Framework\Exception + */ + public function injectionClass($class, $args = array(), $forceCreate = false) { + $argsToInject = !empty($args) ? $args : false; + $originalClass = $class; + $class = self::checkPreference($class); + $originalClass = $originalClass == $class ? null : $originalClass; $refClass = new ReflectionClass($class); - if (!$refClass->getConstructor()) { - if ($refClass->hasMethod('getInstance') && $refClass->getMethod('getInstance')->isStatic()) { - return $refClass->getMethod('getInstance')->invoke(null); - } - - return $refClass->newInstanceWithoutConstructor(); - } try { - if ( $autoInstance = $this->getInstance($class, [], true)) + if (!$forceCreate && $autoInstance = $this->getInstance($originalClass ?: $class, [], true)) return $autoInstance; + + if (!$refClass->getConstructor() && !$argsToInject) { + if ($refClass->hasMethod('getInstance') && $refClass->getMethod('getInstance')->isStatic()) { + return $refClass->getMethod('getInstance')->invoke(null); + } + return $refClass->newInstanceWithoutConstructor(); + } + } catch (\Throwable $th) { //throw $th; } $rMethod = new ReflectionMethod($class, "__construct"); - $params = $rMethod->getParameters(); - $argsToInject = []; - foreach ($params as $param) { - //$param is an instance of ReflectionParameter - try { - if (version_compare(phpversion(), "7.2.0", "<")) { - if ($param->getClass()) { - $injectionClass = $param->getClass()->name; - if (class_exists($injectionClass)) { - $argsToInject[$param->getPosition()] = $this->injectionClass($injectionClass); - continue; + if(!$argsToInject){ + $params = $rMethod->getParameters(); + $argsToInject = []; + foreach ($params as $param) { + //$param is an instance of ReflectionParameter + try { + if (version_compare(phpversion(), "7.2.0", "<")) { + if ($param->getClass()) { + $injectionClass = $param->getClass()->name; + if (class_exists($injectionClass)) { + $argsToInject[$param->getPosition()] = $this->injectionClass($injectionClass); + continue; + } + if (!$param->isOptional()) { + throw new \Phacil\Framework\Exception\ReflectionException("Error Processing Request: " . $injectionClass . "not exist"); + } } - if (!$param->isOptional()) { - throw new \Phacil\Framework\Exception\ReflectionException("Error Processing Request: " . $injectionClass . "not exist"); - } - } - } else { - if ($param->getType()) { - $injectionClass = $param->getType()->getName(); - if (class_exists($injectionClass)) { - $argsToInject[$param->getPosition()] = $this->injectionClass($injectionClass); - continue; - } - if (!$param->isOptional()) { - throw new \Phacil\Framework\Exception\ReflectionException("Error Processing Request: " . $injectionClass . "not exist"); + } else { + if ($param->getType()) { + $injectionClass = $param->getType()->getName(); + if (class_exists($injectionClass)) { + $argsToInject[$param->getPosition()] = $this->injectionClass($injectionClass); + continue; + } + if (!$param->isOptional()) { + throw new \Phacil\Framework\Exception\ReflectionException("Error Processing Request: " . $injectionClass . "not exist"); + } } } + } catch (\Exception $th) { + throw $th; } - } catch (\Exception $th) { - throw $th; - } - if ($param->isOptional() && $param->isDefaultValueAvailable()) { - $argsToInject[] = $param->getDefaultValue(); - continue; - } - if ($param->isOptional()) { - $argsToInject[] = null; + if ($param->isOptional() && $param->isDefaultValueAvailable()) { + $argsToInject[] = $param->getDefaultValue(); + continue; + } + if ($param->isOptional()) { + $argsToInject[] = null; + } } } + - return self::setAutoInstance($refClass->newInstanceArgs($argsToInject)); + return self::setAutoInstance($refClass->newInstanceArgs($argsToInject), $originalClass); } } diff --git a/system/etc/preferences.json b/system/etc/preferences.json new file mode 100644 index 0000000..7f177dc --- /dev/null +++ b/system/etc/preferences.json @@ -0,0 +1,7 @@ +{ + "preferences": { + "Phacil\\Framework\\Databases\\Object\\ResultInterface": "Phacil\\Framework\\Databases\\Object\\Result", + "Phacil\\Framework\\Interfaces\\Loader": "Phacil\\Framework\\Loader", + "Phacil\\Framework\\Interfaces\\Url": "Phacil\\Framework\\Url" + } +} \ No newline at end of file diff --git a/system/system.php b/system/system.php index 7a1ce19..4b3d171 100644 --- a/system/system.php +++ b/system/system.php @@ -99,6 +99,8 @@ final class startEngineExacTI { self::$RegistryAlt = &$this->registry; + $this->registry::addPreference(\Phacil\Framework\Config::DIR_SYSTEM()."etc/preferences.json"); + if($this->composer) { $this->registry->set('composer', $this->composer); } @@ -379,9 +381,9 @@ $engine->engine = $engine; // Loader /** - * @var Loader + * @var \Phacil\Framework\Interfaces\Loader */ -$engine->load = new Loader($engine->registry); +$engine->load = $engine->getRegistry()->create("Phacil\Framework\Interfaces\Loader", [$engine->registry]); // Config /** @var Config */ @@ -444,7 +446,10 @@ if($engine->config->get('PatternSiteTitle') == true) { } // Url -$engine->url = new Url($engine->config->get('config_url'), $engine->config->get('config_use_ssl') ? $engine->config->get('config_ssl') : $engine->config->get('config_url')); +/** + * @var \Phacil\Framework\Interfaces\Url + */ +$engine->url = $engine->getRegistry()->create("Phacil\Framework\Interfaces\Url", [$engine->config->get('config_url'), $engine->config->get('config_use_ssl') ? $engine->config->get('config_ssl') : $engine->config->get('config_url')]); // Log if(!$engine->config->get('config_error_filename')){ diff --git a/system/url/autoload.php b/system/url/autoload.php index cacf16e..67a430b 100644 --- a/system/url/autoload.php +++ b/system/url/autoload.php @@ -8,10 +8,11 @@ namespace Phacil\Framework; +use Phacil\Framework\Interfaces\Url as UrlInterface; use Phacil\Framework\Config; use Phacil\Framework\Request; -class Url { +class Url implements UrlInterface { /** *