Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ab49211
Merge pull request #265 from WebFiori/dev
usernane Aug 4, 2025
4d48bda
Update composer.json
usernane Aug 4, 2025
19fc94a
chore: Merge pull request #266 from WebFiori/dev
usernane Oct 7, 2025
fb1e6a3
chore: Merge pull request #268 from WebFiori/dev
usernane Oct 9, 2025
bd05e13
chore(main): release 3.0.0-Beta.29
github-actions[bot] Oct 9, 2025
22433ff
Merge pull request #267 from WebFiori/release-please--branches--main
usernane Oct 9, 2025
8ffb523
chore: Merge pull request #269 from WebFiori/dev
usernane Oct 21, 2025
bd9a3bd
chore(main): release 3.0.0-Beta.30
github-actions[bot] Oct 21, 2025
3e82c23
Merge pull request #270 from WebFiori/release-please--branches--main
usernane Oct 21, 2025
6bf9c26
chore: Merge pull request #271 from WebFiori/dev
usernane Oct 27, 2025
f08d491
chore(main): release 3.0.0-beta.31
github-actions[bot] Oct 27, 2025
d81cfd0
Merge pull request #272 from WebFiori/release-please--branches--main
usernane Oct 27, 2025
9915709
Merge branch 'dev' into feat-env-vars
usernane Feb 17, 2026
a816705
Merge branch 'dev' into feat-env-vars
usernane Feb 17, 2026
f28f977
feat: Env Vars for Json Driver
usernane Feb 17, 2026
e9ad0f4
test: Added Env Vars Test Config
usernane Feb 17, 2026
f0ee1a7
test: Added Scheduler Password Test
usernane Feb 17, 2026
b34cd18
feat: Optional Config Var
usernane Feb 17, 2026
32da35f
docs: Updated PHP Docs For Config
usernane Feb 17, 2026
89cd39d
feat: Add `env:` to Class Driver
usernane Feb 17, 2026
e7429c1
Update JsonDriverTest.php
usernane Feb 17, 2026
a8ee667
fix: App Directories Creation
usernane Feb 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions App/Config/config-with-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"base-url":"DYNAMIC",
"theme":null,
"home-page":"BASE_URL",
"primary-lang":"env:LANG",
"titles":{
"AR":"افتراضي",
"EN":"Default"
},
"name-separator":"|",
"scheduler-password":"env:SCHEDULER_PASS",
"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_2":{
"value":"env:VERBOSE",
"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_2":{
"value":"example.com",
"description":"Host name that will be used when runing the application as command line utility."
},
"HOST":"env:HOST"
},
"smtp-connections":{
"conn00": {
"host":"smtp.outlook.com",
"port":"244",
"username":"env:SMTP_00_USER",
"password":"env:SMTP_00_PASS",
"address":"env:SMTP_00_ADDRESS",
"sender-name":"env:SMTP_00_NAME",
"access-token":"env:SMTP_TOKEN"
}
},
"database-connections":{
"New_Connection":{
"type":"mysql",
"host":"env:DB_HOST_1",
"port":3306,
"username":"cool",
"database":"env:DB_NAME_1",
"password":"env:DB_PASS_1",
"extras":{
}
},
"New_Connection_2":{
"type":"mysql",
"host":"env:DB_HOST_2",
"port":3306,
"database":"env:DB_NAME_2",
"password":"env:DB_PASS_2",
"username":"cool",
"extras":{
}
}
}
}
65 changes: 65 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,70 @@
# Changelog

## [3.0.0-beta.31](https://github.com/WebFiori/framework/compare/v3.0.0-Beta.30...v3.0.0-beta.31) (2025-10-27)


### Bug Fixes

