1<?php
2
3namespace Google;
4
5/**
6 * Extension to the regular Google\Model that automatically
7 * exposes the items array for iteration, so you can just
8 * iterate over the object rather than a reference inside.
9 */
10class Collection extends Model implements \Iterator, \Countable
11{
12  protected $collection_key = 'items';
13
14  /** @return void */
15  #[\ReturnTypeWillChange]
16  public function rewind()
17  {
18    if (isset($this->{$this->collection_key})
19        && is_array($this->{$this->collection_key})) {
20      reset($this->{$this->collection_key});
21    }
22  }
23
24  /** @return mixed */
25  #[\ReturnTypeWillChange]
26  public function current()
27  {
28    $this->coerceType($this->key());
29    if (is_array($this->{$this->collection_key})) {
30      return current($this->{$this->collection_key});
31    }
32  }
33
34  /** @return mixed */
35  #[\ReturnTypeWillChange]
36  public function key()
37  {
38    if (isset($this->{$this->collection_key})
39        && is_array($this->{$this->collection_key})) {
40      return key($this->{$this->collection_key});
41    }
42  }
43
44  /** @return void */
45  #[\ReturnTypeWillChange]
46  public function next()
47  {
48    return next($this->{$this->collection_key});
49  }
50
51  /** @return bool */
52  #[\ReturnTypeWillChange]
53  public function valid()
54  {
55    $key = $this->key();
56    return $key !== null && $key !== false;
57  }
58
59  /** @return int */
60  #[\ReturnTypeWillChange]
61  public function count()
62  {
63    if (!isset($this->{$this->collection_key})) {
64      return 0;
65    }
66    return count($this->{$this->collection_key});
67  }
68
69  /** @return bool */
70  public function offsetExists($offset)
71  {
72    if (!is_numeric($offset)) {
73      return parent::offsetExists($offset);
74    }
75    return isset($this->{$this->collection_key}[$offset]);
76  }
77
78  /** @return mixed */
79  public function offsetGet($offset)
80  {
81    if (!is_numeric($offset)) {
82      return parent::offsetGet($offset);
83    }
84    $this->coerceType($offset);
85    return $this->{$this->collection_key}[$offset];
86  }
87
88  /** @return void */
89  public function offsetSet($offset, $value)
90  {
91    if (!is_numeric($offset)) {
92      parent::offsetSet($offset, $value);
93    }
94    $this->{$this->collection_key}[$offset] = $value;
95  }
96
97  /** @return void */
98  public function offsetUnset($offset)
99  {
100    if (!is_numeric($offset)) {
101      parent::offsetUnset($offset);
102    }
103    unset($this->{$this->collection_key}[$offset]);
104  }
105
106  private function coerceType($offset)
107  {
108    $keyType = $this->keyType($this->collection_key);
109    if ($keyType && !is_object($this->{$this->collection_key}[$offset])) {
110      $this->{$this->collection_key}[$offset] =
111          new $keyType($this->{$this->collection_key}[$offset]);
112    }
113  }
114}
115