Essai au propre

This commit is contained in:
Gauvain Boiché
2020-04-01 16:45:39 +02:00
parent f282fd0d32
commit 745270ab61
1538 changed files with 80 additions and 351590 deletions

View File

@@ -1,313 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\BaseMemcacheProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* Base Memcache storage for profiling information in a Memcache.
*
* @author Andrej Hudec <pulzarraider@gmail.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface
{
const TOKEN_PREFIX = 'sf_profiler_';
protected $dsn;
protected $lifetime;
/**
* @param string $dsn A data source name
* @param string $username
* @param string $password
* @param int $lifetime The lifetime to use for the purge
*/
public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
{
$this->dsn = $dsn;
$this->lifetime = (int) $lifetime;
}
/**
* {@inheritdoc}
*/
public function find($ip, $url, $limit, $method, $start = null, $end = null)
{
$indexName = $this->getIndexName();
$indexContent = $this->getValue($indexName);
if (!$indexContent) {
return array();
}
$profileList = explode("\n", $indexContent);
$result = array();
foreach ($profileList as $item) {
if (0 === $limit) {
break;
}
if ('' == $item) {
continue;
}
$values = explode("\t", $item, 7);
list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = $values;
$statusCode = isset($values[6]) ? $values[6] : null;
$itemTime = (int) $itemTime;
if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
continue;
}
if (!empty($start) && $itemTime < $start) {
continue;
}
if (!empty($end) && $itemTime > $end) {
continue;
}
$result[$itemToken] = array(
'token' => $itemToken,
'ip' => $itemIp,
'method' => $itemMethod,
'url' => $itemUrl,
'time' => $itemTime,
'parent' => $itemParent,
'status_code' => $statusCode,
);
--$limit;
}
usort($result, function ($a, $b) {
if ($a['time'] === $b['time']) {
return 0;
}
return $a['time'] > $b['time'] ? -1 : 1;
});
return $result;
}
/**
* {@inheritdoc}
*/
public function purge()
{
// delete only items from index
$indexName = $this->getIndexName();
$indexContent = $this->getValue($indexName);
if (!$indexContent) {
return false;
}
$profileList = explode("\n", $indexContent);
foreach ($profileList as $item) {
if ('' == $item) {
continue;
}
if (false !== $pos = strpos($item, "\t")) {
$this->delete($this->getItemName(substr($item, 0, $pos)));
}
}
return $this->delete($indexName);
}
/**
* {@inheritdoc}
*/
public function read($token)
{
if (empty($token)) {
return false;
}
$profile = $this->getValue($this->getItemName($token));
if (false !== $profile) {
$profile = $this->createProfileFromData($token, $profile);
}
return $profile;
}
/**
* {@inheritdoc}
*/
public function write(Profile $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(),
);
$profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));
if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime)) {
if (!$profileIndexed) {
// Add to index
$indexName = $this->getIndexName();
$indexRow = implode("\t", array(
$profile->getToken(),
$profile->getIp(),
$profile->getMethod(),
$profile->getUrl(),
$profile->getTime(),
$profile->getParentToken(),
$profile->getStatusCode(),
))."\n";
return $this->appendValue($indexName, $indexRow, $this->lifetime);
}
return true;
}
return false;
}
/**
* Retrieve item from the memcache server.
*
* @param string $key
*
* @return mixed
*/
abstract protected function getValue($key);
/**
* Store an item on the memcache server under the specified key.
*
* @param string $key
* @param mixed $value
* @param int $expiration
*
* @return bool
*/
abstract protected function setValue($key, $value, $expiration = 0);
/**
* Delete item from the memcache server.
*
* @param string $key
*
* @return bool
*/
abstract protected function delete($key);
/**
* Append data to an existing item on the memcache server.
*
* @param string $key
* @param string $value
* @param int $expiration
*
* @return bool
*/
abstract protected function appendValue($key, $value, $expiration = 0);
private 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) {
continue;
}
if (!$childProfileData = $this->getValue($this->getItemName($token))) {
continue;
}
$profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
}
return $profile;
}
/**
* Get item name.
*
* @param string $token
*
* @return string
*/
private function getItemName($token)
{
$name = self::TOKEN_PREFIX.$token;
if ($this->isItemNameValid($name)) {
return $name;
}
return false;
}
/**
* Get name of index.
*
* @return string
*/
private function getIndexName()
{
$name = self::TOKEN_PREFIX.'index';
if ($this->isItemNameValid($name)) {
return $name;
}
return false;
}
private function isItemNameValid($name)
{
$length = \strlen($name);
if ($length > 250) {
throw new \RuntimeException(sprintf('The memcache item key "%s" is too long (%s bytes). Allowed maximum size is 250 bytes.', $name, $length));
}
return true;
}
}

