composer update

This commit is contained in:
isUnknown 2025-09-23 08:15:07 +02:00
parent 0b3c362c5e
commit a1f0701630
142 changed files with 4530 additions and 1195 deletions

View file

@ -0,0 +1,69 @@
<?php
namespace Kirby\Query\Runners;
use Closure;
use Kirby\Query\Parser\Parser;
use Kirby\Query\Query;
use Kirby\Query\Visitors\DefaultVisitor;
/**
* Runner that caches the AST in memory
*
* @package Kirby Query
* @author Roman Steiner <roman@toastlab.ch>
* @link https://getkirby.com
* @license https://opensource.org/licenses/MIT
* @since 5.1.0
* @unstable
*/
class DefaultRunner extends Runner
{
/**
* Creates a runner for the Query
*/
public static function for(Query $query): static
{
return new static(
global: $query::$entries,
interceptor: $query->intercept(...),
cache: $query::$cache
);
}
protected function resolver(string $query): Closure
{
// Load closure from cache
if (isset($this->cache[$query]) === true) {
return $this->cache[$query];
}
// Parse query as AST
$parser = new Parser($query);
$ast = $parser->parse();
// Cache closure to resolve same query
return $this->cache[$query] = fn (array $context) => $ast->resolve(
new DefaultVisitor($this->global, $context, $this->interceptor)
);
}
/**
* Executes a query within a given data context
*
* @param array $context Optional variables to be passed to the query
*
* @throws \Exception when query is invalid or executor not callable
*/
public function run(string $query, array $context = []): mixed
{
// Try resolving query directly from data context or global functions
$entry = Scope::get($query, $context, $this->global, false);
if ($entry !== false) {
return $entry;
}
return $this->resolver($query)($context);
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Kirby\Query\Runners;
use ArrayAccess;
use Closure;
use Kirby\Query\Query;
/**
* @package Kirby Query
* @author Roman Steiner <roman@toastlab.ch>,
* Nico Hoffmann <nico@getkirby.com>
* @link https://getkirby.com
* @license https://opensource.org/licenses/MIT
* @since 5.1.0
* @unstable
*/
abstract class Runner
{
/**
* @param array $global Allowed global function closures
*/
public function __construct(
public array $global = [],
protected Closure|null $interceptor = null,
protected ArrayAccess|array &$cache = [],
) {
}
/**
* Creates a runner instance for the Query
*/
abstract public static function for(Query $query): static;
/**
* Executes a query within a given data context
*
* @param array $context Optional variables to be passed to the query
*
* @throws \Exception when query is invalid or executor not callable
*/
abstract public function run(string $query, array $context = []): mixed;
}

View file

@ -0,0 +1,94 @@
<?php
namespace Kirby\Query\Runners;
use Closure;
use Exception;
/**
* Helper class to execute logic during runtime
*
* @package Kirby Query
* @author Roman Steiner <roman@toastlab.ch>
* @link https://getkirby.com
* @license https://opensource.org/licenses/MIT
* @since 5.1.0
* @unstable
*/
class Scope
{
/**
* Access the key on the object/array during runtime
*/
public static function access(
array|object|null $object,
string|int $key,
bool $nullSafe = false,
...$arguments
): mixed {
if ($object === null && $nullSafe === true) {
return null;
}
if (is_array($object) === true) {
if ($item = $object[$key] ?? $object[(string)$key] ?? null) {
if ($arguments) {
return $item(...$arguments);
}
if ($item instanceof Closure) {
return $item();
}
}
return $item;
}
if (is_object($object) === true) {
$key = (string)$key;
if (
method_exists($object, $key) === true ||
method_exists($object, '__call') === true
) {
return $object->$key(...$arguments);
}
return $object->$key ?? null;
}
throw new Exception("Cannot access \"$key\" on " . gettype($object));
}
/**
* Resolves a mapping from global context or functions during runtime
*/
public static function get(
string $name,
array $context = [],
array $global = [],
false|null $fallback = null
): mixed {
// What looks like a variable might actually be a global function
// but if there is a variable with the same name,
// the variable takes precedence
if (isset($context[$name]) === true) {
if ($context[$name] instanceof Closure) {
return $context[$name]();
}
return $context[$name];
}
if (isset($global[$name]) === true) {
return $global[$name]();
}
// Alias to access the global context
if ($name === 'this') {
return $context;
}
return $fallback;
}
}