Passed
Push — master ( d18874...8189de )
by Evgeniy
02:24
created

StreamTarget   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

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

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A export() 0 17 2
A createStream() 0 22 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
     * @var resource|string A string stream identifier or a stream resource.
31
     *
32
     * @psalm-var mixed
33
     */
34
    private $stream;
35
36
    /**
37
     * @param resource|string $stream A string stream identifier or a stream resource.
38
     */
39 9
    public function __construct($stream = 'php://stdout')
40
    {
41 9
        $this->stream = $stream;
42 9
        parent::__construct();
43 9
    }
44
45 9
    protected function export(): void
46
    {
47 9
        $stream = $this->createStream();
48 7
        flock($stream, LOCK_EX);
49
50 7
        if (fwrite($stream, $this->formatMessages("\n")) === false) {
51 4
            flock($stream, LOCK_UN);
52 4
            fclose($stream);
53 4
            throw new RuntimeException(sprintf(
54 4
                'Unable to export the log because of an error writing to the stream: %s',
55 4
                error_get_last()['message'] ?? '',
56
            ));
57
        }
58
59 3
        $this->stream = stream_get_meta_data($stream)['uri'];
60 3
        flock($stream, LOCK_UN);
61 3
        fclose($stream);
62 3
    }
63
64
    /**
65
     * Check and create a stream resource.
66
     *
67
     * @throws RuntimeException if the stream cannot be opened.
68
     * @throws InvalidArgumentException if the stream is invalid.
69
     *
70
     * @return resource The stream resource.
71
     */
72 9
    private function createStream()
73
    {
74 9
        $stream = $this->stream;
75
76 9
        if (is_string($stream)) {
77 4
            $stream = @fopen($stream, 'ab');
78 4
            if ($stream === false) {
79 1
                throw new RuntimeException(sprintf(
80 1
                    'The "%s" stream cannot be opened.',
81 1
                    (string) $this->stream,
82
                ));
83
            }
84
        }
85
86 8
        if (!is_resource($stream) || get_resource_type($stream) !== 'stream') {
87 1
            throw new InvalidArgumentException(sprintf(
88 1
                'Invalid stream provided. It must be a string stream identifier or a stream resource, "%s" received.',
89 1
                gettype($stream),
90
            ));
91
        }
92
93 7
        return $stream;
94
    }
95
}
96