Skip to content

Commit 68c0a53

Browse files
committed
csfix + update docs
1 parent 5c960dd commit 68c0a53

15 files changed

+127
-140
lines changed

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ class SomeService
123123
- [ ] Make MonologStackLogger implement Monolog's ResettableInterface?
124124
- [ ] Consider how this might play with Laravel, the insanely popular PHP
125125
framework that I do my best to avoid. 😜
126-
- [ ] Track what's going on with PSR-3 v2/v3 as well as monolog and
127-
laminas-log. Eventually, we should rely on the updated + better-typed
128-
versions of the spec. We may need to drop the laminas-log test code since
129-
laminas-log will likely always require psr/[email protected]
130126

131127
132128

composer.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,21 @@
5050
"cs-check": "phpcs",
5151
"cs-fix": "phpcbf",
5252
"dev": "@dev:qa",
53-
"dev:analyze": "phpstan",
53+
"dev:analyze": "phpstan analyze",
5454
"dev:coverage": "XDEBUG_MODE=coverage phpunit --coverage-text --colors=always",
5555
"dev:coverage:html": "XDEBUG_MODE=coverage phpunit --coverage-html build/coverage && echo '\\nCoverage Report: build/coverage/index.html'",
56-
"dev:cs": "phpcs",
57-
"dev:cs:fix": "phpcbf",
56+
"dev:cs": "ecs check",
57+
"dev:cs:fix": "ecs check --fix",
5858
"dev:qa": [
5959
"@dev:analyze",
6060
"@dev:test",
6161
"@dev:cs"
6262
],
63-
"dev:test": "phpunit --testdox --color=always",
64-
"test": "XDEBUG_MODE=coverage phpunit --coverage-text --colors=always --testdox"
63+
"dev:test": "phpunit --testdox --color=always"
6564
},
6665
"scripts-descriptions": {
6766
"dev": "Shortcut for dev:qa.",
68-
"dev:analyze": "Run static analysis with psalm.",
67+
"dev:analyze": "Run static analysis with phpstan.",
6968
"dev:coverage": "Report unit test coverage with output in the terminal.",
7069
"dev:coverage:html": "Generate unit test coverage report.",
7170
"dev:cs": "Run code style checks.",

ecs.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php declare(strict_types=1);
2+
3+
use Symplify\EasyCodingStandard\Config\ECSConfig;
4+
5+
return ECSConfig::configure()
6+
->withPaths([
7+
__DIR__ . '/src',
8+
__DIR__ . '/tests',
9+
])
10+
->withRootFiles()
11+
->withRules([
12+
\PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer::class,
13+
\PhpCsFixer\Fixer\Import\NoUnusedImportsFixer::class,
14+
])
15+
->withPhpCsFixerSets(perCS20: true)
16+
->withPreparedSets(psr12: true, common: true, symplify: true)
17+
->withConfiguredRule(PhpCsFixer\Fixer\Phpdoc\PhpdocLineSpanFixer::class, [
18+
'property' => 'single',
19+
'method' => 'single',
20+
'const' => 'single',
21+
])
22+
->withConfiguredRule(PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer::class, [
23+
'operators' => [
24+
'=>' => 'align',
25+
'=' => 'align',
26+
],
27+
])
28+
->withConfiguredRule(PhpCsFixer\Fixer\Phpdoc\PhpdocLineSpanFixer::class, [
29+
'const' => 'single',
30+
'method' => 'single',
31+
'property' => 'single',
32+
])
33+
->withConfiguredRule(Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer::class, [
34+
'inline_short_lines' => false,
35+
])
36+
->withSkip([
37+
Symplify\CodingStandard\Fixer\ArrayNotation\ArrayOpenerAndCloserNewlineFixer::class,
38+
39+
// <?php declare(strict_types=1); doesn't need to take up three or four lines:
40+
PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer::class,
41+
PhpCsFixer\Fixer\PhpTag\LinebreakAfterOpeningTagFixer::class,
42+
43+
Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer::class,
44+
Symplify\CodingStandard\Fixer\ArrayNotation\ArrayListItemNewlineFixer::class,
45+
])
46+
;

src/MonologStackLogger.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
<?php
2-
3-
declare(strict_types=1);
1+
<?php declare(strict_types=1);
42

53
namespace TimDev\StackLogger;
64

75
use Monolog\Handler\NullHandler;
86
use Monolog\Logger as MonologLogger;
9-
use Psr\Log\LoggerInterface as PsrInterface;
107

118
/**
129
* Extends Psr3Logger to provide a monolog-like withName() method.
@@ -24,7 +21,7 @@ public function withName(string $name): static
2421
{
2522
// this works, but requires WrappedPSR3::$logger to be non-private.
2623
// Is there a better way?
27-
$new = clone $this;
24+
$new = clone $this;
2825
$new->logger = $this->logger->withName($name);
2926
$new->parent = $this;
3027
return $new;

src/Psr3StackLogger.php

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
<?php
2-
3-
declare(strict_types=1);
1+
<?php declare(strict_types=1);
42

53
namespace TimDev\StackLogger;
64

75
use Psr\Log\LoggerInterface as PsrInterface;
86
use Psr\Log\LoggerTrait;
97
use Psr\Log\NullLogger;
10-
use function PHPStan\dumpType;
118

129
/**
1310
* Implements LoggerInterface by wrapping a PSR3 logger.
@@ -21,7 +18,7 @@ class Psr3StackLogger implements StackLogger
2118
/** @var L */
2219
protected PsrInterface $logger;
2320

24-
/** @var static */
21+
/** @var static */
2522
protected ?StackLogger $parent = null;
2623

2724
/** @var array<mixed> */
@@ -39,23 +36,16 @@ public function getWrapped(): PsrInterface
3936
return $this->logger;
4037
}
4138

