Issues (11)

src/Trace/Trace.php (1 issue)

Severity
1
<?php
2
3
namespace Tequilarapido\Consolify\Trace;
4
5
class Trace
6
{
7
    protected $uid;
8
9
    protected $basePath;
10
11
    protected $truncateLines = 3;
12
13
    public static function fromFile($file)
14
    {
15
        $instance = new static();
16
17
        return $instance->setUid($instance->fileToUid($file));
18
    }
19
20
    public static function fromUid($uid)
21
    {
22
        return (new static())->setUid($uid);
23
    }
24
25
    public function setBasePath($basePath)
26
    {
27
        $this->basePath = $basePath;
28
29
        return $this;
30
    }
31
32
    public function setUid($uid)
33
    {
34
        $this->uid = $uid;
35
36
        return $this;
37
    }
38
39
    public function get($from = null, $truncate = true)
40
    {
41
        if (! $file = $this->getFile()) {
42
            throw new TraceException('Cannot find file to trace.');
43
        }
44
45
        return $this->readLast($file, $from, $truncate);
46
    }
47
48
    public function getFile()
49
    {
50
        if (! file_exists($file = $this->uidToFile($this->uid))) {
51
            return;
52
        }
53
54
        return $file;
55
    }
56
57
    protected function readLast($file, $last_position, $truncate)
58
    {
59
        clearstatcache(false, $file);
60
        $len = filesize($file);
61
62
        // First time or file was deleted/reset
63
        if ($len < $last_position) {
64
            return [
65
                'last_position' => 0,
66
                'operation'     => 'ERASE',
67
            ];
68
        }
69
70
        // If there is new content
71
        if ($len > $last_position) {
72
            $f = fopen($file, 'rb');
73
            if (! $f) {
0 ignored issues
show
$f is of type false|resource, thus it always evaluated to false.
Loading history...
74
                throw new \LogicException("Cannot read file. [$file]");
75
            }
76
77
            $lines = [];
78
            fseek($f, $last_position);
79
            while (! feof($f)) {
80
                $lines = array_merge(
81
                    $lines,
82
                    explode("\n", fread($f, 4096))
83
                );
84
            }
85
            $last_position = ftell($f);
86
            fclose($f);
87
        } else {
88
            $lines = [];
89
        }
90
91
        if ($truncate) {
92
            if (count($lines) > $this->truncateLines) {
93
                $lines = array_slice($lines, -1 * $this->truncateLines);
94
                array_unshift($lines, '...');
95
            }
96
        }
97
98
        return [
99
            'last_position' => $last_position,
100
            'operation'     => 'APPEND',
101
            'lines'         => $this->format($lines),
102
        ];
103
    }
104
105
    protected function format($lines)
106
    {
107
        /*
108
         * @todo format using an ansi converer to preserve colors ?
109
         */
110
        return $lines;
111
    }
112
113
    public function addEraseLine()
114
    {
115
        $this->addCommandLine(TraceReserved::ERASE);
116
    }
117
118
    public function addTerminateLine()
119
    {
120
        $this->addCommandLine(TraceReserved::COMPLETED);
121
    }
122
123
    public function addCommandLine($command)
124
    {
125
        file_put_contents($this->getFile(), "[{$command}]".PHP_EOL, FILE_APPEND);
126
    }
127
128
    /**
129
     * Converts uid to filepath.
130
     *
131
     *      UID     = {SUBFOLDER}_{NAME}
132
     *          ->
133
     *      PATH    = {storage_path}/{SUBFOLDER}/{NAME}.log
134
     *
135
     * @param $uid
136
     *
137
     * @return null|string
138
     */
139
    public function uidToFile($uid)
140
    {
141
        list($subfolder, $filename) = explode('_', $uid);
142
143
        return str_replace('//', '/', "{$this->basePath}/{$subfolder}/{$filename}.log");
144
    }
145
146
    /**
147
     * Convert full log path to UID.
148
     *
149
     *      PATH    = {storage_path}/{SUBFOLDER}/{NAME}.log
150
     *          ->
151
     *      UID     = {SUBFOLDER}_{NAME}
152
     *
153
     * @param $fullPath
154
     *
155
     * @return mixed
156
     */
157
    public function fileToUid($fullPath)
158
    {
159
        return $this->relativeFileToUid(
160
            str_replace($this->basePath.'/', '', $fullPath)
161
        );
162
    }
163
164
    /**
165
     * Convert relative log path to UID.
166
     *
167
     *      PATH    = {SUBFOLDER}/{NAME}.log
168
     *          ->
169
     *      UID     = {SUBFOLDER}_{NAME}
170
     *
171
     * @param $relativePath
172
     *
173
     * @return mixed
174
     */
175
    public function relativeFileToUid($relativePath)
176
    {
177
        $uid = implode('_', explode('/', trim($relativePath, '/')));
178
179
        return str_replace('.log', '', $uid);
180
    }
181
}
182