Skip to content

Commit 9e0fa84

Browse files
authored
Merge pull request #197 from WebFiori/dev
Enhanced How Missing Connection Properties are Shown in `JsonDriver`
2 parents debbcff + 13750f3 commit 9e0fa84

File tree

8 files changed

+184
-32
lines changed

8 files changed

+184
-32
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ php-cs-fixer-v2.phar
1414
app/sto
1515
app/config/*
1616
.idea/*
17+
!/app/config/config-with-err-00.json

app/config/config-with-err-00.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"base-url":"DYNAMIC",
3+
"theme":null,
4+
"home-page":"BASE_URL",
5+
"primary-lang":"EN",
6+
"titles":{
7+
"AR":"افتراضي",
8+
"EN":"Default"
9+
},
10+
"name-separator":"|",
11+
"scheduler-password":"NO_PASSWORD",
12+
"app-names":{
13+
"AR":"تطبيق",
14+
"EN":"Application"
15+
},
16+
"app-descriptions":{
17+
"AR":"",
18+
"EN":""
19+
},
20+
"version-info":{
21+
"version":"1.0",
22+
"version-type":"Stable",
23+
"release-date":"2023-10-30"
24+
},
25+
"env-vars":{
26+
"WF_VERBOSE":{
27+
"value":false,
28+
"description":"Configure the verbosity of error messsages at run-time. This should be set to true in testing and false in production."
29+
},
30+
"CLI_HTTP_HOST":{
31+
"value":"example.com",
32+
"description":"Host name that will be used when runing the application as command line utility."
33+
}
34+
},
35+
"smtp-connections":{
36+
},
37+
"database-connections":{
38+
"New_Connection":{
39+
"type":"mysql",
40+
"host":"localhost",
41+
"port":3306,
42+
"database":"my_db",
43+
"password":"test@222",
44+
"extras":{
45+
}
46+
}
47+
}
48+
}

tests/webfiori/framework/test/cli/RunSQLCommandTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use tables\Schema2;
77
use webfiori\database\ConnectionInfo;
88
use webfiori\framework\App;
9+
use webfiori\framework\config\Controller;
10+
use webfiori\framework\config\JsonDriver;
911

1012
class RunSQLCommandTest extends TestCase {
1113
/**
@@ -82,6 +84,54 @@ public function testCLIQuery01() {
8284
"Error: 1051 - Unknown table 'testing_db.test2_x'\n"
8385
], $runner->getOutput());
8486
}
87+
/**
88+
* @test
89+
*/
90+
public function testCLIQuery02() {
91+
92+
JsonDriver::setConfigFileName('run-sql-test');
93+
App::setConfigDriver(JsonDriver::class);
94+
95+
$conn = new ConnectionInfo('mysql', 'root', '123456', 'testing_db', '127.0.0.1');
96+
$conn->setName('testing-connection');
97+
App::getConfig()->addOrUpdateDBConnection($conn);
98+
$driver = new JsonDriver();
99+
$driver->setConfigFileName('run-sql-test');
100+
101+
Controller::setDriver($driver);
102+
103+
$this->assertTrue(get_class(App::getConfig()) == JsonDriver::class);
104+
105+
$runner = App::getRunner();
106+
$runner->setArgsVector([
107+
'webfiori',
108+
'run-query',
109+
]);
110+
$runner->setInputs([
111+
'0',
112+
'0',
113+
'select * from hello;',
114+
'y'
115+
]);
116+
117+
118+
$this->assertEquals(1146, $runner->start());
119+
120+
$this->assertEquals([
121+
"Select database connection:\n",
122+
"0: testing-connection <--\n",
123+
"What type of query you would like to run?\n",
124+
"0: Run general query.\n",
125+
"1: Run query on table instance.\n",
126+
"2: Run query from file.\n",
127+
"Please type in SQL query:\n",
128+
"The following query will be executed on the database 'testing_db':\n",
129+
"select * from hello;\n",
130+
"Continue?(Y/n)\n",
131+
"Info: Executing query on database testing_db...\n",
132+
"Error: 1146 - Table 'testing_db.hello' doesn't exist\n"
133+
], $runner->getOutput());
134+
}
85135
/**
86136
* @test
87137
*/

