Upgraded database backend for PHP 8.1.

Changes implemented:
- Proper type definitions, for both return types and properties.
- Streamlined if statements, removing unnecessary statements.
- Upgraded Mongo backend to be compatible with driver 1.15.
This commit is contained in:
Abel Hoogeveen 2022-12-22 10:46:13 +01:00
parent 029511f0cd
commit 4b200dbd63
17 changed files with 107 additions and 101 deletions

View File

@ -10,14 +10,16 @@
}
],
"require": {
"php": ">=7.4.0",
"php": ">=8.1.0",
"fuzeworks/core": "~1.3.0",
"fuzeworks/mvcr": "~1.3.0",
"ext-pdo": "*"
"ext-pdo": "*",
"ext-mongodb": "*"
},
"require-dev": {
"phpunit/phpunit": "^9",
"fuzeworks/tracycomponent": "~1.3.0"
"fuzeworks/tracycomponent": "~1.3.0",
"mongodb/mongodb": "~1.15.0"
},
"autoload": {
"psr-4": {

View File

@ -63,51 +63,51 @@ class Database
*
* @var array
*/
protected $dbConfig;
protected array $dbConfig;
/**
* All engines that can be used for databases
*
* @var iDatabaseEngine[]
*/
protected $engines = [];
protected array $engines = [];
/**
* All tableModels that can be used for connections
*
* @var iDatabaseTableModel[]
*/
protected $tableModels = [];
protected array $tableModels = [];
/**
* Whether all DatabaseEngines have been loaded yet
*
* @var bool
*/
protected $enginesLoaded = false;
protected bool $enginesLoaded = false;
/**
* Array of all the database engines
*
* @var iDatabaseEngine[]
*/
protected $connections = [];
protected array $connections = [];
/**
* Array of all the tableModels
*
* @var iDatabaseTableModel[]
*/
protected $tables;
protected array $tables;
/**
* Register with the TracyBridge upon startup
*/
public function init()
public function init(): void
{
$this->dbConfig = Factory::getInstance()->config->get('database')->toArray();
if (class_exists('Tracy\Debugger', true))
if (class_exists('Tracy\Debugger'))
DatabaseTracyBridge::register();
}
@ -145,7 +145,7 @@ class Database
/** @var iDatabaseEngine $engine */
// If a databaseEngine is provided by the event, use that. Otherwise search in the list of engines
if (is_object($event->databaseEngine) && $event->databaseEngine instanceof iDatabaseEngine)
if ($event->databaseEngine instanceof iDatabaseEngine)
{
// Do intervention first
$engine = $this->connections[$event->connectionName] = $event->databaseEngine;
@ -177,7 +177,7 @@ class Database
}
// Tie it into the Tracy Bar if available
if (class_exists('\Tracy\Debugger', true))
if (class_exists('\Tracy\Debugger'))
DatabaseTracyBridge::registerDatabase($engine);
return $engine;
@ -205,7 +205,7 @@ class Database
/** @var iDatabaseTableModel $tableModel */
// If a TableModel is provided by the event, use that. Otherwise search in the list of tableModels
if (is_object($event->tableModel) && $event->tableModel instanceof iDatabaseTableModel)
if ($event->tableModel instanceof iDatabaseTableModel)
{
$tableModel = $this->tables[$event->connectionName . "|" . $event->tableName] = $event->tableModel;
if (!$tableModel->isSetup())

View File

@ -49,7 +49,7 @@ abstract class DatabaseDriver implements iDatabaseEngine
*
* @var array
*/
private $queries = [];
private array $queries = [];
/**
* Log information about a query. Used for debugging issues
@ -74,7 +74,7 @@ abstract class DatabaseDriver implements iDatabaseEngine
*
* @return array
*/
public function getQueries()
public function getQueries(): array
{
return $this->queries;
}

View File

@ -36,11 +36,11 @@
namespace FuzeWorks\DatabaseEngine;
use InvalidArgumentException;
use MongoDB\Driver\Monitoring\CommandFailedEvent;
use MongoDB\Driver\Monitoring\CommandStartedEvent;
use MongoDB\Driver\Monitoring\CommandSubscriber;
use MongoDB\Driver\Monitoring\CommandSucceededEvent;
use Tracy\Debugger;
class MongoCommandSubscriber implements CommandSubscriber
{
@ -48,17 +48,17 @@ class MongoCommandSubscriber implements CommandSubscriber
/**
* @var MongoEngine
*/
private $mongoEngine;
private MongoEngine $mongoEngine;
/**
* @var float
*/
private $commandTimings = 0.0;
private float $commandTimings = 0.0;
/**
* @var string
*/
private $queryString;
private string $queryString;
public function __construct(MongoEngine $engine)
{
@ -71,10 +71,10 @@ class MongoCommandSubscriber implements CommandSubscriber
* @link https://secure.php.net/manual/en/mongodb-driver-monitoring-commandsubscriber.commandfailed.php
* @param CommandFailedEvent $event An event object encapsulating information about the failed command.
* @return void
* @throws \InvalidArgumentException on argument parsing errors.
* @throws InvalidArgumentException on argument parsing errors.
* @since 1.3.0
*/
public function commandFailed(CommandFailedEvent $event)
public function commandFailed(CommandFailedEvent $event): void
{
// TODO: Implement commandFailed() method.
}
@ -85,10 +85,10 @@ class MongoCommandSubscriber implements CommandSubscriber
* @link https://secure.php.net/manual/en/mongodb-driver-monitoring-commandsubscriber.commandstarted.php
* @param CommandStartedEvent $event An event object encapsulating information about the started command.
* @return void
* @throws \InvalidArgumentException on argument parsing errors.
* @throws InvalidArgumentException on argument parsing errors.
* @since 1.3.0
*/
public function commandStarted(CommandStartedEvent $event)
public function commandStarted(CommandStartedEvent $event): void
{
$this->commandTimings = microtime(true);
$this->queryString = strtoupper($event->getCommandName());
@ -168,10 +168,10 @@ class MongoCommandSubscriber implements CommandSubscriber
* @link https://secure.php.net/manual/en/mongodb-driver-monitoring-commandsubscriber.commandsucceeded.php
* @param CommandSucceededEvent $event An event object encapsulating information about the successful command.
* @return void
* @throws \InvalidArgumentException on argument parsing errors.
* @throws InvalidArgumentException on argument parsing errors.
* @since 1.3.0
*/
public function commandSucceeded(CommandSucceededEvent $event)
public function commandSucceeded(CommandSucceededEvent $event): void
{
// Get variables
$queryTimings = microtime(true) - $this->commandTimings;

View File

@ -74,19 +74,19 @@ class MongoEngine extends DatabaseDriver
*
* @var bool
*/
protected $setUp = false;
protected bool $setUp = false;
/**
* @var Client
* @var Client|null
*/
protected $mongoConnection;
protected ?Client $mongoConnection = null;
/**
* Connection string with the database
*
* @var string
* @var string|null
*/
protected $uri;
protected ?string $uri = null;
/**
* Returns the name of this engine
@ -126,9 +126,9 @@ class MongoEngine extends DatabaseDriver
public function setUp(array $parameters): bool
{
// Prepare variables for connection
$this->uri = isset($parameters['uri']) ? $parameters['uri'] : null;
$uriOptions = isset($parameters['uriOptions']) ? $parameters['uriOptions'] : [];
$driverOptions = isset($parameters['driverOptions']) ? $parameters['driverOptions'] : [];
$this->uri = $parameters['uri'] ?? null;
$uriOptions = $parameters['uriOptions'] ?? [];
$driverOptions = $parameters['driverOptions'] ?? [];
// Don't attempt and connect without a URI
if (is_null($this->uri))
@ -205,7 +205,7 @@ class MongoEngine extends DatabaseDriver
*/
public function transactionStart(): bool
{
// TODO: Implement transactionStart() method.
return false;
}
/**
@ -213,7 +213,7 @@ class MongoEngine extends DatabaseDriver
*/
public function transactionEnd(): bool
{
// TODO: Implement transactionEnd() method.
return false;
}
/**
@ -221,7 +221,7 @@ class MongoEngine extends DatabaseDriver
*/
public function transactionCommit(): bool
{
// TODO: Implement transactionCommit() method.
return false;
}
/**
@ -229,6 +229,6 @@ class MongoEngine extends DatabaseDriver
*/
public function transactionRollback(): bool
{
// TODO: Implement transactionRollback() method.
return false;
}
}

View File

@ -38,7 +38,6 @@ namespace FuzeWorks\DatabaseEngine;
use FuzeWorks\Exception\DatabaseException;
use FuzeWorks\Exception\TransactionException;
use FuzeWorks\Logger;
use FuzeWorks\Model\iDatabaseTableModel;
use PDO;
use PDOException;
use PDOStatement;
@ -61,28 +60,28 @@ class PDOEngine extends DatabaseDriver
*
* @var bool
*/
protected $setUp = false;
protected bool $setUp = false;
/**
* The PDO object connected with the database
*
* @var PDO
*/
protected $pdoConnection;
protected PDO $pdoConnection;
/**
* Connection string with the database
*
* @var string
* @var string|null
*/
protected $dsn;
protected ?string $dsn = null;
/**
* Whether a transaction has failed and should be reverted in the future
*
* @var bool
*/
protected $transactionFailed = false;
protected bool $transactionFailed = false;
/**
* Whether a transaction should be automatically committed if not manually aborted by the user.
@ -92,7 +91,7 @@ class PDOEngine extends DatabaseDriver
*
* @var bool
*/
protected $transactionAutocommit = false;
protected bool $transactionAutocommit = false;
/**
* Returns the name of this engine
@ -129,9 +128,9 @@ class PDOEngine extends DatabaseDriver
public function setUp(array $parameters): bool
{
// Prepare variables for connection
$this->dsn = isset($parameters['dsn']) ? $parameters['dsn'] : null;
$username = isset($parameters['username']) ? $parameters['username'] : '';
$password = isset($parameters['password']) ? $parameters['password'] : '';
$this->dsn = $parameters['dsn'] ?? null;
$username = $parameters['username'] ?? '';
$password = $parameters['password'] ?? '';
// Don't attempt connection without DSN
if (is_null($this->dsn))

View File

@ -71,7 +71,7 @@ class PDOStatementWrapper
/**
* @var PDOStatement
*/
private $statement;
private PDOStatement $statement;
/**
* Callable for logging queries and errors
@ -83,7 +83,7 @@ class PDOStatementWrapper
/**
* @var PDOEngine
*/
private $engine;
private PDOEngine $engine;
public function __construct(PDOStatement $statement, callable $logQueryCallable, PDOEngine $engine)
{
@ -97,7 +97,7 @@ class PDOStatementWrapper
* @return bool
* @throws DatabaseException
*/
public function execute(array $input_parameters = [])
public function execute(array $input_parameters = []): bool
{
// Run the query and benchmark the time
$benchmarkStart = microtime(true);
@ -118,7 +118,7 @@ class PDOStatementWrapper
throw new DatabaseException("Could not run query. Database returned an error. Error code: " . $errInfo['code']);
}
return $result;
return true;
}
/**

View File

@ -38,7 +38,6 @@ namespace FuzeWorks;
use FuzeWorks\DatabaseEngine\iDatabaseEngine;
use Tracy\IBarPanel;
use Tracy\Debugger;
use Tracy\Dumper;
/**
* DatabaseTracyBridge Class.
@ -57,9 +56,9 @@ class DatabaseTracyBridge implements IBarPanel
/**
* @var iDatabaseEngine[]
*/
public static $databases = array();
public static array $databases = array();
protected $results = array();
protected array $results = array();
public static function register()
{

View File

@ -54,28 +54,28 @@ class DatabaseLoadDriverEvent extends Event
*
* @var iDatabaseEngine|null
*/
public $databaseEngine = null;
public ?iDatabaseEngine $databaseEngine = null;
/**
* The name of the engine to be loaded
*
* @var string
*/
public $engineName;
public string $engineName;
/**
* Parameters of the database to be loaded
*
* @var array
*/
public $parameters;
public array $parameters;
/**
* Database group to load
*
* @var bool
* @var string
*/
public $connectionName;
public string $connectionName;
public function init(string $engineName, array $parameters, string $connectionName)
{

View File

@ -49,35 +49,35 @@ class DatabaseLoadTableModelEvent extends Event
*
* @var iDatabaseTableModel|null
*/
public $tableModel = null;
public ?iDatabaseTableModel $tableModel = null;
/**
* The name of the engine to be loaded
*
* @var string
*/
public $engineName;
public string $engineName;
/**
* The name of the table this model manages
*
* @var string
*/
public $tableName;
public string $tableName;
/**
* Parameters of the database to be loaded
*
* @var array
*/
public $parameters;
public array $parameters;
/**
* Database group to load
*
* @var bool
* @var string
*/
public $connectionName;
public string $connectionName;
public function init(string $engineName, array $parameters, string $connectionName, string $tableName)

View File

@ -49,28 +49,28 @@ class MongoTableModel implements iDatabaseTableModel
*
* @var Database
*/
private $databases;
private Database $databases;
/**
* Whether the tableModel has been properly setup
*
* @var bool
*/
protected $setup = false;
protected bool $setup = false;
/**
* Holds the PDOEngine for this model
*
* @var MongoEngine
*/
protected $dbEngine;
protected MongoEngine $dbEngine;
/**
* Holds the collection that is being modified
*
* @var Collection
*/
protected $collection;
protected Collection $collection;
/**
* Initializes the model
@ -79,8 +79,11 @@ class MongoTableModel implements iDatabaseTableModel
* @param string $tableName
* @throws DatabaseException
*/
public function setUp(iDatabaseEngine $engine, string $tableName)
public function setUp(iDatabaseEngine $engine, string $tableName): void
{
if (!$engine instanceof MongoEngine)
throw new DatabaseException('MongoTableModel can only be used with a MongoEngine');
$this->dbEngine = $engine;
$this->collection = $this->getCollection($tableName);
$this->setup = true;
@ -96,7 +99,7 @@ class MongoTableModel implements iDatabaseTableModel
* @return Collection
* @throws DatabaseException
*/
protected function getCollection(string $collectionString)
protected function getCollection(string $collectionString): Collection
{
// Determine collection
$coll = explode('.', $collectionString);
@ -167,7 +170,7 @@ class MongoTableModel implements iDatabaseTableModel
* @param array $filter
* @param array $options
* @param string $table
* @return array
* @return TableModelResult
* @throws DatabaseException
*/
public function read(array $filter = [], array $options = [], string $table = 'default'): TableModelResult
@ -182,9 +185,7 @@ class MongoTableModel implements iDatabaseTableModel
$results = $collection->find($filter, $options);
// Convert the result into a TableModelResult
$result = new TableModelResult($results);
return $result;
return new TableModelResult($results);
}
/**
@ -242,7 +243,7 @@ class MongoTableModel implements iDatabaseTableModel
*/
public function transactionStart(): bool
{
// TODO: Implement transactionStart() method.
return $this->dbEngine->transactionStart();
}
/**
@ -250,7 +251,7 @@ class MongoTableModel implements iDatabaseTableModel
*/
public function transactionEnd(): bool
{
// TODO: Implement transactionEnd() method.
return $this->dbEngine->transactionEnd();
}
/**
@ -258,7 +259,7 @@ class MongoTableModel implements iDatabaseTableModel
*/
public function transactionCommit(): bool
{
// TODO: Implement transactionCommit() method.
return $this->dbEngine->transactionCommit();
}
/**
@ -266,7 +267,7 @@ class MongoTableModel implements iDatabaseTableModel
*/
public function transactionRollback(): bool
{
// TODO: Implement transactionRollback() method.
return $this->dbEngine->transactionRollback();
}
/**

View File

@ -65,37 +65,41 @@ class PDOTableModel implements iDatabaseTableModel
*
* @var PDOEngine
*/
protected $dbEngine;
protected PDOEngine $dbEngine;
/**
* Whether the tableModel has been properly setup
*
* @var bool
*/
protected $setup = false;
protected bool $setup = false;
/**
* The table this model manages on the database
*
* @var string
*/
protected $tableName;
protected string $tableName;
/**
* The last statement used by PDO
*
* @var PDOStatementWrapper
*/
protected $lastStatement;
protected PDOStatementWrapper $lastStatement;
/**
* Initializes the model
*
* @param iDatabaseEngine $engine
* @param string $tableName
* @throws DatabaseException
*/
public function setUp(iDatabaseEngine $engine, string $tableName)
public function setUp(iDatabaseEngine $engine, string $tableName): void
{
if (!$engine instanceof PDOEngine)
throw new DatabaseException('PDOTableModel can only be used with PDOEngine');
$this->dbEngine = $engine;
$this->tableName = $tableName;
$this->setup = true;
@ -211,6 +215,7 @@ class PDOTableModel implements iDatabaseTableModel
$where = $this->filter($filter);
// Determine fields and values
$fields = [];
foreach ($data as $key => $val)
$fields[] = $key."=:".$key;
@ -341,6 +346,8 @@ class PDOTableModel implements iDatabaseTableModel
$record = $record[0];
// Determine the fields and values
$fields = [];
$values = [];
foreach ($record as $key => $val)
{
$fields[] = $key;

View File

@ -47,26 +47,26 @@ class TableModelResult implements IteratorAggregate
*
* @var Traversable
*/
private $raw;
private iterable $raw;
/**
* Result from the TableModel, possibly altered by TableModelResult methods.
*
* @var ArrayObject
*/
private $result;
private ArrayObject $result;
/**
* @var Traversable
*/
private $traversable;
private iterable $traversable;
/**
* Whether the raw input has already been fully fetched
*
* @var bool
*/
private $fullyFetched = false;
private bool $fullyFetched = false;
public function __construct(iterable $results)
{
@ -129,16 +129,16 @@ class TableModelResult implements IteratorAggregate
* <b>Traversable</b>
* @since 5.0.0
*/
public function getIterator()
public function getIterator(): Traversable
{
return $this->traversable;
}
private function allToArray(): bool
private function allToArray(): void
{
// If the input has already been fetched, ignore it
if ($this->fullyFetched)
return true;
return;
$result = [];
foreach ($this->raw as $key => $val)
@ -159,8 +159,6 @@ class TableModelResult implements IteratorAggregate
// Set fullyFetched to true so it doesn't get fetched again
$this->fullyFetched = true;
return true;
}
}

View File

@ -72,9 +72,10 @@ interface iDatabaseTableModel
*
* @param iDatabaseEngine $engine
* @param string $tableName
* @return mixed
* @return void
* @throws DatabaseException
*/
public function setUp(iDatabaseEngine $engine, string $tableName);
public function setUp(iDatabaseEngine $engine, string $tableName): void;
/**
* Returns whether the TableModel has been setup yet

View File

@ -24,7 +24,7 @@
<tr>
<td>
<?php if (!empty($query['errors'])): ?>
<span title="<?= htmlSpecialChars((isset($query['errors']['message']) ? $query['errors']['message'] : ''), ENT_IGNORE | ENT_QUOTES, 'UTF-8') ?>">ERROR</span>
<span title="<?= htmlSpecialChars(($query['errors']['message'] ?? ''), ENT_IGNORE | ENT_QUOTES, 'UTF-8') ?>">ERROR</span>
<br /><a class="tracy-toggle tracy-collapsed" data-tracy-ref="^tr .nette-DbConnectionPanel-explain">explain</a>
<?php elseif ($query['timings'] !== 0): echo sprintf('%0.3f', $query['timings'] * 1000); endif ?>
</td>
@ -37,7 +37,7 @@
</tr>
<tr>
<td><?= htmlSpecialChars($query['errors']['code'], ENT_NOQUOTES, 'UTF-8') ?></td>
<td><?= htmlSpecialChars((isset($query['errors']['message']) ? $query['errors']['message'] : ''), ENT_NOQUOTES, 'UTF-8') ?></td>
<td><?= htmlSpecialChars(($query['errors']['message'] ?? ''), ENT_NOQUOTES, 'UTF-8') ?></td>
</tr>
</table>
<?php endif ?>

View File

@ -47,7 +47,7 @@ $configurator->setLogDirectory(dirname(__FILE__) . '/temp');
// Other values
$configurator->setTimeZone('Europe/Amsterdam');
$configurator->enableDebugMode(true)->setDebugAddress('ALL');
$configurator->enableDebugMode()->setDebugAddress('ALL');
// Implement the Layout Component
$configurator->addComponent(new DatabaseComponent());

View File

@ -36,7 +36,6 @@
use FuzeWorks\Factory;
use FuzeWorks\Database;
use FuzeWorks\Exception\DatabaseException;
/**
* Class databaseTest.
@ -49,7 +48,7 @@ class DatabaseTest extends DatabaseTestAbstract
/**
* @var Database
*/
protected $database;
protected Database $database;
public function setUp(): void
{