View File

@@ -1,112 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\MemcacheProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* Memcache Profiler Storage.
*
* @author Andrej Hudec <pulzarraider@gmail.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
class MemcacheProfilerStorage extends BaseMemcacheProfilerStorage
{
/**
* @var \Memcache
*/
private $memcache;
/**
* Internal convenience method that returns the instance of the Memcache.
*
* @return \Memcache
*
* @throws \RuntimeException
*/
protected function getMemcache()
{
if (null === $this->memcache) {
if (!preg_match('#^memcache://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcache with an invalid dsn "%s". The expected format is "memcache://[host]:port".', $this->dsn));
}
$host = $matches[1] ?: $matches[2];
$port = $matches[3];
$memcache = new \Memcache();
$memcache->addServer($host, $port);
$this->memcache = $memcache;
}
return $this->memcache;
}
/**
* Set instance of the Memcache.
*
* @param \Memcache $memcache
*/
public function setMemcache($memcache)
{
$this->memcache = $memcache;
}
/**
* {@inheritdoc}
*/
protected function getValue($key)
{
return $this->getMemcache()->get($key);
}
/**
* {@inheritdoc}
*/
protected function setValue($key, $value, $expiration = 0)
{
return $this->getMemcache()->set($key, $value, false, time() + $expiration);
}
/**
* {@inheritdoc}
*/
protected function delete($key)
{
return $this->getMemcache()->delete($key);
}
/**
* {@inheritdoc}
*/
protected function appendValue($key, $value, $expiration = 0)
{
$memcache = $this->getMemcache();
if (method_exists($memcache, 'append')) {
// Memcache v3.0
if (!$result = $memcache->append($key, $value, false, $expiration)) {
return $memcache->set($key, $value, false, $expiration);
}
return $result;
}
// simulate append in Memcache <3.0
$content = $memcache->get($key);
return $memcache->set($key, $content.$value, false, $expiration);
}
}

View File

@@ -1,108 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\MemcachedProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* Memcached Profiler Storage.
*
* @author Andrej Hudec <pulzarraider@gmail.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
class MemcachedProfilerStorage extends BaseMemcacheProfilerStorage
{
/**
* @var \Memcached
*/
private $memcached;
/**
* Internal convenience method that returns the instance of the Memcached.
*
* @return \Memcached
*
* @throws \RuntimeException
*/
protected function getMemcached()
{
if (null === $this->memcached) {
if (!preg_match('#^memcached://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcached with an invalid dsn "%s". The expected format is "memcached://[host]:port".', $this->dsn));
}
$host = $matches[1] ?: $matches[2];
$port = $matches[3];
$memcached = new \Memcached();
// disable compression to allow appending
$memcached->setOption(\Memcached::OPT_COMPRESSION, false);
$memcached->addServer($host, $port);
$this->memcached = $memcached;
}
return $this->memcached;
}
/**
* Set instance of the Memcached.
*
* @param \Memcached $memcached
*/
public function setMemcached($memcached)
{
$this->memcached = $memcached;
}
/**
* {@inheritdoc}
*/
protected function getValue($key)
{
return $this->getMemcached()->get($key);
}
/**
* {@inheritdoc}
*/
protected function setValue($key, $value, $expiration = 0)
{
return $this->getMemcached()->set($key, $value, time() + $expiration);
}
/**
* {@inheritdoc}
*/
protected function delete($key)
{
return $this->getMemcached()->delete($key);
}
/**
* {@inheritdoc}
*/
protected function appendValue($key, $value, $expiration = 0)
{
$memcached = $this->getMemcached();
if (!$result = $memcached->append($key, $value)) {
return $memcached->set($key, $value, $expiration);
}
return $result;
}
}

