Skip to content

Commit

Permalink
Proxy any calls to the decorated object (#272)
Browse files Browse the repository at this point in the history
* Proxy any calls to the decorated object

* Apply fixes from StyleCI

* Add type

* Proxy calls for var-dumper proxy

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
xepozz and StyleCIBot authored Sep 10, 2024
1 parent 3c60409 commit 7e1c705
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 20 deletions.
16 changes: 10 additions & 6 deletions src/Collector/ContainerInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
use Psr\Container\ContainerInterface;
use Yiisoft\Proxy\ProxyManager;
use Yiisoft\Proxy\ProxyTrait;
use Yiisoft\Yii\Debug\ProxyDecoratedCalls;

use function is_callable;
use function is_object;
use function is_string;

final class ContainerInterfaceProxy implements ContainerInterface
{
use ProxyDecoratedCalls;
use ProxyLogTrait;
use ProxyTrait;

Expand All @@ -30,8 +32,10 @@ final class ContainerInterfaceProxy implements ContainerInterface

private array $serviceProxy = [];

public function __construct(protected ContainerInterface $container, ContainerProxyConfig $config)
{
public function __construct(
protected ContainerInterface $decorated,
ContainerProxyConfig $config,
) {
$this->config = $config;
$this->proxyManager = new ProxyManager($this->config->getProxyCachePath());
}
Expand All @@ -53,7 +57,7 @@ public function get($id): mixed
} catch (ContainerExceptionInterface $e) {
$this->repeatError($e);
} finally {
$this->logProxy(ContainerInterface::class, $this->container, 'get', [$id], $instance, $timeStart);
$this->logProxy(ContainerInterface::class, $this->decorated, 'get', [$id], $instance, $timeStart);
}

if (
Expand All @@ -79,7 +83,7 @@ private function getInstance(string $id): mixed
return $this;
}

return $this->container->get($id);
return $this->decorated->get($id);
}

private function isDecorated(string $service): bool
Expand Down Expand Up @@ -196,11 +200,11 @@ public function has($id): bool
$result = null;

try {
$result = $this->container->has($id);
$result = $this->decorated->has($id);
} catch (ContainerExceptionInterface $e) {
$this->repeatError($e);
} finally {
$this->logProxy(ContainerInterface::class, $this->container, 'has', [$id], $result, $timeStart);
$this->logProxy(ContainerInterface::class, $this->decorated, 'has', [$id], $result, $timeStart);
}

return (bool)$result;
Expand Down
7 changes: 5 additions & 2 deletions src/Collector/EventDispatcherInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
namespace Yiisoft\Yii\Debug\Collector;

use Psr\EventDispatcher\EventDispatcherInterface;
use Yiisoft\Yii\Debug\ProxyDecoratedCalls;

final class EventDispatcherInterfaceProxy implements EventDispatcherInterface
{
use ProxyDecoratedCalls;

public function __construct(
private readonly EventDispatcherInterface $dispatcher,
private readonly EventDispatcherInterface $decorated,
private readonly EventCollector $collector
) {
}
Expand All @@ -21,6 +24,6 @@ public function dispatch(object $event): object

$this->collector->collect($event, $callStack['file'] . ':' . $callStack['line']);

return $this->dispatcher->dispatch($event);
return $this->decorated->dispatch($event);
}
}
3 changes: 3 additions & 0 deletions src/Collector/HttpClientInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Yiisoft\Yii\Debug\ProxyDecoratedCalls;

final class HttpClientInterfaceProxy implements ClientInterface
{
use ProxyDecoratedCalls;

public function __construct(
private readonly ClientInterface $decorated,
private readonly HttpClientCollector $collector
Expand Down
23 changes: 13 additions & 10 deletions src/Collector/LoggerInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Stringable;
use Yiisoft\Yii\Debug\ProxyDecoratedCalls;

final class LoggerInterfaceProxy implements LoggerInterface
{
use ProxyDecoratedCalls;

public function __construct(
private readonly LoggerInterface $logger,
private readonly LoggerInterface $decorated,
private readonly LogCollector $collector
) {
}
Expand All @@ -26,15 +29,15 @@ public function emergency(string|Stringable $message, array $context = []): void
$context,
$callStack['file'] . ':' . $callStack['line']
);
$this->logger->emergency($message, $context);
$this->decorated->emergency($message, $context);
}

public function alert(string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect(LogLevel::ALERT, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->alert($message, $context);
$this->decorated->alert($message, $context);
}

public function critical(string|Stringable $message, array $context = []): void
Expand All @@ -47,55 +50,55 @@ public function critical(string|Stringable $message, array $context = []): void
$context,
$callStack['file'] . ':' . $callStack['line']
);
$this->logger->critical($message, $context);
$this->decorated->critical($message, $context);
}

