Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace Guzzle\Common;
4
 
5
use Guzzle\Common\Exception\InvalidArgumentException;
6
use Guzzle\Common\Exception\RuntimeException;
7
 
8
/**
9
 * Key value pair collection object
10
 */
11
class Collection implements \ArrayAccess, \IteratorAggregate, \Countable, ToArrayInterface
12
{
13
    /** @var array Data associated with the object. */
14
    protected $data;
15
 
16
    /**
17
     * @param array $data Associative array of data to set
18
     */
19
    public function __construct(array $data = array())
20
    {
21
        $this->data = $data;
22
    }
23
 
24
    /**
25
     * Create a new collection from an array, validate the keys, and add default values where missing
26
     *
27
     * @param array $config   Configuration values to apply.
28
     * @param array $defaults Default parameters
29
     * @param array $required Required parameter names
30
     *
31
     * @return self
32
     * @throws InvalidArgumentException if a parameter is missing
33
     */
34
    public static function fromConfig(array $config = array(), array $defaults = array(), array $required = array())
35
    {
36
        $data = $config + $defaults;
37
 
38
        if ($missing = array_diff($required, array_keys($data))) {
39
            throw new InvalidArgumentException('Config is missing the following keys: ' . implode(', ', $missing));
40
        }
41
 
42
        return new self($data);
43
    }
44
 
45
    public function count()
46
    {
47
        return count($this->data);
48
    }
49
 
50
    public function getIterator()
51
    {
52
        return new \ArrayIterator($this->data);
53
    }
54
 
55
    public function toArray()
56
    {
57
        return $this->data;
58
    }
59
 
60
    /**
61
     * Removes all key value pairs
62
     *
63
     * @return Collection
64
     */
65
    public function clear()
66
    {
67
        $this->data = array();
68
 
69
        return $this;
70
    }
71
 
72
    /**
73
     * Get all or a subset of matching key value pairs
74
     *
75
     * @param array $keys Pass an array of keys to retrieve only a subset of key value pairs
76
     *
77
     * @return array Returns an array of all matching key value pairs
78
     */
79
    public function getAll(array $keys = null)
80
    {
81
        return $keys ? array_intersect_key($this->data, array_flip($keys)) : $this->data;
82
    }
83
 
84
    /**
85
     * Get a specific key value.
86
     *
87
     * @param string $key Key to retrieve.
88
     *
89
     * @return mixed|null Value of the key or NULL
90
     */
91
    public function get($key)
92
    {
93
        return isset($this->data[$key]) ? $this->data[$key] : null;
94
    }
95
 
96
    /**
97
     * Set a key value pair
98
     *
99
     * @param string $key   Key to set
100
     * @param mixed  $value Value to set
101
     *
102
     * @return Collection Returns a reference to the object
103
     */
104
    public function set($key, $value)
105
    {
106
        $this->data[$key] = $value;
107
 
108
        return $this;
109
    }
110
 
111
    /**
112
     * Add a value to a key.  If a key of the same name has already been added, the key value will be converted into an
113
     * array and the new value will be pushed to the end of the array.
114
     *
115
     * @param string $key   Key to add
116
     * @param mixed  $value Value to add to the key
117
     *
118
     * @return Collection Returns a reference to the object.
119
     */
120
    public function add($key, $value)
121
    {
122
        if (!array_key_exists($key, $this->data)) {
123
            $this->data[$key] = $value;
124
        } elseif (is_array($this->data[$key])) {
125
            $this->data[$key][] = $value;
126
        } else {
127
            $this->data[$key] = array($this->data[$key], $value);
128
        }
129
 
130
        return $this;
131
    }
132
 
133
    /**
134
     * Remove a specific key value pair
135
     *
136
     * @param string $key A key to remove
137
     *
138
     * @return Collection
139
     */
140
    public function remove($key)
141
    {
142
        unset($this->data[$key]);
143
 
144
        return $this;
145
    }
146
 
147
    /**
148
     * Get all keys in the collection
149
     *
150
     * @return array
151
     */
152
    public function getKeys()
153
    {
154
        return array_keys($this->data);
155
    }
156
 
157
    /**
158
     * Returns whether or not the specified key is present.
159
     *
160
     * @param string $key The key for which to check the existence.
161
     *
162
     * @return bool
163
     */
164
    public function hasKey($key)
165
    {
166
        return array_key_exists($key, $this->data);
167
    }
168
 
169
    /**
170
     * Case insensitive search the keys in the collection
171
     *
172
     * @param string $key Key to search for
173
     *
174
     * @return bool|string Returns false if not found, otherwise returns the key
175
     */
176
    public function keySearch($key)
177
    {
178
        foreach (array_keys($this->data) as $k) {
179
            if (!strcasecmp($k, $key)) {
180
                return $k;
181
            }
182
        }
183
 
184
        return false;
185
    }
186
 
187
    /**
188
     * Checks if any keys contains a certain value
189
     *
190
     * @param string $value Value to search for
191
     *
192
     * @return mixed Returns the key if the value was found FALSE if the value was not found.
193
     */
194
    public function hasValue($value)
195
    {
196
        return array_search($value, $this->data);
197
    }
198
 
199
    /**
200
     * Replace the data of the object with the value of an array
201
     *
202
     * @param array $data Associative array of data
203
     *
204
     * @return Collection Returns a reference to the object
205
     */
206
    public function replace(array $data)
207
    {
208
        $this->data = $data;
209
 
210
        return $this;
211
    }
212
 
213
    /**
214
     * Add and merge in a Collection or array of key value pair data.
215
     *
216
     * @param Collection|array $data Associative array of key value pair data
217
     *
218
     * @return Collection Returns a reference to the object.
219
     */
220
    public function merge($data)
221
    {
222
        foreach ($data as $key => $value) {
223
            $this->add($key, $value);
224
        }
225
 
226
        return $this;
227
    }
228
 
229
    /**
230
     * Over write key value pairs in this collection with all of the data from an array or collection.
231
     *
232
     * @param array|\Traversable $data Values to override over this config
233
     *
234
     * @return self
235
     */
236
    public function overwriteWith($data)
237
    {
238
        if (is_array($data)) {
239
            $this->data = $data + $this->data;
240
        } elseif ($data instanceof Collection) {
241
            $this->data = $data->toArray() + $this->data;
242
        } else {
243
            foreach ($data as $key => $value) {
244
                $this->data[$key] = $value;
245
            }
246
        }
247
 
248
        return $this;
249
    }
250
 
251
    /**
252
     * Returns a Collection containing all the elements of the collection after applying the callback function to each
253
     * one. The Closure should accept three parameters: (string) $key, (string) $value, (array) $context and return a
254
     * modified value
255
     *
256
     * @param \Closure $closure Closure to apply
257
     * @param array    $context Context to pass to the closure
258
     * @param bool     $static  Set to TRUE to use the same class as the return rather than returning a Collection
259
     *
260
     * @return Collection
261
     */
262
    public function map(\Closure $closure, array $context = array(), $static = true)
263
    {
264
        $collection = $static ? new static() : new self();
265
        foreach ($this as $key => $value) {
266
            $collection->add($key, $closure($key, $value, $context));
267
        }
268
 
269
        return $collection;
270
    }
271
 
272
    /**
273
     * Iterates over each key value pair in the collection passing them to the Closure. If the  Closure function returns
274
     * true, the current value from input is returned into the result Collection.  The Closure must accept three
275
     * parameters: (string) $key, (string) $value and return Boolean TRUE or FALSE for each value.
276
     *
277
     * @param \Closure $closure Closure evaluation function
278
     * @param bool     $static  Set to TRUE to use the same class as the return rather than returning a Collection
279
     *
280
     * @return Collection
281
     */
282
    public function filter(\Closure $closure, $static = true)
283
    {
284
        $collection = ($static) ? new static() : new self();
285
        foreach ($this->data as $key => $value) {
286
            if ($closure($key, $value)) {
287
                $collection->add($key, $value);
288
            }
289
        }
290
 
291
        return $collection;
292
    }
293
 
294
    public function offsetExists($offset)
295
    {
296
        return isset($this->data[$offset]);
297
    }
298
 
299
    public function offsetGet($offset)
300
    {
301
        return isset($this->data[$offset]) ? $this->data[$offset] : null;
302
    }
303
 
304
    public function offsetSet($offset, $value)
305
    {
306
        $this->data[$offset] = $value;
307
    }
308
 
309
    public function offsetUnset($offset)
310
    {
311
        unset($this->data[$offset]);
312
    }
313
 
314
    /**
315
     * Set a value into a nested array key. Keys will be created as needed to set the value.
316
     *
317
     * @param string $path  Path to set
318
     * @param mixed  $value Value to set at the key
319
     *
320
     * @return self
321
     * @throws RuntimeException when trying to setPath using a nested path that travels through a scalar value
322
     */
323
    public function setPath($path, $value)
324
    {
325
        $current =& $this->data;
326
        $queue = explode('/', $path);
327
        while (null !== ($key = array_shift($queue))) {
328
            if (!is_array($current)) {
329
                throw new RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array");
330
            } elseif (!$queue) {
331
                $current[$key] = $value;
332
            } elseif (isset($current[$key])) {
333
                $current =& $current[$key];
334
            } else {
335
                $current[$key] = array();
336
                $current =& $current[$key];
337
            }
338
        }
339
 
340
        return $this;
341
    }
342
 
343
    /**
344
     * Gets a value from the collection using an array path (e.g. foo/baz/bar would retrieve bar from two nested arrays)
345
     * Allows for wildcard searches which recursively combine matches up to the level at which the wildcard occurs. This
346
     * can be useful for accepting any key of a sub-array and combining matching keys from each diverging path.
347
     *
348
     * @param string $path      Path to traverse and retrieve a value from
349
     * @param string $separator Character used to add depth to the search
350
     * @param mixed  $data      Optional data to descend into (used when wildcards are encountered)
351
     *
352
     * @return mixed|null
353
     */
354
    public function getPath($path, $separator = '/', $data = null)
355
    {
356
        if ($data === null) {
357
            $data =& $this->data;
358
        }
359
 
360
        $path = is_array($path) ? $path : explode($separator, $path);
361
        while (null !== ($part = array_shift($path))) {
362
            if (!is_array($data)) {
363
                return null;
364
            } elseif (isset($data[$part])) {
365
                $data =& $data[$part];
366
            } elseif ($part != '*') {
367
                return null;
368
            } else {
369
                // Perform a wildcard search by diverging and merging paths
370
                $result = array();
371
                foreach ($data as $value) {
372
                    if (!$path) {
373
                        $result = array_merge_recursive($result, (array) $value);
374
                    } elseif (null !== ($test = $this->getPath($path, $separator, $value))) {
375
                        $result = array_merge_recursive($result, (array) $test);
376
                    }
377
                }
378
                return $result;
379
            }
380
        }
381
 
382
        return $data;
383
    }
384
 
385
    /**
386
     * Inject configuration settings into an input string
387
     *
388
     * @param string $input Input to inject
389
     *
390
     * @return string
391
     * @deprecated
392
     */
393
    public function inject($input)
394
    {
395
        Version::warn(__METHOD__ . ' is deprecated');
396
        $replace = array();
397
        foreach ($this->data as $key => $val) {
398
            $replace['{' . $key . '}'] = $val;
399
        }
400
 
401
        return strtr($input, $replace);
402
    }
403
}