View File

@@ -1,257 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\MongoDbProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
class MongoDbProfilerStorage implements ProfilerStorageInterface
{
protected $dsn;
protected $lifetime;
private $mongo;
/**
* @param string $dsn A data source name
* @param string $username Not used
* @param string $password Not used
* @param int $lifetime The lifetime to use for the purge
*/
public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
{
$this->dsn = $dsn;
$this->lifetime = (int) $lifetime;
}
/**
* {@inheritdoc}
*/
public function find($ip, $url, $limit, $method, $start = null, $end = null)
{
$cursor = $this->getMongo()->find($this->buildQuery($ip, $url, $method, $start, $end), array('_id', 'parent', 'ip', 'method', 'url', 'time', 'status_code'))->sort(array('time' => -1))->limit($limit);
$tokens = array();
foreach ($cursor as $profile) {
$tokens[] = $this->getData($profile);
}
return $tokens;
}
/**
* {@inheritdoc}
*/
public function purge()
{
$this->getMongo()->remove(array());
}
/**
* {@inheritdoc}
*/
public function read($token)
{
$profile = $this->getMongo()->findOne(array('_id' => $token, 'data' => array('$exists' => true)));
if (null !== $profile) {
$profile = $this->createProfileFromData($this->getData($profile));
}
return $profile;
}
/**
* {@inheritdoc}
*/
public function write(Profile $profile)
{
$this->cleanup();
$record = array(
'_id' => $profile->getToken(),
'parent' => $profile->getParentToken(),
'data' => base64_encode(serialize($profile->getCollectors())),
'ip' => $profile->getIp(),
'method' => $profile->getMethod(),
'url' => $profile->getUrl(),
'time' => $profile->getTime(),
'status_code' => $profile->getStatusCode(),
);
$result = $this->getMongo()->update(array('_id' => $profile->getToken()), array_filter($record, function ($v) { return !empty($v); }), array('upsert' => true));
return (bool) (isset($result['ok']) ? $result['ok'] : $result);
}
/**
* Internal convenience method that returns the instance of the MongoDB Collection.
*
* @return \MongoCollection
*
* @throws \RuntimeException
*/
protected function getMongo()
{
if (null !== $this->mongo) {
return $this->mongo;
}
if (!$parsedDsn = $this->parseDsn($this->dsn)) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use MongoDB with an invalid dsn "%s". The expected format is "mongodb://[user:pass@]host/database/collection"', $this->dsn));
}
list($server, $database, $collection) = $parsedDsn;
$mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? '\Mongo' : '\MongoClient';
$mongo = new $mongoClass($server);
return $this->mongo = $mongo->selectCollection($database, $collection);
}
/**
* @return Profile
*/
protected function createProfileFromData(array $data)
{
$profile = $this->getProfile($data);
if ($data['parent']) {
$parent = $this->getMongo()->findOne(array('_id' => $data['parent'], 'data' => array('$exists' => true)));
if ($parent) {
$profile->setParent($this->getProfile($this->getData($parent)));
}
}
$profile->setChildren($this->readChildren($data['token']));
return $profile;
}
/**
* @param string $token
*
* @return Profile[] An array of Profile instances
*/
protected function readChildren($token)
{
$profiles = array();
$cursor = $this->getMongo()->find(array('parent' => $token, 'data' => array('$exists' => true)));
foreach ($cursor as $d) {
$profiles[] = $this->getProfile($this->getData($d));
}
return $profiles;
}
protected function cleanup()
{
$this->getMongo()->remove(array('time' => array('$lt' => time() - $this->lifetime)));
}
/**
* @param string $ip
* @param string $url
* @param string $method
* @param int $start
* @param int $end
*
* @return array
*/
private function buildQuery($ip, $url, $method, $start, $end)
{
$query = array();
if (!empty($ip)) {
$query['ip'] = $ip;
}
if (!empty($url)) {
$query['url'] = $url;
}
if (!empty($method)) {
$query['method'] = $method;
}
if (!empty($start) || !empty($end)) {
$query['time'] = array();
}
if (!empty($start)) {
$query['time']['$gte'] = $start;
}
if (!empty($end)) {
$query['time']['$lte'] = $end;
}
return $query;
}
/**
* @return array
*/
private function getData(array $data)
{
return array(
'token' => $data['_id'],
'parent' => isset($data['parent']) ? $data['parent'] : null,
'ip' => isset($data['ip']) ? $data['ip'] : null,
'method' => isset($data['method']) ? $data['method'] : null,
'url' => isset($data['url']) ? $data['url'] : null,
'time' => isset($data['time']) ? $data['time'] : null,
'data' => isset($data['data']) ? $data['data'] : null,
'status_code' => isset($data['status_code']) ? $data['status_code'] : null,
);
}
/**
* @return Profile
*/
private function getProfile(array $data)
{
$profile = new Profile($data['token']);
$profile->setIp($data['ip']);
$profile->setMethod($data['method']);
$profile->setUrl($data['url']);
$profile->setTime($data['time']);
$profile->setCollectors(unserialize(base64_decode($data['data'])));
return $profile;
}
/**
* @param string $dsn
*
* @return array|null Array($server, $database, $collection)
*/
private function parseDsn($dsn)
{
if (!preg_match('#^(mongodb://.*)/(.*)/(.*)$#', $dsn, $matches)) {
return;
}
$server = $matches[1];
$database = $matches[2];
$collection = $matches[3];
preg_match('#^mongodb://(([^:]+):?(.*)(?=@))?@?([^/]*)(.*)$#', $server, $matchesServer);
if ('' == $matchesServer[5] && '' != $matches[2]) {
$server .= '/'.$matches[2];
}
return array($server, $database, $collection);
}
}