public function error(string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect(LogLevel::ERROR, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->error($message, $context);
$this->decorated->error($message, $context);
}

public function warning(string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect(LogLevel::WARNING, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->warning($message, $context);
$this->decorated->warning($message, $context);
}

public function notice(string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect(LogLevel::NOTICE, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->notice($message, $context);
$this->decorated->notice($message, $context);
}

public function info(string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect(LogLevel::INFO, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->info($message, $context);
$this->decorated->info($message, $context);
}

public function debug(string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect(LogLevel::DEBUG, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->debug($message, $context);
$this->decorated->debug($message, $context);
}

public function log(mixed $level, string|Stringable $message, array $context = []): void
{
$callStack = $this->getCallStack();

$this->collector->collect($level, $message, $context, $callStack['file'] . ':' . $callStack['line']);
$this->logger->log($level, $message, $context);
$this->decorated->log($level, $message, $context);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/Collector/VarDumperHandlerInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
namespace Yiisoft\Yii\Debug\Collector;

use Yiisoft\VarDumper\HandlerInterface;
use Yiisoft\Yii\Debug\ProxyDecoratedCalls;

final class VarDumperHandlerInterfaceProxy implements HandlerInterface
{
use ProxyDecoratedCalls;

public function __construct(
private readonly HandlerInterface $decorated,
private readonly VarDumperCollector $collector,
Expand Down
26 changes: 26 additions & 0 deletions src/ProxyDecoratedCalls.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug;

/**
* @property object $decorated
*/
trait ProxyDecoratedCalls
{
public function __set(string $name, mixed $value): void
{
$this->decorated->$name = $value;
}

public function __get(string $name)
{
return $this->decorated->$name;
}

public function __call(string $name, array $arguments)
{
return $this->decorated->$name(...$arguments);
}
}
35 changes: 35 additions & 0 deletions tests/Unit/Collector/ContainerInterfaceProxyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,41 @@ public function test2(): void
$this->assertSame('from tests', $implementation->getName());
}

public function testProxyDecoratedCall(): void
{
$container = new class () implements ContainerInterface {
public $var = null;

public function getProxiedCall(): string
{
return 'ok';
}

public function setProxiedCall($args): mixed
{
return $args;
}

public function get($id)
{
throw new class () extends Exception implements ContainerExceptionInterface {
};
}

public function has($id): bool
{
throw new class () extends Exception implements ContainerExceptionInterface {
};
}
};
$proxy = new ContainerInterfaceProxy($container, new ContainerProxyConfig());

$this->assertEquals('ok', $proxy->getProxiedCall());
$this->assertEquals($args = [1, new stdClass(), 'string'], $proxy->setProxiedCall($args));
$proxy->var = '123';
$this->assertEquals('123', $proxy->var);
}

private function createConfig(int $logLevel = ContainerInterfaceProxy::LOG_ARGUMENTS): ContainerProxyConfig
{
return new ContainerProxyConfig(
Expand Down
28 changes: 28 additions & 0 deletions tests/Unit/Collector/EventDispatcherInterfaceProxyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,32 @@ public function testDispatch(): void
$this->assertSame($event, $newEvent);
$this->assertCount(1, $collector->getCollected());
}

public function testProxyDecoratedCall(): void
{
$dispatcher = new class () implements EventDispatcherInterface {
public $var = null;

public function getProxiedCall(): string
{
return 'ok';
}

public function setProxiedCall($args): mixed
{
return $args;
}

public function dispatch(object $event)
{
}
};
$collector = new EventCollector(new TimelineCollector());
$proxy = new EventDispatcherInterfaceProxy($dispatcher, $collector);

$this->assertEquals('ok', $proxy->getProxiedCall());
$this->assertEquals($args = [1, new stdClass(), 'string'], $proxy->setProxiedCall($args));
$proxy->var = '123';
$this->assertEquals('123', $proxy->var);
}
}
31 changes: 31 additions & 0 deletions tests/Unit/Collector/HttpClientInterfaceProxyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use stdClass;
use Yiisoft\Yii\Debug\Collector\HttpClientCollector;
use Yiisoft\Yii\Debug\Collector\HttpClientInterfaceProxy;
use Yiisoft\Yii\Debug\Collector\TimelineCollector;
Expand All @@ -34,4 +37,32 @@ public function testSendRequest(): void
$this->assertSame($newResponse, $response);
$this->assertCount(1, $collector->getCollected());
}

public function testProxyDecoratedCall(): void
{
$httpClient = new class () implements ClientInterface {
public $var = null;

public function getProxiedCall(): string
{
return 'ok';
}

public function setProxiedCall($args): mixed
{
return $args;
}

public function sendRequest(RequestInterface $request): ResponseInterface
{
}
};
$collector = new HttpClientCollector(new TimelineCollector());
$proxy = new HttpClientInterfaceProxy($httpClient, $collector);

$this->assertEquals('ok', $proxy->getProxiedCall());
$this->assertEquals($args = [1, new stdClass(), 'string'], $proxy->setProxiedCall($args));
$proxy->var = '123';
$this->assertEquals('123', $proxy->var);
}
}
Loading

0 comments on commit 7e1c705

Please sign in to comment.