[ Index ]

PHP Cross Reference of phpBB-3.3.3-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, $statusCode = null)
  53      {
  54          $file = $this->getIndexFilename();
  55  
  56          if (!file_exists($file)) {
  57              return [];
  58          }
  59  
  60          $file = fopen($file, 'r');
  61          fseek($file, 0, \SEEK_END);
  62  
  63          $result = [];
  64          while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
  65              $values = str_getcsv($line);
  66              list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values;
  67              $csvTime = (int) $csvTime;
  68  
  69              if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) {
  70                  continue;
  71              }
  72  
  73              if (!empty($start) && $csvTime < $start) {
  74                  continue;
  75              }
  76  
  77              if (!empty($end) && $csvTime > $end) {
  78                  continue;
  79              }
  80  
  81              $result[$csvToken] = [
  82                  'token' => $csvToken,
  83                  'ip' => $csvIp,
  84                  'method' => $csvMethod,
  85                  'url' => $csvUrl,
  86                  'time' => $csvTime,
  87                  'parent' => $csvParent,
  88                  'status_code' => $csvStatusCode,
  89              ];
  90          }
  91  
  92          fclose($file);
  93  
  94          return array_values($result);
  95      }
  96  
  97      /**
  98       * {@inheritdoc}
  99       */
 100      public function purge()
 101      {
 102          $flags = \FilesystemIterator::SKIP_DOTS;
 103          $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
 104          $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
 105  
 106          foreach ($iterator as $file) {
 107              if (is_file($file)) {
 108                  unlink($file);
 109              } else {
 110                  rmdir($file);
 111              }
 112          }
 113      }
 114  
 115      /**
 116       * {@inheritdoc}
 117       */
 118      public function read($token)
 119      {
 120          if (!$token || !file_exists($file = $this->getFilename($token))) {
 121              return null;
 122          }
 123  
 124          return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
 125      }
 126  
 127      /**
 128       * {@inheritdoc}
 129       *
 130       * @throws \RuntimeException
 131       */
 132      public function write(Profile $profile)
 133      {
 134          $file = $this->getFilename($profile->getToken());
 135  
 136          $profileIndexed = is_file($file);
 137          if (!$profileIndexed) {
 138              // Create directory
 139              $dir = \dirname($file);
 140              if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
 141                  throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir));
 142              }
 143          }
 144  
 145          $profileToken = $profile->getToken();
 146          // when there are errors in sub-requests, the parent and/or children tokens
 147          // may equal the profile token, resulting in infinite loops
 148          $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
 149          $childrenToken = array_filter(array_map(function ($p) use ($profileToken) {
 150              return $profileToken !== $p->getToken() ? $p->getToken() : null;
 151          }, $profile->getChildren()));
 152  
 153          // Store profile
 154          $data = [
 155              'token' => $profileToken,
 156              'parent' => $parentToken,
 157              'children' => $childrenToken,
 158              'data' => $profile->getCollectors(),
 159              'ip' => $profile->getIp(),
 160              'method' => $profile->getMethod(),
 161              'url' => $profile->getUrl(),
 162              'time' => $profile->getTime(),
 163              'status_code' => $profile->getStatusCode(),
 164          ];
 165  
 166          if (false === file_put_contents($file, serialize($data))) {
 167              return false;
 168          }
 169  
 170          if (!$profileIndexed) {
 171              // Add to index
 172              if (false === $file = fopen($this->getIndexFilename(), 'a')) {
 173                  return false;
 174              }
 175  
 176              fputcsv($file, [
 177                  $profile->getToken(),
 178                  $profile->getIp(),
 179                  $profile->getMethod(),
 180                  $profile->getUrl(),
 181                  $profile->getTime(),
 182                  $profile->getParentToken(),
 183                  $profile->getStatusCode(),
 184              ]);
 185              fclose($file);
 186          }
 187  
 188          return true;
 189      }
 190  
 191      /**
 192       * Gets filename to store data, associated to the token.
 193       *
 194       * @param string $token
 195       *
 196       * @return string The profile filename
 197       */
 198      protected function getFilename($token)
 199      {
 200          // Uses 4 last characters, because first are mostly the same.
 201          $folderA = substr($token, -2, 2);
 202          $folderB = substr($token, -4, 2);
 203  
 204          return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
 205      }
 206  
 207      /**
 208       * Gets the index filename.
 209       *
 210       * @return string The index filename
 211       */
 212      protected function getIndexFilename()
 213      {
 214          return $this->folder.'/index.csv';
 215      }
 216  
 217      /**
 218       * Reads a line in the file, backward.
 219       *
 220       * This function automatically skips the empty lines and do not include the line return in result value.
 221       *
 222       * @param resource $file The file resource, with the pointer placed at the end of the line to read
 223       *
 224       * @return mixed A string representing the line or null if beginning of file is reached
 225       */
 226      protected function readLineFromFile($file)
 227      {
 228          $line = '';
 229          $position = ftell($file);
 230  
 231          if (0 === $position) {
 232              return null;
 233          }
 234  
 235          while (true) {
 236              $chunkSize = min($position, 1024);
 237              $position -= $chunkSize;
 238              fseek($file, $position);
 239  
 240              if (0 === $chunkSize) {
 241                  // bof reached
 242                  break;
 243              }
 244  
 245              $buffer = fread($file, $chunkSize);
 246  
 247              if (false === ($upTo = strrpos($buffer, "\n"))) {
 248                  $line = $buffer.$line;
 249                  continue;
 250              }
 251  
 252              $position += $upTo;
 253              $line = substr($buffer, $upTo + 1).$line;
 254              fseek($file, max(0, $position), \SEEK_SET);
 255  
 256              if ('' !== $line) {
 257                  break;
 258              }
 259          }
 260  
 261          return '' === $line ? null : $line;
 262      }
 263  
 264      protected function createProfileFromData($token, $data, $parent = null)
 265      {
 266          $profile = new Profile($token);
 267          $profile->setIp($data['ip']);
 268          $profile->setMethod($data['method']);
 269          $profile->setUrl($data['url']);
 270          $profile->setTime($data['time']);
 271          $profile->setStatusCode($data['status_code']);
 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: Sun Feb 14 20:08:31 2021 Cross-referenced by PHPXref 0.7.1