View File

@@ -1,84 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\MysqlProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* A ProfilerStorage for Mysql.
*
* @author Jan Schumann <js@schumann-it.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
class MysqlProfilerStorage extends PdoProfilerStorage
{
/**
* {@inheritdoc}
*/
protected function initDb()
{
if (null === $this->db) {
if (0 !== strpos($this->dsn, 'mysql')) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Mysql with an invalid dsn "%s". The expected format is "mysql:dbname=database_name;host=host_name".', $this->dsn));
}
if (!class_exists('PDO') || !\in_array('mysql', \PDO::getAvailableDrivers(), true)) {
throw new \RuntimeException('You need to enable PDO_Mysql extension for the profiler to run properly.');
}
$db = new \PDO($this->dsn, $this->username, $this->password);
$db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token VARCHAR(255) PRIMARY KEY, data LONGTEXT, ip VARCHAR(64), method VARCHAR(6), url VARCHAR(255), time INTEGER UNSIGNED, parent VARCHAR(255), created_at INTEGER UNSIGNED, status_code SMALLINT UNSIGNED, KEY (created_at), KEY (ip), KEY (method), KEY (url), KEY (parent))');
$this->db = $db;
}
return $this->db;
}
/**
* {@inheritdoc}
*/
protected function buildCriteria($ip, $url, $start, $end, $limit, $method)
{
$criteria = array();
$args = array();
if ($ip = preg_replace('/[^\d\.]/', '', $ip)) {
$criteria[] = 'ip LIKE :ip';
$args[':ip'] = '%'.$ip.'%';
}
if ($url) {
$criteria[] = 'url LIKE :url';
$args[':url'] = '%'.addcslashes($url, '%_\\').'%';
}
if ($method) {
$criteria[] = 'method = :method';
$args[':method'] = $method;
}
if (!empty($start)) {
$criteria[] = 'time >= :start';
$args[':start'] = $start;
}
if (!empty($end)) {
$criteria[] = 'time <= :end';
$args[':end'] = $end;
}
return array($criteria, $args);
}
}

