diff --git a/src/FuzeWorks/Database.php b/src/FuzeWorks/Database.php index 1cfae0b..e89bb04 100644 --- a/src/FuzeWorks/Database.php +++ b/src/FuzeWorks/Database.php @@ -39,8 +39,12 @@ use FuzeWorks\DatabaseEngine\iDatabaseEngine; use FuzeWorks\DatabaseEngine\MongoEngine; use FuzeWorks\DatabaseEngine\PDOEngine; use FuzeWorks\Event\DatabaseLoadDriverEvent; +use FuzeWorks\Event\DatabaseLoadTableModelEvent; use FuzeWorks\Exception\DatabaseException; use FuzeWorks\Exception\EventException; +use FuzeWorks\Model\iDatabaseTableModel; +use FuzeWorks\Model\MongoTableModel; +use FuzeWorks\Model\PDOTableModel; /** * Database loading class @@ -68,6 +72,13 @@ class Database */ protected $engines = []; + /** + * All tableModels that can be used for connections + * + * @var iDatabaseTableModel[] + */ + protected $tableModels = []; + /** * Whether all DatabaseEngines have been loaded yet * @@ -76,11 +87,18 @@ class Database protected $enginesLoaded = false; /** - * Array of all the non-default databases + * Array of all the database engines * * @var iDatabaseEngine[] */ protected $connections = []; + + /** + * Array of all the tableModels + * + * @var iDatabaseTableModel[] + */ + protected $tables; /** * Register with the TracyBridge upon startup @@ -142,7 +160,7 @@ class Database elseif (!empty($event->engineName) && !empty($event->parameters)) { // Do provided config third - $engineClass = get_class($this->getEngine($event->engineName)); + $engineClass = get_class($this->fetchEngine($event->engineName)); $engine = $this->connections[$event->connectionName] = new $engineClass(); $engine->setUp($event->parameters); } @@ -153,7 +171,7 @@ class Database throw new DatabaseException("Could not get database. Database not found in config."); $engineName = $this->dbConfig['connections'][$event->connectionName]['engineName']; - $engineClass = get_class($this->getEngine($engineName)); + $engineClass = get_class($this->fetchEngine($engineName)); $engine = $this->connections[$event->connectionName] = new $engineClass(); $engine->setUp($this->dbConfig['connections'][$event->connectionName]); } @@ -165,6 +183,51 @@ class Database return $engine; } + /** + * @param string $tableName + * @param string $tableModelName + * @param string $connectionName + * @param array $parameters + * @return iDatabaseTableModel + * @throws DatabaseException + */ + public function getTableModel(string $tableName, string $tableModelName, string $connectionName = 'default', array $parameters = []): iDatabaseTableModel + { + try { + /** @var DatabaseLoadTableModelEvent $event */ + $event = Events::fireEvent('databaseLoadTableModelEvent', strtolower($tableModelName), $parameters, $connectionName, $tableName); + } catch (EventException $e) { + throw new DatabaseException("Could not get TableModel. databaseLoadTableModelEvent threw exception: '" . $e->getMessage() . "'"); + } + + if ($event->isCancelled()) + throw new DatabaseException("Could not get TableModel. Cancelled by databaseLoadTableModelEvent."); + + /** @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) + { + $tableModel = $this->tables[$event->connectionName . "|" . $event->tableName] = $event->tableModel; + if (!$tableModel->setup()) + $tableModel->setUp($this->get($event->connectionName, $tableModel->getEngineName(), $event->parameters), $event->tableName); + } + // If the connection already exists, use that + elseif (isset($this->tables[$event->connectionName . "|" . $event->tableName])) + { + $tableModel = $this->tables[$event->connectionName . "|" . $event->tableName]; + } + // Otherwise use the provided configuration + else + { + $tableModelClass = get_class($this->fetchTableModel($event->tableModelName)); + $tableModel = $this->tables[$event->connectionName . "|" . $event->tableName] = new $tableModelClass(); + $tableModel->setUp($this->get($event->connectionName, $tableModel->getEngineName(), $event->parameters), $event->tableName); + } + + // And return the tableModel + return $tableModel; + } + /** * Get a loaded database engine. * @@ -172,13 +235,13 @@ class Database * @return iDatabaseEngine * @throws DatabaseException */ - public function getEngine(string $engineName): iDatabaseEngine + public function fetchEngine(string $engineName): iDatabaseEngine { // First retrieve the name $engineName = strtolower($engineName); // Then load all engines - $this->loadDatabaseEngines(); + $this->loadDatabaseComponents(); // If the engine exists, return it if (isset($this->engines[$engineName])) @@ -188,6 +251,29 @@ class Database throw new DatabaseException("Could not get engine. Engine does not exist."); } + /** + * Fetch a loaded TableModel + * + * @param string $tableModelName + * @return iDatabaseTableModel + * @throws DatabaseException + */ + public function fetchTableModel(string $tableModelName): iDatabaseTableModel + { + // First retrieve the name + $tableModelName = strtolower($tableModelName); + + // Then load all the tableModels + $this->loadDatabaseComponents(); + + // If the tableModel exists, return it + if (isset($this->tableModels[$tableModelName])) + return $this->tableModels[$tableModelName]; + + // Otherwise throw an exception + throw new DatabaseException("Could not get tableModel. TableModel does not exist."); + } + /** * Register a new database engine * @@ -212,13 +298,36 @@ class Database return true; } + /** + * Register a new database tableModel + * + * @param iDatabaseTableModel $tableModel + * @return bool + * @throws DatabaseException + */ + public function registerTableModel(iDatabaseTableModel $tableModel): bool + { + // First retrieve the name + $tableModelName = strtolower($tableModel->getName()); + + // Check if the tableModel is already set + if (isset($this->tableModels[$tableModelName])) + throw new DatabaseException("Could not register tableModel. TableModel '" . $tableModelName . "' already registered."); + + // Install it + $this->tableModels[$tableModelName] = $tableModel; + Logger::log("Registered TableModel type: '" . $tableModelName . "'"); + + return true; + } + /** * Load all databaseEngines by firing a databaseLoadEngineEvent and by loading all the default engines * * @return bool * @throws DatabaseException */ - protected function loadDatabaseEngines(): bool + protected function loadDatabaseComponents(): bool { // If already loaded, skip if ($this->enginesLoaded) @@ -235,6 +344,10 @@ class Database $this->registerEngine(new PDOEngine()); $this->registerEngine(new MongoEngine()); + // Load the tableModels provided by the DatabaseComponent + $this->registerTableModel(new PDOTableModel()); + $this->registerTableModel(new MongoTableModel()); + // And save results $this->enginesLoaded = true; return true; diff --git a/src/FuzeWorks/DatabaseTracyBridge.php b/src/FuzeWorks/DatabaseTracyBridge.php index 1a44674..6496a98 100644 --- a/src/FuzeWorks/DatabaseTracyBridge.php +++ b/src/FuzeWorks/DatabaseTracyBridge.php @@ -133,8 +133,6 @@ class DatabaseTracyBridge implements IBarPanel $results = array_slice($results, -10); } - //dump($results['queries']['mysql:host=localhost;dbname=hello']); - return $this->results = $results; } diff --git a/src/FuzeWorks/Event/DatabaseLoadTableModelEvent.php b/src/FuzeWorks/Event/DatabaseLoadTableModelEvent.php new file mode 100644 index 0000000..0f32831 --- /dev/null +++ b/src/FuzeWorks/Event/DatabaseLoadTableModelEvent.php @@ -0,0 +1,90 @@ +tableModelName = $tableModelName; + $this->parameters = $parameters; + $this->connectionName = $connectionName; + $this->tableName = $tableName; + } +} \ No newline at end of file diff --git a/src/FuzeWorks/Model/MongoTableModel.php b/src/FuzeWorks/Model/MongoTableModel.php index a2008f6..c0d2a6a 100644 --- a/src/FuzeWorks/Model/MongoTableModel.php +++ b/src/FuzeWorks/Model/MongoTableModel.php @@ -36,9 +36,9 @@ namespace FuzeWorks\Model; use FuzeWorks\Database; +use FuzeWorks\DatabaseEngine\iDatabaseEngine; use FuzeWorks\DatabaseEngine\MongoEngine; use FuzeWorks\Exception\DatabaseException; -use FuzeWorks\Factory; use MongoDB\Collection; class MongoTableModel implements iDatabaseTableModel @@ -51,6 +51,13 @@ class MongoTableModel implements iDatabaseTableModel */ private $databases; + /** + * Whether the tableModel has been properly setup + * + * @var bool + */ + protected $setup = false; + /** * Holds the PDOEngine for this model * @@ -66,24 +73,22 @@ class MongoTableModel implements iDatabaseTableModel protected $collection; /** - * Initializes the model to connect with the database. + * Initializes the model * - * @param string $connectionName - * @param array $parameters + * @param iDatabaseEngine $engine * @param string $tableName * @throws DatabaseException - * @see MongoEngine::setUp() */ - public function __construct(string $connectionName = 'default', array $parameters = [], string $tableName = 'default.default') + public function setUp(iDatabaseEngine $engine, string $tableName) { - if (is_null($this->databases)) - $this->databases = Factory::getInstance()->databases; - - // Load databaseEngine - $this->dbEngine = $this->databases->get($connectionName, 'mongo', $parameters); - - // Determine the collection + $this->dbEngine = $engine; $this->collection = $this->getCollection($tableName); + $this->setup = true; + } + + public function isSetup(): bool + { + return $this->setup; } /** @@ -109,6 +114,14 @@ class MongoTableModel implements iDatabaseTableModel return 'mongo'; } + /** + * @return string + */ + public function getEngineName(): string + { + return 'mongo'; + } + /** * @param array $data * @param array $options diff --git a/src/FuzeWorks/Model/PDOTableModel.php b/src/FuzeWorks/Model/PDOTableModel.php index 35e29d8..14f60ac 100644 --- a/src/FuzeWorks/Model/PDOTableModel.php +++ b/src/FuzeWorks/Model/PDOTableModel.php @@ -36,13 +36,11 @@ namespace FuzeWorks\Model; -use FuzeWorks\Database; +use FuzeWorks\DatabaseEngine\iDatabaseEngine; use FuzeWorks\DatabaseEngine\PDOEngine; use FuzeWorks\DatabaseEngine\PDOStatementWrapper; use FuzeWorks\Exception\DatabaseException; -use FuzeWorks\Exception\EventException; use FuzeWorks\Exception\TransactionException; -use FuzeWorks\Factory; use PDO; use PDOStatement; @@ -62,13 +60,6 @@ use PDOStatement; */ class PDOTableModel implements iDatabaseTableModel { - /** - * Holds the FuzeWorks Database loader - * - * @var Database - */ - private $databases; - /** * Holds the PDOEngine for this model * @@ -76,6 +67,13 @@ class PDOTableModel implements iDatabaseTableModel */ protected $dbEngine; + /** + * Whether the tableModel has been properly setup + * + * @var bool + */ + protected $setup = false; + /** * The table this model manages on the database * @@ -91,21 +89,21 @@ class PDOTableModel implements iDatabaseTableModel protected $lastStatement; /** - * Initializes the model to connect with the database. + * Initializes the model * - * @param string $connectionName - * @param array $parameters - * @param string|null $tableName - * @throws DatabaseException - * @see PDOEngine::setUp() + * @param iDatabaseEngine $engine + * @param string $tableName */ - public function __construct(string $connectionName = 'default', array $parameters = [], string $tableName = 'default') + public function setUp(iDatabaseEngine $engine, string $tableName) { - if (is_null($this->databases)) - $this->databases = Factory::getInstance()->databases; - - $this->dbEngine = $this->databases->get($connectionName, 'pdo', $parameters); + $this->dbEngine = $engine; $this->tableName = $tableName; + $this->setup = true; + } + + public function isSetup(): bool + { + return $this->setup; } public function getName(): string @@ -113,6 +111,14 @@ class PDOTableModel implements iDatabaseTableModel return 'pdo'; } + /** + * @return string + */ + public function getEngineName(): string + { + return 'pdo'; + } + /** * @param array $data * @param array $options diff --git a/src/FuzeWorks/Model/iDatabaseTableModel.php b/src/FuzeWorks/Model/iDatabaseTableModel.php index 1edb160..f92df40 100644 --- a/src/FuzeWorks/Model/iDatabaseTableModel.php +++ b/src/FuzeWorks/Model/iDatabaseTableModel.php @@ -37,6 +37,7 @@ namespace FuzeWorks\Model; +use FuzeWorks\DatabaseEngine\iDatabaseEngine; use FuzeWorks\Exception\DatabaseException; interface iDatabaseTableModel @@ -46,6 +47,15 @@ interface iDatabaseTableModel */ public function getName(): string; + /** + * @return string + */ + public function getEngineName(): string; + + public function setUp(iDatabaseEngine $engine, string $tableName); + + public function isSetup(): bool; + /** * @param array $data * @param array $options diff --git a/test/bootstrap.php b/test/bootstrap.php index 1451ba7..fc7a619 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -34,6 +34,9 @@ * @version Version 1.1.4 */ +use FuzeWorks\DatabaseComponent; +use FuzeWorks\TracyComponent; + require_once(dirname(__DIR__) . '/vendor/autoload.php'); $configurator = new FuzeWorks\Configurator(); @@ -47,8 +50,8 @@ $configurator->setTimeZone('Europe/Amsterdam'); $configurator->enableDebugMode(true)->setDebugAddress('ALL'); // Implement the Layout Component -$configurator->addComponent(new \FuzeWorks\DatabaseComponent()); -$configurator->addComponent(new \FuzeWorks\TracyComponent()); +$configurator->addComponent(new DatabaseComponent()); +$configurator->addComponent(new TracyComponent()); // Create container $container = $configurator->createContainer();