Passed
Push — master ( 590c20...494ff0 )
by Blizzz
17:26 queued 12s
created
lib/private/Profiler/FileProfilerStorage.php 2 patches
Indentation   +252 added lines, -252 removed lines patch added patch discarded remove patch
@@ -32,256 +32,256 @@
 block discarded – undo
32 32
  * Storage for profiler using files.
33 33
  */
34 34
 class FileProfilerStorage {
35
-	// Folder where profiler data are stored.
36
-	private string $folder;
37
-
38
-	/**
39
-	 * Constructs the file storage using a "dsn-like" path.
40
-	 *
41
-	 * Example : "file:/path/to/the/storage/folder"
42
-	 *
43
-	 * @throws \RuntimeException
44
-	 */
45
-	public function __construct(string $folder) {
46
-		$this->folder = $folder;
47
-
48
-		if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) {
49
-			throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder));
50
-		}
51
-	}
52
-
53
-	public function find(?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array {
54
-		$file = $this->getIndexFilename();
55
-
56
-		if (!file_exists($file)) {
57
-			return [];
58
-		}
59
-
60
-		$file = fopen($file, 'r');
61
-		fseek($file, 0, \SEEK_END);
62
-
63
-		$result = [];
64
-		while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
65
-			$values = str_getcsv($line);
66
-			[$csvToken, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode] = $values;
67
-			$csvTime = (int) $csvTime;
68
-
69
-			if ($url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) {
70
-				continue;
71
-			}
72
-
73
-			if (!empty($start) && $csvTime < $start) {
74
-				continue;
75
-			}
76
-
77
-			if (!empty($end) && $csvTime > $end) {
78
-				continue;
79
-			}
80
-
81
-			$result[$csvToken] = [
82
-				'token' => $csvToken,
83
-				'method' => $csvMethod,
84
-				'url' => $csvUrl,
85
-				'time' => $csvTime,
86
-				'parent' => $csvParent,
87
-				'status_code' => $csvStatusCode,
88
-			];
89
-		}
90
-
91
-		fclose($file);
92
-
93
-		return array_values($result);
94
-	}
95
-
96
-	public function purge(): void {
97
-		$flags = \FilesystemIterator::SKIP_DOTS;
98
-		$iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
99
-		$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
100
-
101
-		foreach ($iterator as $file) {
102
-			$file = (string)$file->getPathInfo();
103
-			if (is_file($file)) {
104
-				unlink($file);
105
-			} else {
106
-				rmdir($file);
107
-			}
108
-		}
109
-	}
110
-
111
-	public function read(string $token): ?IProfile {
112
-		if (!$token || !file_exists($file = $this->getFilename($token))) {
113
-			return null;
114
-		}
115
-
116
-		if (\function_exists('gzcompress')) {
117
-			$file = 'compress.zlib://'.$file;
118
-		}
119
-
120
-		return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
121
-	}
122
-
123
-	/**
124
-	 * @throws \RuntimeException
125
-	 */
126
-	public function write(IProfile $profile): bool {
127
-		$file = $this->getFilename($profile->getToken());
128
-
129
-		$profileIndexed = is_file($file);
130
-		if (!$profileIndexed) {
131
-			// Create directory
132
-			$dir = \dirname($file);
133
-			if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
134
-				throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir));
135
-			}
136
-		}
137
-
138
-		$profileToken = $profile->getToken();
139
-		// when there are errors in sub-requests, the parent and/or children tokens
140
-		// may equal the profile token, resulting in infinite loops
141
-		$parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
142
-		$childrenToken = array_filter(array_map(function (IProfile $p) use ($profileToken) {
143
-			return $profileToken !== $p->getToken() ? $p->getToken() : null;
144
-		}, $profile->getChildren()));
145
-
146
-		// Store profile
147
-		$data = [
148
-			'token' => $profileToken,
149
-			'parent' => $parentToken,
150
-			'children' => $childrenToken,
151
-			'data' => $profile->getCollectors(),
152
-			'method' => $profile->getMethod(),
153
-			'url' => $profile->getUrl(),
154
-			'time' => $profile->getTime(),
155
-			'status_code' => $profile->getStatusCode(),
156
-		];
157
-
158
-		$context = stream_context_create();
159
-
160
-		if (\function_exists('gzcompress')) {
161
-			$file = 'compress.zlib://'.$file;
162
-			stream_context_set_option($context, 'zlib', 'level', 3);
163
-		}
164
-
165
-		if (false === file_put_contents($file, serialize($data), 0, $context)) {
166
-			return false;
167
-		}
168
-
169
-		if (!$profileIndexed) {
170
-			// Add to index
171
-			if (false === $file = fopen($this->getIndexFilename(), 'a')) {
172
-				return false;
173
-			}
174
-
175
-			fputcsv($file, [
176
-				$profile->getToken(),
177
-				$profile->getMethod(),
178
-				$profile->getUrl(),
179
-				$profile->getTime(),
180
-				$profile->getParentToken(),
181
-				$profile->getStatusCode(),
182
-			]);
183
-			fclose($file);
184
-		}
185
-
186
-		return true;
187
-	}
188
-
189
-	/**
190
-	 * Gets filename to store data, associated to the token.
191
-	 *
192
-	 * @return string The profile filename
193
-	 */
194
-	protected function getFilename(string $token): string {
195
-		// Uses 4 last characters, because first are mostly the same.
196
-		$folderA = substr($token, -2, 2);
197
-		$folderB = substr($token, -4, 2);
198
-
199
-		return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
200
-	}
201
-
202
-	/**
203
-	 * Gets the index filename.
204
-	 *
205
-	 * @return string The index filename
206
-	 */
207
-	protected function getIndexFilename(): string {
208
-		return $this->folder.'/index.csv';
209
-	}
210
-
211
-	/**
212
-	 * Reads a line in the file, backward.
213
-	 *
214
-	 * This function automatically skips the empty lines and do not include the line return in result value.
215
-	 *
216
-	 * @param resource $file The file resource, with the pointer placed at the end of the line to read
217
-	 *
218
-	 * @return ?string A string representing the line or null if beginning of file is reached
219
-	 */
220
-	protected function readLineFromFile($file): ?string {
221
-		$line = '';
222
-		$position = ftell($file);
223
-
224
-		if (0 === $position) {
225
-			return null;
226
-		}
227
-
228
-		while (true) {
229
-			$chunkSize = min($position, 1024);
230
-			$position -= $chunkSize;
231
-			fseek($file, $position);
232
-
233
-			if (0 === $chunkSize) {
234
-				// bof reached
235
-				break;
236
-			}
237
-
238
-			$buffer = fread($file, $chunkSize);
239
-
240
-			if (false === ($upTo = strrpos($buffer, "\n"))) {
241
-				$line = $buffer.$line;
242
-				continue;
243
-			}
244
-
245
-			$position += $upTo;
246
-			$line = substr($buffer, $upTo + 1).$line;
247
-			fseek($file, max(0, $position), \SEEK_SET);
248
-
249
-			if ('' !== $line) {
250
-				break;
251
-			}
252
-		}
253
-
254
-		return '' === $line ? null : $line;
255
-	}
256
-
257
-	protected function createProfileFromData(string $token, array $data, IProfile $parent = null): IProfile {
258
-		$profile = new Profile($token);
259
-		$profile->setMethod($data['method']);
260
-		$profile->setUrl($data['url']);
261
-		$profile->setTime($data['time']);
262
-		$profile->setStatusCode($data['status_code']);
263
-		$profile->setCollectors($data['data']);
264
-
265
-		if (!$parent && $data['parent']) {
266
-			$parent = $this->read($data['parent']);
267
-		}
268
-
269
-		if ($parent) {
270
-			$profile->setParent($parent);
271
-		}
272
-
273
-		foreach ($data['children'] as $token) {
274
-			if (!$token || !file_exists($file = $this->getFilename($token))) {
275
-				continue;
276
-			}
277
-
278
-			if (\function_exists('gzcompress')) {
279
-				$file = 'compress.zlib://'.$file;
280
-			}
281
-
282
-			$profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
283
-		}
284
-
285
-		return $profile;
286
-	}
35
+    // Folder where profiler data are stored.
36
+    private string $folder;
37
+
38
+    /**
39
+     * Constructs the file storage using a "dsn-like" path.
40
+     *
41
+     * Example : "file:/path/to/the/storage/folder"
42
+     *
43
+     * @throws \RuntimeException
44
+     */
45
+    public function __construct(string $folder) {
46
+        $this->folder = $folder;
47
+
48
+        if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) {
49
+            throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder));
50
+        }
51
+    }
52
+
53
+    public function find(?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array {
54
+        $file = $this->getIndexFilename();
55
+
56
+        if (!file_exists($file)) {
57
+            return [];
58
+        }
59
+
60
+        $file = fopen($file, 'r');
61
+        fseek($file, 0, \SEEK_END);
62
+
63
+        $result = [];
64
+        while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
65
+            $values = str_getcsv($line);
66
+            [$csvToken, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode] = $values;
67
+            $csvTime = (int) $csvTime;
68
+
69
+            if ($url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) {
70
+                continue;
71
+            }
72
+
73
+            if (!empty($start) && $csvTime < $start) {
74
+                continue;
75
+            }
76
+
77
+            if (!empty($end) && $csvTime > $end) {
78
+                continue;
79
+            }
80
+
81
+            $result[$csvToken] = [
82
+                'token' => $csvToken,
83
+                'method' => $csvMethod,
84
+                'url' => $csvUrl,
85
+                'time' => $csvTime,
86
+                'parent' => $csvParent,
87
+                'status_code' => $csvStatusCode,
88
+            ];
89
+        }
90
+
91
+        fclose($file);
92
+
93
+        return array_values($result);
94
+    }
95
+
96
+    public function purge(): void {
97
+        $flags = \FilesystemIterator::SKIP_DOTS;
98
+        $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
99
+        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
100
+
101
+        foreach ($iterator as $file) {
102
+            $file = (string)$file->getPathInfo();
103
+            if (is_file($file)) {
104
+                unlink($file);
105
+            } else {
106
+                rmdir($file);
107
+            }
108
+        }
109
+    }
110
+
111
+    public function read(string $token): ?IProfile {
112
+        if (!$token || !file_exists($file = $this->getFilename($token))) {
113
+            return null;
114
+        }
115
+
116
+        if (\function_exists('gzcompress')) {
117
+            $file = 'compress.zlib://'.$file;
118
+        }
119
+
120
+        return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
121
+    }
122
+
123
+    /**
124
+     * @throws \RuntimeException
125
+     */
126
+    public function write(IProfile $profile): bool {
127
+        $file = $this->getFilename($profile->getToken());
128
+
129
+        $profileIndexed = is_file($file);
130
+        if (!$profileIndexed) {
131
+            // Create directory
132
+            $dir = \dirname($file);
133
+            if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
134
+                throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir));
135
+            }
136
+        }
137
+
138
+        $profileToken = $profile->getToken();
139
+        // when there are errors in sub-requests, the parent and/or children tokens
140
+        // may equal the profile token, resulting in infinite loops
141
+        $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
142
+        $childrenToken = array_filter(array_map(function (IProfile $p) use ($profileToken) {
143
+            return $profileToken !== $p->getToken() ? $p->getToken() : null;
144
+        }, $profile->getChildren()));
145
+
146
+        // Store profile
147
+        $data = [
148
+            'token' => $profileToken,
149
+            'parent' => $parentToken,
150
+            'children' => $childrenToken,
151
+            'data' => $profile->getCollectors(),
152
+            'method' => $profile->getMethod(),
153
+            'url' => $profile->getUrl(),
154
+            'time' => $profile->getTime(),
155
+            'status_code' => $profile->getStatusCode(),
156
+        ];
157
+
158
+        $context = stream_context_create();
159
+
160
+        if (\function_exists('gzcompress')) {
161
+            $file = 'compress.zlib://'.$file;
162
+            stream_context_set_option($context, 'zlib', 'level', 3);
163
+        }
164
+
165
+        if (false === file_put_contents($file, serialize($data), 0, $context)) {
166
+            return false;
167
+        }
168
+
169
+        if (!$profileIndexed) {
170
+            // Add to index
171
+            if (false === $file = fopen($this->getIndexFilename(), 'a')) {
172
+                return false;
173
+            }
174
+
175
+            fputcsv($file, [
176
+                $profile->getToken(),
177
+                $profile->getMethod(),
178
+                $profile->getUrl(),
179
+                $profile->getTime(),
180
+                $profile->getParentToken(),
181
+                $profile->getStatusCode(),
182
+            ]);
183
+            fclose($file);
184
+        }
185
+
186
+        return true;
187
+    }
188
+
189
+    /**
190
+     * Gets filename to store data, associated to the token.
191
+     *
192
+     * @return string The profile filename
193
+     */
194
+    protected function getFilename(string $token): string {
195
+        // Uses 4 last characters, because first are mostly the same.
196
+        $folderA = substr($token, -2, 2);
197
+        $folderB = substr($token, -4, 2);
198
+
199
+        return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
200
+    }
201
+
202
+    /**
203
+     * Gets the index filename.
204
+     *
205
+     * @return string The index filename
206
+     */
207
+    protected function getIndexFilename(): string {
208
+        return $this->folder.'/index.csv';
209
+    }
210
+
211
+    /**
212
+     * Reads a line in the file, backward.
213
+     *
214
+     * This function automatically skips the empty lines and do not include the line return in result value.
215
+     *
216
+     * @param resource $file The file resource, with the pointer placed at the end of the line to read
217
+     *
218
+     * @return ?string A string representing the line or null if beginning of file is reached
219
+     */
220
+    protected function readLineFromFile($file): ?string {
221
+        $line = '';
222
+        $position = ftell($file);
223
+
224
+        if (0 === $position) {
225
+            return null;
226
+        }
227
+
228
+        while (true) {
229
+            $chunkSize = min($position, 1024);
230
+            $position -= $chunkSize;
231
+            fseek($file, $position);
232
+
233
+            if (0 === $chunkSize) {
234
+                // bof reached
235
+                break;
236
+            }
237
+
238
+            $buffer = fread($file, $chunkSize);
239
+
240
+            if (false === ($upTo = strrpos($buffer, "\n"))) {
241
+                $line = $buffer.$line;
242
+                continue;
243
+            }
244
+
245
+            $position += $upTo;
246
+            $line = substr($buffer, $upTo + 1).$line;
247
+            fseek($file, max(0, $position), \SEEK_SET);
248
+
249
+            if ('' !== $line) {
250
+                break;
251
+            }
252
+        }
253
+
254
+        return '' === $line ? null : $line;
255
+    }
256
+
257
+    protected function createProfileFromData(string $token, array $data, IProfile $parent = null): IProfile {
258
+        $profile = new Profile($token);
259
+        $profile->setMethod($data['method']);
260
+        $profile->setUrl($data['url']);
261
+        $profile->setTime($data['time']);
262
+        $profile->setStatusCode($data['status_code']);
263
+        $profile->setCollectors($data['data']);
264
+
265
+        if (!$parent && $data['parent']) {
266
+            $parent = $this->read($data['parent']);
267
+        }
268
+
269
+        if ($parent) {
270
+            $profile->setParent($parent);
271
+        }
272
+
273
+        foreach ($data['children'] as $token) {
274
+            if (!$token || !file_exists($file = $this->getFilename($token))) {
275
+                continue;
276
+            }
277
+
278
+            if (\function_exists('gzcompress')) {
279
+                $file = 'compress.zlib://'.$file;
280
+            }
281
+
282
+            $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
283
+        }
284
+
285
+        return $profile;
286
+    }
287 287
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-declare(strict_types = 1);
3
+declare(strict_types=1);
4 4
 /**
5 5
  * @copyright 2022 Carl Schwan <[email protected]>
6 6
  *
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 		$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
100 100
 
101 101
 		foreach ($iterator as $file) {
102
-			$file = (string)$file->getPathInfo();
102
+			$file = (string) $file->getPathInfo();
103 103
 			if (is_file($file)) {
104 104
 				unlink($file);
105 105
 			} else {
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
 		// when there are errors in sub-requests, the parent and/or children tokens
140 140
 		// may equal the profile token, resulting in infinite loops
141 141
 		$parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
142
-		$childrenToken = array_filter(array_map(function (IProfile $p) use ($profileToken) {
142
+		$childrenToken = array_filter(array_map(function(IProfile $p) use ($profileToken) {
143 143
 			return $profileToken !== $p->getToken() ? $p->getToken() : null;
144 144
 		}, $profile->getChildren()));
145 145
 
Please login to merge, or discard this patch.