Passed
Push — main ( 4889b2...808ce0 )
by Michiel
07:43
created

Properties   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 289
Duplicated Lines 0 %

Test Coverage

Coverage 67.05%

Importance

Changes 0
Metric Value
wmc 36
eloc 69
dl 0
loc 289
ccs 59
cts 88
cp 0.6705
rs 9.52
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A load() 0 8 2
A __toString() 0 8 2
A store() 0 22 5
A parse() 0 3 1
A __construct() 0 7 4
A outVal() 0 9 3
A storeOutputStream() 0 13 3
A append() 0 7 3
A keys() 0 3 1
A get() 0 7 2
A getProperties() 0 3 1
A writeComments() 0 9 2
A isEmpty() 0 3 1
A put() 0 3 1
A getProperty() 0 7 2
A containsKey() 0 3 1
A setProperty() 0 6 1
A propertyNames() 0 3 1
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
namespace Phing\Util;
21
22
use Phing\Io\BufferedWriter;
23
use Phing\Io\File;
24
use Phing\Io\FileParserInterface;
25
use Phing\Io\FileWriter;
26
use Phing\Io\IniFileParser;
27
use Phing\Io\IOException;
28
use Phing\Io\OutputStream;
29
use Phing\Io\OutputStreamWriter;
30
31
/**
32
 * Convenience class for reading and writing property files.
33
 *
34
 * FIXME
35
 *        - Add support for arrays (separated by ',')
36
 *
37
 */