42-
/** @param L $logger */
43-
final protected function setWrapped(PsrInterface $logger): void
44-
{
45-
$this->logger = $logger;
46-
}
47-
4839
/**
4940
* Context Handling
5041
*
5142
* @param array<string, mixed> $context
52-
* @return static
5343
*/
5444
#[\Override]
5545
public function withContext(array $context = []): static
5646
{
57-
$child = clone $this;
58-
$child->parent = $this;
47+
$child = clone $this;
48+
$child->parent = $this;
5949
$child->context = $context;
6050
return $child;
6151
}
@@ -71,6 +61,28 @@ public function addContext(array $context): static
7161
return $this;
7262
}
7363

64+
/* PSR3 Implementation, wrapping our wrapped instance. */
65+
66+
#[\Override]
67+
public function log($level, string|\Stringable $message, array $context = []): void
68+
{
69+
assert(is_string($level) || is_int($level));
70+
$context = $this->processContext($context);
71+
$this->logger->log($level, $message, $context);
72+
}
73+
74+
public static function makeNullLogger(): StackLogger
75+
{
76+
$instance = new NullLogger();
77+
return new self($instance);
78+
}
79+
80+
/** @param L $logger */
81+
final protected function setWrapped(PsrInterface $logger): void
82+
{
83+
$this->logger = $logger;
84+
}
85+
7486
/**
7587
* Merges $context on top of the instances accumulated context, and
7688
* processes any callable elements in the final context.
@@ -83,10 +95,7 @@ protected function processContext(array $context = []): array
8395
$context = array_merge($this->mergedContext(), $context);
8496

8597
// handle any callables in final context.
86-
return array_map(
87-
static fn($c): mixed => is_callable($c) ? $c($context) : $c,
88-
$context
89-
);
98+
return array_map(static fn($c): mixed => is_callable($c) ? $c($context) : $c, $context);
9099
}
91100

92101
/**
@@ -95,30 +104,12 @@ protected function processContext(array $context = []): array
95104
*/
96105
protected function contextToMerge(): array
97106
{
98-
return [
99-
... ($this->parent !== null) ? $this->parent->contextToMerge() : [],
100-
$this->context
101-
];
107+
return [...($this->parent !== null) ? $this->parent->contextToMerge() : [], $this->context];
102108
}
103109

104110
/** @return array<mixed> */
105111
protected function mergedContext(): array
106112
{
107113
return array_merge(...$this->contextToMerge());
108114
}
109-
110-
/* PSR3 Implementation, wrapping our wrapped instance. */
111-
112-
#[\Override]
113-
public function log($level, string|\Stringable $message, array $context = []): void
114-
{
115-
assert(is_string($level) || is_int($level));
116-
$context = $this->processContext($context);
117-
$this->logger->log($level, $message, $context);
118-
}
119-
public static function makeNullLogger(): StackLogger
120-
{
121-
$instance = new NullLogger();
122-
return new self($instance);
123-
}
124115
}

src/StackLogger.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
<?php
2-
3-
declare(strict_types=1);
1+
<?php declare(strict_types=1);
42

53
namespace TimDev\StackLogger;
64

src/WrappingStackLogger.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
<?php
2-
3-
declare(strict_types=1);
1+
<?php declare(strict_types=1);
42

53
namespace TimDev\StackLogger;
64

tests/BaseTestCase.php

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
<?php
2-
3-
declare(strict_types=1);
1+
<?php declare(strict_types=1);
42

53
namespace TimDev\StackLogger\Test;
64

75
use PHPUnit\Framework\TestCase;
8-
use TimDev\StackLogger\StackLogger;
96
use TimDev\StackLogger\Test\Support\TestStackLogger;
107

