* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Storage for profiler using files * * @author Alexandre Salomé */ class FileProfilerStorage implements ProfilerStorageInterface { /** * Folder where profiler data are stored * * @var string */ private $folder; /** * Construct the file storage using a "dsn-like" path : * * "file:/path/to/the/storage/folder" * * @param string $dsn The DSN */ public function __construct($dsn) { if (0 !== strpos($dsn, 'file:')) { throw new \InvalidArgumentException("FileStorage DSN must start with file:"); } $this->folder = substr($dsn, 5); if (!is_dir($this->folder)) { mkdir($this->folder); } } /** * {@inheritdoc} */ public function find($ip, $url, $limit) { $file = $this->getIndexFilename(); if (!file_exists($file)) { return array(); } $file = fopen($file, 'r'); $result = array(); while (!feof($file) && $limit > 0) { list($csvToken, $csvIp, $csvUrl, $csvTime, $csvParent) = fgetcsv($file); $row = array( 'token' => $csvToken, 'ip' => $csvIp, 'url' => $csvUrl, 'time' => $csvTime, 'parent' => $csvParent ); if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url)) { continue; } $result[] = $row; $limit--; } fclose($file); return $result; } /** * {@inheritdoc} */ public function purge() { $flags = \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $file) { if (is_file($file)) { unlink($file); } } } /** * {@inheritdoc} */ public function read($token) { $file = $this->getFilename($token); if (!file_exists($file)) { return null; } return unserialize(file_get_contents($file)); } /** * {@inheritdoc} */ public function write(Profile $profile) { $file = $this->getFilename($profile->getToken()); if (file_exists($file)) { return false; } // Create directory $dir = dirname($file); if (!is_dir($dir)) { mkdir($dir, 0777, true); } // Store profile file_put_contents($file, serialize($profile)); // Add to index $file = fopen($this->getIndexFilename(), 'a'); fputcsv($file, array( $profile->getToken(), $profile->getIp(), $profile->getUrl(), $profile->getTime(), $profile->getParent() ? $profile->getParent()->getToken() : null )); fclose($file); return true; } /** * Get filename to store data, associated to the token * * @return string The profile filename */ protected function getFilename($token) { // Use 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; } /** * Get the index filename * * @return string The index filename */ protected function getIndexFilename() { return $this->folder.'/'.'index.csv'; } }