*/ class Data implements DataInterface, ArrayAccess { private const DELIMITERS = ['.', '/']; /** * Internal representation of data data * * @var array */ protected $data; /** * Constructor * * @param array $data */ public function __construct(array $data = []) { $this->data = $data; } /** * {@inheritdoc} */ public function append(string $key, $value = null): void { $currentValue =& $this->data; $keyPath = self::keyToPathArray($key); $endKey = array_pop($keyPath); foreach ($keyPath as $currentKey) { if (! isset($currentValue[$currentKey])) { $currentValue[$currentKey] = []; } $currentValue =& $currentValue[$currentKey]; } if (!isset($currentValue[$endKey])) { $currentValue[$endKey] = []; } if (!is_array($currentValue[$endKey])) { // Promote this key to an array. // TODO: Is this really what we want to do? $currentValue[$endKey] = [$currentValue[$endKey]]; } $currentValue[$endKey][] = $value; } /** * {@inheritdoc} */ public function set(string $key, $value = null): void { $currentValue =& $this->data; $keyPath = self::keyToPathArray($key); $endKey = array_pop($keyPath); foreach ($keyPath as $currentKey) { if (!isset($currentValue[$currentKey])) { $currentValue[$currentKey] = []; } if (!is_array($currentValue[$currentKey])) { throw new DataException(sprintf('Key path "%s" within "%s" cannot be indexed into (is not an array)', $currentKey, self::formatPath($key))); } $currentValue =& $currentValue[$currentKey]; } $currentValue[$endKey] = $value; } /** * {@inheritdoc} */ public function remove(string $key): void { $currentValue =& $this->data; $keyPath = self::keyToPathArray($key); $endKey = array_pop($keyPath); foreach ($keyPath as $currentKey) { if (!isset($currentValue[$currentKey])) { return; } $currentValue =& $currentValue[$currentKey]; } unset($currentValue[$endKey]); } /** * {@inheritdoc} * * @psalm-mutation-free */ public function get(string $key, $default = null) { /** @psalm-suppress ImpureFunctionCall */ $hasDefault = \func_num_args() > 1; $currentValue = $this->data; $keyPath = self::keyToPathArray($key); foreach ($keyPath as $currentKey) { if (!is_array($currentValue) || !array_key_exists($currentKey, $currentValue)) { if ($hasDefault) { return $default; } throw new MissingPathException($key, sprintf('No data exists at the given path: "%s"', self::formatPath($keyPath))); } $currentValue = $currentValue[$currentKey]; } return $currentValue === null ? $default : $currentValue; } /** * {@inheritdoc} * * @psalm-mutation-free */ public function has(string $key): bool { $currentValue = $this->data; foreach (self::keyToPathArray($key) as $currentKey) { if ( !is_array($currentValue) || !array_key_exists($currentKey, $currentValue) ) { return false; } $currentValue = $currentValue[$currentKey]; } return true; } /** * {@inheritdoc} * * @psalm-mutation-free */ public function getData(string $key): DataInterface { $value = $this->get($key); if (is_array($value) && Util::isAssoc($value)) { return new Data($value); } throw new DataException(sprintf('Value at "%s" could not be represented as a DataInterface', self::formatPath($key))); } /** * {@inheritdoc} */ public function import(array $data, int $mode = self::REPLACE): void { $this->data = Util::mergeAssocArray($this->data, $data, $mode); } /** * {@inheritdoc} */ public function importData(DataInterface $data, int $mode = self::REPLACE): void { $this->import($data->export(), $mode); } /** * {@inheritdoc} * * @psalm-mutation-free */ public function export(): array { return $this->data; } /** * {@inheritdoc} * * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->has($key); } /** * {@inheritdoc} * * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->get($key, null); } /** * {@inheritdoc} * * @param string $key * @param mixed $value * * @return void */ #[\ReturnTypeWillChange] public function offsetSet($key, $value) { $this->set($key, $value); } /** * {@inheritdoc} * * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($key) { $this->remove($key); } /** * @param string $path * * @return string[] * * @psalm-return non-empty-list * * @psalm-pure */ protected static function keyToPathArray(string $path): array { if (\strlen($path) === 0) { throw new InvalidPathException('Path cannot be an empty string'); } $path = \str_replace(self::DELIMITERS, '.', $path); return \explode('.', $path); } /** * @param string|string[] $path * * @return string * * @psalm-pure */ protected static function formatPath($path): string { if (is_string($path)) { $path = self::keyToPathArray($path); } return implode(' ยป ', $path); } } __halt_compiler();----SIGNATURE:----tCrZK/6x7zGjaI2stnt80bPVXulAH3Gv9rTm+pJ8mnpDhYtlM8Z84JJMoYAd+lWfMZznDSZw5CtHEYUW+gJALjLthUCgQibADihatbfdBw0KUp5bpK+I3Hp8Lhsjn6OQ4qjtxYnztX2ZNYjTmEwe/tl8do96SLBPb9DkKR9nEBBqF6gkRamFsEPDUSBfHaG+K7qn8Gkfr+7U15kzSuzGTi8HvDJxMvORrqjPV7SDvDm9V7xcDp+UplSF2Wdkt3Y9r0+yD1bfKd2UeE0bwzomTeLoDJcw4K4iLjzZe4+gb9Wkw6FCRJ9dpq2Lob9sZ576QdSqPlkS4MoQP6dURzuGiVN6IproIyf5jICx/0v2eYCHpkKPIEHfCFaWwvYdT1zD+nixZLkCCh2GLYpBk1UEq+a0WpY0onXyb05v1zjAhsjWcjysUVGFhwnFo0VNNOKNT+Vb4nyuh2mkLOwLl1b4ECqxvL+rkO5iu7NSt2i3XcGYMOns2E+KfxXl+Ygpfi8NyqNMHCimwb//QE+0gNLkzx5Zl6rj8Y5JQCdQ+fQeuz0vkbE51XdoM460nE5oU2FokVMfz2Yyu3RahlKG7O1kma1d6b5DSMsAWiPiVP1FQmV9VYFOq0gLS/WRm64M9sSCpmn6jGYg2ee8wABWtLyS1LlRQrkwwkHpXoOzOo7FETc=----ATTACHMENT:----NTk1MTg0NjU2MTIwMDQyNSAzMjgwNjA3MzYxMzA5NDYgNjAzMzc0MTkwOTIzODk5MA==