StreamTarget   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 60
ccs 30
cts 30
cp 1
rs 10
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A export() 0 17 2
A __construct() 0 3 1
A createStream() 0 23 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Log;
6
7
use InvalidArgumentException;
8
use RuntimeException;
9
10
use function error_get_last;
11
use function fclose;
12
use function flock;
13
use function fopen;
14
use function fwrite;
15
use function gettype;
16
use function get_resource_type;
17
use function is_resource;
18
use function sprintf;
19
use function stream_get_meta_data;
20
21
use const LOCK_EX;
22
use const LOCK_UN;
23
24
/**
25
 * StreamTarget is the log target that writes to the specified output stream.
26
 */
27
final class StreamTarget extends Target
28
{
29
    /**
30
     * @param resource|string $stream A string stream identifier or a stream resource.
31
     */
32 9
    public function __construct(private $stream = 'php://stdout')
33
    {
34 9
        parent::__construct();
35
    }
36
37 9
    protected function export(): void
38
    {
39 9
        $stream = $this->createStream();
40 7
        flock($stream, LOCK_EX);
41
42 7
        if (fwrite($stream, $this->formatMessages("\n")) === false) {
43 4
            flock($stream, LOCK_UN);
44 4
            fclose($stream);
45 4
            throw new RuntimeException(sprintf(
46 4
                'Unable to export the log because of an error writing to the stream: %s',
47 4
                error_get_last()['message'] ?? '',
48 4
            ));
49
        }
50
51 3
        $this->stream = stream_get_meta_data($stream)['uri'];
52 3
        flock($stream, LOCK_UN);
53 3
        fclose($stream);
54
    }
55
56
    /**
57
     * Check and create a stream resource.
58
     *
59
     * @throws RuntimeException if the stream cannot be opened.
60
     * @throws InvalidArgumentException if the stream is invalid.
61
     *
62
     * @return resource The stream resource.
63
     */
64 9
    private function createStream()
65
    {
66 9
        $stream = $this->stream;
67
68 9
        if (is_string($stream)) {
69 4
            $stream = @fopen($stream, 'ab');
70 4
            if ($stream === false) {
71 1
                throw new RuntimeException(sprintf(
72 1
                    'The "%s" stream cannot be opened.',
73 1
                    (string) $this->stream,
74 1
                ));
75
            }
76
        }
77
78
        /** @psalm-suppress DocblockTypeContradiction */
79 8
        if (!is_resource($stream) || get_resource_type($stream) !== 'stream') {
80 1
            throw new InvalidArgumentException(sprintf(
81 1
                'Invalid stream provided. It must be a string stream identifier or a stream resource, "%s" received.',
82 1
                gettype($stream),
83 1
            ));
84
        }
85
86 7
        return $stream;
87
    }
88
}
89