Skip to content

[MonologBridge] Use composition instead of inheritance in monolog bridge #35740

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

Merged
merged 1 commit into from
Sep 18, 2020
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
6 changes: 6 additions & 0 deletions UPGRADE-5.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Mime

* Deprecated `Address::fromString()`, use `Address::create()` instead

Monolog
-------

* The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` has been deprecated and replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` will become final in 6.0.
* The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` has been deprecated and replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` will become final in 6.0

PropertyAccess
--------------

Expand Down
6 changes: 6 additions & 0 deletions UPGRADE-6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ Mime

* Removed `Address::fromString()`, use `Address::create()` instead

Monolog
-------

* The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` has been replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` is now final.
* The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` has been replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` is now final.

OptionsResolver
---------------

Expand Down
7 changes: 7 additions & 0 deletions src/Symfony/Bridge/Monolog/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
CHANGELOG
=========

5.2.0
-----

* The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` has been deprecated and replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` will become final in 6.0.
* The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` has been deprecated and replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` will become final in 6.0

5.1.0
-----

* Added `MailerHandler`

5.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bridge\Monolog\Handler\FingersCrossed;

use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\HttpException;
Expand All @@ -19,17 +20,29 @@
* Activation strategy that ignores certain HTTP codes.
*
* @author Shaun Simmons <shaun@envysphere.com>
* @author Pierrick Vignand <pierrick.vignand@gmail.com>
*
* @final
*/
class HttpCodeActivationStrategy extends ErrorLevelActivationStrategy
class HttpCodeActivationStrategy extends ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
private $inner;
private $exclusions;
private $requestStack;

