118 lines
2.6 KiB
PHP
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;
|
|
}
|
|
}
|