tests/webfiori/framework/test/config/JsonDriverTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public function test00() {
5757
* @test
5858
*/
5959
public function testSetConfigFileName00() {
60+
JsonDriver::setConfigFileName('app-config.json');
6061
$this->assertEquals('app-config', JsonDriver::getConfigFileName());
6162
JsonDriver::setConfigFileName('super-conf.json');
6263
$this->assertEquals('super-conf', JsonDriver::getConfigFileName());
@@ -425,5 +426,15 @@ public function testDatabaseConnections01() {
425426
$this->assertEquals('root', $account->getUsername());
426427

427428
}
428-
429+
/**
430+
* @test
431+
* @depends testSetConfigFileName00
432+
*/
433+
public function testAppWithError00() {
434+
$this->expectExceptionMessage('The property "username" of the connection "New_Connection" is missing.');
435+
JsonDriver::setConfigFileName('config-with-err-00');
436+
$driver = new JsonDriver();
437+
$driver->initialize();
438+
$driver->getDBConnections();
439+
}
429440
}

webfiori/framework/App.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static function getConfigDriver() : string {
6969
*
7070
* @var string
7171
*/
72-
private static $ConfigDriver = '\\webfiori\\framework\\config\\ClassDriver';
72+
private static $ConfigDriver = 'webfiori\\framework\\config\\ClassDriver';
7373
/**
7474
* A constant that indicates that the status of the class is 'initialized'.
7575
*
@@ -136,7 +136,7 @@ private function __construct() {
136136
mb_regex_encoding($encoding);
137137
}
138138
$this->initAutoLoader();
139-
$this->loadEnvVars();
139+
Controller::get()->updateEnv();
140140
/**
141141
* Set memory limit.
142142
*/
@@ -294,7 +294,14 @@ public static function getClassStatus() {
294294
* @return ConfigurationDriver
295295
*/
296296
public static function getConfig(): ConfigurationDriver {
297-
return Controller::getDriver();
297+
$driver = Controller::getDriver();
298+
299+
if (get_class($driver) != self::$ConfigDriver) {
300+
Controller::setDriver(new self::$ConfigDriver());
301+
Controller::get()->updateEnv();
302+
$driver = Controller::getDriver();
303+
}
304+
return $driver;
298305
}
299306

300307
/**
@@ -533,7 +540,7 @@ private function initFrameworkVersionInfo() {
533540
*
534541
* @since 2.1
535542
*/
536-
define('WF_VERSION', '3.0.0-RC16');
543+
define('WF_VERSION', '3.0.0-RC18');
537544
/**
538545
* A constant that tells the type of framework version.
539546
*
@@ -549,7 +556,7 @@ private function initFrameworkVersionInfo() {
549556
*
550557
* @since 2.1
551558
*/
552-
define('WF_RELEASE_DATE', '2023-09-11');
559+
define('WF_RELEASE_DATE', '2023-10-30');
553560
}
554561

555562
/**
@@ -621,9 +628,6 @@ private function initThemesPath() {
621628
define('THEMES_PATH', $themesPath);
622629
}
623630
}
624-
private function loadEnvVars() {
625-
Controller::get()->updateEnv();
626-
}
627631
/**
628632
* Sets new error and exception handler.
629633
*/

webfiori/framework/DB.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function __construct($connName) {
6262
}
6363

6464
if (!($conn instanceof ConnectionInfo)) {
65-
throw new DatabaseException("No connection was found which has the name '$connName'.");
65+
throw new DatabaseException("No connection was found which has the name '$connName'. Driver: ". get_class(App::getConfig()).'.');
6666
}
6767
}
6868
parent::__construct($conn);

webfiori/framework/config/JsonDriver.php

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use webfiori\database\ConnectionInfo;
55
use webfiori\email\SMTPAccount;
66
use webfiori\file\File;
7+
use webfiori\framework\exceptions\InitializationException;
78
use webfiori\http\Uri;
89
use webfiori\json\Json;
910

@@ -134,8 +135,8 @@ public function addOrUpdateDBConnection(ConnectionInfo $dbConnectionsInfo) {
134135
'username' => $dbConnectionsInfo->getUsername(),
135136
'database' => $dbConnectionsInfo->getDBName(),
136137
'password' => $dbConnectionsInfo->getPassword(),
137-
'extars' => $dbConnectionsInfo->getExtars(),
138138
]);
139+
$connectionJAsJson->addArray('extras', $dbConnectionsInfo->getExtars(), true);
139140
$this->json->get('database-connections')->add($dbConnectionsInfo->getName(), $connectionJAsJson);
140141
$this->writeJson();
141142
}
@@ -207,33 +208,66 @@ public function getDBConnection(string $conName) {
207208
$jsonObj = $this->json->get('database-connections')->get($conName);
208209

209210
if ($jsonObj !== null) {
211+
$extras = $jsonObj->get('extras');
212+
$extrasArr = [];
213+
if ($extras instanceof Json) {
214+
foreach ($extras->getProperties() as $prop) {
215+
$extrasArr[$prop->getName()] = $prop->getValue();
216+
}
217+
}
210218
return new ConnectionInfo(
211219
$jsonObj->get('type'),
212220
$jsonObj->get('username'),
213221
$jsonObj->get('password'),
214222
$jsonObj->get('database'),
215223
$jsonObj->get('host'),
216224
$jsonObj->get('port'),
217-
$jsonObj->get('extras') !== null ? $jsonObj->get('extras') : []);
225+
$extrasArr);
218226
}
219227
}
220-
228+
/**
229+
* Returns an associative array that contain the information of database connections.
230+
*
231+
* @return array An associative array. The indices are connections names and
232+
* values are objects of type 'ConnectionInfo'.
233+
*/
221234
public function getDBConnections(): array {
222235
$accountsInfo = $this->json->get('database-connections');
223236
$retVal = [];
224237

225238
foreach ($accountsInfo->getProperties() as $propObj) {
239+
$name = $propObj->getName();
226240
$jsonObj = $propObj->getValue();
227-
$acc = new ConnectionInfo($jsonObj->get('type'), $jsonObj->get('username'), $jsonObj->get('password'), $jsonObj->get('database'));
228-
$acc->setExtras($jsonObj->get('extras') !== null ? $jsonObj->get('extras') : []);
229-
$acc->setHost($jsonObj->get('host'));
241+
$acc = new ConnectionInfo(
242+
$this->getProp($jsonObj, 'type', $name),
243+
$this->getProp($jsonObj, 'username', $name),
244+
$this->getProp($jsonObj, 'password', $name),
245+
$this->getProp($jsonObj, 'database', $name));
246+
$extrasObj = $jsonObj->get('extras');
247+
248+
if ($extrasObj !== null && $extrasObj instanceof Json) {
249+
$extrasArr = [];
250+
251+
foreach ($extrasObj->getProperties() as $prop) {
252+
$extrasArr[$prop->getName()] = $prop->getValue();
253+
}
254+
$acc->setExtras($extrasArr);
255+
}
256+
$acc->setHost($this->getProp($jsonObj, 'host', $name));
230257
$acc->setName($propObj->getName());
231-
$acc->setPort($jsonObj->get('port'));
258+
$acc->setPort($this->getProp($jsonObj, 'port', $name));
232259
$retVal[$propObj->getName()] = $acc;
233260
}
234261

235262
return $retVal;
236263
}
264+
private function getProp(Json $j, $name, string $connName) {
265+
$val = $j->get($name);
266+
if ($val === null) {
267+
throw new InitializationException('The property "'.$name.'" of the connection "'.$connName.'" is missing.');
268+
}
269+
return $val;
270+
}
237271

