Skip to content

Commit 6a0acfe

Browse files
committed
added FileSession, used by default [Closes #362][Closes #356]
1 parent eaf2af3 commit 6a0acfe

File tree

9 files changed

+134
-19
lines changed

9 files changed

+134
-19
lines changed

examples/ajax-fetch.php

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
use Tracy\Debugger;
88

9-
// session is required for this functionality
10-
session_start();
11-
129
// For security reasons, Tracy is visible only on localhost.
1310
// You may force Tracy to run in development mode by passing the Debugger::DEVELOPMENT instead of Debugger::DETECT.
1411
Debugger::enable(Debugger::DETECT, __DIR__ . '/log');

examples/ajax-jquery.php

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
use Tracy\Debugger;
88

9-
// session is required for this functionality
10-
session_start();
11-
129
// For security reasons, Tracy is visible only on localhost.
1310
// You may force Tracy to run in development mode by passing the Debugger::DEVELOPMENT instead of Debugger::DETECT.
1411
Debugger::enable(Debugger::DETECT, __DIR__ . '/log');

examples/preloading.php

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
use Tracy\Debugger;
88

9-
// session is required for this functionality
10-
session_start();
11-
129
// For security reasons, Tracy is visible only on localhost.
1310
// You may force Tracy to run in development mode by passing the Debugger::DEVELOPMENT instead of Debugger::DETECT.
1411
Debugger::enable(Debugger::DETECT, __DIR__ . '/log');

examples/redirect.php

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
use Tracy\Debugger;
88

9-
// session is required for this functionality
10-
session_start();
11-
129
// For security reasons, Tracy is visible only on localhost.
1310
// You may force Tracy to run in development mode by passing the Debugger::DEVELOPMENT instead of Debugger::DETECT.
1411
Debugger::enable(Debugger::DETECT, __DIR__ . '/log');

readme.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,18 @@ any scripts:
177177
AJAX and redirected requests
178178
----------------------------
179179

180-
Tracy is able to show Debug bar and Bluescreens for AJAX and redirected requests. You just have to start session before Tracy:
180+
Tracy is able to show Debug bar and Bluescreens for AJAX and redirected requests. Tracy keeps the data in a temporary files and uses the `tracy-session` cookie. Tracy can be configured to use a standard PHP session:
181181

182182
```php
183-
session_start();
183+
Debugger::setSessionStorage(new Tracy\NativeSession);
184184
Debugger::enable();
185185
```
186186

187187
In case you use non-standard session handler, you can start Tracy immediately (in order to handle any errors), then initialize your session handler
188188
and then inform Tracy that session is ready to use via `dispatch()`:
189189

190190
```php
191+
Debugger::setSessionStorage(new Tracy\NativeSession);
191192
Debugger::enable();
192193

193194
// initialize session handler

src/Bridges/Nette/TracyExtension.php

+14-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public function getConfigSchema(): Nette\Schema\Schema
4040
'fromEmail' => Expect::email()->dynamic(),
4141
'emailSnooze' => Expect::string()->dynamic(),
4242
'logSeverity' => Expect::anyOf(Expect::scalar(), Expect::listOf('scalar')),
43+
'storage' => Expect::string(),
4344
'editor' => Expect::string()->dynamic(),
4445
'browser' => Expect::string()->dynamic(),
4546
'errorTemplate' => Expect::string()->dynamic(),
@@ -83,7 +84,7 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class)
8384
$builder = $this->getContainerBuilder();
8485

8586
$options = (array) $this->config;
86-
unset($options['bar'], $options['blueScreen'], $options['netteMailer']);
87+
unset($options['bar'], $options['blueScreen'], $options['netteMailer'], $options['storage']);
8788
if (isset($options['logSeverity'])) {
8889
$res = 0;
8990
foreach ((array) $options['logSeverity'] as $level) {
@@ -135,9 +136,18 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class)
135136
));
136137
}
137138

138-
if (!$this->cliMode && ($name = $builder->getByType(Nette\Http\Session::class))) {
139-
$initialize->addBody('$this->getService(?)->start();', [$name]);
140-
$initialize->addBody('Tracy\Debugger::dispatch();');
139+
if (!$this->cliMode) {
140+
if ($this->config->storage === 'session') {
141+
if ($name = $builder->getByType(Nette\Http\Session::class)) {
142+
$initialize->addBody('$this->getService(?)->start();', [$name]);
143+
}
144+
145+
$initialize->addBody('Tracy\Debugger::dispatch();');
146+
147+
} elseif ($this->config->storage !== null) {
148+
$initialize->addBody('Tracy\Debugger::setStorage(new Tracy\FileSession(?));', [$this->config->storage]);
149+
$initialize->addBody('Tracy\Debugger::dispatch();');
150+
}
141151
}
142152
}
143153

src/Tracy/Debugger/Debugger.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ public static function enable($mode = null, ?string $logDirectory = null, $email
235235
'Logger/FireLogger',
236236
'Logger/Logger',
237237
'Session/SessionStorage',
238+
'Session/FileSession',
238239
'Session/NativeSession',
239240
'Helpers',
240241
] as $path) {
@@ -482,7 +483,12 @@ public static function setSessionStorage(SessionStorage $storage): void
482483
public static function getSessionStorage(): SessionStorage
483484
{
484485
if (!self::$sessionStorage) {
485-
self::$sessionStorage = new NativeSession;
486+
return is_dir($dir = session_save_path())
487+
|| is_dir($dir = ini_get('upload_tmp_dir'))
488+
|| is_dir($dir = sys_get_temp_dir())
489+
|| ($dir = self::$logDirectory)
490+
? new FileSession($dir)
491+
: new NativeSession;
486492
}
487493

488494
return self::$sessionStorage;

src/Tracy/Session/FileSession.php

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Tracy (https://tracy.nette.org)
5+
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Tracy;
11+
12+
13+
class FileSession implements SessionStorage
14+
{
15+
private const FILE_PREFIX = 'tracy-';
16+
private const COOKIE_LIFETIME = 31557600;
17+
18+
/** @var string */
19+
public $cookieName = 'tracy-session';
20+
21+
/** @var float probability that the clean() routine is started */
22+
public $gcProbability = 0.001;
23+
24+
/** @var string */
25+
private $dir;
26+
27+
/** @var resource */
28+
private $file;
29+
30+
/** @var array */
31+
private $data = [];
32+
33+
34+
public function __construct(string $dir)
35+
{
36+
$this->dir = $dir;
37+
}
38+
39+
40+
public function isAvailable(): bool
41+
{
42+
if (!$this->file) {
43+
$this->open();
44+
}
45+
46+
return true;
47+
}
48+
49+
50+
private function open(): void
51+
{
52+
$id = $_COOKIE[$this->cookieName] ?? null;
53+
if (
54+
!is_string($id)
55+
|| !preg_match('#^\w{10}\z#i', $id)
56+
|| !($file = @fopen($path = $this->dir . '/' . self::FILE_PREFIX . $id, 'r+')) // intentionally @
57+
) {
58+
$id = Helpers::createId();
59+
setcookie($this->cookieName, $id, time() + self::COOKIE_LIFETIME, '/', '', false, true);
60+
61+
$file = @fopen($path = $this->dir . '/' . self::FILE_PREFIX . $id, 'c+'); // intentionally @
62+
if ($file === false) {
63+
throw new \RuntimeException("Unable to create file '$path'. " . error_get_last()['message']);
64+
}
65+
}
66+
67+
if (!@flock($file, LOCK_EX)) { // intentionally @
68+
throw new \RuntimeException("Unable to acquire exclusive lock on '$path'. ", error_get_last()['message']);
69+
}
70+
71+
$this->file = $file;
72+
$this->data = @unserialize(stream_get_contents($this->file)) ?: []; // @ - file may be empty
73+
74+
if (mt_rand() / mt_getrandmax() < $this->gcProbability) {
75+
$this->clean();
76+
}
77+
}
78+
79+
80+
public function &getData(): array
81+
{
82+
return $this->data;
83+
}
84+
85+
86+
public function clean(): void
87+
{
88+
$old = strtotime('-1 week');
89+
foreach (glob($this->dir . '/' . self::FILE_PREFIX . '*') as $file) {
90+
if (filemtime($file) < $old) {
91+
unlink($file);
92+
}
93+
}
94+
}
95+
96+
97+
public function __destruct()
98+
{
99+
if (!$this->file) {
100+
return;
101+
}
102+
103+
ftruncate($this->file, 0);
104+
fseek($this->file, 0);
105+
fwrite($this->file, serialize($this->data));
106+
fclose($this->file);
107+
$this->file = null;
108+
}
109+
}

src/tracy.php

+1
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@
2727
require __DIR__ . '/Tracy/OutputDebugger/OutputDebugger.php';
2828
require __DIR__ . '/Tracy/Session/SessionStorage.php';
2929
require __DIR__ . '/Tracy/Session/NativeSession.php';
30+
require __DIR__ . '/Tracy/Session/FileSession.php';
3031
require __DIR__ . '/Tracy/Helpers.php';
3132
require __DIR__ . '/Tracy/functions.php';

0 commit comments

Comments
 (0)