flatrr/src/SelfReferencingFlatArray.php

115 lines
3 KiB
PHP
Raw Normal View History

2018-08-17 21:02:50 +00:00
<?php
/* Flatrr | https://github.com/jobyone/flatrr | MIT License */
2021-09-13 16:52:13 +00:00
2018-08-17 22:09:45 +00:00
namespace Flatrr;
2018-08-17 21:02:50 +00:00
class SelfReferencingFlatArray extends FlatArray
{
2022-12-03 18:30:34 +00:00
/** @var array<string,string> */
2021-09-13 16:52:13 +00:00
protected $cache = [];
2022-12-03 18:30:34 +00:00
public function get(string $name = null, bool $raw = false, bool $unescape = true): mixed
2018-08-17 21:02:50 +00:00
{
$out = parent::get($name);
if ($raw) {
return $out;
}
$out = $this->filter($out);
if ($unescape) {
$out = $this->unescape($out);
}
return $out;
}
2022-12-03 18:30:34 +00:00
public function set(null|string $name, mixed $value): static
2020-06-23 03:32:03 +00:00
{
2021-09-13 16:52:13 +00:00
$this->cache = [];
2022-12-03 18:30:34 +00:00
$this->filter(parent::set($name, $value));
return $this;
2020-06-23 03:32:03 +00:00
}
2022-12-03 18:30:34 +00:00
public function pop(null|string $name): mixed
2020-06-23 03:32:03 +00:00
{
return $this->filter(parent::pop($name));
}
2022-12-03 18:30:34 +00:00
public function shift(null|string $name): mixed
2020-06-23 03:32:03 +00:00
{
return $this->filter(parent::shift($name));
}
public function current(): mixed
2020-06-23 03:32:03 +00:00
{
return $this->filter(parent::current());
}
2022-12-03 18:30:34 +00:00
protected function unescape(mixed $value): mixed
2018-08-17 21:02:50 +00:00
{
2020-06-23 03:32:03 +00:00
//map this function onto array values
if (is_array($value)) {
return array_map(
[$this, 'unescape'],
$value
);
2018-08-17 21:02:50 +00:00
}
//search/replace on string values
if (is_string($value)) {
//unescape references
$value = preg_replace(
2020-06-23 03:32:03 +00:00
'/\$\\\?\{([^\}\\\]+)\\\?\}/S',
2018-08-17 21:02:50 +00:00
'\${$1}',
$value
);
//return
return $value;
}
//fall back to just returning value, it's some other datatype
return $value;
}
/**
* Recursively replace ${var/name} type strings in string values with
*/
2022-12-03 18:30:34 +00:00
protected function filter(mixed $value): mixed
2018-08-17 21:02:50 +00:00
{
2020-06-22 23:19:41 +00:00
//map this function onto array values
if (is_array($value)) {
return array_map(
[$this, 'filter'],
$value
);
2018-08-17 21:02:50 +00:00
}
//search/replace on string values
2020-06-22 23:19:41 +00:00
if (is_string($value) && strpos($value, '${') !== false) {
2018-08-17 21:02:50 +00:00
//search for valid replacements
2021-09-13 16:52:13 +00:00
return $this->cache[$value] ??
($this->cache[$value] = preg_replace_callback(
//search for things like ${var/name}, escape with \ before last brace
'/\$\{([^\}]*[^\.\\\])\}/',
//replace match with value from $this if it exists
[$this, 'filter_regex'],
//applied to $value
$value
));
2018-08-17 21:02:50 +00:00
}
//fall back to just returning value, it's some other datatype
return $value;
}
2020-06-22 23:19:41 +00:00
2022-12-03 18:30:34 +00:00
/**
* @param array<int,null|string> $matches
* @return string
2022-12-03 18:30:34 +00:00
*/
protected function filter_regex(array $matches): string
2020-06-22 23:19:41 +00:00
{
2022-12-03 18:30:34 +00:00
$value = $this->get($matches[1], false, false);
if ($value !== null) {
2020-06-22 23:19:41 +00:00
if (!is_array($value)) {
return $value;
}
}
return $matches[0];
}
2018-08-17 21:02:50 +00:00
}