/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php |
@@ -0,0 +1,176 @@ |
<?php |
|
/* |
* This file is part of the Monolog package. |
* |
* (c) Jordi Boggiano <j.boggiano@seld.be> |
* |
* For the full copyright and license information, please view the LICENSE |
* file that was distributed with this source code. |
*/ |
|
namespace Monolog\Handler; |
|
use Monolog\Logger; |
|
/** |
* Stores to any stream resource |
* |
* Can be used to store into php://stderr, remote and local files, etc. |
* |
* @author Jordi Boggiano <j.boggiano@seld.be> |
*/ |
class StreamHandler extends AbstractProcessingHandler |
{ |
protected $stream; |
protected $url; |
private $errorMessage; |
protected $filePermission; |
protected $useLocking; |
private $dirCreated; |
|
/** |
* @param resource|string $stream |
* @param int $level The minimum logging level at which this handler will be triggered |
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not |
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) |
* @param Boolean $useLocking Try to lock log file before doing any writes |
* |
* @throws \Exception If a missing directory is not buildable |
* @throws \InvalidArgumentException If stream is not a resource or string |
*/ |
public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) |
{ |
parent::__construct($level, $bubble); |
if (is_resource($stream)) { |
$this->stream = $stream; |
} elseif (is_string($stream)) { |
$this->url = $stream; |
} else { |
throw new \InvalidArgumentException('A stream must either be a resource or a string.'); |
} |
|
$this->filePermission = $filePermission; |
$this->useLocking = $useLocking; |
} |
|
/** |
* {@inheritdoc} |
*/ |
public function close() |
{ |
if ($this->url && is_resource($this->stream)) { |
fclose($this->stream); |
} |
$this->stream = null; |
} |
|
/** |
* Return the currently active stream if it is open |
* |
* @return resource|null |
*/ |
public function getStream() |
{ |
return $this->stream; |
} |
|
/** |
* Return the stream URL if it was configured with a URL and not an active resource |
* |
* @return string|null |
*/ |
public function getUrl() |
{ |
return $this->url; |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function write(array $record) |
{ |
if (!is_resource($this->stream)) { |
if (null === $this->url || '' === $this->url) { |
throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); |
} |
$this->createDir(); |
$this->errorMessage = null; |
set_error_handler(array($this, 'customErrorHandler')); |
$this->stream = fopen($this->url, 'a'); |
if ($this->filePermission !== null) { |
@chmod($this->url, $this->filePermission); |
} |
restore_error_handler(); |
if (!is_resource($this->stream)) { |
$this->stream = null; |
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url)); |
} |
} |
|
if ($this->useLocking) { |
// ignoring errors here, there's not much we can do about them |
flock($this->stream, LOCK_EX); |
} |
|
$this->streamWrite($this->stream, $record); |
|
if ($this->useLocking) { |
flock($this->stream, LOCK_UN); |
} |
} |
|
/** |
* Write to stream |
* @param resource $stream |
* @param array $record |
*/ |
protected function streamWrite($stream, array $record) |
{ |
fwrite($stream, (string) $record['formatted']); |
} |
|
private function customErrorHandler($code, $msg) |
{ |
$this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg); |
} |
|
/** |
* @param string $stream |
* |
* @return null|string |
*/ |
private function getDirFromStream($stream) |
{ |
$pos = strpos($stream, '://'); |
if ($pos === false) { |
return dirname($stream); |
} |
|
if ('file://' === substr($stream, 0, 7)) { |
return dirname(substr($stream, 7)); |
} |
|
return; |
} |
|
private function createDir() |
{ |
// Do not try to create dir if it has already been tried. |
if ($this->dirCreated) { |
return; |
} |
|
$dir = $this->getDirFromStream($this->url); |
if (null !== $dir && !is_dir($dir)) { |
$this->errorMessage = null; |
set_error_handler(array($this, 'customErrorHandler')); |
$status = mkdir($dir, 0777, true); |
restore_error_handler(); |
if (false === $status) { |
throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir)); |
} |
} |
$this->dirCreated = true; |
} |
} |