Skip to content

Commit

Permalink
Implement native Nette Container adapter for future compatibility.
Browse files Browse the repository at this point in the history
  • Loading branch information
janbarasek committed Sep 10, 2022
1 parent 222c25e commit 31c09b2
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 14 deletions.
3 changes: 1 addition & 2 deletions src/ApiExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ public function beforeCompile(): void
foreach ($endpointServices as $endpointService) {
$builder->addDefinition($this->prefix('endpoint') . '.' . str_replace('\\', '.', $endpointService))
->setFactory($endpointService)
->addTag('structured-api-endpoint')
->addSetup('?->injectContainer($this)', ['@self']);
->addTag('structured-api-endpoint');
}

$builder->addDefinition($this->prefix('convention'))
Expand Down
14 changes: 8 additions & 6 deletions src/ApiManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
use Baraja\ServiceMethodInvoker;
use Baraja\ServiceMethodInvoker\ProjectEntityRepository;
use Baraja\StructuredApi\Entity\Convention;
use Baraja\StructuredApi\Middleware\Container;
use Baraja\StructuredApi\Middleware\MatchExtension;
use Baraja\StructuredApi\Tracy\Panel;
use Baraja\Url\Url;
use Nette\DI\Container;
use Nette\DI\Container as NetteContainer;
use Nette\Http\Request;
use Nette\Http\Response as HttpResponse;
use Tracy\Debugger;
Expand All @@ -23,6 +24,8 @@ final class ApiManager
{
private Serializer $serializer;

private Container $container;

/** @var array<string, class-string> (endpointPath => endpointType) */
private array $endpoints;

Expand All @@ -35,13 +38,14 @@ final class ApiManager
*/
public function __construct(
array $endpoints,
private Container $container,
NetteContainer $netteContainer,
private Request $request,
private HttpResponse $response,
private Convention $convention,
private ?ProjectEntityRepository $projectEntityRepository = null,
) {
$this->serializer = new Serializer($convention);
$this->container = new Container($netteContainer);
$this->endpoints = $endpoints;
}

Expand Down Expand Up @@ -144,15 +148,13 @@ public function getEndpoints(): array
/**
* Create new API endpoint instance with all injected dependencies.
*
* @param class-string $className
* @param array<string|int, mixed> $params
* @internal
*/
public function getEndpointService(string $className, array $params): Endpoint
{
/** @phpstan-ignore-next-line */
$endpoint = $this->container->getByType($className);
MetaDataManager::endpointInjectDependencies($endpoint, $this->container);
assert($endpoint instanceof Endpoint);
$endpoint = $this->container->getEndpoint($className);
$endpoint->setConvention($this->convention);

$createReflection = static function (object $class, string $propertyName): ?\ReflectionProperty {
Expand Down
6 changes: 4 additions & 2 deletions src/Endpoint/BaseEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

use Baraja\Localization\Localization;
use Baraja\StructuredApi\Entity\Convention;
use Baraja\StructuredApi\Middleware\Container;
use Baraja\StructuredApi\Response\Status\ErrorResponse;
use Baraja\StructuredApi\Response\Status\OkResponse;
use Baraja\StructuredApi\Response\Status\StatusResponse;
use Baraja\StructuredApi\Response\Status\SuccessResponse;
use Nette\Caching\Cache;
use Nette\Caching\Storage;
use Nette\DI\Container;
use Nette\Http\Request;
use Nette\Localization\Translator;
use Nette\Security\Authorizator;
Expand Down Expand Up @@ -294,7 +294,9 @@ final public function startupCheck(): void

final public function saveState(): void
{
$this->onSaveState($this);
foreach ($this->onSaveState as $saveState) {
$saveState($this);
}
}


Expand Down
18 changes: 14 additions & 4 deletions src/MetaDataManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Baraja\StructuredApi;


use Nette\DI\Container;
use Baraja\StructuredApi\Middleware\Container;
use Nette\DI\Extensions\InjectExtension;
use Nette\Loaders\RobotLoader;

Expand Down Expand Up @@ -68,13 +68,25 @@ public static function createEndpointServices(): array

public static function endpointInjectDependencies(Endpoint $endpoint, Container $container): void
{
if ($endpoint instanceof BaseEndpoint) {
$endpoint->injectContainer($container);
}
$injectProperties = InjectExtension::getInjectProperties($endpoint::class);
if ($injectProperties === []) {
return;
}

$ref = new \ReflectionClass($endpoint);
foreach ($injectProperties as $property => $service) {
if ($service === 'Nette\DI\Container') {
throw new \LogicException(
sprintf(
'%s [property "%s"]: Injecting the entire Container is not an allowed operation. Please use DIC.',
$endpoint::class,
$property,
),
);
}
trigger_error(
sprintf(
'%s: Property "%s" with @inject annotation or #[Inject] attribute is deprecated design pattern. '
Expand All @@ -88,9 +100,7 @@ public static function endpointInjectDependencies(Endpoint $endpoint, Container
$p->setAccessible(true);
$p->setValue(
$endpoint,
$service === Container::class
? $container
: $container->getByType($service), // @phpstan-ignore-line
$container->getByType($service), // @phpstan-ignore-line
);
}
}
Expand Down
66 changes: 66 additions & 0 deletions src/Middleware/Container.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Baraja\StructuredApi\Middleware;


use Baraja\StructuredApi\Endpoint;
use Baraja\StructuredApi\MetaDataManager;
use Nette\DI\Container as NetteContainer;

final class Container
{
public function __construct(
private NetteContainer $container,
) {
}


public function setContainer(NetteContainer $container): void
{
$this->container = $container;
}


/**
* @template T
* @param class-string<T> $type
* @return ?T
*/
public function getByType(string $type): object
{
return $this->container->getByType($type);
}


/**
* @param class-string $className
*/
public function getEndpoint(string $className): Endpoint
{
$endpoint = $this->getByType($className);
if (!$endpoint instanceof Endpoint) {
throw new \LogicException(
sprintf(
'Service "%s" must be instance of "%s", but type "%s" given.',
$className,
Endpoint::class,
$endpoint::class,
),
);
}
MetaDataManager::endpointInjectDependencies($endpoint, $this);

return $endpoint;
}


/**
* @return array<string, mixed>
*/
public function getParameters(): array
{
return $this->container->getParameters();
}
}

0 comments on commit 31c09b2

Please sign in to comment.