Files
lichterei-web/kirby/src/Query/Argument.php
Bastian Allgeier 7928c28702 Upgrade to 3.9.6
2023-07-27 12:08:43 +02:00

118 lines
2.6 KiB
PHP

<?php
namespace Kirby\Query;
use Closure;
use Kirby\Toolkit\Str;
/**
* The Argument class represents a single
* parameter passed to a method in a chained query
*
* @package Kirby Query
* @author Nico Hoffmann <nico@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*/
class Argument
{
public function __construct(
public mixed $value
) {
}
/**
* Sanitizes argument string into actual
* PHP type/object as new Argument instance
*/
public static function factory(string $argument): static
{
$argument = trim($argument);
// remove grouping parantheses
if (
Str::startsWith($argument, '(') &&
Str::endsWith($argument, ')')
) {
$argument = trim(substr($argument, 1, -1));
}
// string with single quotes
if (
Str::startsWith($argument, "'") &&
Str::endsWith($argument, "'")
) {
$string = substr($argument, 1, -1);
$string = str_replace("\'", "'", $string);
return new static($string);
}
// string with double quotes
if (
Str::startsWith($argument, '"') &&
Str::endsWith($argument, '"')
) {
$string = substr($argument, 1, -1);
$string = str_replace('\"', '"', $string);
return new static($string);
}
// array: split and recursive sanitizing
if (
Str::startsWith($argument, '[') &&
Str::endsWith($argument, ']')
) {
$array = substr($argument, 1, -1);
$array = Arguments::factory($array);
return new static($array);
}
// numeric
if (is_numeric($argument) === true) {
if (strpos($argument, '.') === false) {
return new static((int)$argument);
}
return new static((float)$argument);
}
// Closure
if (Str::startsWith($argument, '() =>')) {
$query = Str::after($argument, '() =>');
$query = trim($query);
return new static(fn () => $query);
}
return new static(match ($argument) {
'null' => null,
'true' => true,
'false' => false,
// resolve parameter for objects and methods itself
default => new Query($argument)
});
}
/**
* Return the argument value and
* resolves nested objects to scaler types
*/
public function resolve(array|object $data = []): mixed
{
// don't resolve the Closure immediately, instead
// resolve it to the sub-query and create a new Closure
// that resolves the sub-query with the same data set once called
if ($this->value instanceof Closure) {
$query = ($this->value)();
return fn () => static::factory($query)->resolve($data);
}
if (is_object($this->value) === true) {
return $this->value->resolve($data);
}
return $this->value;
}
}