diff -r 000000000000 -r 7f95f8617b0b vendor/symfony/src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php Sat Sep 24 15:40:41 2011 +0200 @@ -0,0 +1,230 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Profiler; + +use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; + +/** + * Base PDO storage for profiling information in a PDO database. + * + * @author Fabien Potencier + * @author Jan Schumann + */ +abstract class PdoProfilerStorage implements ProfilerStorageInterface +{ + protected $dsn; + protected $username; + protected $password; + protected $lifetime; + protected $db; + + /** + * Constructor. + * + * @param string $dsn A data source name + * @param string $username The username for the database + * @param string $password The password for the database + * @param integer $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) + { + list($criteria, $args) = $this->buildCriteria($ip, $url, $limit); + + $criteria = $criteria ? 'WHERE '.implode(' AND ', $criteria) : ''; + + $db = $this->initDb(); + $tokens = $this->fetch($db, 'SELECT token, ip, url, time, parent FROM sf_profiler_data '.$criteria.' ORDER BY time DESC LIMIT '.((integer) $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, 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]); + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function write(Profile $profile) + { + $db = $this->initDb(); + $args = array( + ':token' => $profile->getToken(), + ':parent' => $profile->getParent() ? $profile->getParent()->getToken() : '', + ':data' => base64_encode(serialize($profile->getCollectors())), + ':ip' => $profile->getIp(), + ':url' => $profile->getUrl(), + ':time' => $profile->getTime(), + ':created_at' => time(), + ); + try { + $this->exec($db, 'INSERT INTO sf_profiler_data (token, parent, data, ip, url, time, created_at) VALUES (:token, :parent, :data, :ip, :url, :time, :created_at)', $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 $limit The maximum number of tokens to return + * + * @return array An array with (criteria, args) + */ + abstract protected function buildCriteria($ip, $url, $limit); + + /** + * 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); + + return $return; + } + + protected function close($db) + { + } + + protected function createProfileFromData($token, $data, $parent = null) + { + $profile = new Profile($token); + $profile->setIp($data['ip']); + $profile->setUrl($data['url']); + $profile->setTime($data['time']); + $profile->setCollectors(unserialize(base64_decode($data['data']))); + + if (!$parent && isset($data['parent']) && $data['parent']) { + $parent = $this->read($data['parent']); + } + + if ($parent) { + $profile->setParent($parent); + } + + $profile->setChildren($this->readChildren($token, $parent)); + + return $profile; + } + + /** + * Reads the child profiles for the given token. + * + * @param string $token The parent token + * + * @return array An array of Profile instance + */ + protected function readChildren($token, $parent) + { + $db = $this->initDb(); + $data = $this->fetch($db, 'SELECT token, data, ip, 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; + } +}