[ Index ]

PHP Cross Reference of phpBB-3.2.8-deutsch

title

Body

[close]

/vendor/symfony/http-kernel/Profiler/ -> FileProfilerStorage.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\HttpKernel\Profiler;
  13  
  14  /**
  15   * Storage for profiler using files.
  16   *
  17   * @author Alexandre Salomé <alexandre.salome@gmail.com>
  18   */
  19  class FileProfilerStorage implements ProfilerStorageInterface
  20  {
  21      /**
  22       * Folder where profiler data are stored.
  23       *
  24       * @var string
  25       */
  26      private $folder;
  27  
  28      /**
  29       * Constructs the file storage using a "dsn-like" path.
  30       *
  31       * Example : "file:/path/to/the/storage/folder"
  32       *
  33       * @param string $dsn The DSN
  34       *
  35       * @throws \RuntimeException
  36       */
  37      public function __construct($dsn)
  38      {
  39          if (0 !== strpos($dsn, 'file:')) {
  40              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));
  41          }
  42          $this->folder = substr($dsn, 5);
  43  
  44          if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) {
  45              throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder));
  46          }
  47      }
  48  
  49      /**
  50       * {@inheritdoc}
  51       */
  52      public function find($ip, $url, $limit, $method, $start = null, $end = null)
  53      {
  54          $file = $this->getIndexFilename();
  55  
  56          if (!file_exists($file)) {
  57              return array();
  58          }
  59  
  60          $file = fopen($file, 'r');
  61          fseek($file, 0, SEEK_END);
  62  
  63          $result = array();
  64          while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
  65              $values = str_getcsv($line);
  66              list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = $values;
  67              $csvStatusCode = isset($values[6]) ? $values[6] : null;
  68  
  69              $csvTime = (int) $csvTime;
  70  
  71              if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method)) {
  72                  continue;
  73              }
  74  
  75              if (!empty($start) && $csvTime < $start) {
  76                  continue;
  77              }
  78  
  79              if (!empty($end) && $csvTime > $end) {
  80                  continue;
  81              }
  82  
  83              $result[$csvToken] = array(
  84                  'token' => $csvToken,
  85                  'ip' => $csvIp,
  86                  'method' => $csvMethod,
  87                  'url' => $csvUrl,
  88                  'time' => $csvTime,
  89                  'parent' => $csvParent,
  90                  'status_code' => $csvStatusCode,
  91              );
  92          }
  93  
  94          fclose($file);
  95  
  96          return array_values($result);
  97      }
  98  
  99      /**
 100       * {@inheritdoc}
 101       */
 102      public function purge()
 103      {
 104          $flags = \FilesystemIterator::SKIP_DOTS;
 105          $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
 106          $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
 107  
 108          foreach ($iterator as $file) {
 109              if (is_file($file)) {
 110                  unlink($file);
 111              } else {
 112                  rmdir($file);
 113              }
 114          }
 115      }
 116  
 117      /**
 118       * {@inheritdoc}
 119       */
 120      public function read($token)
 121      {
 122          if (!$token || !file_exists($file = $this->getFilename($token))) {
 123              return;
 124          }
 125  
 126          return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
 127      }
 128  
 129      /**
 130       * {@inheritdoc}
 131       *
 132       * @throws \RuntimeException
 133       */
 134      public function write(Profile $profile)
 135      {
 136          $file = $this->getFilename($profile->getToken());
 137  
 138          $profileIndexed = is_file($file);
 139          if (!$profileIndexed) {
 140              // Create directory
 141              $dir = \dirname($file);
 142              if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
 143                  throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir));
 144              }
 145          }
 146  
 147          $profileToken = $profile->getToken();
 148          // when there are errors in sub-requests, the parent and/or children tokens
 149          // may equal the profile token, resulting in infinite loops
 150          $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
 151          $childrenToken = array_filter(array_map(function ($p) use ($profileToken) {
 152              return $profileToken !== $p->getToken() ? $p->getToken() : null;
 153          }, $profile->getChildren()));
 154  
 155          // Store profile
 156          $data = array(
 157              'token' => $profileToken,
 158              'parent' => $parentToken,
 159              'children' => $childrenToken,
 160              'data' => $profile->getCollectors(),
 161              'ip' => $profile->getIp(),
 162              'method' => $profile->getMethod(),
 163              'url' => $profile->getUrl(),
 164              'time' => $profile->getTime(),
 165          );
 166  
 167          if (false === file_put_contents($file, serialize($data))) {
 168              return false;
 169          }
 170  
 171          if (!$profileIndexed) {
 172              // Add to index
 173              if (false === $file = fopen($this->getIndexFilename(), 'a')) {
 174                  return false;
 175              }
 176  
 177              fputcsv($file, array(
 178                  $profile->getToken(),
 179                  $profile->getIp(),
 180                  $profile->getMethod(),
 181                  $profile->getUrl(),
 182                  $profile->getTime(),
 183                  $profile->getParentToken(),
 184                  $profile->getStatusCode(),
 185              ));
 186              fclose($file);
 187          }
 188  
 189          return true;
 190      }
 191  
 192      /**
 193       * Gets filename to store data, associated to the token.
 194       *
 195       * @param string $token
 196       *
 197       * @return string The profile filename
 198       */
 199      protected function getFilename($token)
 200      {
 201          // Uses 4 last characters, because first are mostly the same.
 202          $folderA = substr($token, -2, 2);
 203          $folderB = substr($token, -4, 2);
 204  
 205          return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
 206      }
 207  
 208      /**
 209       * Gets the index filename.
 210       *
 211       * @return string The index filename
 212       */
 213      protected function getIndexFilename()
 214      {
 215          return $this->folder.'/index.csv';
 216      }
 217  
 218      /**
 219       * Reads a line in the file, backward.
 220       *
 221       * This function automatically skips the empty lines and do not include the line return in result value.
 222       *
 223       * @param resource $file The file resource, with the pointer placed at the end of the line to read
 224       *
 225       * @return mixed A string representing the line or null if beginning of file is reached
 226       */
 227      protected function readLineFromFile($file)
 228      {
 229          $line = '';
 230          $position = ftell($file);
 231  
 232          if (0 === $position) {
 233              return;
 234          }
 235  
 236          while (true) {
 237              $chunkSize = min($position, 1024);
 238              $position -= $chunkSize;
 239              fseek($file, $position);
 240  
 241              if (0 === $chunkSize) {
 242                  // bof reached
 243                  break;
 244              }
 245  
 246              $buffer = fread($file, $chunkSize);
 247  
 248              if (false === ($upTo = strrpos($buffer, "\n"))) {
 249                  $line = $buffer.$line;
 250                  continue;
 251              }
 252  
 253              $position += $upTo;
 254              $line = substr($buffer, $upTo + 1).$line;
 255              fseek($file, max(0, $position), SEEK_SET);
 256  
 257              if ('' !== $line) {
 258                  break;
 259              }
 260          }
 261  
 262          return '' === $line ? null : $line;
 263      }
 264  
 265      protected function createProfileFromData($token, $data, $parent = null)
 266      {
 267          $profile = new Profile($token);
 268          $profile->setIp($data['ip']);
 269          $profile->setMethod($data['method']);
 270          $profile->setUrl($data['url']);
 271          $profile->setTime($data['time']);
 272          $profile->setCollectors($data['data']);
 273  
 274          if (!$parent && $data['parent']) {
 275              $parent = $this->read($data['parent']);
 276          }
 277  
 278          if ($parent) {
 279              $profile->setParent($parent);
 280          }
 281  
 282          foreach ($data['children'] as $token) {
 283              if (!$token || !file_exists($file = $this->getFilename($token))) {
 284                  continue;
 285              }
 286  
 287              $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
 288          }
 289  
 290          return $profile;
 291      }
 292  }


Generated: Tue Apr 7 19:42:26 2020 Cross-referenced by PHPXref 0.7.1