From 8a7744e3800f3d3176bd457d06901625dce044f4 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Sat, 28 Oct 2023 17:08:24 +0300 Subject: [PATCH 01/13] Refactoring + Additional Tests --- .../framework/test/cli/RunSQLCommandTest.php | 50 +++++++++++++++++++ webfiori/framework/App.php | 18 +++++-- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/tests/webfiori/framework/test/cli/RunSQLCommandTest.php b/tests/webfiori/framework/test/cli/RunSQLCommandTest.php index 011defcf..349f3136 100644 --- a/tests/webfiori/framework/test/cli/RunSQLCommandTest.php +++ b/tests/webfiori/framework/test/cli/RunSQLCommandTest.php @@ -6,6 +6,8 @@ use tables\Schema2; use webfiori\database\ConnectionInfo; use webfiori\framework\App; +use webfiori\framework\config\Controller; +use webfiori\framework\config\JsonDriver; class RunSQLCommandTest extends TestCase { /** @@ -82,6 +84,54 @@ public function testCLIQuery01() { "Error: 1051 - Unknown table 'testing_db.test2_x'\n" ], $runner->getOutput()); } + /** + * @test + */ + public function testCLIQuery02() { + + JsonDriver::setConfigFileName('run-sql-test'); + App::setConfigDriver(JsonDriver::class); + + $conn = new ConnectionInfo('mysql', 'root', '123456', 'testing_db', '127.0.0.1'); + $conn->setName('testing-connection'); + App::getConfig()->addOrUpdateDBConnection($conn); + $driver = new JsonDriver(); + $driver->setConfigFileName('run-sql-test'); + + Controller::setDriver($driver); + + $this->assertTrue(get_class(App::getConfig()) == JsonDriver::class); + + $runner = App::getRunner(); + $runner->setArgsVector([ + 'webfiori', + 'run-query', + ]); + $runner->setInputs([ + '0', + '0', + 'select * from hello;', + 'y' + ]); + + + $this->assertEquals(1146, $runner->start()); + + $this->assertEquals([ + "Select database connection:\n", + "0: testing-connection <--\n", + "What type of query you would like to run?\n", + "0: Run general query.\n", + "1: Run query on table instance.\n", + "2: Run query from file.\n", + "Please type in SQL query:\n", + "The following query will be executed on the database 'testing_db':\n", + "select * from hello;\n", + "Continue?(Y/n)\n", + "Info: Executing query on database testing_db...\n", + "Error: 1146 - Table 'testing_db.hello' doesn't exist\n" + ], $runner->getOutput()); + } /** * @test */ diff --git a/webfiori/framework/App.php b/webfiori/framework/App.php index 1125f167..28209b21 100644 --- a/webfiori/framework/App.php +++ b/webfiori/framework/App.php @@ -55,6 +55,10 @@ class App { */ public static function setConfigDriver(string $clazz) { self::$ConfigDriver = $clazz; + + if (self::$ClassStatus == self::STATUS_INITIALIZED) { + + } } /** * Returns the class that represents configuration driver. @@ -136,7 +140,7 @@ private function __construct() { mb_regex_encoding($encoding); } $this->initAutoLoader(); - $this->loadEnvVars(); + Controller::get()->updateEnv(); /** * Set memory limit. */ @@ -294,7 +298,14 @@ public static function getClassStatus() { * @return ConfigurationDriver */ public static function getConfig(): ConfigurationDriver { - return Controller::getDriver(); + $driver = Controller::getDriver(); + + if (get_class($driver) != self::$ConfigDriver) { + Controller::setDriver(new self::$ConfigDriver()); + Controller::get()->updateEnv(); + $driver = Controller::getDriver(); + } + return $driver; } /** @@ -621,9 +632,6 @@ private function initThemesPath() { define('THEMES_PATH', $themesPath); } } - private function loadEnvVars() { - Controller::get()->updateEnv(); - } /** * Sets new error and exception handler. */ From 29d16f993f13b7a3b3989a02c57aa6132f6a80b2 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 15:49:05 +0300 Subject: [PATCH 02/13] Enhanced How Missing Connection Properties are Shown --- .../framework/test/config/JsonDriverTest.php | 11 ++- webfiori/framework/config/JsonDriver.php | 80 ++++++++++++++----- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/tests/webfiori/framework/test/config/JsonDriverTest.php b/tests/webfiori/framework/test/config/JsonDriverTest.php index 717fc398..859331a0 100644 --- a/tests/webfiori/framework/test/config/JsonDriverTest.php +++ b/tests/webfiori/framework/test/config/JsonDriverTest.php @@ -425,5 +425,14 @@ public function testDatabaseConnections01() { $this->assertEquals('root', $account->getUsername()); } - + /** + * @test + */ + public function testAppWithError00() { + $this->expectExceptionMessage('The property "username" of the connection "New_Connection" is missing.'); + JsonDriver::setConfigFileName('config-with-err-00'); + $driver = new JsonDriver(); + $driver->initialize(); + $driver->getDBConnections(); + } } diff --git a/webfiori/framework/config/JsonDriver.php b/webfiori/framework/config/JsonDriver.php index c06d60da..d2f3785e 100644 --- a/webfiori/framework/config/JsonDriver.php +++ b/webfiori/framework/config/JsonDriver.php @@ -1,6 +1,7 @@ $dbConnectionsInfo->getUsername(), 'database' => $dbConnectionsInfo->getDBName(), 'password' => $dbConnectionsInfo->getPassword(), - 'extars' => $dbConnectionsInfo->getExtars(), ]); + $connectionJAsJson->addArray('extras', $dbConnectionsInfo->getExtars(), true); $this->json->get('database-connections')->add($dbConnectionsInfo->getName(), $connectionJAsJson); $this->writeJson(); } @@ -207,6 +208,13 @@ public function getDBConnection(string $conName) { $jsonObj = $this->json->get('database-connections')->get($conName); if ($jsonObj !== null) { + $extras = $jsonObj->get('extras'); + $extrasArr = []; + if ($extras instanceof Json) { + foreach ($extras->getProperties() as $prop) { + $extrasArr[$prop->getName()] = $prop->getValue(); + } + } return new ConnectionInfo( $jsonObj->get('type'), $jsonObj->get('username'), @@ -214,26 +222,52 @@ public function getDBConnection(string $conName) { $jsonObj->get('database'), $jsonObj->get('host'), $jsonObj->get('port'), - $jsonObj->get('extras') !== null ? $jsonObj->get('extras') : []); + $extrasArr); } } - + /** + * Returns an associative array that contain the information of database connections. + * + * @return array An associative array. The indices are connections names and + * values are objects of type 'ConnectionInfo'. + */ public function getDBConnections(): array { $accountsInfo = $this->json->get('database-connections'); $retVal = []; foreach ($accountsInfo->getProperties() as $propObj) { + $name = $propObj->getName(); $jsonObj = $propObj->getValue(); - $acc = new ConnectionInfo($jsonObj->get('type'), $jsonObj->get('username'), $jsonObj->get('password'), $jsonObj->get('database')); - $acc->setExtras($jsonObj->get('extras') !== null ? $jsonObj->get('extras') : []); - $acc->setHost($jsonObj->get('host')); + $acc = new ConnectionInfo( + $this->getProp($jsonObj, 'type', $name), + $this->getProp($jsonObj, 'username', $name), + $this->getProp($jsonObj, 'password', $name), + $this->getProp($jsonObj, 'database', $name)); + $extrasObj = $jsonObj->get('extras'); + + if ($extrasObj !== null && $extrasObj instanceof Json) { + $extrasArr = []; + + foreach ($extrasObj->getProperties() as $prop) { + $extrasArr[$prop->getName()] = $prop->getValue(); + } + $acc->setExtras($extrasArr); + } + $acc->setHost($this->getProp($jsonObj, 'host', $name)); $acc->setName($propObj->getName()); - $acc->setPort($jsonObj->get('port')); + $acc->setPort($this->getProp($jsonObj, 'port', $name)); $retVal[$propObj->getName()] = $acc; } return $retVal; } + private function getProp(Json $j, $name, string $connName) { + $val = $j->get($name); + if ($val === null) { + throw new Exception('The property "'.$name.'" of the connection "'.$connName.'" is missing.'); + } + return $val; + } public function getDescription(string $langCode) { return $this->json->get('app-descriptions')->get(strtoupper(trim($langCode))); @@ -321,17 +355,21 @@ public function getSMTPConnection(string $name) { if ($jsonObj !== null) { return new SMTPAccount([ - 'sender-address' => $jsonObj->get('address'), - 'pass' => $jsonObj->get('password'), - 'port' => $jsonObj->get('port'), - 'sender-name' => $jsonObj->get('sender-name'), - 'server-address' => $jsonObj->get('host'), - 'user' => $jsonObj->get('username'), + 'sender-address' => $this->getProp($jsonObj, 'address', $name), + 'pass' => $this->getProp($jsonObj, 'password', $name), + 'port' => $this->getProp($jsonObj, 'port', $name), + 'sender-name' => $this->getProp($jsonObj, 'sender-name', $name), + 'server-address' => $this->getProp($jsonObj, 'host', $name), + 'user' => $this->getProp($jsonObj, 'username', $name), 'account-name' => $name ]); } } - + /** + * Returns an array that contains all added SMTP accounts. + * + * @return array An array that contains all added SMTP accounts. + */ public function getSMTPConnections(): array { $accountsInfo = $this->json->get('smtp-connections'); $retVal = []; @@ -340,13 +378,13 @@ public function getSMTPConnections(): array { $jsonObj = $prop->getValue(); $acc = new SMTPAccount(); $acc->setAccountName($name); - $acc->setAddress($jsonObj->get('address')); - $acc->setPassword($jsonObj->get('password')); - $acc->setPort($jsonObj->get('port')); - $acc->setSenderName($jsonObj->get('sender-name')); - $acc->setServerAddress($jsonObj->get('host')); - $acc->setUsername($jsonObj->get('username')); - $retVal[] = $acc; + $acc->setAddress($this->getProp($jsonObj, 'address', $name)); + $acc->setPassword($this->getProp($jsonObj, 'password', $name)); + $acc->setPort($this->getProp($jsonObj, 'port', $name)); + $acc->setSenderName($this->getProp($jsonObj, 'sender-name', $name)); + $acc->setServerAddress($this->getProp($jsonObj, 'host', $name)); + $acc->setUsername($this->getProp($jsonObj, 'username', $name)); + $retVal[$name] = $acc; } return $retVal; From 437a0acde30a4ca4b271ed31329ff384aaa35bd1 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 15:57:49 +0300 Subject: [PATCH 03/13] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 304fe057..cf638036 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ php-cs-fixer-v2.phar app/sto app/config/* .idea/* +!/app/config/config-with-err-00.json From a25cf699b03a19cf52003cf44dbfbf7ba820a2f3 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 15:57:53 +0300 Subject: [PATCH 04/13] Create config-with-err-00.json --- app/config/config-with-err-00.json | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 app/config/config-with-err-00.json diff --git a/app/config/config-with-err-00.json b/app/config/config-with-err-00.json new file mode 100644 index 00000000..42dbf2c5 --- /dev/null +++ b/app/config/config-with-err-00.json @@ -0,0 +1,48 @@ +{ + "base-url":"DYNAMIC", + "theme":null, + "home-page":"BASE_URL", + "primary-lang":"EN", + "titles":{ + "AR":"افتراضي", + "EN":"Default" + }, + "name-separator":"|", + "scheduler-password":"NO_PASSWORD", + "app-names":{ + "AR":"تطبيق", + "EN":"Application" + }, + "app-descriptions":{ + "AR":"", + "EN":"" + }, + "version-info":{ + "version":"1.0", + "version-type":"Stable", + "release-date":"2023-10-30" + }, + "env-vars":{ + "WF_VERBOSE":{ + "value":false, + "description":"Configure the verbosity of error messsages at run-time. This should be set to true in testing and false in production." + }, + "CLI_HTTP_HOST":{ + "value":"example.com", + "description":"Host name that will be used when runing the application as command line utility." + } + }, + "smtp-connections":{ + }, + "database-connections":{ + "New_Connection":{ + "type":"mysql", + "host":"localhost", + "port":3306, + "database":"my_db", + "password":"test@222", + "extras":{ + } + } + } +} \ No newline at end of file From d5ceb877ae9bb5d70dac41ad738df74bf2d2c5ce Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:01:27 +0300 Subject: [PATCH 05/13] Update JsonDriverTest.php --- tests/webfiori/framework/test/config/JsonDriverTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/webfiori/framework/test/config/JsonDriverTest.php b/tests/webfiori/framework/test/config/JsonDriverTest.php index 859331a0..110aa51e 100644 --- a/tests/webfiori/framework/test/config/JsonDriverTest.php +++ b/tests/webfiori/framework/test/config/JsonDriverTest.php @@ -427,6 +427,7 @@ public function testDatabaseConnections01() { } /** * @test + * @depends testSetConfigFileName00 */ public function testAppWithError00() { $this->expectExceptionMessage('The property "username" of the connection "New_Connection" is missing.'); From 0424d4c8d323ab466e20f152c05751eb25d8415c Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:17:21 +0300 Subject: [PATCH 06/13] Update App.php --- webfiori/framework/App.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webfiori/framework/App.php b/webfiori/framework/App.php index 28209b21..f4237a95 100644 --- a/webfiori/framework/App.php +++ b/webfiori/framework/App.php @@ -73,7 +73,7 @@ public static function getConfigDriver() : string { * * @var string */ - private static $ConfigDriver = '\\webfiori\\framework\\config\\ClassDriver'; + private static $ConfigDriver = 'webfiori\\framework\\config\\ClassDriver'; /** * A constant that indicates that the status of the class is 'initialized'. * From 6924930e81ed026e9416ff4ccce6fa8ba5866061 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:17:28 +0300 Subject: [PATCH 07/13] Update DB.php --- webfiori/framework/DB.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webfiori/framework/DB.php b/webfiori/framework/DB.php index 68fcec59..56c8f5c2 100644 --- a/webfiori/framework/DB.php +++ b/webfiori/framework/DB.php @@ -62,7 +62,7 @@ public function __construct($connName) { } if (!($conn instanceof ConnectionInfo)) { - throw new DatabaseException("No connection was found which has the name '$connName'."); + throw new DatabaseException("No connection was found which has the name '$connName'. Driver: ". get_class(App::getConfig()).'.'); } } parent::__construct($conn); From 7daaee1f359e76d8918db6ec1963851eb6160546 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:26:50 +0300 Subject: [PATCH 08/13] Update JsonDriverTest.php --- tests/webfiori/framework/test/config/JsonDriverTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/webfiori/framework/test/config/JsonDriverTest.php b/tests/webfiori/framework/test/config/JsonDriverTest.php index 110aa51e..2101f70f 100644 --- a/tests/webfiori/framework/test/config/JsonDriverTest.php +++ b/tests/webfiori/framework/test/config/JsonDriverTest.php @@ -57,6 +57,7 @@ public function test00() { * @test */ public function testSetConfigFileName00() { + JsonDriver::setConfigFileName('app-config.json'); $this->assertEquals('app-config', JsonDriver::getConfigFileName()); JsonDriver::setConfigFileName('super-conf.json'); $this->assertEquals('super-conf', JsonDriver::getConfigFileName()); From 35aee6ce3478c4923e122a86fb1fb620da1767ed Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:26:57 +0300 Subject: [PATCH 09/13] Update DatabaseSessionStorage.php --- webfiori/framework/session/DatabaseSessionStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webfiori/framework/session/DatabaseSessionStorage.php b/webfiori/framework/session/DatabaseSessionStorage.php index cc86d75b..84f847e5 100644 --- a/webfiori/framework/session/DatabaseSessionStorage.php +++ b/webfiori/framework/session/DatabaseSessionStorage.php @@ -39,7 +39,7 @@ public function __construct() { try { $this->dbController = new SessionDB(); } catch (DatabaseException $ex) { - if ($ex->getMessage() == "No connection was found which has the name 'sessions-connection'.") { + if (str_contains($ex->getMessage(), '"No connection was found')) { throw new SessionException("Connection 'sessions-connection' was not found in application configuration."); } else { throw $ex; From feaf8981de31dcc5c7a73d4985de4b1ddc5719b7 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:35:25 +0300 Subject: [PATCH 10/13] Update DatabaseSessionStorage.php --- webfiori/framework/session/DatabaseSessionStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webfiori/framework/session/DatabaseSessionStorage.php b/webfiori/framework/session/DatabaseSessionStorage.php index 84f847e5..ad56967e 100644 --- a/webfiori/framework/session/DatabaseSessionStorage.php +++ b/webfiori/framework/session/DatabaseSessionStorage.php @@ -39,7 +39,7 @@ public function __construct() { try { $this->dbController = new SessionDB(); } catch (DatabaseException $ex) { - if (str_contains($ex->getMessage(), '"No connection was found')) { + if (strpos($ex->getMessage(), 'sessions-connection') !== false) { throw new SessionException("Connection 'sessions-connection' was not found in application configuration."); } else { throw $ex; From 3d19c7d79cccdd9b8ccd26b0d7606383a9b77802 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:42:49 +0300 Subject: [PATCH 11/13] Update App.php --- webfiori/framework/App.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/webfiori/framework/App.php b/webfiori/framework/App.php index f4237a95..e3948d3a 100644 --- a/webfiori/framework/App.php +++ b/webfiori/framework/App.php @@ -55,10 +55,6 @@ class App { */ public static function setConfigDriver(string $clazz) { self::$ConfigDriver = $clazz; - - if (self::$ClassStatus == self::STATUS_INITIALIZED) { - - } } /** * Returns the class that represents configuration driver. From 4933b2a04750c7976337f93db1cfae9946595f0f Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 16:42:55 +0300 Subject: [PATCH 12/13] Update JsonDriver.php --- webfiori/framework/config/JsonDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webfiori/framework/config/JsonDriver.php b/webfiori/framework/config/JsonDriver.php index d2f3785e..e457b380 100644 --- a/webfiori/framework/config/JsonDriver.php +++ b/webfiori/framework/config/JsonDriver.php @@ -1,10 +1,10 @@ get($name); if ($val === null) { - throw new Exception('The property "'.$name.'" of the connection "'.$connName.'" is missing.'); + throw new InitializationException('The property "'.$name.'" of the connection "'.$connName.'" is missing.'); } return $val; } From 13750f3c787caaf2ee90e8fd4bb82f3cebd08c0f Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Mon, 30 Oct 2023 17:18:06 +0300 Subject: [PATCH 13/13] Update App.php --- webfiori/framework/App.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webfiori/framework/App.php b/webfiori/framework/App.php index e3948d3a..99f1be62 100644 --- a/webfiori/framework/App.php +++ b/webfiori/framework/App.php @@ -540,7 +540,7 @@ private function initFrameworkVersionInfo() { * * @since 2.1 */ - define('WF_VERSION', '3.0.0-RC16'); + define('WF_VERSION', '3.0.0-RC18'); /** * A constant that tells the type of framework version. * @@ -556,7 +556,7 @@ private function initFrameworkVersionInfo() { * * @since 2.1 */ - define('WF_RELEASE_DATE', '2023-09-11'); + define('WF_RELEASE_DATE', '2023-10-30'); } /**