* Bug in Finding Class Loader Path ([6831a96](https://github.com/WebFiori/framework/commit/6831a96d91962480b097561b559e2ecf07af1c0b))
* Show Framework Logo ([e47f1a5](https://github.com/WebFiori/framework/commit/e47f1a5d70b5d5982ff87247de3feb98ce75d558))


### Miscellaneous Chores

* Merge pull request [#271](https://github.com/WebFiori/framework/issues/271) from WebFiori/dev ([6bf9c26](https://github.com/WebFiori/framework/commit/6bf9c26ab448e60bcdfee5f6f91b2cdc97304006))
* Updated Framework Version ([3d719ea](https://github.com/WebFiori/framework/commit/3d719ea32aea00d973dbb61e5ddf98194a5e7e0f))
* Updated Index ([0b128ec](https://github.com/WebFiori/framework/commit/0b128ec53339304b351df9d1953e192dc233a24a))

## [3.0.0-Beta.30](https://github.com/WebFiori/framework/compare/v3.0.0-Beta.29...v3.0.0-Beta.30) (2025-10-21)


### Features

* Added a Script to Update Version ([e998c47](https://github.com/WebFiori/framework/commit/e998c476b2629b6b8307d6ad52813cdc1a63eb05))


### Bug Fixes

* Metadata ([84facc3](https://github.com/WebFiori/framework/commit/84facc3638ce6989d9b3efcf6dc05f9b7f87944b))


### Miscellaneous Chores

* Merge pull request [#269](https://github.com/WebFiori/framework/issues/269) from WebFiori/dev ([8ffb523](https://github.com/WebFiori/framework/commit/8ffb523559ab609095da446b2d592607dac1f20e))

## [3.0.0-Beta.29](https://github.com/WebFiori/framework/compare/v3.0.0-Beta.28...v3.0.0-Beta.29) (2025-10-09)


### Bug Fixes

* API Creation ([d3c384f](https://github.com/WebFiori/framework/commit/d3c384f48f61c828cf9358cbb1675e26be25b0ee))
* Command Writer ([338e8d2](https://github.com/WebFiori/framework/commit/338e8d2d7e72e66463bb8d57a6b34f20aa38ff3b))
* Fix Test Case ([6b26e2f](https://github.com/WebFiori/framework/commit/6b26e2f023cea94eb7fdf2a665f1a721e5e190eb))
* Fix Test Cases ([1086336](https://github.com/WebFiori/framework/commit/108633622e1938699360b45d65d3565bcf611e85))
* Fix Test Cases ([0c914de](https://github.com/WebFiori/framework/commit/0c914de97f37eef1bf862c4b37f323470dfcf5ef))
* Fixes and Tests Refactoring ([5ff31ab](https://github.com/WebFiori/framework/commit/5ff31ab5dc2c33b8a9389f3bf33001a525f57a7d))
* Getting Arg Value in CLI ([c56b9bf](https://github.com/WebFiori/framework/commit/c56b9bf6f34617336ad1f750943f705d84357ba0))
* Migrations Command ([ce54748](https://github.com/WebFiori/framework/commit/ce5474803a26352b75eaea66604b630378b98aa9))
* Namespaces ([e51d354](https://github.com/WebFiori/framework/commit/e51d354a2be0843f55e70ced529c45341988ba2e))
* References to Classes ([a140646](https://github.com/WebFiori/framework/commit/a1406462197a32a8bd16a6d12168c8c2a4fda016))
* Tasks Names Check ([3c80893](https://github.com/WebFiori/framework/commit/3c80893d4c793e330f571205a702b853540d9a36))
* Test Cases ([f78c6d5](https://github.com/WebFiori/framework/commit/f78c6d5a2b9fa10baa98ce9c229295d95f5b0fef))
* Test Classes ([cd68b49](https://github.com/WebFiori/framework/commit/cd68b49acbc7dab3d8abc25fa3df21b129d19bf4))
* Theme Creation ([6864c23](https://github.com/WebFiori/framework/commit/6864c236e7174113a4b4dc26e8289ed2645bb278))
* Theme Resources Creation ([e9f1025](https://github.com/WebFiori/framework/commit/e9f10258f4433982e922cac494dec69b06f34e8b))
* Writing Classes ([2fcb0c5](https://github.com/WebFiori/framework/commit/2fcb0c5993d7eb47c270d8113f58a2cf13f76046))


### Miscellaneous Chores

* Merge pull request [#266](https://github.com/WebFiori/framework/issues/266) from WebFiori/dev ([19fc94a](https://github.com/WebFiori/framework/commit/19fc94a9166ecafb2572e0926f9992b93a170341))
* Merge pull request [#268](https://github.com/WebFiori/framework/issues/268) from WebFiori/dev ([fb1e6a3](https://github.com/WebFiori/framework/commit/fb1e6a3bb3d5b69642641fd323e82785f28c72f9))
* Updated Database Library ([7f853fd](https://github.com/WebFiori/framework/commit/7f853fd25fd9f0b1211fb18fc807a2436f403946))
* Updated Database to v1.0.0 ([c35b109](https://github.com/WebFiori/framework/commit/c35b109d292df38b32965ceed0bd7e0a90c8cc08))
* Updated Dependencies ([ff05d95](https://github.com/WebFiori/framework/commit/ff05d95b8923ee631649c4610bf7dd348dcd4869))
* Updated HTTP to v4 ([ab525fc](https://github.com/WebFiori/framework/commit/ab525fc9a37db07ae454b53e961cddba628b82e3))
* Updated Version Number ([c2bac79](https://github.com/WebFiori/framework/commit/c2bac791aa6aca1bd9e8742c017d75e8574fd38d))

## [3.0.0-Beta.26](https://github.com/WebFiori/framework/compare/v3.0.0-Beta.26...v3.0.0-Beta.26) (2025-04-07)


Expand Down
2 changes: 1 addition & 1 deletion WebFiori/Framework/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ private static function getRoot() {
* @throws Exception
*/
private static function initAutoLoader() {
Ini::createAppDirs();
/**
* Initialize autoloader.
*/
Expand All @@ -744,7 +745,6 @@ private static function initAutoLoader() {
}

if (!class_exists(APP_DIR.'\\Ini\\AutoLoad')) {
Ini::createAppDirs();
Ini::get()->createIniClass('AutoLoad', 'Add user-defined directories to the set of directories at which the framework will search for classes.');
}
self::call(APP_DIR.'\\Ini\\AutoLoad::initialize');
Expand Down
112 changes: 106 additions & 6 deletions WebFiori/Framework/Config/ClassDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@
* create a class called 'AppConfig' on the directory APP_DIR/Config and
* use it to read and write configurations.
*
* ## Environment Variable Support
*
* This driver supports environment variable substitution using the 'env:' prefix.
* The following configuration sections support this feature:
* - Database connections (all properties)
* - SMTP connections (all properties)
* - Environment variables (value field)
* - Scheduler password
*
* Values stored in the generated PHP class can use the 'env:' prefix, and they
* will be resolved to their environment variable values when read.
*
* @author Ibrahim
*/
class ClassDriver implements ConfigurationDriver {
Expand Down Expand Up @@ -60,6 +72,9 @@ public static function a($file, $str, $tabSize = 0) {
* a named constant at run time using the function 'define'. This means
* the constant will be accesaable anywhere within the appllication's environment.
*
* Note: The value parameter supports the 'env:' prefix for referencing
* system environment variables (e.g., "env:MY_VAR").
*
* @param string $name The name of the named constant such as 'MY_CONSTANT'.
*
* @param mixed $value The value of the constant.
Expand All @@ -77,6 +92,10 @@ public function addEnvVar(string $name, mixed $value = null, ?string $descriptio
/**
* Adds new database connections information or update existing connection.
*
* Note: When using this driver, connection properties support environment variable
* substitution using the 'env:' prefix. Values will be stored in the generated PHP class
* and resolved when read.
*
* @param ConnectionInfo $dbConnectionsInfo An object which holds connection information.
*/
public function addOrUpdateDBConnection(ConnectionInfo $dbConnectionsInfo) {
Expand All @@ -86,6 +105,10 @@ public function addOrUpdateDBConnection(ConnectionInfo $dbConnectionsInfo) {
/**
* Adds new SMTP account or Updates an existing one.
*
* Note: When using this driver, SMTP account properties support environment variable
* substitution using the 'env:' prefix. Values will be stored in the generated PHP class
* and resolved when read.
*
* @param SMTPAccount $emailAccount An instance of 'SMTPAccount'.
*/
public function addOrUpdateSMTPAccount(SMTPAccount $emailAccount) {
Expand Down Expand Up @@ -157,6 +180,9 @@ public function getBaseURL(): string {
/**
* Returns database connection information given connection name.
*
* Note: Connection properties that use the 'env:' prefix will be
* automatically resolved to their environment variable values.
*
* @param string $conName The name of the connection.
*
* @return ConnectionInfo|null The method will return an object of type
Expand All @@ -174,10 +200,30 @@ public function getDBConnection(string $conName) {
/**
* Returns an associative array that contain the information of database connections.
*
* Note: Connection properties that use the 'env:' prefix will be
* automatically resolved to their environment variable values.
*
* @return array An associative array of objects of type ConnectionInfo.
*/
public function getDBConnections(): array {
return $this->configVars['database-connections'];
$connections = $this->configVars['database-connections'];

foreach ($connections as $name => $connObj) {
if ($connObj instanceof ConnectionInfo) {
$connObj->setHost(Controller::resolveEnvValue($connObj->getHost()));
$connObj->setUsername(Controller::resolveEnvValue($connObj->getUsername()));
$connObj->setPassword(Controller::resolveEnvValue($connObj->getPassword()));
$connObj->setDBName(Controller::resolveEnvValue($connObj->getDBName()));

$extras = $connObj->getExtars();
foreach ($extras as $key => $value) {
$extras[$key] = Controller::resolveEnvValue($value);
}
$connObj->setExtras($extras);
}
}

return $connections;
}

public function getDescription(string $langCode) {
Expand All @@ -198,12 +244,25 @@ public function getDescriptions(): array {
/**
* Returns an associative array of application constants.
*
* Note: Environment variable values that use the 'env:' prefix will be
* automatically resolved to their system environment variable values.
*
* @return array The indices of the array are names of the constants and
* values are sub-associative arrays. Each sub-array will have two indices,
* 'value' and 'description'.
*/
public function getEnvVars(): array {
return $this->configVars['env-vars'];
$vars = $this->configVars['env-vars'];

foreach ($vars as $name => $varData) {
if (is_array($varData) && isset($varData['value'])) {
$vars[$name]['value'] = Controller::resolveEnvValue($varData['value']);
} else {
$vars[$name] = Controller::resolveEnvValue($varData);
}
}

return $vars;
}
/**
* Returns a string that represents the URL of home page of the application.
Expand All @@ -221,9 +280,17 @@ public function getHomePage() : string {
public function getPrimaryLanguage() : string {
return $this->configVars['site']['primary-lang'];
}

/**
* Returns sha256 hash of the password which is used to prevent unauthorized
* access to run the tasks or access scheduler web interface.
*
* Note: The scheduler password value supports environment variable substitution
* using the 'env:' prefix (e.g., "env:SCHEDULER_PASS").
*
* @return string Password hash or the string 'NO_PASSWORD' if there is no password.
*/
public function getSchedulerPassword(): string {
return $this->configVars['scheduler-password'];
return Controller::resolveEnvValue($this->configVars['scheduler-password']);
}

public function getSMTPAccount(string $name) {
Expand All @@ -242,15 +309,48 @@ public function getSMTPAccount(string $name) {
* will return an object of type SMTPAccount. Else, the
* method will return null.
*
*/ /**
* Returns SMTP connection given its name.
*
* Note: SMTP account properties that use the 'env:' prefix will be
* automatically resolved to their environment variable values.
*
* @param string $name The name of the account.
*
* @return SMTPAccount|null If the account is found, The method
* will return an object of type SMTPAccount. Else, the
* method will return null.
*
*/
public function getSMTPConnection(string $name) {
if (isset($this->getSMTPConnections()[$name])) {
return $this->getSMTPConnections()[$name];
}
}

/**
* Returns an array that contains all added SMTP accounts.
*
* Note: SMTP account properties that use the 'env:' prefix will be
* automatically resolved to their environment variable values.
*
* @return array An associative array of SMTPAccount objects.
*/
public function getSMTPConnections(): array {
return $this->configVars['smtp-connections'];
$connections = $this->configVars['smtp-connections'];

foreach ($connections as $name => $smtpObj) {
if ($smtpObj instanceof SMTPAccount) {
$smtpObj->setServerAddress(Controller::resolveEnvValue($smtpObj->getServerAddress()));
$smtpObj->setPort(Controller::resolveEnvValue($smtpObj->getPort()));
$smtpObj->setUsername(Controller::resolveEnvValue($smtpObj->getUsername()));
$smtpObj->setPassword(Controller::resolveEnvValue($smtpObj->getPassword()));
$smtpObj->setAddress(Controller::resolveEnvValue($smtpObj->getAddress()));
$smtpObj->setSenderName(Controller::resolveEnvValue($smtpObj->getSenderName()));
$smtpObj->setAccessToken(Controller::resolveEnvValue($smtpObj->getAccessToken()));
}
}

return $connections;
}

public function getTheme(): string {
Expand Down
Loading
Loading