1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Compolomus\IniObject; |
6
|
|
|
|
7
|
|
|
use InvalidArgumentException; |
8
|
|
|
use SplFileObject; |
9
|
|
|
|
10
|
|
|
class IniObject |
11
|
|
|
{ |
12
|
|
|
private $filename; |
13
|
|
|
|
14
|
|
|
protected $config; |
15
|
|
|
|
16
|
|
|
private $sections; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* IniObject constructor. |
20
|
|
|
* |
21
|
|
|
* @param string|null $filename |
22
|
|
|
* @param array $data |
23
|
|
|
* @param array $config |
24
|
|
|
*/ |
25
|
12 |
|
public function __construct(?string $filename = null, array $data = [], array $config = []) |
26
|
|
|
{ |
27
|
12 |
|
if (! count($config)) { |
28
|
12 |
|
$this->initDefaultConfig(); |
29
|
|
|
} |
30
|
12 |
|
if ($filename !== null && file_exists($filename) && ! count($data)) { |
31
|
12 |
|
$data = parse_ini_file( |
32
|
12 |
|
$filename, |
33
|
12 |
|
true, |
34
|
12 |
|
$this->config['strict'] ? INI_SCANNER_TYPED : INI_SCANNER_NORMAL |
35
|
|
|
); |
36
|
|
|
} |
37
|
12 |
|
if ($data) { |
|
|
|
|
38
|
12 |
|
$this->sectionLoad($data); |
39
|
12 |
|
$this->setFilename($filename); |
40
|
|
|
} |
41
|
12 |
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @param array $data |
45
|
|
|
* @throws InvalidArgumentException |
46
|
|
|
*/ |
47
|
12 |
|
private function sectionLoad(array $data): void |
48
|
|
|
{ |
49
|
12 |
|
$sections = []; |
50
|
12 |
|
foreach ($data as $sectionName => $params) { |
51
|
12 |
|
$sections[$sectionName] = new Section($sectionName, $params); |
52
|
|
|
} |
53
|
12 |
|
$this->sections = $sections; |
54
|
12 |
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* @param string $name |
58
|
|
|
* @return Section |
59
|
|
|
*/ |
60
|
7 |
|
public function getSection(string $name): Section |
61
|
|
|
{ |
62
|
7 |
|
if (! isset($this->sections[$name])) { |
63
|
1 |
|
throw new InvalidArgumentException('Section not found'); |
64
|
|
|
} |
65
|
|
|
|
66
|
7 |
|
return $this->sections[$name]; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param string $name |
71
|
|
|
*/ |
72
|
1 |
|
public function removeSection(string $name): void |
73
|
|
|
{ |
74
|
1 |
|
if (! isset($this->sections[$name])) { |
75
|
1 |
|
throw new InvalidArgumentException('Section not found for remove'); |
76
|
|
|
} |
77
|
1 |
|
unset($this->sections[$name]); |
78
|
1 |
|
} |
79
|
|
|
|
80
|
2 |
|
public function addSection(string $name, array $section): void |
81
|
|
|
{ |
82
|
2 |
|
if (isset($this->sections[$name])) { |
83
|
1 |
|
throw new InvalidArgumentException('Overwrite section denied'); |
84
|
|
|
} |
85
|
2 |
|
$this->sections[$name] = new Section($name, $section); |
86
|
2 |
|
} |
87
|
|
|
|
88
|
1 |
|
public function updateSection(string $name, array $section): void |
89
|
|
|
{ |
90
|
1 |
|
if (! isset($this->sections[$name])) { |
91
|
1 |
|
throw new InvalidArgumentException('Section not found for update'); |
92
|
|
|
} |
93
|
1 |
|
$this->sections[$name] = new Section($name, $section); |
94
|
1 |
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* default config |
98
|
|
|
*/ |
99
|
12 |
|
private function initDefaultConfig(): void |
100
|
|
|
{ |
101
|
12 |
|
$this->config = [ |
102
|
|
|
'strict' => false, |
103
|
|
|
'overwrite' => true, |
104
|
|
|
]; |
105
|
12 |
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param string $filename |
109
|
|
|
*/ |
110
|
12 |
|
private function setFilename(?string $filename): void |
111
|
|
|
{ |
112
|
12 |
|
$this->filename = $filename; |
113
|
12 |
|
} |
114
|
|
|
|
115
|
1 |
|
public function __toString() |
116
|
|
|
{ |
117
|
1 |
|
$return = ''; |
118
|
|
|
|
119
|
1 |
|
foreach ($this->sections as $section) { |
120
|
1 |
|
$return .= $section; |
121
|
|
|
} |
122
|
|
|
|
123
|
1 |
|
return trim($return) . PHP_EOL; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @return array |
128
|
|
|
*/ |
129
|
1 |
|
public function toArray(): array |
130
|
|
|
{ |
131
|
1 |
|
$return = []; |
132
|
|
|
|
133
|
1 |
|
foreach ($this->sections as $section) { |
134
|
1 |
|
$return[$section->getName()] = $section->toArray(); |
135
|
|
|
} |
136
|
|
|
|
137
|
1 |
|
return $return; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* @param string|null $filename |
142
|
|
|
* @return bool |
143
|
|
|
*/ |
144
|
1 |
|
public function save(string $filename = null): bool |
145
|
|
|
{ |
146
|
1 |
|
if (! $this->config['overwrite'] && file_exists($filename)) { |
147
|
1 |
|
throw new InvalidArgumentException('Overwrite file protection'); |
148
|
|
|
} |
149
|
1 |
|
if ($filename !== null) { |
150
|
1 |
|
$this->setFilename($filename); |
151
|
|
|
} |
152
|
|
|
|
153
|
1 |
|
return (bool) (new SPLFileObject($this->filename, 'w+b'))->fwrite((string) $this); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.