BaseMemcacheProfilerStorage.php

Namespace

Symfony\Component\HttpKernel\Profiler

File

drupal/core/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php
View source
<?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;


/**
 * Base Memcache storage for profiling information in a Memcache.
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface {
  const TOKEN_PREFIX = 'sf_profiler_';
  protected $dsn;
  protected $lifetime;

  /**
   * Constructor.
   *
   * @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) {
    $indexName = $this
      ->getIndexName();
    $indexContent = $this
      ->getValue($indexName);
    if (!$indexContent) {
      return array();
    }
    $profileList = explode("\n", $indexContent);
    $result = array();
    foreach ($profileList as $item) {
      if ($limit === 0) {
        break;
      }
      if ($item == '') {
        continue;
      }
      list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6);
      if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
        continue;
      }
      $result[$itemToken] = array(
        'token' => $itemToken,
        'ip' => $itemIp,
        'method' => $itemMethod,
        'url' => $itemUrl,
        'time' => $itemTime,
        'parent' => $itemParent,
      );
      --$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(),
        )) . "\n";
        return $this
          ->appendValue($indexName, $indexRow, $this->lifetime);
      }
      return true;
    }
    return false;
  }

  /**
   * Retrieve item from the memcache server
   *
   * @param string $key
   *
   * @return mixed
   */
  protected abstract function getValue($key);

  /**
   * Store an item on the memcache server under the specified key
   *
   * @param string $key
   * @param mixed  $value
   * @param int    $expiration
   *
   * @return boolean
   */
  protected abstract function setValue($key, $value, $expiration = 0);

  /**
   * Delete item from the memcache server
   *
   * @param string $key
   *
   * @return boolean
   */
  protected abstract function delete($key);

  /**
   * Append data to an existing item on the memcache server
   * @param string $key
   * @param string $value
   * @param int    $expiration
   *
   * @return boolean
   */
  protected abstract 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;
  }

}

Classes

Namesort descending Description
BaseMemcacheProfilerStorage Base Memcache storage for profiling information in a Memcache.