IniHelper_Section::addLine()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 2
c 1
b 1
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * File containing the {@link IniHelper} class.
4
 * @package Application Utils
5
 * @subpackage IniHelper
6
 * @see IniHelper_Section
7
 */
8
9
declare(strict_types=1);
10
11
namespace AppUtils;
12
13
use AppUtils\IniHelper\INILine;
14
15
/**
16
 * Container for a section in the INI document: stores
17
 * all ini lines contained within it, and offers methods
18
 * to handle the values.
19
 *
20
 * @package Application Utils
21
 * @subpackage IniHelper
22
 * @author Sebastian Mordziol <[email protected]>
23
 */
24
class IniHelper_Section
25
{
26
    protected IniHelper $ini;
27
    protected string $name;
28
    
29
   /**
30
    * @var INILine[]
31
    */
32
    protected array $lines = array();
33
    
34
    public function __construct(IniHelper $ini, string $name)
35
    {
36
        $this->ini = $ini;
37
        $this->name = $name;
38
    }
39
    
40
   /**
41
    * The section's name.
42
    * @return string
43
    */
44
    public function getName() : string
45
    {
46
        return $this->name;
47
    }
48
    
49
   /**
50
    * Whether this is the default section: this 
51
    * is used internally to store all variables that
52
    * are not in any specific section.
53
    * 
54
    * @return bool
55
    */
56
    public function isDefault() : bool
57
    {
58
        return $this->name === IniHelper::SECTION_DEFAULT;
59
    }
60
    
61
   /**
62
    * Adds a line instance to the section.
63
    * 
64
    * @param INILine $line
65
    * @return IniHelper_Section
66
    */
67
    public function addLine(INILine $line) : IniHelper_Section
68
    {
69
        $this->lines[] = $line;
70
        
71
        return $this;
72
    }
73
    
74
   /**
75
    * Converts the values contained in the section into 
76
    * an associative array.
77
    * 
78
    * @return array<string,array<int,string>>
79
    */
80
    public function toArray() : array
81
    {
82
        $result = array();
83
        
84
        foreach($this->lines as $line)
85
        {
86
            if(!$line->isValue()) {
87
                continue;
88
            }
89
90
            $name = $line->getVarName();
91
            
92
            if(!isset($result[$name])) 
93
            {
94
                $result[$name] = $line->getVarValue();
95
                continue;
96
            }
97
            
98
            // name exists in collection? Then this is a
99
            // duplicate key, and we need to convert it to
100
            // an indexed array of values.
101
            if(!is_array($result[$name])) 
102
            {
103
                $result[$name] = array($result[$name]);
104
            }
105
            
106
            $result[$name][] = $line->getVarValue();
107
        }
108
        
109
        return $result;
110
    }
111
112
    /**
113
     * Converts the section's lines into an INI string.
114
     *
115
     * @return string
116
     * @throws IniHelper_Exception
117
     */
118
    public function toString() : string
119
    {
120
        $lines = array();
121
        if(!$this->isDefault()) 
122
        {
123
            $lines[] = '['.$this->getName().']';
124
        }
125
        
126
        foreach($this->lines as $line) 
127
        {
128
            // we already did this
129
            if($line->isSection()) {
130
                continue;
131
            }
132
            
133
            $lines[] = $line->toString();
134
        }
135
        
136
        return implode($this->ini->getEOLChar(), $lines);
137
    }
138
139
   /**
140
    * Deletes a line from the section.
141
    * 
142
    * @param INILine $toDelete
143
    * @return IniHelper_Section
144
    */
145
    public function deleteLine(INILine $toDelete) : IniHelper_Section
146
    {
147
        $keep = array();
148
        
149
        foreach($this->lines as $line)
150
        {
151
            if($line !== $toDelete) {
152
                $keep[] = $line;
153
            }
154
        }
155
        
156
        $this->lines = $keep;
157
        
158
        return $this;
159
    }
160
161
    /**
162
     * Sets the value of a variable, overwriting any existing value.
163
     *
164
     * @param string $name
165
     * @param mixed $value If an array is specified, it is treated as duplicate keys and will add a line for each value.
166
     * @return IniHelper_Section
167
     * @throws IniHelper_Exception
168
     */
169
    public function setValue(string $name, $value) : IniHelper_Section
170
    {
171
        $lines = $this->getLinesByVariable($name);
172
        
173
        // array value? Treat it as duplicate keys.
174
        // Removes any superfluous values that may
175
        // already exist, if there are more than the
176
        // new set of values.
177
        if(is_array($value))
178
        {
179
            $values = array_values($value);
180
            $amountNew = count($values);
181
            $amountExisting = count($lines);
182
            
183
            $max = $amountNew;
184
            if($amountExisting > $max) {
185
                $max = $amountExisting;
186
            }
187
            
188
            for($i=0; $i < $max; $i++) 
189
            {
190
                // new value exists
191
                if(isset($values[$i]))
192
                {
193
                    if(isset($lines[$i])) {
194
                        $lines[$i]->setValue($values[$i]);
195
                    } else {
196
                        $this->addValueLine($name, $values[$i]);
197
                    }
198
                }
199
                else 
200
                {
201
                    $this->deleteLine($lines[$i]);
202
                }
203
            }
204
        }
205
        
206
        // single value: if duplicate keys exist, they
207
        // are removed and replaced by a single value.
208
        else
209
        {
210
            // remove all superfluous lines
211
            if(!empty($lines))
212
            {
213
                $line = array_shift($lines); // keep only the first line
214
                $line->setValue($value);
215
                
216
                foreach($lines as $delete) {
217
                    $this->deleteLine($delete);
218
                }
219
            }
220
            else 
221
            {
222
                $this->addValueLine($name, $value);
223
            }
224
        }
225
        
226
        return $this;
227
    }
228
    
229
   /**
230
    * Adds a variable value to the section. Unlike setValue(), this
231
    * will not overwrite any existing value. If the name is an existing
232
    * variable name, it will be converted to duplicate keys.
233
    * 
234
    * @param string $name
235
    * @param mixed $value If this is an array, it will be treated as duplicate keys, and all values that are not present yet will be added.
236
    * @return IniHelper_Section
237
    */
238
    public function addValue(string $name, $value) : IniHelper_Section
239
    {
240
        // array value? Treat it as duplicate keys.
241
        if(is_array($value))
242
        {
243
            $values = array_values($value);
244
            
245
            foreach($values as $setValue)
246
            {
247
                $this->addValue($name, $setValue);
248
            }
249
            
250
            return $this;
251
        }
252
        
253
        $lines = $this->getLinesByVariable($name);
254
        
255
        if(empty($lines))
256
        {
257
            $this->addValueLine($name, $value);
258
        }
259
        else
260
        {
261
            $found = false;
262
            
263
            foreach($lines as $line)
264
            {
265
                if($line->getVarValue() === $value) {
266
                    $found = $line;
267
                    break;
268
                }
269
            }
270
            
271
            if(!$found)
272
            {
273
                $this->addValueLine($name, $value);
274
            }
275
        }
276
        
277
        return $this;
278
    }
279
280
    /**
281
     * @param string $name
282
     * @param mixed|NULL $value
283
     * @return INILine
284
     * @throws IniHelper_Exception
285
     */
286
    protected function addValueLine(string $name, $value) : INILine
287
    {
288
        $line = new INILine(
289
            sprintf('%s=%s', $name, 'dummyvalue'),
290
            0
291
        );
292
        
293
        $line->setValue($value);
294
        $this->addLine($line);
295
        
296
        return $line;
297
    }
298
    
299
    
300
   /**
301
    * Retrieves all lines for the specified variable name.
302
    *  
303
    * @param string $name
304
    * @return INILine[]
305
    */
306
    public function getLinesByVariable(string $name) : array
307
    {
308
        $result = array();
309
        
310
        foreach($this->lines as $line)
311
        {
312
            if($line->isValue() && $line->getVarName() === $name) {
313
                $result[] = $line;
314
            }
315
        }
316
        
317
        return $result;
318
    }
319
}
320