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
/**
21
 * Convenience class for reading and writing property files.
22
 *
23
 * FIXME
24
 *        - Add support for arrays (separated by ',')
25
 *
26
 * @package phing.system.util
27
 */
28
class Properties
29
{
30
    private $properties = [];
31

32
    /**
33
     * @var FileParserInterface
34
     */
35
    private $fileParser;
36

37
    /**
38
     * @var PhingFile
39
     */
40
    private $file = null;
41

42
    /**
43
     * Constructor
44
     *
45
     * @param array $properties
46
     * @param FileParserInterface $fileParser
47
     */
48 1
    public function __construct($properties = null, FileParserInterface $fileParser = null)
49
    {
50 1
        $this->fileParser = $fileParser == null ? new IniFileParser() : $fileParser;
51

52 1
        if (is_array($properties)) {
53 0
            foreach ($properties as $key => $value) {
54 0
                $this->setProperty($key, $value);
55
            }
56
        }
57
    }
58

59
    /**
60
     * Load properties from a file.
61
     *
62
     * @param  PhingFile $file
63
     * @return void
64
     * @throws IOException - if unable to read file.
65
     */
66 1
    public function load(PhingFile $file)
67
    {
68 1
        if ($file->canRead()) {
69 1
            $this->parse($file);
70

71 1
            $this->file = $file;
72
        } else {
73 0
            throw new IOException("Can not read file " . $file->getPath());
74
        }
75
    }
76

77
    /**
78
     * Parses the file given.
79
     *
80
     * @param PhingFile $file
81
     */
82 1
    protected function parse(PhingFile $file)
83
    {
84 1
        $this->properties = $this->fileParser->parseFile($file);
85
    }
86

87
    /**
88
     * Process values when being written out to properties file.
89
     * does things like convert true => "true"
90
     *
91
     * @param  mixed $val The property value (may be boolean, etc.)
92
     * @return string
93
     */
94 1
    protected function outVal($val)
95
    {
96 1
        if ($val === true) {
97 0
            $val = "true";
98 1
        } elseif ($val === false) {
99 0
            $val = "false";
100
        }
101

102 1
        return $val;
103
    }
104

105
    /**
106
     * Create string representation that can be written to file and would be loadable using load() method.
107
     *
108
     * Essentially this function creates a string representation of properties that is ready to
109
     * write back out to a properties file.  This is used by store() method.
110
     *
111
     * @return string
112
     */
113 1
    public function __toString()
114
    {
115 1
        $buf = "";
116 1
        foreach ($this->properties as $key => $item) {
117 1
            $buf .= $key . "=" . $this->outVal($item) . PHP_EOL;
118
        }
119

120 1
        return $buf;
121
    }
122

123
    /**
124
     * Stores current properties to specified file.
125
     *
126
     * @param  PhingFile $file File to create/overwrite with properties.
127
     * @param  string $header Header text that will be placed (within comments) at the top of properties file.
128
     * @return void
129
     * @throws IOException - on error writing properties file.
130
     */
131 1
    public function store(PhingFile $file = null, $header = null)
132
    {
133 1
        if ($file == null) {
134 0
            $file = $this->file;
135
        }
136

137 1
        if ($file == null) {
138 0
            throw new IOException("Unable to write to empty filename");
139
        }
140

141
        // stores the properties in this object in the file denoted
142
        // if file is not given and the properties were loaded from a
143
        // file prior, this method stores them in the file used by load()
144
        try {
145 1
            $fw = new FileWriter($file);
146 1
            if ($header !== null) {
147 1
                $fw->write("# " . $header . PHP_EOL);
148
            }
149 1
            $fw->write((string) $this);
150 1
            $fw->close();
151 0
        } catch (IOException $e) {
152 0
            throw new IOException("Error writing property file: " . $e->getMessage());
153
        }
154
    }
155

156 0
    public function storeOutputStream(OutputStream $os, $comments)
157
    {
158 0
        $this->_storeOutputStream(new BufferedWriter(new OutputStreamWriter($os)), $comments);
159
    }
160

161 0
    private function _storeOutputStream(BufferedWriter $bw, $comments)
162
    {
163 0
        if ($comments != null) {
164 0
            self::writeComments($bw, $comments);
165
        }
166 0
        $bw->write("#" . gmdate('D, d M Y H:i:s', time()) . ' GMT');
167 0
        $bw->newLine();
168 0
        foreach ($this->getProperties() as $key => $value) {
169 0
            $bw->write($key . "=" . $value);
170 0
            $bw->newLine();
171
        }
172 0
        $bw->flush();
173
    }
174

175 0
    private static function writeComments(BufferedWriter $bw, $comments)
176
    {
177 0
        $rows = explode("\n", $comments);
178 0
        $bw->write("#" . PHP_EOL);
179 0
        foreach ($rows as $row) {
180 0
            $bw->write(sprintf("#%s%s", trim($row), PHP_EOL));
181
        }
182 0
        $bw->write("#");
183 0
        $bw->newLine();
184
    }
185

186
    /**
187
     * Returns copy of internal properties hash.
188
     * Mostly for performance reasons, property hashes are often
189
     * preferable to passing around objects.
190
     *
191
     * @return array
192
     */
193 1
    public function getProperties()
194
    {
195 1
        return $this->properties;
196
    }
197

198
    /**
199
     * Get value for specified property.
200
     * This is the same as get() method.
201
     *
202
     * @param  string $prop The property name (key).
203
     * @return mixed
204
     * @see    get()
205
     */
206 1
    public function getProperty($prop)
207
    {
208 1
        if (!isset($this->properties[$prop])) {
209 1
            return null;
210
        }
211

212 1
        return $this->properties[$prop];
213
    }
214

215
    /**
216
     * Get value for specified property.
217
     * This function exists to provide a hashtable-like interface for
218
     * properties.
219
     *
220
     * @param  string $prop The property name (key).
221
     * @return mixed
222
     * @see    getProperty()
223
     */
224 1
    public function get($prop)
225
    {
226 1
        if (!isset($this->properties[$prop])) {
227 0
            return null;
228
        }
229

230 1
        return $this->properties[$prop];
231
    }
232

233
    /**
234
     * Set the value for a property.
235
     *
236
     * @param  string $key
237
     * @param  mixed $value
238
     * @return mixed  Old property value or null if none was set.
239
     */
240 1
    public function setProperty($key, $value)
241
    {
242 1
        $oldValue = $this->properties[$key] ?? null;
243 1
        $this->properties[$key] = $value;
244

245 1
        return $oldValue;
246
    }
247

248
    /**
249
     * Set the value for a property.
250
     * This function exists to provide hashtable-lie
251
     * interface for properties.
252
     *
253
     * @param  string $key
254
     * @param  mixed $value
255
     * @return mixed
256
     */
257 1
    public function put($key, $value)
258
    {
259 1
        return $this->setProperty($key, $value);
260
    }
261

262
    /**
263
     * Appends a value to a property if it already exists with a delimiter
264
     *
265
     * If the property does not, it just adds it.
266
     *
267
     * @param string $key
268
     * @param mixed $value
269
     * @param string $delimiter
270
     */
271 1
    public function append($key, $value, $delimiter = ',')
272
    {
273 1
        $newValue = $value;
274 1
        if (isset($this->properties[$key]) && !empty($this->properties[$key])) {
275 1
            $newValue = $this->properties[$key] . $delimiter . $value;
276
        }
277 1
        $this->properties[$key] = $newValue;
278
    }
279

280
    /**
281
     * Same as keys() function, returns an array of property names.
282
     *
283
     * @return array
284
     */
285 1
    public function propertyNames()
286
    {
287 1
        return $this->keys();
288
    }
289

290
    /**
291
     * Whether loaded properties array contains specified property name.
292
     *
293
     * @param  $key
294
     * @return boolean
295
     */
296 1
    public function containsKey($key)
297
    {
298 1
        return isset($this->properties[$key]);
299
    }
300

301
    /**
302
     * Returns properties keys.
303
     * Use this for foreach () {} iterations, as this is
304
     * faster than looping through property values.
305
     *
306
     * @return array
307
     */
308 1
    public function keys()
309
    {
310 1
        return array_keys($this->properties);
311
    }
312

313
    /**
314
     * Whether properties list is empty.
315
     *
316
     * @return boolean
317
     */
318 1
    public function isEmpty()
319
    {
320 1
        return empty($this->properties);
321
    }
322
}

Read our documentation on viewing source code .

Loading