Git viewing holonet/common / bf853db1b818caac37856cf8b80e1e429fd13982 / src/collection/Registry.php


Filter

      <?php
/**
 * This file is part of the hdev common library package
 * (c) Matthias Lantsch.
 *
 * class file for the Registry class
 *
 * @license http://www.wtfpl.net/ Do what the fuck you want Public License
 * @author  Matthias Lantsch <[email protected]>
 */

namespace holonet\common\collection;

use ArrayAccess;

/**
 * Registry is a key value storage collection class that allows for multilevel keys and placeholders
 *  e.g. toplevel.lowerlevel => $data['toplevel']['lowerlevel']
 *  e.g. "%app.name%-test" => $data['app']['name'] . "-test".
 */
class Registry implements ArrayAccess {
	/**
	 * @var array Multilevel array with key=value pairs
	 */
	private $data = array();

	/**
	 * Clear all values from the registry.
	 */
	public function clear(): void {
		$this->data = array();
	}

	/**
	 * Return the value for a certain key or a default.
	 * @param mixed|null $default
	 * @return mixed value
	 */
	public function get(string $key, $default = null) {
		return $this->offsetGet($key) ?? $default;
	}

	/**
	 * If $replace is given and false, no place holders will be replaced.
	 */
	public function getAll(bool $replace = true): array {
		return $replace ? $this->replacePlaceholder($this->data) : $this->data;
	}

	/**
	 * Check if the registry has a certain key.
	 */
	public function has(string $key): bool {
		return $this->offsetExists($key);
	}

	/**
	 * Whether an offset exists.
	 * @see http://php.net/manual/en/arrayaccess.offsetexists.php
	 * @param string $offset
	 * @return bool true on success or false on failure
	 */
	public function offsetExists($offset): bool {
		$parts = explode('.', $offset);
		$position = $this->data;
		foreach ($parts as $sublevel) {
			if (!isset($position[$sublevel])) {
				return false;
			}
			$position = $position[$sublevel];
		}

		return true;
	}

	/**
	 * Offset to retrieve.
	 * @see http://php.net/manual/en/arrayaccess.offsetget.php
	 * @param string $offset
	 * @return mixed|null can return all value types or null if not found
	 */
	public function offsetGet($offset) {
		$parts = explode('.', $offset);
		$position = $this->data;

		foreach ($parts as $sublevel) {
			if (!isset($position[$sublevel])) {
				return null;
			}
			$position = $position[$sublevel];
		}

		return $this->replacePlaceholder($position);
	}

	/**
	 * Offset to set.
	 * @see http://php.net/manual/en/arrayaccess.offsetset.php
	 * @param string $offset
	 * @param $value
	 */
	public function offsetSet($offset, $value): void {
		$parts = explode('.', $offset);
		$position = &$this->data;
		foreach ($parts as $key => $sublevel) {
			if ($key === array_key_last($parts)) {
				$position[$sublevel] = $value;
			} else {
				if (!isset($position[$sublevel])) {
					$position[$sublevel] = array();
				}
				$position = &$position[$sublevel];
			}
		}
	}

	/**
	 * Offset to unset.
	 * @see http://php.net/manual/en/arrayaccess.offsetunset.php
	 * @param string $offset
	 */
	public function offsetUnset($offset): void {
		$parts = explode('.', $offset);
		$position = &$this->data;
		foreach ($parts as $key => $sublevel) {
			if (!isset($position[$sublevel])) {
				return;
			}

			if ($key === array_key_last($parts)) {
				unset($position[$sublevel]);
			} else {
				$position = &$position[$sublevel];
			}
		}
	}

	/**
	 * Set the value for a certain key.
	 * @param mixed $value The value to be set
	 */
	public function set(string $key, $value): void {
		$this->offsetSet($key, $value);
	}

	public function setAll(array $data): void {
		$this->data = array_replace_recursive($this->data, $data);
	}

	/**
	 * Clear the value for a certain key.
	 */
	public function unset(string $key): void {
		$this->offsetUnset($key);
	}

	/**
	 * sreplaces place holders in values of the registry
	 * recursively calls this function if we are talking an array.
	 * @param mixed $position The value to be searched for placeholders
	 * @return mixed the updated value
	 */
	private function replacePlaceholder($position) {
		if (is_string($position) && mb_strpos($position, '%') !== false) {
			$matches = array();
			preg_match_all('/%([^%]+)%/', $position, $matches, PREG_SET_ORDER);
			foreach ($matches as $placeholderPair) {
				//if the placeholder is a value in the registry, replace it, otherwise leave it with the % signs
				$position = str_replace($placeholderPair[0], $this->get($placeholderPair[1], $placeholderPair[0]), $position);
			}
		} elseif (is_array($position)) {
			foreach ($position as $key => $val) {
				$position[$key] = $this->replacePlaceholder($val);
			}
		}

		return $position;
	}
}