Explorar o código

stream handler creates a directory if its possible

Dominik Zogg %!s(int64=10) %!d(string=hai) anos
pai
achega
fe12c5278f

+ 31 - 1
src/Monolog/Handler/StreamHandler.php

@@ -35,6 +35,7 @@ class StreamHandler extends AbstractProcessingHandler
      * @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)
@@ -43,6 +44,16 @@ class StreamHandler extends AbstractProcessingHandler
         if (is_resource($stream)) {
             $this->stream = $stream;
         } elseif (is_string($stream)) {
+            $dir = $this->getDirFromStream($stream);
+            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->url = $stream;
         } else {
             throw new \InvalidArgumentException('A stream must either be a resource or a string.');
@@ -99,6 +110,25 @@ class StreamHandler extends AbstractProcessingHandler
 
     private function customErrorHandler($code, $msg)
     {
-        $this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $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;
     }
 }

+ 45 - 1
tests/Monolog/Handler/StreamHandlerTest.php

@@ -112,7 +112,51 @@ class StreamHandlerTest extends TestCase
      */
     public function testWriteNonExistingResource()
     {
-        $handler = new StreamHandler('/foo/bar/baz/'.rand(0, 10000));
+        $handler = new StreamHandler('ftp://foo/bar/baz/'.rand(0, 10000));
+        $handler->handle($this->getRecord());
+    }
+
+    /**
+     * @covers Monolog\Handler\StreamHandler::__construct
+     * @covers Monolog\Handler\StreamHandler::write
+     */
+    public function testWriteNonExistingPath()
+    {
+        $handler = new StreamHandler(sys_get_temp_dir().'/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
+        $handler->handle($this->getRecord());
+    }
+
+    /**
+     * @covers Monolog\Handler\StreamHandler::__construct
+     * @covers Monolog\Handler\StreamHandler::write
+     */
+    public function testWriteNonExistingFileResource()
+    {
+        $handler = new StreamHandler('file://'.sys_get_temp_dir().'/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
+        $handler->handle($this->getRecord());
+    }
+
+    /**
+     * @expectedException Exception
+     * @expectedExceptionMessageRegExp /There is no existing directory at/
+     * @covers Monolog\Handler\StreamHandler::__construct
+     * @covers Monolog\Handler\StreamHandler::write
+     */
+    public function testWriteNonExistingAndNotCreatablePath()
+    {
+        $handler = new StreamHandler('/foo/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
+        $handler->handle($this->getRecord());
+    }
+
+    /**
+     * @expectedException Exception
+     * @expectedExceptionMessageRegExp /There is no existing directory at/
+     * @covers Monolog\Handler\StreamHandler::__construct
+     * @covers Monolog\Handler\StreamHandler::write
+     */
+    public function testWriteNonExistingAndNotCreatableFileResource()
+    {
+        $handler = new StreamHandler('file:///foo/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
         $handler->handle($this->getRecord());
     }
 }