Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.89% covered (warning)
88.89%
40 / 45
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
LogrotateLogsChannel
88.89% covered (warning)
88.89%
40 / 45
0.00% covered (danger)
0.00%
0 / 3
9.11
0.00% covered (danger)
0.00%
0 / 1
 getLogFileForIndex
n/a
0 / 0
n/a
0 / 0
0
 getIndexForFilePath
n/a
0 / 0
n/a
0 / 0
0
 getLineLocationForDateTime
89.66% covered (warning)
89.66%
26 / 29
0.00% covered (danger)
0.00%
0 / 1
4.02
 getLogFileBefore
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 getLogFileAfter
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
3.01
1<?php
2
3namespace Olz\Apps\Logs\Utils;
4
5abstract class LogrotateLogsChannel extends BaseLogsChannel {
6    /** @param non-negative-int $index */
7    abstract protected function getLogFileForIndex(int $index): LogFileInterface;
8
9    /** @return non-negative-int */
10    abstract protected function getIndexForFilePath(string $file_path): int;
11
12    protected function getLineLocationForDateTime(
13        \DateTime $date_time,
14    ): LineLocation {
15        $iso_date_time = $date_time->format('Y-m-d H:i:s');
16        $index = 0;
17        $continue = true;
18        while ($continue) {
19            try {
20                $log_file = $this->getLogFileForIndex($index);
21                $file_index = $this->getOrCreateIndex($log_file);
22                if ($iso_date_time >= $file_index['start_date']) {
23                    $continue = false;
24                } else {
25                    $index++;
26                }
27            } catch (\Exception $exc) {
28                $continue = false;
29                throw $exc;
30            }
31        }
32        $log_file = $this->getLogFileForIndex($index);
33        $file_index = $this->getOrCreateIndex($log_file);
34        $number_of_lines = count($file_index['lines']);
35        $fp = $log_file->open('r');
36
37        [$line_number, $cmp] = $this->generalUtils()->binarySearch(
38            function ($line_number) use ($log_file, $fp, $file_index, $date_time) {
39                $index = $file_index['lines'][$line_number];
40                $log_file->seek($fp, $index);
41                $line = $log_file->gets($fp);
42                $date_time_at_index = $this->parseDateTimeOfLine($line ?? '');
43                return $date_time <=> $date_time_at_index;
44            },
45            0,
46            $number_of_lines - 1,
47        );
48
49        $log_file->close($fp);
50        return new LineLocation($log_file, $line_number, $cmp);
51    }
52
53    protected function getLogFileBefore(LogFileInterface $log_file): LogFileInterface {
54        $path = $log_file->getPath();
55        $index = $this->getIndexForFilePath($path);
56        $index_before = $index + 1;
57        $new_log_file = $this->getLogFileForIndex($index_before);
58        if (!$new_log_file->exists()) {
59            throw new \Exception("No such file: {$new_log_file->getPath()}");
60        }
61        return $new_log_file;
62    }
63
64    protected function getLogFileAfter(LogFileInterface $log_file): LogFileInterface {
65        $path = $log_file->getPath();
66        $index = $this->getIndexForFilePath($path);
67        $index_after = $index - 1;
68        if ($index_after < 0) {
69            throw new \Exception("Reached the start of the list");
70        }
71        $new_log_file = $this->getLogFileForIndex($index_after);
72        if (!$new_log_file->exists()) {
73            throw new \Exception("No such file: {$new_log_file->getPath()}");
74        }
75        return $new_log_file;
76    }
77}