vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php line 23

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Monolog package.
  4.  *
  5.  * (c) Jordi Boggiano <j.boggiano@seld.be>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Monolog\Handler;
  11. use Monolog\Logger;
  12. /**
  13.  * Stores to any stream resource
  14.  *
  15.  * Can be used to store into php://stderr, remote and local files, etc.
  16.  *
  17.  * @author Jordi Boggiano <j.boggiano@seld.be>
  18.  */
  19. class StreamHandler extends AbstractProcessingHandler
  20. {
  21.     protected $stream;
  22.     protected $url;
  23.     private $errorMessage;
  24.     protected $filePermission;
  25.     protected $useLocking;
  26.     private $dirCreated;
  27.     /**
  28.      * @param resource|string $stream
  29.      * @param int             $level          The minimum logging level at which this handler will be triggered
  30.      * @param bool            $bubble         Whether the messages that are handled can bubble up the stack or not
  31.      * @param int|null        $filePermission Optional file permissions (default (0644) are only for owner read/write)
  32.      * @param bool            $useLocking     Try to lock log file before doing any writes
  33.      *
  34.      * @throws \Exception                If a missing directory is not buildable
  35.      * @throws \InvalidArgumentException If stream is not a resource or string
  36.      */
  37.     public function __construct($stream$level Logger::DEBUG$bubble true$filePermission null$useLocking false)
  38.     {
  39.         parent::__construct($level$bubble);
  40.         if (is_resource($stream)) {
  41.             $this->stream $stream;
  42.         } elseif (is_string($stream)) {
  43.             $this->url $stream;
  44.         } else {
  45.             throw new \InvalidArgumentException('A stream must either be a resource or a string.');
  46.         }
  47.         $this->filePermission $filePermission;
  48.         $this->useLocking $useLocking;
  49.     }
  50.     /**
  51.      * {@inheritdoc}
  52.      */
  53.     public function close()
  54.     {
  55.         if ($this->url && is_resource($this->stream)) {
  56.             fclose($this->stream);
  57.         }
  58.         $this->stream null;
  59.         $this->dirCreated null;
  60.     }
  61.     /**
  62.      * Return the currently active stream if it is open
  63.      *
  64.      * @return resource|null
  65.      */
  66.     public function getStream()
  67.     {
  68.         return $this->stream;
  69.     }
  70.     /**
  71.      * Return the stream URL if it was configured with a URL and not an active resource
  72.      *
  73.      * @return string|null
  74.      */
  75.     public function getUrl()
  76.     {
  77.         return $this->url;
  78.     }
  79.     /**
  80.      * {@inheritdoc}
  81.      */
  82.     protected function write(array $record)
  83.     {
  84.         if (!is_resource($this->stream)) {
  85.             if (null === $this->url || '' === $this->url) {
  86.                 throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
  87.             }
  88.             $this->createDir();
  89.             $this->errorMessage null;
  90.             set_error_handler(array($this'customErrorHandler'));
  91.             $this->stream fopen($this->url'a');
  92.             if ($this->filePermission !== null) {
  93.                 @chmod($this->url$this->filePermission);
  94.             }
  95.             restore_error_handler();
  96.             if (!is_resource($this->stream)) {
  97.                 $this->stream null;
  98.                 throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage$this->url));
  99.             }
  100.         }
  101.         if ($this->useLocking) {
  102.             // ignoring errors here, there's not much we can do about them
  103.             flock($this->streamLOCK_EX);
  104.         }
  105.         $this->streamWrite($this->stream$record);
  106.         if ($this->useLocking) {
  107.             flock($this->streamLOCK_UN);
  108.         }
  109.     }
  110.     /**
  111.      * Write to stream
  112.      * @param resource $stream
  113.      * @param array $record
  114.      */
  115.     protected function streamWrite($stream, array $record)
  116.     {
  117.         fwrite($stream, (string) $record['formatted']);
  118.     }
  119.     private function customErrorHandler($code$msg)
  120.     {
  121.         $this->errorMessage preg_replace('{^(fopen|mkdir)\(.*?\): }'''$msg);
  122.     }
  123.     /**
  124.      * @param string $stream
  125.      *
  126.      * @return null|string
  127.      */
  128.     private function getDirFromStream($stream)
  129.     {
  130.         $pos strpos($stream'://');
  131.         if ($pos === false) {
  132.             return dirname($stream);
  133.         }
  134.         if ('file://' === substr($stream07)) {
  135.             return dirname(substr($stream7));
  136.         }
  137.         return;
  138.     }
  139.     private function createDir()
  140.     {
  141.         // Do not try to create dir if it has already been tried.
  142.         if ($this->dirCreated) {
  143.             return;
  144.         }
  145.         $dir $this->getDirFromStream($this->url);
  146.         if (null !== $dir && !is_dir($dir)) {
  147.             $this->errorMessage null;
  148.             set_error_handler(array($this'customErrorHandler'));
  149.             $status mkdir($dir0777true);
  150.             restore_error_handler();
  151.             if (false === $status && !is_dir($dir)) {
  152.                 throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage$dir));
  153.             }
  154.         }
  155.         $this->dirCreated true;
  156.     }
  157. }