118
/**
@@ -17,12 +14,10 @@
1714
*/
1815
abstract class BaseTestCase extends TestCase
1916
{
20-
abstract protected function makeTestSubject(): TestStackLogger;
21-
2217
private TestStackLogger $log;
2318

2419
#[\Override]
25-
public function setUp(): void
20+
protected function setUp(): void
2621
{
2722
$this->log = $this->makeTestSubject();
2823
}
@@ -50,10 +45,7 @@ public function testAddsContext(): void
5045

5146
$this->log
5247
->addContext(['even more' => 'context'])
53-
->warning(
54-
'This message should get four context elements.',
55-
['foo' => 'bar']
56-
);
48+
->warning('This message should get four context elements.', ['foo' => 'bar']);
5749
self::assertEquals(4, $this->log->contextCountAt(2));
5850

5951
$this->log->debug('Back to three!');
@@ -70,7 +62,7 @@ public function testCreateChildWithContext(): void
7062

7163
public function testAccumulatesContext(): void
7264
{
73-
$log = $this->log->withContext(['initial' => 'context']);
65+
$log = $this->log->withContext(['initial' => 'context']);
7466
$child = $log->withContext(['more' => 'context']);
7567

7668
// $child should have two context items.
@@ -87,10 +79,7 @@ public function testAccumulatesContext(): void
8779
$log->info('I should have one context item (on my second record)');
8880

8981
self::assertCount(1, $log->contextAt(1));
90-
self::assertEquals(
91-
['initial'],
92-
$log->contextKeysAt(1)
93-
);
82+
self::assertEquals(['initial'], $log->contextKeysAt(1));
9483
}
9584

9685
public function testMergesContext(): void
@@ -101,30 +90,24 @@ public function testMergesContext(): void
10190
$log
10291
->withContext(['a' => 'Allison', 'b' => 'Bob'])
10392
->emergency('Allison and Bruno', ['b' => 'Bruno']);
104-
self::assertEquals(
105-
['Allison', 'Bruno'],
106-
$this->log->contextValuesAt(0)
107-
);
93+
self::assertEquals(['Allison', 'Bruno'], $this->log->contextValuesAt(0));
10894

10995
// But original logger should still have (only) Alice.
11096
$log->critical('Alice alone.');
111-
self::assertEquals(
112-
['a' => 'Alice'],
113-
$this->log->contextAt(1)
114-
);
97+
self::assertEquals(['a' => 'Alice'], $this->log->contextAt(1));
11598
}
11699

117100
public function testInvokesCallables(): void
118101
{
119102
$logger = $this->log;
120-
$child = $logger->withContext(
103+
$child = $logger->withContext(
121104
[
122105
// A callable context element that returns the number of
123106
// elements in the record's context.
124107
'counter' => function (array $ctx) {
125108
return count($ctx);
126-
}
127-
]
109+
},
110+
],
128111
);
129112
$child->notice('Only one context element, the result of the callable.');
130113
self::assertEquals(1, $child->contextAt(0)['counter']);
@@ -133,10 +116,10 @@ public function testInvokesCallables(): void
133116
$child->warning('A log with three context items.', ['Third' => 'Context Item']);
134117
self::assertEquals(
135118
$child->contextCountAt(1), // === 3
136-
$child->contextAt(1)['counter']
119+
$child->contextAt(1)['counter'],
137120
);
138121

139-
$start = microtime(true);
122+
$start = microtime(true);
140123
$child2 = $logger->withContext(['elapsed_micros' => fn() => 1000000 * (microtime(true) - $start)]);
141124
usleep(1000);
142125
$child2->alert('At least 1000 μ-sec have passed.');
@@ -149,15 +132,16 @@ public function testInvokesCallables(): void
149132
*/
150133
public function testLongChain(): void
151134
{
152-
$logger = $this->log;
135+
$logger = $this->log;
153136
$numLoggers = 20;
154137
foreach (range(1, $numLoggers) as $i) {
155138
$logger = $logger->withContext(["gen{$i}" => $i]);
156139
}
157-
$logger->withContext(["count" => fn(array $ctx) => count($ctx)]);
158-
$logger->error("I come from a long lineage", ['final' => 'I should be the 21st context element']);
140+
$logger->withContext(['count' => fn(array $ctx) => count($ctx)]);
141+
$logger->error('I come from a long lineage', ['final' => 'I should be the 21st context element']);
159142
self::assertIsIterable($logger->recordAt(0)['context']);
160143
self::assertCount($numLoggers + 1, $logger->recordAt(0)['context']);
161144
}
162145

146+
abstract protected function makeTestSubject(): TestStackLogger;
163147
}

0 commit comments

Comments
 (0)