/**
* @param array $exclusions each exclusion must have a "code" and "urls" keys
* @param array $exclusions each exclusion must have a "code" and "urls" keys
* @param ActivationStrategyInterface|int|string $inner an ActivationStrategyInterface to decorate
*/
public function __construct(RequestStack $requestStack, array $exclusions, $actionLevel)
public function __construct(RequestStack $requestStack, array $exclusions, $inner)
{
if (!$inner instanceof ActivationStrategyInterface) {
trigger_deprecation('symfony/monolog-bridge', '5.2', 'Passing an actionLevel (int|string) as constructor\'s 3rd argument of "%s" is deprecated, "%s" expected.', __CLASS__, ActivationStrategyInterface::class);

$actionLevel = $inner;
$inner = new ErrorLevelActivationStrategy($actionLevel);
}

foreach ($exclusions as $exclusion) {
if (!\array_key_exists('code', $exclusion)) {
throw new \LogicException(sprintf('An exclusion must have a "code" key.'));
Expand All @@ -39,15 +52,14 @@ public function __construct(RequestStack $requestStack, array $exclusions, $acti
}
}

parent::__construct($actionLevel);

$this->inner = $inner;
$this->requestStack = $requestStack;
$this->exclusions = $exclusions;
}

public function isHandlerActivated(array $record): bool
{
$isActivated = parent::isHandlerActivated($record);
$isActivated = $this->inner->isHandlerActivated($record);

if (
$isActivated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bridge\Monolog\Handler\FingersCrossed;

use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\HttpException;
Expand All @@ -20,23 +21,36 @@
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Fabien Potencier <fabien@symfony.com>
* @author Pierrick Vignand <pierrick.vignand@gmail.com>
*
* @final
*/
class NotFoundActivationStrategy extends ErrorLevelActivationStrategy
class NotFoundActivationStrategy extends ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
private $inner;
private $exclude;
private $requestStack;

public function __construct(RequestStack $requestStack, array $excludedUrls, $actionLevel)
/**
* @param ActivationStrategyInterface|int|string $inner an ActivationStrategyInterface to decorate
*/
public function __construct(RequestStack $requestStack, array $excludedUrls, $inner)
{
parent::__construct($actionLevel);
if (!$inner instanceof ActivationStrategyInterface) {
trigger_deprecation('symfony/monolog-bridge', '5.2', 'Passing an actionLevel (int|string) as constructor\'s 3rd argument of "%s" is deprecated, "%s" expected.', __CLASS__, ActivationStrategyInterface::class);

$actionLevel = $inner;
$inner = new ErrorLevelActivationStrategy($actionLevel);
}

$this->inner = $inner;
$this->requestStack = $requestStack;
$this->exclude = '{('.implode('|', $excludedUrls).')}i';
}

public function isHandlerActivated(array $record): bool
{
$isActivated = parent::isHandlerActivated($record);
$isActivated = $this->inner->isHandlerActivated($record);

if (
$isActivated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bridge\Monolog\Tests\Handler\FingersCrossed;

use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy;
Expand All @@ -20,22 +21,30 @@

class HttpCodeActivationStrategyTest extends TestCase
{
public function testExclusionsWithoutCode()
/**
* @group legacy
*/
public function testExclusionsWithoutCodeLegacy(): void
{
$this->expectException('LogicException');
new HttpCodeActivationStrategy(new RequestStack(), [['urls' => []]], Logger::WARNING);
}

public function testExclusionsWithoutUrls()
/**
* @group legacy
*/
public function testExclusionsWithoutUrlsLegacy(): void
{
$this->expectException('LogicException');
new HttpCodeActivationStrategy(new RequestStack(), [['code' => 404]], Logger::WARNING);
}

/**
* @dataProvider isActivatedProvider
*
* @group legacy
*/
public function testIsActivated($url, $record, $expected)
public function testIsActivatedLegacy($url, $record, $expected): void
{
$requestStack = new RequestStack();
$requestStack->push(Request::create($url));
Expand All @@ -51,10 +60,44 @@ public function testIsActivated($url, $record, $expected)
Logger::WARNING
);

$this->assertEquals($expected, $strategy->isHandlerActivated($record));
self::assertEquals($expected, $strategy->isHandlerActivated($record));
}

public function testExclusionsWithoutCode(): void
{
$this->expectException('LogicException');
new HttpCodeActivationStrategy(new RequestStack(), [['urls' => []]], new ErrorLevelActivationStrategy(Logger::WARNING));
}

public function testExclusionsWithoutUrls(): void
{
$this->expectException('LogicException');
new HttpCodeActivationStrategy(new RequestStack(), [['code' => 404]], new ErrorLevelActivationStrategy(Logger::WARNING));
}

/**
* @dataProvider isActivatedProvider
*/
public function testIsActivated($url, $record, $expected)
{
$requestStack = new RequestStack();
$requestStack->push(Request::create($url));

$strategy = new HttpCodeActivationStrategy(
$requestStack,
[
['code' => 403, 'urls' => []],
['code' => 404, 'urls' => []],
['code' => 405, 'urls' => []],
['code' => 400, 'urls' => ['^/400/a', '^/400/b']],
],
new ErrorLevelActivationStrategy(Logger::WARNING)
);

self::assertEquals($expected, $strategy->isHandlerActivated($record));
}

public function isActivatedProvider()
public function isActivatedProvider(): array
{
return [
['/test', ['level' => Logger::ERROR], true],
Expand All @@ -70,7 +113,7 @@ public function isActivatedProvider()
];
}

protected function getContextException($code)
private function getContextException(int $code): array
{
return ['exception' => new HttpException($code)];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bridge\Monolog\Tests\Handler\FingersCrossed;

use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy;
Expand All @@ -22,18 +23,33 @@ class NotFoundActivationStrategyTest extends TestCase
{
/**
* @dataProvider isActivatedProvider
*
* @group legacy
*/
public function testIsActivated($url, $record, $expected)
public function testIsActivatedLegacy(string $url, array $record, bool $expected): void
{
$requestStack = new RequestStack();
$requestStack->push(Request::create($url));

$strategy = new NotFoundActivationStrategy($requestStack, ['^/foo', 'bar'], Logger::WARNING);

$this->assertEquals($expected, $strategy->isHandlerActivated($record));
self::assertEquals($expected, $strategy->isHandlerActivated($record));
}

public function isActivatedProvider()
/**
* @dataProvider isActivatedProvider
*/
public function testIsActivated(string $url, array $record, bool $expected): void
{
$requestStack = new RequestStack();
$requestStack->push(Request::create($url));

$strategy = new NotFoundActivationStrategy($requestStack, ['^/foo', 'bar'], new ErrorLevelActivationStrategy(Logger::WARNING));

self::assertEquals($expected, $strategy->isHandlerActivated($record));
}

public function isActivatedProvider(): array
{
return [
['/test', ['level' => Logger::DEBUG], false],
Expand All @@ -48,7 +64,7 @@ public function isActivatedProvider()
];
}

protected function getContextException($code)
protected function getContextException(int $code): array
{
return ['exception' => new HttpException($code)];
}
Expand Down
3 changes: 2 additions & 1 deletion src/Symfony/Bridge/Monolog/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"php": ">=7.2.5",
"monolog/monolog": "^1.25.1|^2",
"symfony/service-contracts": "^1.1|^2",
"symfony/http-kernel": "^4.4|^5.0"
"symfony/http-kernel": "^4.4|^5.0",
"symfony/deprecation-contracts": "^2.1"
},
"require-dev": {
"symfony/console": "^4.4|^5.0",
Expand Down