diff options
| author | 2025-03-13 22:40:41 +0100 | |
|---|---|---|
| committer | 2025-03-13 22:40:41 +0100 | |
| commit | a7361a3e7cd335c8932deba88fe60e8f673c2d40 (patch) | |
| tree | bb4c007188d54897210f2a0539c2df0f438fb069 /app/Utils/dotNotationUtil.php | |
| parent | df545b513b1c43e54da5b023bf3fe01bf36ad013 (diff) | |
Implement JSON string concatenation with & operator (#7414)
Inspired by [JSONata syntax](https://docs.jsonata.org/expressions).
fix https://github.com/FreshRSS/FreshRSS/issues/6565
Diffstat (limited to 'app/Utils/dotNotationUtil.php')
| -rw-r--r-- | app/Utils/dotNotationUtil.php | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/app/Utils/dotNotationUtil.php b/app/Utils/dotNotationUtil.php index 77ae96c30..89b91bc5b 100644 --- a/app/Utils/dotNotationUtil.php +++ b/app/Utils/dotNotationUtil.php @@ -18,9 +18,39 @@ final class FreshRSS_dotNotation_Util return static::value($default); } /** @var \ArrayAccess<string,mixed>|array<string,mixed> $array */ - if (in_array($key, [null, '', '.', '$'], true)) { + if ($key === null) { return $array; } + $key = trim($key); + + if (in_array($key, ['', '.', '$'], true)) { + return $array; + } + + // If the key is a simple string, return the text + if (preg_match('/^(?P<delim>[\'"])(?P<text>[^&]*)(?P=delim)$/', $key, $matches)) { + $text = $matches['text']; + $text = str_replace('&', '&', $text); // Unescape `&` + return $text; + } + + // Escape `&` operator + $key = preg_replace_callback('/(?P<delim>[\'"])(?P<text>.*?)(?P=delim)/', + fn(array $matches): string => str_replace('&', '&', $matches[0]), + $key) ?? $key; + + // If the key contains string concatenations with `&`, process them + $concats = explode('&', $key); + if (count($concats) > 1) { + $text = ''; + foreach ($concats as $concat) { + $result = static::get($array, $concat, $default); + if (is_scalar($result)) { + $text .= (string)$result; + } + } + return $text; + } // Compatibility with brackets path such as `items[0].value` $key = preg_replace('/\[(\d+)\]/', '.$1', $key); |