238272
public function getDescription(string $langCode) {
239273
return $this->json->get('app-descriptions')->get(strtoupper(trim($langCode)));
@@ -321,17 +355,21 @@ public function getSMTPConnection(string $name) {
321355

322356
if ($jsonObj !== null) {
323357
return new SMTPAccount([
324-
'sender-address' => $jsonObj->get('address'),
325-
'pass' => $jsonObj->get('password'),
326-
'port' => $jsonObj->get('port'),
327-
'sender-name' => $jsonObj->get('sender-name'),
328-
'server-address' => $jsonObj->get('host'),
329-
'user' => $jsonObj->get('username'),
358+
'sender-address' => $this->getProp($jsonObj, 'address', $name),
359+
'pass' => $this->getProp($jsonObj, 'password', $name),
360+
'port' => $this->getProp($jsonObj, 'port', $name),
361+
'sender-name' => $this->getProp($jsonObj, 'sender-name', $name),
362+
'server-address' => $this->getProp($jsonObj, 'host', $name),
363+
'user' => $this->getProp($jsonObj, 'username', $name),
330364
'account-name' => $name
331365
]);
332366
}
333367
}
334-
368+
/**
369+
* Returns an array that contains all added SMTP accounts.
370+
*
371+
* @return array An array that contains all added SMTP accounts.
372+
*/
335373
public function getSMTPConnections(): array {
336374
$accountsInfo = $this->json->get('smtp-connections');
337375
$retVal = [];
@@ -340,13 +378,13 @@ public function getSMTPConnections(): array {
340378
$jsonObj = $prop->getValue();
341379
$acc = new SMTPAccount();
342380
$acc->setAccountName($name);
343-
$acc->setAddress($jsonObj->get('address'));
344-
$acc->setPassword($jsonObj->get('password'));
345-
$acc->setPort($jsonObj->get('port'));
346-
$acc->setSenderName($jsonObj->get('sender-name'));
347-
$acc->setServerAddress($jsonObj->get('host'));
348-
$acc->setUsername($jsonObj->get('username'));
349-
$retVal[] = $acc;
381+
$acc->setAddress($this->getProp($jsonObj, 'address', $name));
382+
$acc->setPassword($this->getProp($jsonObj, 'password', $name));
383+
$acc->setPort($this->getProp($jsonObj, 'port', $name));
384+
$acc->setSenderName($this->getProp($jsonObj, 'sender-name', $name));
385+
$acc->setServerAddress($this->getProp($jsonObj, 'host', $name));
386+
$acc->setUsername($this->getProp($jsonObj, 'username', $name));
387+
$retVal[$name] = $acc;
350388
}
351389

352390
return $retVal;

webfiori/framework/session/DatabaseSessionStorage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function __construct() {
3939
try {
4040
$this->dbController = new SessionDB();
4141
} catch (DatabaseException $ex) {
42-
if ($ex->getMessage() == "No connection was found which has the name 'sessions-connection'.") {
42+
if (strpos($ex->getMessage(), 'sessions-connection') !== false) {
4343
throw new SessionException("Connection 'sessions-connection' was not found in application configuration.");
4444
} else {
4545
throw $ex;

0 commit comments

Comments
 (0)