class FileProfilerStorage in Zircon Profile 8
Same name and namespace in other branches
- 8.0 vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php \Symfony\Component\HttpKernel\Profiler\FileProfilerStorage
Storage for profiler using files.
@author Alexandre Salomé <alexandre.salome@gmail.com>
Hierarchy
- class \Symfony\Component\HttpKernel\Profiler\FileProfilerStorage implements ProfilerStorageInterface
Expanded class hierarchy of FileProfilerStorage
1 file declares its use of FileProfilerStorage
- FileProfilerStorageTest.php in vendor/
symfony/ http-kernel/ Tests/ Profiler/ FileProfilerStorageTest.php
File
- vendor/
symfony/ http-kernel/ Profiler/ FileProfilerStorage.php, line 19
Namespace
Symfony\Component\HttpKernel\ProfilerView source
class FileProfilerStorage implements ProfilerStorageInterface {
/**
* Folder where profiler data are stored.
*
* @var string
*/
private $folder;
/**
* Constructs the file storage using a "dsn-like" path.
*
* Example : "file:/path/to/the/storage/folder"
*
* @param string $dsn The DSN
*
* @throws \RuntimeException
*/
public function __construct($dsn) {
if (0 !== strpos($dsn, 'file:')) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn));
}
$this->folder = substr($dsn, 5);
if (!is_dir($this->folder)) {
mkdir($this->folder, 0777, true);
}
}
/**
* {@inheritdoc}
*/
public function find($ip, $url, $limit, $method, $start = null, $end = null) {
$file = $this
->getIndexFilename();
if (!file_exists($file)) {
return array();
}
$file = fopen($file, 'r');
fseek($file, 0, SEEK_END);
$result = array();
while (count($result) < $limit && ($line = $this
->readLineFromFile($file))) {
$values = str_getcsv($line);
list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = $values;
$csvStatusCode = isset($values[6]) ? $values[6] : null;
$csvTime = (int) $csvTime;
if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method)) {
continue;
}
if (!empty($start) && $csvTime < $start) {
continue;
}
if (!empty($end) && $csvTime > $end) {
continue;
}
$result[$csvToken] = array(
'token' => $csvToken,
'ip' => $csvIp,
'method' => $csvMethod,
'url' => $csvUrl,
'time' => $csvTime,
'parent' => $csvParent,
'status_code' => $csvStatusCode,
);
}
fclose($file);
return array_values($result);
}
/**
* {@inheritdoc}
*/
public function purge() {
$flags = \FilesystemIterator::SKIP_DOTS;
$iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
foreach ($iterator as $file) {
if (is_file($file)) {
unlink($file);
}
else {
rmdir($file);
}
}
}
/**
* {@inheritdoc}
*/
public function read($token) {
if (!$token || !file_exists($file = $this
->getFilename($token))) {
return;
}
return $this
->createProfileFromData($token, unserialize(file_get_contents($file)));
}
/**
* {@inheritdoc}
*/
public function write(Profile $profile) {
$file = $this
->getFilename($profile
->getToken());
$profileIndexed = is_file($file);
if (!$profileIndexed) {
// Create directory
$dir = dirname($file);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
}
// Store profile
$data = array(
'token' => $profile
->getToken(),
'parent' => $profile
->getParentToken(),
'children' => array_map(function ($p) {
return $p
->getToken();
}, $profile
->getChildren()),
'data' => $profile
->getCollectors(),
'ip' => $profile
->getIp(),
'method' => $profile
->getMethod(),
'url' => $profile
->getUrl(),
'time' => $profile
->getTime(),
);
if (false === file_put_contents($file, serialize($data))) {
return false;
}
if (!$profileIndexed) {
// Add to index
if (false === ($file = fopen($this
->getIndexFilename(), 'a'))) {
return false;
}
fputcsv($file, array(
$profile
->getToken(),
$profile
->getIp(),
$profile
->getMethod(),
$profile
->getUrl(),
$profile
->getTime(),
$profile
->getParentToken(),
$profile
->getStatusCode(),
));
fclose($file);
}
return true;
}
/**
* Gets filename to store data, associated to the token.
*
* @param string $token
*
* @return string The profile filename
*/
protected function getFilename($token) {
// Uses 4 last characters, because first are mostly the same.
$folderA = substr($token, -2, 2);
$folderB = substr($token, -4, 2);
return $this->folder . '/' . $folderA . '/' . $folderB . '/' . $token;
}
/**
* Gets the index filename.
*
* @return string The index filename
*/
protected function getIndexFilename() {
return $this->folder . '/index.csv';
}
/**
* Reads a line in the file, backward.
*
* This function automatically skips the empty lines and do not include the line return in result value.
*
* @param resource $file The file resource, with the pointer placed at the end of the line to read
*
* @return mixed A string representing the line or null if beginning of file is reached
*/
protected function readLineFromFile($file) {
$line = '';
$position = ftell($file);
if (0 === $position) {
return;
}
while (true) {
$chunkSize = min($position, 1024);
$position -= $chunkSize;
fseek($file, $position);
if (0 === $chunkSize) {
// bof reached
break;
}
$buffer = fread($file, $chunkSize);
if (false === ($upTo = strrpos($buffer, "\n"))) {
$line = $buffer . $line;
continue;
}
$position += $upTo;
$line = substr($buffer, $upTo + 1) . $line;
fseek($file, max(0, $position), SEEK_SET);
if ('' !== $line) {
break;
}
}
return '' === $line ? null : $line;
}
protected function createProfileFromData($token, $data, $parent = null) {
$profile = new Profile($token);
$profile
->setIp($data['ip']);
$profile
->setMethod($data['method']);
$profile
->setUrl($data['url']);
$profile
->setTime($data['time']);
$profile
->setCollectors($data['data']);
if (!$parent && $data['parent']) {
$parent = $this
->read($data['parent']);
}
if ($parent) {
$profile
->setParent($parent);
}
foreach ($data['children'] as $token) {
if (!$token || !file_exists($file = $this
->getFilename($token))) {
continue;
}
$profile
->addChild($this
->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
}
return $profile;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
FileProfilerStorage:: |
private | property | Folder where profiler data are stored. | |
FileProfilerStorage:: |
protected | function | ||
FileProfilerStorage:: |
public | function |
Finds profiler tokens for the given criteria. Overrides ProfilerStorageInterface:: |
|
FileProfilerStorage:: |
protected | function | Gets filename to store data, associated to the token. | |
FileProfilerStorage:: |
protected | function | Gets the index filename. | |
FileProfilerStorage:: |
public | function |
Purges all data from the database. Overrides ProfilerStorageInterface:: |
|
FileProfilerStorage:: |
public | function |
Reads data associated with the given token. Overrides ProfilerStorageInterface:: |
|
FileProfilerStorage:: |
protected | function | Reads a line in the file, backward. | |
FileProfilerStorage:: |
public | function |
Saves a Profile. Overrides ProfilerStorageInterface:: |
|
FileProfilerStorage:: |
public | function | Constructs the file storage using a "dsn-like" path. |