Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
LogCapturingSpi
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 7
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLogs
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLogger
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 capture
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 createLogger
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 getInnerSpi
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLoggerForTest
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Logger;
4
5use Psr\Log\AbstractLogger;
6use Psr\Log\LoggerInterface;
7
8/**
9 * Wrap another Spi and keep a copy of all log messages.
10 *
11 * This is developed for use by PHPUnit bootstrapping, to collect logs
12 * generated during a given unit test, and print them after a failing test.
13 *
14 * @internal For use in MediaWiki core only
15 * @ingroup Debug
16 */
17class LogCapturingSpi implements Spi {
18    /** @var LoggerInterface[] */
19    private $singletons;
20    /** @var Spi */
21    private $inner;
22    /** @var array */
23    private $logs = [];
24
25    public function __construct( Spi $inner ) {
26        $this->inner = $inner;
27    }
28
29    /**
30     * @return array
31     */
32    public function getLogs() {
33        return $this->logs;
34    }
35
36    /**
37     * @param string $channel
38     * @return LoggerInterface
39     */
40    public function getLogger( $channel ) {
41        if ( !isset( $this->singletons[$channel] ) ) {
42            $this->singletons[$channel] = $this->createLogger( $channel );
43        }
44        return $this->singletons[$channel];
45    }
46
47    /**
48     * @param array $log
49     */
50    public function capture( $log ) {
51        $this->logs[] = $log;
52    }
53
54    /**
55     * @param string $channel
56     * @return LoggerInterface
57     */
58    private function createLogger( $channel ) {
59        $inner = $this->inner->getLogger( $channel );
60        return new class( $channel, $inner, $this ) extends AbstractLogger {
61            /** @var string */
62            private $channel;
63            /** @var LoggerInterface */
64            private $logger;
65            /** @var LogCapturingSpi */
66            private $parent;
67
68            public function __construct( $channel, LoggerInterface $logger, LogCapturingSpi $parent ) {
69                $this->channel = $channel;
70                $this->logger = $logger;
71                $this->parent = $parent;
72            }
73
74            public function log( $level, $message, array $context = [] ) {
75                $this->parent->capture( [
76                    'channel' => $this->channel,
77                    'level' => $level,
78                    'message' => $message,
79                    'context' => $context
80                ] );
81                $this->logger->log( $level, $message, $context );
82            }
83        };
84    }
85
86    /**
87     * @internal For use by MediaWikiIntegrationTestCase
88     * @return Spi
89     */
90    public function getInnerSpi(): Spi {
91        return $this->inner;
92    }
93
94    /**
95     * @internal For use by MediaWikiIntegrationTestCase
96     * @param string $channel
97     * @param LoggerInterface|null $logger
98     * @return LoggerInterface|null
99     */
100    public function setLoggerForTest( $channel, LoggerInterface $logger = null ) {
101        $ret = $this->singletons[$channel] ?? null;
102        $this->singletons[$channel] = $logger;
103        return $ret;
104    }
105}