Skip to content

Commit ab9fbd7

Browse files
author
Greg Bowler
authored
Merge pull request #19 from PhpGt/16-overrides
Config override files
2 parents a270fbb + e964298 commit ab9fbd7

15 files changed

+375
-233
lines changed

bin/config-generator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env php
2+
<?php
3+
$args = new CommandLineArguments($argv);

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"type": "library",
55

66
"require": {
7-
"php": ">=7.1.0"
7+
"php": ">=7.1.0",
8+
"magicalex/write-ini-file": "v1.2.3"
89
},
910
"require-dev": {
1011
"phpunit/phpunit": "6.4.*"
@@ -29,4 +30,4 @@
2930
"Gt\\Config\\Test\\": "./test/unit"
3031
}
3132
}
32-
}
33+
}

composer.lock

Lines changed: 50 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Config.php

Lines changed: 31 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,12 @@
22
namespace Gt\Config;
33

44
class Config {
5-
const INI_EXTENSION = "ini";
6-
const FILE_OVERRIDE_DEV = "dev";
7-
const FILE_OVERRIDE_DEPLOY = "deploy";
8-
const FILE_OVERRIDE_PRODUCTION = "production";
9-
const FILE_OVERRIDE_ORDER = [
10-
self::FILE_OVERRIDE_DEV,
11-
self::FILE_OVERRIDE_DEPLOY,
12-
self::FILE_OVERRIDE_PRODUCTION,
13-
];
5+
/** @var ConfigSection[] */
6+
protected $sectionList = [];
147

15-
protected $projectRoot;
16-
protected $kvp = [];
17-
protected $delimeter;
18-
19-
public function __construct(
20-
string $projectRoot = "",
21-
string $filename = "config",
22-
string $delimeter = "."
23-
) {
24-
$this->projectRoot = $projectRoot;
25-
$iniConfig = $this->loadIni($projectRoot, $filename);
26-
$this->kvp = $iniConfig;
27-
$this->delimeter = $delimeter;
28-
}
29-
30-
public function mergeDefaults(
31-
string $defaultDirectoryPath = null,
32-
string $filename = "config.default",
33-
bool $override = false
34-
):void {
35-
if(is_null($defaultDirectoryPath)) {
36-
$defaultDirectoryPath = $this->projectRoot;
37-
}
38-
39-
$defaults = $this->loadIni(
40-
$defaultDirectoryPath,
41-
$filename
42-
);
43-
44-
foreach($defaults as $section => $data) {
45-
foreach($data as $key => $value) {
46-
if(!isset($this->kvp[$section])) {
47-
$this->kvp[$section] = [];
48-
}
49-
50-
if(!isset($this->kvp[$section][$key])) {
51-
$this->kvp[$section][$key] = $value;
52-
}
53-
54-
if($override) {
55-
$this->kvp[$section][$key] = $value;
56-
}
57-
}
58-
}
59-
}
60-
61-
public function loadOverrides():void {
62-
foreach(self::FILE_OVERRIDE_ORDER as $override) {
63-
$this->mergeDefaults(
64-
$this->projectRoot,
65-
"config.$override",
66-
true
67-
);
8+
public function __construct(ConfigSection...$sectionList) {
9+
foreach($sectionList as $section) {
10+
$this->sectionList[$section->getName()] = $section;
6811
}
6912
}
7013

@@ -78,38 +21,46 @@ public function get(string $name):?string {
7821
}
7922

8023
public function getSection(string $sectionName):?ConfigSection {
81-
if(!isset($this->kvp[$sectionName])) {
82-
return null;
83-
}
84-
85-
return new ConfigSection($this->kvp[$sectionName]);
24+
return $this->sectionList[$sectionName] ?? null;
8625
}
8726

8827
protected function getSectionValue(string $name):?string {
89-
$parts = explode($this->delimeter, $name, 2);
28+
$parts = explode(".", $name, 2);
9029
$section = $this->getSection($parts[0]);
9130

9231
if(is_null($section)
9332
|| empty($parts[1])) {
9433
return null;
9534
}
9635

97-
return $section[$parts[1]];
36+
return $section->get($parts[1]);
9837
}
9938

100-
protected function loadIni(string $directoryPath, string $filename):array {
101-
$kvp = [];
102-
103-
$iniPath = $directoryPath
104-
. DIRECTORY_SEPARATOR
105-
. $filename
106-
. "."
107-
. self::INI_EXTENSION;
39+
public function getSectionNames():array {
40+
$names = [];
10841

109-
if(is_file($iniPath)) {
110-
$kvp = parse_ini_file($iniPath, true);
42+
foreach($this->sectionList as $section) {
43+
$names []= $section->getName();
11144
}
11245

113-
return $kvp;
46+
return $names;
47+
}
48+
49+
public function merge(Config $configToOverride):void {
50+
foreach($configToOverride->getSectionNames() as $sectionName) {
51+
if(isset($this->sectionList[$sectionName])) {
52+
foreach($configToOverride->getSection($sectionName)
53+
as $key => $value) {
54+
if(empty($this->sectionList[$sectionName][$key])) {
55+
$this->sectionList[$sectionName][$key] = $value;
56+
}
57+
}
58+
}
59+
else {
60+
$this->sectionList[$sectionName] = $configToOverride->getSection(
61+
$sectionName
62+
);
63+
}
64+
}
11465
}
11566
}

src/ConfigFactory.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
namespace Gt\Config;
3+
4+
class ConfigFactory {
5+
const EXTENSION = "ini";
6+
const FILE_DEFAULT = "default";
7+
const FILE_OVERRIDE_ORDER = [
8+
"dev",
9+
"deploy",
10+
"production",
11+
];
12+
13+
public static function createForProject(string $projectRoot):Config {
14+
$order = array_merge(
15+
[self::FILE_DEFAULT, ""],
16+
self::FILE_OVERRIDE_ORDER
17+
);
18+
19+
$previousConfig = null;
20+
21+
foreach($order as $file) {
22+
$fileName = "config";
23+
$fileName .= ".";
24+
25+
if(!empty($file)) {
26+
$fileName .= $file;
27+
$fileName .= ".";
28+
}
29+
30+
$fileName .= self::EXTENSION;
31+
$config = self::createFromPathName(
32+
implode(DIRECTORY_SEPARATOR,[
33+
$projectRoot,
34+
$fileName,
35+
])
36+
);
37+
if(is_null($config)) {
38+
continue;
39+
}
40+
41+
if($previousConfig) {
42+
$config->merge($previousConfig);
43+
}
44+
45+
$previousConfig = $config;
46+
}
47+
48+
return $config;
49+
}
50+
51+
public static function createFromPathName(string $pathName):?Config {
52+
if(!is_file($pathName)) {
53+
return null;
54+
}
55+
56+
$parser = new IniParser($pathName);
57+
return $parser->parse();
58+
}
59+
60+
public static function createFromArray(array $input):Config {
61+
62+
}
63+
}

src/ConfigSection.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
use Iterator;
66

77
class ConfigSection implements ArrayAccess, Iterator {
8+
protected $name;
89
protected $data;
910
protected $iteratorIndex;
1011

11-
public function __construct(array $data) {
12+
public function __construct(string $name, array $data) {
13+
$this->name = $name;
1214
$this->data = $data;
1315
}
1416

@@ -19,7 +21,7 @@ public function get(string $key):?string {
1921
/**
2022
* @link http://php.net/manual/en/iterator.current.php
2123
*/
22-
public function current():array {
24+
public function current():string {
2325
$key = $this->getIteratorKey();
2426
return $this->data[$key];
2527
}
@@ -71,14 +73,18 @@ public function offsetGet($offset):?string {
7173
* @link http://php.net/manual/en/arrayaccess.offsetset.php
7274
*/
7375
public function offsetSet($offset, $value):void {
74-
throw new ImmutableObjectMutationException();
76+
$this->data[$offset] = $value;
7577
}
7678

7779
/**
7880
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
7981
*/
8082
public function offsetUnset($offset):void {
81-
throw new ImmutableObjectMutationException();
83+
unset($this->data[$offset]);
84+
}
85+
86+
public function getName():string {
87+
return $this->name;
8288
}
8389

8490
protected function getIteratorKey():?string {

src/FileWriter.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
namespace Gt\Config;
3+
4+
use Exception;
5+
use WriteiniFile\WriteiniFile;
6+
7+
class FileWriter {
8+
private $config;
9+
10+
public function __construct(Config $config) {
11+
$this->config = $config;
12+
}
13+
14+
public function writeIni(string $filePath):void {
15+
if(!is_dir(dirname($filePath))) {
16+
mkdir(dirname($filePath), 0775, true);
17+
}
18+
19+
$writer = new WriteiniFile($filePath);
20+
21+
foreach($this->config->getSectionNames() as $sectionName) {
22+
foreach($this->config->getSection($sectionName)
23+
as $key => $value) {
24+
$writer->add([
25+
$sectionName => [
26+
$key => $value,
27+
]
28+
]);
29+
}
30+
}
31+
32+
try {
33+
$writer->write();
34+
}
35+
catch(Exception $exception) {
36+
throw new ConfigException("Unable to write to file: $filePath");
37+
}
38+
}
39+
}

src/ImmutableObjectMutationException.php

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)