Passed
Push — main ( 66554c...a9ed76 )
by Michiel
16:48
created

Properties::storeOutputStream()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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