Skip to content

Commit

Permalink
Merge pull request #1084: Init Core Introspector
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Feb 21, 2024
2 parents 2f1f5ff + 8e75a9e commit dd46fbf
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/Core/src/Internal/Introspector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Spiral\Core\Internal;

use Psr\Container\ContainerInterface;
use Spiral\Core\Container;
use Spiral\Core\ContainerScope;
use Spiral\Core\Internal\Introspector\Accessor;

/**
* @internal
*/
final class Introspector
{
public static function scopeName(?ContainerInterface $container = null): ?string
{
return self::getAccessor($container)->scope->getScopeName();
}

/**
* Returns list of scope names starting from the current scope to the root scope.
*
* @return list<string|null>
*/
public static function scopeNames(?ContainerInterface $container = null): array
{
$scope = self::getAccessor($container)->scope;
$result = [];
do {
$result[] = $scope->getScopeName();
$scope = $scope->getParentScope();
} while ($scope !== null);

return $result;
}

/**
* @psalm-assert Container|null $container
*/
public static function getAccessor(?ContainerInterface $container = null): Accessor
{
if ($container !== null && !$container instanceof Container) {
throw new \InvalidArgumentException('Container must be an instance of ' . Container::class);
}

$container ??= ContainerScope::getContainer();

if (!$container instanceof Container) {
throw new \RuntimeException('Container is not available.');
}

return new Accessor($container);
}
}
41 changes: 41 additions & 0 deletions src/Core/src/Internal/Introspector/Accessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Spiral\Core\Internal\Introspector;

use Psr\Container\ContainerInterface;
use Spiral\Core\BinderInterface;
use Spiral\Core\Config;
use Spiral\Core\Container as PublicContainer;
use Spiral\Core\FactoryInterface;
use Spiral\Core\Internal;
use Spiral\Core\InvokerInterface;
use Spiral\Core\Options;
use Spiral\Core\ResolverInterface;

/**
* @internal
*
* @property-read Internal\State $state
* @property-read ResolverInterface|Internal\Resolver $resolver
* @property-read FactoryInterface|Internal\Factory $factory
* @property-read ContainerInterface|Internal\Container $container
* @property-read BinderInterface|Internal\Binder $binder
* @property-read InvokerInterface|Internal\Invoker $invoker
* @property-read Internal\Scope $scope
* @property-read Config $config
* @property-read Options $options
*/
final class Accessor
{
public function __construct(
public PublicContainer $publicContainer,
) {
}

public function __get(string $name): object
{
return (fn (PublicContainer $c): object => $c->$name)->call($this->publicContainer, $this->publicContainer);
}
}
42 changes: 42 additions & 0 deletions src/Core/tests/Internal/Introspector/CommonTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Spiral\Tests\Core\Internal\Introspector;

use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Spiral\Core\Container;
use Spiral\Core\Internal\Introspector;
use Spiral\Core\Scope;

final class CommonTest extends TestCase
{
public function testScopeName(): void
{
$container = new Container();

self::assertSame('root', Introspector::scopeName($container));

$container->invoke(static fn() => self::assertSame('root', Introspector::scopeName()));

$container->runScope(new Scope('test'), function (ContainerInterface $container): void {
self::assertSame('test', Introspector::scopeName($container));
self::assertSame('test', Introspector::scopeName());
});
}

public function testScopeNames(): void
{
$container = new Container();

$container->runScope(new Scope('test'), function (Container $c): void {
$c->runScope(new Scope(), function (Container $c): void {
$c->runScope(new Scope('bar'), function (Container $c): void {
self::assertSame(['bar', null, 'test', 'root'], Introspector::scopeNames($c));
self::assertSame(['bar', null, 'test', 'root'], Introspector::scopeNames());
});
});
});
}
}

0 comments on commit dd46fbf

Please sign in to comment.