1: <?php
  2: 
  3:   4:   5:   6:   7:   8:   9:  10: 
 11: 
 12: namespace Nette\Collections;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18:  19:  20:  21: 
 22: class KeyNotFoundException extends \RuntimeException
 23: {
 24: }
 25: 
 26: 
 27: 
 28:  29:  30:  31:  32: 
 33: class Hashtable extends Collection implements IMap
 34: {
 35:     
 36:     private $throwKeyNotFound = FALSE;
 37: 
 38: 
 39: 
 40:      41:  42:  43:  44:  45:  46: 
 47:     public function add($key, $item)
 48:     {
 49:         
 50:         if (!is_scalar($key)) {
 51:             throw new \InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given.");
 52:         }
 53: 
 54:         if (parent::offsetExists($key)) {
 55:             throw new \InvalidStateException('An element with the same key already exists.');
 56:         }
 57: 
 58:         $this->beforeAdd($item);
 59:         parent::offsetSet($key, $item);
 60:         return TRUE;
 61:     }
 62: 
 63: 
 64: 
 65:      66:  67: 
 68:     public function append($item)
 69:     {
 70:         throw new \NotSupportedException;
 71:     }
 72: 
 73: 
 74: 
 75:      76:  77:  78: 
 79:     public function getKeys()
 80:     {
 81:         return array_keys($this->getArrayCopy());
 82:     }
 83: 
 84: 
 85: 
 86:      87:  88:  89:  90:  91: 
 92:     public function search($item)
 93:     {
 94:         return array_search($item, $this->getArrayCopy(), TRUE);
 95:     }
 96: 
 97: 
 98: 
 99:     100: 101: 102: 103: 104: 
105:     public function import($arr)
106:     {
107:         $this->updating();
108: 
109:         if (!(is_array($arr) || $arr instanceof \Traversable)) {
110:             throw new \InvalidArgumentException("Argument must be traversable.");
111:         }
112: 
113:         if ($this->getItemType() === NULL) { 
114:             $this->setArray((array) $arr);
115: 
116:         } else {
117:             $this->clear();
118:             foreach ($arr as $key => $item) {
119:                 $this->offsetSet($key, $item);
120:             }
121:         }
122:     }
123: 
124: 
125: 
126:     127: 128: 129: 130: 131: 132: 
133:     public function get($key, $default = NULL)
134:     {
135:         if (!is_scalar($key)) {
136:             throw new \InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given.");
137:         }
138: 
139:         if (parent::offsetExists($key)) {
140:             return parent::offsetGet($key);
141: 
142:         } else {
143:             return $default;
144:         }
145:     }
146: 
147: 
148: 
149:     150: 151: 152: 
153:     public function throwKeyNotFound($val = TRUE)
154:     {
155:         $this->throwKeyNotFound = (bool) $val;
156:     }
157: 
158: 
159: 
160:     
161: 
162: 
163: 
164:     165: 166: 167: 168: 169: 170: 
171:     public function offsetSet($key, $item)
172:     {
173:         if (!is_scalar($key)) { 
174:             throw new \InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given.");
175:         }
176: 
177:         $this->beforeAdd($item);
178:         parent::offsetSet($key, $item);
179:     }
180: 
181: 
182: 
183:     184: 185: 186: 187: 188: 
189:     public function offsetGet($key)
190:     {
191:         if (!is_scalar($key)) {
192:             throw new \InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given.");
193:         }
194: 
195:         if (parent::offsetExists($key)) {
196:             return parent::offsetGet($key);
197: 
198:         } elseif ($this->throwKeyNotFound) {
199:             throw new KeyNotFoundException;
200: 
201:         } else {
202:             return NULL;
203:         }
204:     }
205: 
206: 
207: 
208:     209: 210: 211: 212: 213: 
214:     public function offsetExists($key)
215:     {
216:         if (!is_scalar($key)) {
217:             throw new \InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given.");
218:         }
219: 
220:         return parent::offsetExists($key);
221:     }
222: 
223: 
224: 
225:     226: 227: 228: 229: 230: 
231:     public function offsetUnset($key)
232:     {
233:         $this->updating();
234: 
235:         if (!is_scalar($key)) {
236:             throw new \InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given.");
237:         }
238: 
239:         if (parent::offsetExists($key)) {
240:             parent::offsetUnset($key);
241:         }
242:     }
243: 
244: }
245: