Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxy any calls to the decorated object #272

Merged
merged 5 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading