FileTarget::resolveFilename()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 11
ccs 10
cts 10
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Profiler\Target;
6
7
use Yiisoft\Files\FileHelper;
8
use Yiisoft\Profiler\Message;
9
10
use function dirname;
11
12
/**
13
 * FileTarget records profiling messages in a file specified via {@see FileTarget::$filePath}.
14
 */
15
final class FileTarget extends AbstractTarget
16
{
17
    /**
18
     * @param string $filePath Path of the file to write to. It may contain the placeholders,
19
     * which will be replaced by computed values. The supported placeholders are:
20
     *
21
     * - '{ts}' - profiling completion timestamp.
22
     * - '{date}' - profiling completion date in format 'ymd'.
23
     * - '{time}' - profiling completion time in format 'His'.
24
     *
25
     * The directory containing the file will be automatically created if not existing.
26
     * If target file is already exist it will be overridden.
27
     * @param float $requestBeginTime Time of the beginning of the request. Can be set as `microtime(true)` or
28
     * `$_SERVER['REQUEST_TIME_FLOAT']` in config.
29
     * @param int $directoryMode The permission to be set for newly created directories.
30
     * This value will be used by PHP chmod() function. No umask will be applied.
31
     * Defaults to 0775, meaning the directory is read-writable by owner and group,
32
     * but read-only for other users.
33
     */
34 4
    public function __construct(
35
        private string $filePath,
36
        private float $requestBeginTime,
37
        private int $directoryMode = 0775
38
    ) {
39 4
    }
40
41 3
    public function export(array $messages): void
42
    {
43 3
        $memoryPeakUsage = memory_get_peak_usage();
44
45 3
        $totalTime = microtime(true) - $this->requestBeginTime;
46 3
        $text = "Total processing time: $totalTime ms; Peak memory: $memoryPeakUsage B. \n\n";
47
48 3
        $text .= implode("\n", array_map([$this, 'formatMessage'], $messages));
49
50 3
        $filename = $this->resolveFilename();
51
52 3
        if (file_exists($filename)) {
53 2
            FileHelper::unlink($filename);
54
        } else {
55 1
            $filePath = dirname($filename);
56
57 1
            if (!is_dir($filePath)) {
58 1
                FileHelper::ensureDirectory($filePath, $this->directoryMode);
59
            }
60
        }
61
62 3
        file_put_contents($filename, $text);
63
    }
64
65
    /**
66
     * Resolves value of {@see filename} processing path alias and placeholders.
67
     *
68
     * @return string Actual target filename.
69
     */
70 3
    private function resolveFilename(): string
71
    {
72 3
        return preg_replace_callback(
73 3
            '/{\\w+}/',
74 3
            static fn (array $matches) => match ($matches[0]) {
75 3
                '{ts}' => (string)time(),
76 3
                '{date}' => gmdate('ymd'),
77 3
                '{time}' => gmdate('His'),
78 3
                default => $matches[0],
79 3
            },
80 3
            $this->filePath
81 3
        );
82
    }
83
84
    /**
85
     * Formats a profiling message for display as a string.
86
     *
87
     * @param Message $message Profiling message to be formatted.
88
     * The message structure follows that in {@see Profiler::$messages}.
89
     *
90
     * @return string Formatted message.
91
     */
92 3
    private function formatMessage(Message $message): string
93
    {
94 3
        return date('Y-m-d H:i:s', (int)$message->context('beginTime'))
95 3
            . " [{$message->context('duration')} ms][{$message->context('memoryDiff')} B][{$message->level()}] {$message->token()}";
96
    }
97
}
98