38
class Properties
39
{
40
    private $properties = [];
41
42
    /**
43
     * @var FileParserInterface
44
     */
45
    private $fileParser;
46
47
    /**
48
     * @var File
49
     */
50
    private $file = null;
51
52
    /**
53
     * Constructor
54
     *
55
     * @param array               $properties
56
     * @param FileParserInterface $fileParser
57
     */
58 851
    public function __construct($properties = null, FileParserInterface $fileParser = null)
59
    {
60 851
        $this->fileParser = $fileParser == null ? new IniFileParser() : $fileParser;
61
62 851
        if (is_array($properties)) {
63
            foreach ($properties as $key => $value) {
64
                $this->setProperty($key, $value);
65
            }
66
        }
67 851
    }
68
69
    /**
70
     * Load properties from a file.
71
     *
72
     * @param  File $file
73
     * @return void
74
     * @throws IOException - if unable to read file.
75
     */
76 847
    public function load(File $file)
77
    {
78 847
        if ($file->canRead()) {
79 847
            $this->parse($file);
80
81 847
            $this->file = $file;
82
        } else {
83
            throw new IOException("Can not read file " . $file->getPath());
84
        }
85 847
    }
86
87
    /**
88
     * Parses the file given.
89
     *
90
     * @param File $file
91
     */
92 847
    protected function parse(File $file)
93
    {
94 847
        $this->properties = $this->fileParser->parseFile($file);
95 847
    }
96
97
    /**
98
     * Process values when being written out to properties file.
99
     * does things like convert true => "true"
100
     *
101
     * @param  mixed $val The property value (may be boolean, etc.)
102
     * @return string
103
     */
104 6
    protected function outVal($val)
105
    {
106 6
        if ($val === true) {
107
            $val = "true";
108 6
        } elseif ($val === false) {
109
            $val = "false";
110
        }
111
112 6
        return $val;
113
    }
114
115
    /**
116
     * Create string representation that can be written to file and would be loadable using load() method.
117
     *
118
     * Essentially this function creates a string representation of properties that is ready to
119
     * write back out to a properties file.  This is used by store() method.
120
     *
121
     * @return string
122
     */
123 6
    public function __toString()
124
    {
125 6
        $buf = "";
126 6
        foreach ($this->properties as $key => $item) {
127 6
            $buf .= $key . "=" . $this->outVal($item) . PHP_EOL;
128
        }
129
130 6
        return $buf;
131
    }
132
133
    /**
134
     * Stores current properties to specified file.
135
     *
136
     * @param  File   $file   File to create/overwrite with properties.
137
     * @param  string $header Header text that will be placed (within comments) at the top of properties file.
138
     * @return void
139
     * @throws IOException - on error writing properties file.
140
     */
141 5
    public function store(File $file = null, $header = null)
142
    {
143 5
        if ($file == null) {
144
            $file = $this->file;
145
        }
146
147 5
        if ($file == null) {
148
            throw new IOException("Unable to write to empty filename");
149
        }
150
151
        // stores the properties in this object in the file denoted
152
        // if file is not given and the properties were loaded from a
153
        // file prior, this method stores them in the file used by load()
154
        try {
155 5
            $fw = new FileWriter($file);
156 5
            if ($header !== null) {
157 4
                $fw->write("# " . $header . PHP_EOL);
158
            }
159 5
            $fw->write((string) $this);
160 5
            $fw->close();
161
        } catch (IOException $e) {
162
            throw new IOException("Error writing property file: " . $e->getMessage());
163
        }
164 5
    }
165
166
    public function storeOutputStream(OutputStream $os, $comments)
167
    {
168
        $bw = new BufferedWriter(new OutputStreamWriter($os));
169
        if ($comments != null) {
170
            self::writeComments($bw, $comments);
171
        }
172
        $bw->write("#" . gmdate('D, d M Y H:i:s', time()) . ' GMT');
173
        $bw->newLine();
174
        foreach ($this->getProperties() as $key => $value) {
175
            $bw->write($key . "=" . $value);
176
            $bw->newLine();
177
        }
178
        $bw->flush();
179
    }
180
181
    private static function writeComments(BufferedWriter $bw, $comments)
182
    {
183
        $rows = explode("\n", $comments);
184
        $bw->write("#" . PHP_EOL);
185
        foreach ($rows as $row) {
186
            $bw->write(sprintf("#%s%s", trim($row), PHP_EOL));
187
        }
188
        $bw->write("#");
189
        $bw->newLine();
190
    }
191
192
    /**
193
     * Returns copy of internal properties hash.
194
     * Mostly for performance reasons, property hashes are often
195
     * preferable to passing around objects.
196
     *
197
     * @return array
198
     */
199 1
    public function getProperties()
200
    {
201 1
        return $this->properties;
202
    }
203
204
    /**
205
     * Get value for specified property.
206
     * This is the same as get() method.
207
     *
208
     * @param  string $prop The property name (key).
209
     * @return mixed
210
     * @see    get()
211
     */
212 847
    public function getProperty($prop)
213
    {
214 847
        if (!isset($this->properties[$prop])) {
215 2
            return null;
216
        }
217
218 847
        return $this->properties[$prop];
219
    }
220
221
    /**
222
     * Get value for specified property.
223
     * This function exists to provide a hashtable-like interface for
224
     * properties.
225
     *
226
     * @param  string $prop The property name (key).
227
     * @return mixed
228
     * @see    getProperty()
229
     */
230 1
    public function get($prop)
231
    {
232 1
        if (!isset($this->properties[$prop])) {
233
            return null;
234
        }
235
236 1
        return $this->properties[$prop];
237
    }
238
239
    /**
240
     * Set the value for a property.
241
     *
242
     * @param  string $key
243
     * @param  mixed  $value
244
     * @return mixed  Old property value or null if none was set.
245
     */
246 15
    public function setProperty($key, $value)
247
    {
248 15
        $oldValue = $this->properties[$key] ?? null;
249 15
        $this->properties[$key] = $value;
250
251 15
        return $oldValue;
252
    }
253
254
    /**
255
     * Set the value for a property.
256
     * This function exists to provide hashtable-lie
257
     * interface for properties.
258
     *
259
     * @param  string $key
260
     * @param  mixed  $value
261
     * @return mixed
262
     */
263 6
    public function put($key, $value)
264
    {
265 6
        return $this->setProperty($key, $value);
266
    }
267
268
    /**
269
     * Appends a value to a property if it already exists with a delimiter
270
     *
271
     * If the property does not, it just adds it.
272
     *
273
     * @param string $key
274
     * @param mixed  $value
275
     * @param string $delimiter
276
     */
277 1
    public function append($key, $value, $delimiter = ',')
278
    {
279 1
        $newValue = $value;
280 1
        if (isset($this->properties[$key]) && !empty($this->properties[$key])) {
281 1
            $newValue = $this->properties[$key] . $delimiter . $value;
282
        }
283 1
        $this->properties[$key] = $newValue;
284 1
    }
285
286
    /**
287
     * Same as keys() function, returns an array of property names.
288
     *
289
     * @return array
290
     */
291 846
    public function propertyNames()
292
    {
293 846
        return $this->keys();
294
    }
295
296
    /**
297
     * Whether loaded properties array contains specified property name.
298
     *
299
     * @param  string $key
300
     * @return boolean
301
     */
302 6
    public function containsKey($key)
303
    {
304 6
        return isset($this->properties[$key]);
305
    }
306
307
    /**
308
     * Returns properties keys.
309
     * Use this for foreach () {} iterations, as this is
310
     * faster than looping through property values.
311
     *
312
     * @return array
313
     */
314 846
    public function keys()
315
    {
316 846
        return array_keys($this->properties);
317
    }
318
319
    /**
320
     * Whether properties list is empty.
321
     *
322
     * @return boolean
323
     */
324 1
    public function isEmpty()
325
    {
326 1
        return empty($this->properties);
327
    }
328
}
329