1<?php 2 3 4namespace ComboStrap; 5 6 7use ArrayAccess; 8use ArrayObject; 9use Countable; 10 11/** 12 * Class ArrayCaseInsensitive 13 * @package ComboStrap 14 * 15 * Wrapper around an array to make it case access insensitive 16 */ 17class ArrayCaseInsensitive implements ArrayAccess, \Iterator, Countable 18{ 19 20 /** 21 * A mapping between lower key and original key (ie offset) 22 * @var array 23 */ 24 private array $_keyMapping = array(); 25 /** 26 * @var array 27 */ 28 private array $sourceArray; 29 /** 30 * @var false|mixed 31 */ 32 private $valid; 33 private int $iteratorIndex = 0; 34 /** 35 * @var \ArrayIterator 36 */ 37 private \ArrayIterator $iterator; 38 39 40 public function __construct(array &$source = array()) 41 { 42 $this->sourceArray = &$source; 43 array_walk($source, function ($value, $key) { 44 $this->_keyMapping[strtolower($key)] = $key; 45 }); 46 47 /** 48 * Iterator 49 */ 50 $this->rewind(); 51 } 52 53 public function offsetSet($offset, $value): void 54 { 55 56 if (is_null($offset)) { 57 LogUtility::msg("The offset (key) is null and this is not supported"); 58 } else { 59 if (is_string($offset)) { 60 $lowerCaseOffset = strtolower($offset); 61 $this->_keyMapping[$lowerCaseOffset] = $offset; 62 $this->sourceArray[$offset] = $value; 63 } else { 64 LogUtility::msg("The offset should be a string", LogUtility::LVL_MSG_ERROR); 65 } 66 67 } 68 } 69 70 public function offsetExists($offset): bool 71 { 72 if (is_string($offset)) $offset = strtolower($offset); 73 return isset($this->_keyMapping[$offset]); 74 } 75 76 public function offsetUnset($offset): void 77 { 78 79 if (is_string($offset)) $offset = strtolower($offset); 80 $originalOffset = $this->_keyMapping[$offset] ?? null; 81 unset($this->sourceArray[$originalOffset]); 82 unset($this->_keyMapping[$offset]); 83 84 } 85 86 87 public function offsetGet($offset) 88 { 89 if (is_string($offset)) $offset = strtolower($offset); 90 $sourceOffset = $this->_keyMapping[$offset] ?? null; 91 if ($sourceOffset === null) { 92 return null; 93 } 94 return $this->sourceArray[$sourceOffset] ?? null; 95 } 96 97 function getOriginalArray(): array 98 { 99 return $this->sourceArray; 100 } 101 102 103 public function current() 104 { 105 return $this->iterator->current(); 106 } 107 108 public function next(): void 109 { 110 $this->iterator->next(); 111 } 112 113 public function key() 114 { 115 return $this->iterator->key(); 116 } 117 118 public function valid(): bool 119 { 120 return $this->iterator->valid(); 121 } 122 123 public function rewind(): void 124 { 125 $obj = new ArrayObject($this->sourceArray); 126 $this->iterator = $obj->getIterator(); 127 } 128 129 public function count(): int 130 { 131 return sizeof($this->sourceArray); 132 } 133} 134