220 lines
5.5 KiB
PHP
220 lines
5.5 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is a part of dflydev/dot-access-data.
|
|
*
|
|
* (c) Dragonfly Development Inc.
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Dflydev\DotAccessData;
|
|
|
|
class Data implements DataInterface
|
|
{
|
|
/**
|
|
* Internal representation of data data
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $data;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param array|null $data
|
|
*/
|
|
public function __construct(array $data = null)
|
|
{
|
|
$this->data = $data ?: array();
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function append($key, $value = null)
|
|
{
|
|
if (0 == strlen($key)) {
|
|
throw new \RuntimeException("Key cannot be an empty string");
|
|
}
|
|
|
|
$currentValue =& $this->data;
|
|
$keyPath = explode('.', $key);
|
|
|
|
if (1 == count($keyPath)) {
|
|
if (!isset($currentValue[$key])) {
|
|
$currentValue[$key] = array();
|
|
}
|
|
if (!is_array($currentValue[$key])) {
|
|
// Promote this key to an array.
|
|
// TODO: Is this really what we want to do?
|
|
$currentValue[$key] = array($currentValue[$key]);
|
|
}
|
|
$currentValue[$key][] = $value;
|
|
|
|
return;
|
|
}
|
|
|
|
$endKey = array_pop($keyPath);
|
|
for ( $i = 0; $i < count($keyPath); $i++ ) {
|
|
$currentKey =& $keyPath[$i];
|
|
if ( ! isset($currentValue[$currentKey]) ) {
|
|
$currentValue[$currentKey] = array();
|
|
}
|
|
$currentValue =& $currentValue[$currentKey];
|
|
}
|
|
|
|
if (!isset($currentValue[$endKey])) {
|
|
$currentValue[$endKey] = array();
|
|
}
|
|
if (!is_array($currentValue[$endKey])) {
|
|
$currentValue[$endKey] = array($currentValue[$endKey]);
|
|
}
|
|
// Promote this key to an array.
|
|
// TODO: Is this really what we want to do?
|
|
$currentValue[$endKey][] = $value;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function set($key, $value = null)
|
|
{
|
|
if (0 == strlen($key)) {
|
|
throw new \RuntimeException("Key cannot be an empty string");
|
|
}
|
|
|
|
$currentValue =& $this->data;
|
|
$keyPath = explode('.', $key);
|
|
|
|
if (1 == count($keyPath)) {
|
|
$currentValue[$key] = $value;
|
|
|
|
return;
|
|
}
|
|
|
|
$endKey = array_pop($keyPath);
|
|
for ( $i = 0; $i < count($keyPath); $i++ ) {
|
|
$currentKey =& $keyPath[$i];
|
|
if (!isset($currentValue[$currentKey])) {
|
|
$currentValue[$currentKey] = array();
|
|
}
|
|
if (!is_array($currentValue[$currentKey])) {
|
|
throw new \RuntimeException("Key path at $currentKey of $key cannot be indexed into (is not an array)");
|
|
}
|
|
$currentValue =& $currentValue[$currentKey];
|
|
}
|
|
$currentValue[$endKey] = $value;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function remove($key)
|
|
{
|
|
if (0 == strlen($key)) {
|
|
throw new \RuntimeException("Key cannot be an empty string");
|
|
}
|
|
|
|
$currentValue =& $this->data;
|
|
$keyPath = explode('.', $key);
|
|
|
|
if (1 == count($keyPath)) {
|
|
unset($currentValue[$key]);
|
|
|
|
return;
|
|
}
|
|
|
|
$endKey = array_pop($keyPath);
|
|
for ( $i = 0; $i < count($keyPath); $i++ ) {
|
|
$currentKey =& $keyPath[$i];
|
|
if (!isset($currentValue[$currentKey])) {
|
|
return;
|
|
}
|
|
$currentValue =& $currentValue[$currentKey];
|
|
}
|
|
unset($currentValue[$endKey]);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function get($key, $default = null)
|
|
{
|
|
$currentValue = $this->data;
|
|
$keyPath = explode('.', $key);
|
|
|
|
for ( $i = 0; $i < count($keyPath); $i++ ) {
|
|
$currentKey = $keyPath[$i];
|
|
if (!isset($currentValue[$currentKey]) ) {
|
|
return $default;
|
|
}
|
|
if (!is_array($currentValue)) {
|
|
return $default;
|
|
}
|
|
$currentValue = $currentValue[$currentKey];
|
|
}
|
|
|
|
return $currentValue === null ? $default : $currentValue;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function has($key)
|
|
{
|
|
$currentValue = &$this->data;
|
|
$keyPath = explode('.', $key);
|
|
|
|
for ( $i = 0; $i < count($keyPath); $i++ ) {
|
|
$currentKey = $keyPath[$i];
|
|
if (
|
|
!is_array($currentValue) ||
|
|
!array_key_exists($currentKey, $currentValue)
|
|
) {
|
|
return false;
|
|
}
|
|
$currentValue = &$currentValue[$currentKey];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function getData($key)
|
|
{
|
|
$value = $this->get($key);
|
|
if (is_array($value) && Util::isAssoc($value)) {
|
|
return new Data($value);
|
|
}
|
|
|
|
throw new \RuntimeException("Value at '$key' could not be represented as a DataInterface");
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function import(array $data, $clobber = true)
|
|
{
|
|
$this->data = Util::mergeAssocArray($this->data, $data, $clobber);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function importData(DataInterface $data, $clobber = true)
|
|
{
|
|
$this->import($data->export(), $clobber);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function export()
|
|
{
|
|
return $this->data;
|
|
}
|
|
}
|