View File

@@ -1,265 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\PdoProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* Base PDO storage for profiling information in a PDO database.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jan Schumann <js@schumann-it.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
abstract class PdoProfilerStorage implements ProfilerStorageInterface
{
protected $dsn;
protected $username;
protected $password;
protected $lifetime;
protected $db;
/**
* @param string $dsn A data source name
* @param string $username The username for the database
* @param string $password The password for the database
* @param int $lifetime The lifetime to use for the purge
*/
public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->lifetime = (int) $lifetime;
}
/**
* {@inheritdoc}
*/
public function find($ip, $url, $limit, $method, $start = null, $end = null)
{
if (null === $start) {
$start = 0;
}
if (null === $end) {
$end = time();
}
list($criteria, $args) = $this->buildCriteria($ip, $url, $start, $end, $limit, $method);
$criteria = $criteria ? 'WHERE '.implode(' AND ', $criteria) : '';
$db = $this->initDb();
$tokens = $this->fetch($db, 'SELECT token, ip, method, url, time, parent, status_code FROM sf_profiler_data '.$criteria.' ORDER BY time DESC LIMIT '.((int) $limit), $args);
$this->close($db);
return $tokens;
}
/**
* {@inheritdoc}
*/
public function read($token)
{
$db = $this->initDb();
$args = array(':token' => $token);
$data = $this->fetch($db, 'SELECT data, parent, ip, method, url, time FROM sf_profiler_data WHERE token = :token LIMIT 1', $args);
$this->close($db);
if (isset($data[0]['data'])) {
return $this->createProfileFromData($token, $data[0]);
}
}
/**
* {@inheritdoc}
*/
public function write(Profile $profile)
{
$db = $this->initDb();
$args = array(
':token' => $profile->getToken(),
':parent' => $profile->getParentToken(),
':data' => base64_encode(serialize($profile->getCollectors())),
':ip' => $profile->getIp(),
':method' => $profile->getMethod(),
':url' => $profile->getUrl(),
':time' => $profile->getTime(),
':created_at' => time(),
':status_code' => $profile->getStatusCode(),
);
try {
if ($this->has($profile->getToken())) {
$this->exec($db, 'UPDATE sf_profiler_data SET parent = :parent, data = :data, ip = :ip, method = :method, url = :url, time = :time, created_at = :created_at, status_code = :status_code WHERE token = :token', $args);
} else {
$this->exec($db, 'INSERT INTO sf_profiler_data (token, parent, data, ip, method, url, time, created_at, status_code) VALUES (:token, :parent, :data, :ip, :method, :url, :time, :created_at, :status_code)', $args);
}
$this->cleanup();
$status = true;
} catch (\Exception $e) {
$status = false;
}
$this->close($db);
return $status;
}
/**
* {@inheritdoc}
*/
public function purge()
{
$db = $this->initDb();
$this->exec($db, 'DELETE FROM sf_profiler_data');
$this->close($db);
}
/**
* Build SQL criteria to fetch records by ip and url.
*
* @param string $ip The IP
* @param string $url The URL
* @param string $start The start period to search from
* @param string $end The end period to search to
* @param string $limit The maximum number of tokens to return
* @param string $method The request method
*
* @return array An array with (criteria, args)
*/
abstract protected function buildCriteria($ip, $url, $start, $end, $limit, $method);
/**
* Initializes the database.
*
* @throws \RuntimeException When the requested database driver is not installed
*/
abstract protected function initDb();
protected function cleanup()
{
$db = $this->initDb();
$this->exec($db, 'DELETE FROM sf_profiler_data WHERE created_at < :time', array(':time' => time() - $this->lifetime));
$this->close($db);
}
protected function exec($db, $query, array $args = array())
{
$stmt = $this->prepareStatement($db, $query);
foreach ($args as $arg => $val) {
$stmt->bindValue($arg, $val, \is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
}
$success = $stmt->execute();
if (!$success) {
throw new \RuntimeException(sprintf('Error executing query "%s"', $query));
}
}
protected function prepareStatement($db, $query)
{
try {
$stmt = $db->prepare($query);
} catch (\Exception $e) {
$stmt = false;
}
if (false === $stmt) {
throw new \RuntimeException('The database cannot successfully prepare the statement');
}
return $stmt;
}
protected function fetch($db, $query, array $args = array())
{
$stmt = $this->prepareStatement($db, $query);
foreach ($args as $arg => $val) {
$stmt->bindValue($arg, $val, \is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
}
$stmt->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
protected function close($db)
{
}
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(unserialize(base64_decode($data['data'])));
if (!$parent && !empty($data['parent'])) {
$parent = $this->read($data['parent']);
}
if ($parent) {
$profile->setParent($parent);
}
$profile->setChildren($this->readChildren($token, $profile));
return $profile;
}
/**
* Reads the child profiles for the given token.
*
* @param string $token The parent token
* @param string $parent The parent instance
*
* @return Profile[] An array of Profile instance
*/
protected function readChildren($token, $parent)
{
$db = $this->initDb();
$data = $this->fetch($db, 'SELECT token, data, ip, method, url, time FROM sf_profiler_data WHERE parent = :token', array(':token' => $token));
$this->close($db);
if (!$data) {
return array();
}
$profiles = array();
foreach ($data as $d) {
$profiles[] = $this->createProfileFromData($d['token'], $d, $parent);
}
return $profiles;
}
/**
* Returns whether data for the given token already exists in storage.
*
* @param string $token The profile token
*
* @return string
*/
protected function has($token)
{
$db = $this->initDb();
$tokenExists = $this->fetch($db, 'SELECT 1 FROM sf_profiler_data WHERE token = :token LIMIT 1', array(':token' => $token));
$this->close($db);
return !empty($tokenExists);
}
}

View File

@@ -1,395 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\RedisProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* RedisProfilerStorage stores profiling information in Redis.
*
* @author Andrej Hudec <pulzarraider@gmail.com>
* @author Stephane PY <py.stephane1@gmail.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
class RedisProfilerStorage implements ProfilerStorageInterface
{
const TOKEN_PREFIX = 'sf_profiler_';
const REDIS_OPT_SERIALIZER = 1;
const REDIS_OPT_PREFIX = 2;
const REDIS_SERIALIZER_NONE = 0;
const REDIS_SERIALIZER_PHP = 1;
protected $dsn;
protected $lifetime;
/**
* @var \Redis
*/
private $redis;
/**
* @param string $dsn A data source name
* @param string $username Not used
* @param string $password Not used
* @param int $lifetime The lifetime to use for the purge
*/
public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
{
$this->dsn = $dsn;
$this->lifetime = (int) $lifetime;
}
/**
* {@inheritdoc}
*/
public function find($ip, $url, $limit, $method, $start = null, $end = null)
{
$indexName = $this->getIndexName();
if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) {
return array();
}
$profileList = array_reverse(explode("\n", $indexContent));
$result = array();
foreach ($profileList as $item) {
if (0 === $limit) {
break;
}
if ('' == $item) {
continue;
}
$values = explode("\t", $item, 7);
list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = $values;
$statusCode = isset($values[6]) ? $values[6] : null;
$itemTime = (int) $itemTime;
if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
continue;
}
if (!empty($start) && $itemTime < $start) {
continue;
}
if (!empty($end) && $itemTime > $end) {
continue;
}
$result[] = array(
'token' => $itemToken,
'ip' => $itemIp,
'method' => $itemMethod,
'url' => $itemUrl,
'time' => $itemTime,
'parent' => $itemParent,
'status_code' => $statusCode,
);
--$limit;
}
return $result;
}
/**
* {@inheritdoc}
*/
public function purge()
{
// delete only items from index
$indexName = $this->getIndexName();
$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE);
if (!$indexContent) {
return false;
}
$profileList = explode("\n", $indexContent);
$result = array();
foreach ($profileList as $item) {
if ('' == $item) {
continue;
}
if (false !== $pos = strpos($item, "\t")) {
$result[] = $this->getItemName(substr($item, 0, $pos));
}
}
$result[] = $indexName;
return $this->delete($result);
}
/**
* {@inheritdoc}
*/
public function read($token)
{
if (empty($token)) {
return false;
}
$profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP);
if (false !== $profile) {
$profile = $this->createProfileFromData($token, $profile);
}
return $profile;
}
/**
* {@inheritdoc}
*/
public function write(Profile $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(),
);
$profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));
if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) {
if (!$profileIndexed) {
// Add to index
$indexName = $this->getIndexName();
$indexRow = implode("\t", array(
$profile->getToken(),
$profile->getIp(),
$profile->getMethod(),
$profile->getUrl(),
$profile->getTime(),
$profile->getParentToken(),
$profile->getStatusCode(),
))."\n";
return $this->appendValue($indexName, $indexRow, $this->lifetime);
}
return true;
}
return false;
}
/**
* Internal convenience method that returns the instance of Redis.
*
* @return \Redis
*
* @throws \RuntimeException
*/
protected function getRedis()
{
if (null === $this->redis) {
$data = parse_url($this->dsn);
if (false === $data || !isset($data['scheme']) || 'redis' !== $data['scheme'] || !isset($data['host']) || !isset($data['port'])) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn));
}
if (!\extension_loaded('redis')) {
throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.');
}
$redis = new \Redis();
$redis->connect($data['host'], $data['port']);
if (isset($data['path'])) {
$redis->select(substr($data['path'], 1));
}
if (isset($data['pass'])) {
$redis->auth($data['pass']);
}
$redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX);
$this->redis = $redis;
}
return $this->redis;
}
/**
* Set instance of the Redis.
*
* @param \Redis $redis
*/
public function setRedis($redis)
{
$this->redis = $redis;
}
private 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) {
continue;
}
if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) {
continue;
}
$profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
}
return $profile;
}
/**
* Gets the item name.
*
* @param string $token
*
* @return string
*/
private function getItemName($token)
{
$name = $token;
if ($this->isItemNameValid($name)) {
return $name;
}
return false;
}
/**
* Gets the name of the index.
*
* @return string
*/
private function getIndexName()
{
$name = 'index';
if ($this->isItemNameValid($name)) {
return $name;
}
return false;
}
private function isItemNameValid($name)
{
$length = \strlen($name);
if ($length > 2147483648) {
throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length));
}
return true;
}
/**
* Retrieves an item from the Redis server.
*
* @param string $key
* @param int $serializer
*
* @return mixed
*/
private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE)
{
$redis = $this->getRedis();
$redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);
return $redis->get($key);
}
/**
* Stores an item on the Redis server under the specified key.
*
* @param string $key
* @param mixed $value
* @param int $expiration
* @param int $serializer
*
* @return bool
*/
private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE)
{
$redis = $this->getRedis();
$redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);
return $redis->setex($key, $expiration, $value);
}
/**
* Appends data to an existing item on the Redis server.
*
* @param string $key
* @param string $value
* @param int $expiration
*
* @return bool
*/
private function appendValue($key, $value, $expiration = 0)
{
$redis = $this->getRedis();
$redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE);
if ($redis->exists($key)) {
$redis->append($key, $value);
return $redis->setTimeout($key, $expiration);
}
return $redis->setex($key, $expiration, $value);
}
/**
* Removes the specified keys.
*
* @return bool
*/
private function delete(array $keys)
{
return (bool) $this->getRedis()->delete($keys);
}
}

