Skip to content

Commit

Permalink
Move more logic into Runtime class
Browse files Browse the repository at this point in the history
  • Loading branch information
distantnative committed Jan 19, 2025
1 parent f4aea63 commit f935ea7
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 31 deletions.
32 changes: 28 additions & 4 deletions src/Query/Runners/Runtime.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
*/
class Runtime
{
/**
* 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 ($nullSafe === true && $object === null) {
if ($object === null && $nullSafe === true) {
return null;
}

Expand All @@ -42,9 +45,7 @@ public static function access(
}

if (is_object($object) === true) {
if (is_int($key) === true) {
$key = (string)$key;
}
$key = (string)$key;

if (
method_exists($object, $key) === true ||
Expand All @@ -58,4 +59,27 @@ public static function access(

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 $functions = []
): mixed {
if ($result = $context[$name] ?? null) {
if ($result instanceof Closure) {
return $result();
}

return $result;
}

if ($function = $functions[$name] ?? null) {
return $function();
}

return null;
}
}
12 changes: 3 additions & 9 deletions src/Query/Visitors/Transpiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,9 @@ public function variable(string $name): string
}

if (isset($this->mappings[$key]) === false) {
$name = var_export($name, true);
$this->mappings[$key] = <<<PHP
match(true) {
isset(\$context[$name]) && \$context[$name] instanceof Closure => \$context[$name](),
isset(\$context[$name]) => \$context[$name],
isset(\$functions[$name]) => \$functions[$name](),
default => null
}
PHP;
$name = var_export($name, true);
$this->uses[Runtime::class] = true;
$this->mappings[$key] = "Runtime::get($name, \$context, \$functions)";
}

return $key;
Expand Down
102 changes: 102 additions & 0 deletions tests/Query/Runners/RuntimeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace Kirby\Query\Runners;

use Exception;

class FooObj {
public string $bax = 'qox';

public function print(string $string = 'bar'): string
{
return $string;
}
}

/**
* @coversDefaultClass \Kirby\Query\Runners\Runtime
*/
class RuntimeTest extends TestCase
{
/**
* @covers ::access
*/
public function testAccessWithArray(): void
{
$array = [
'bar' => 'bar',
'bax' => fn (string $string = 'bax') => $string
];

$result = Runtime::access($array, 'bar');
$this->assertSame('bar', $result);

$result = Runtime::access($array, 'bax');
$this->assertSame('bax', $result);

$result = Runtime::access($array, 'bax', false, 'custom');
$this->assertSame('custom', $result);

$result = Runtime::access($array, 'fox');
$this->assertNull($result);
}

/**
* @covers ::access
*/
public function testAccessWithObject(): void
{
$obj = new FooObj;
$result = Runtime::access($obj, 'print');
$this->assertSame('bar', $result);

$result = Runtime::access($obj, 'print', false, 'custom');
$this->assertSame('custom', $result);

$result = Runtime::access($obj, 'bax');
$this->assertSame('qox', $result);

$result = Runtime::access($obj, 'fox');
$this->assertNull($result);
}

/**
* @covers ::access
*/
public function testAccessWithNullSafe(): void
{
$result = Runtime::access(null, 'bar', true);
$this->assertNull($result);
}

/**
* @covers ::access
*/
public function testAccessWithoutNullSafe(): void
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Cannot access "bar" on NULL');
Runtime::access(null, 'bar', false);
}

/**
* @covers ::get
*/
public function testGet(): void
{
$context = ['foo' => 'bar', 'qox' => fn () => 'bax'];
$functions = ['fox' => fn () => 'fax'];

$result = Runtime::get('foo', $context);
$this->assertSame('bar', $result);

$result = Runtime::get('qox', $context);
$this->assertSame('bax', $result);

$result = Runtime::get('fox', $context);
$this->assertNull($result);

$result = Runtime::get('fox', $context, $functions);
$this->assertSame('fax', $result);
}
}
31 changes: 13 additions & 18 deletions tests/Query/Runners/TranspiledTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,24 +92,19 @@ public function testRepresentation(): void
$visitor->mappings['$_foo'] = 'bar';
$runner = new Transpiled(root: static::TMP);
$representation = $runner->representation($visitor, $query, $parser->parse());
$this->assertSame(<<<EOT
<?php
use Kirby\Toolkit\Str;
use Kirby\Query\Runners\Runtime;
// $query
return function(array \$context, array \$functions, Closure \$intercept) {
\$_foo = bar;
\$_2375276105 = match(true) {
isset(\$context['user']) && \$context['user'] instanceof Closure => \$context['user'](),
isset(\$context['user']) => \$context['user'],
isset(\$functions['user']) => \$functions['user'](),
default => null
};
return Runtime::access((\$intercept(\$_2375276105)), 'add', false, 5.0);
};
EOT, $representation);
$this->assertSame(<<<PHP
<?php
use Kirby\Toolkit\Str;
use Kirby\Query\Runners\Runtime;
// $query
return function(array \$context, array \$functions, Closure \$intercept) {
\$_foo = bar;
\$_2375276105 = Runtime::get('user', \$context, \$functions);
return Runtime::access((\$intercept(\$_2375276105)), 'add', false, 5.0);
};
PHP, $representation);
}

/**
Expand Down

0 comments on commit f935ea7

Please sign in to comment.