View File

@@ -1,144 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Profiler;
@trigger_error('The '.__NAMESPACE__.'\SqliteProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
/**
* SqliteProfilerStorage stores profiling information in a SQLite database.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
* Use {@link FileProfilerStorage} instead.
*/
class SqliteProfilerStorage extends PdoProfilerStorage
{
/**
* @throws \RuntimeException When neither of SQLite3 or PDO_SQLite extension is enabled
*/
protected function initDb()
{
if (null === $this->db || $this->db instanceof \SQLite3) {
if (0 !== strpos($this->dsn, 'sqlite')) {
throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Sqlite with an invalid dsn "%s". The expected format is "sqlite:/path/to/the/db/file".', $this->dsn));
}
if (class_exists('SQLite3')) {
$db = new \SQLite3(substr($this->dsn, 7, \strlen($this->dsn)), \SQLITE3_OPEN_READWRITE | \SQLITE3_OPEN_CREATE);
if (method_exists($db, 'busyTimeout')) {
// busyTimeout only exists for PHP >= 5.3.3
$db->busyTimeout(1000);
}
} elseif (class_exists('PDO') && \in_array('sqlite', \PDO::getAvailableDrivers(), true)) {
$db = new \PDO($this->dsn);
} else {
throw new \RuntimeException('You need to enable either the SQLite3 or PDO_SQLite extension for the profiler to run properly.');
}
$db->exec('PRAGMA temp_store=MEMORY; PRAGMA journal_mode=MEMORY;');
$db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token STRING, data STRING, ip STRING, method STRING, url STRING, time INTEGER, parent STRING, created_at INTEGER, status_code INTEGER)');
$db->exec('CREATE INDEX IF NOT EXISTS data_created_at ON sf_profiler_data (created_at)');
$db->exec('CREATE INDEX IF NOT EXISTS data_ip ON sf_profiler_data (ip)');
$db->exec('CREATE INDEX IF NOT EXISTS data_method ON sf_profiler_data (method)');
$db->exec('CREATE INDEX IF NOT EXISTS data_url ON sf_profiler_data (url)');
$db->exec('CREATE INDEX IF NOT EXISTS data_parent ON sf_profiler_data (parent)');
$db->exec('CREATE UNIQUE INDEX IF NOT EXISTS data_token ON sf_profiler_data (token)');
$this->db = $db;
}
return $this->db;
}
protected function exec($db, $query, array $args = array())
{
if ($db instanceof \SQLite3) {
$stmt = $this->prepareStatement($db, $query);
foreach ($args as $arg => $val) {
$stmt->bindValue($arg, $val, \is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT);
}
$res = $stmt->execute();
if (false === $res) {
throw new \RuntimeException(sprintf('Error executing SQLite query "%s"', $query));
}
$res->finalize();
} else {
parent::exec($db, $query, $args);
}
}
protected function fetch($db, $query, array $args = array())
{
$return = array();
if ($db instanceof \SQLite3) {
$stmt = $this->prepareStatement($db, $query);
foreach ($args as $arg => $val) {
$stmt->bindValue($arg, $val, \is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT);
}
$res = $stmt->execute();
while ($row = $res->fetchArray(\SQLITE3_ASSOC)) {
$return[] = $row;
}
$res->finalize();
$stmt->close();
} else {
$return = parent::fetch($db, $query, $args);
}
return $return;
}
/**
* {@inheritdoc}
*/
protected function buildCriteria($ip, $url, $start, $end, $limit, $method)
{
$criteria = array();
$args = array();
if ($ip = preg_replace('/[^\d\.]/', '', $ip)) {
$criteria[] = 'ip LIKE :ip';
$args[':ip'] = '%'.$ip.'%';
}
if ($url) {
$criteria[] = 'url LIKE :url ESCAPE "\"';
$args[':url'] = '%'.addcslashes($url, '%_\\').'%';
}
if ($method) {
$criteria[] = 'method = :method';
$args[':method'] = $method;
}
if (!empty($start)) {
$criteria[] = 'time >= :start';
$args[':start'] = $start;
}
if (!empty($end)) {
$criteria[] = 'time <= :end';
$args[':end'] = $end;
}
return array($criteria, $args);
}
protected function close($db)
{
if ($db instanceof \SQLite3) {
$db->close();
}
}
}