1<?php 2/** 3 * Zend Framework (http://framework.zend.com/) 4 * 5 * @link http://github.com/zendframework/zf2 for the canonical source repository 6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 7 * @license http://framework.zend.com/license/new-bsd New BSD License 8 */ 9 10namespace Zend\Log\Writer; 11 12use Traversable; 13use Zend\Log\Exception; 14use Zend\Log\Formatter\Simple as SimpleFormatter; 15use Zend\Stdlib\ErrorHandler; 16 17class Stream extends AbstractWriter 18{ 19 /** 20 * Separator between log entries 21 * 22 * @var string 23 */ 24 protected $logSeparator = PHP_EOL; 25 26 /** 27 * Holds the PHP stream to log to. 28 * 29 * @var null|stream 30 */ 31 protected $stream = null; 32 33 /** 34 * Constructor 35 * 36 * @param string|resource|array|Traversable $streamOrUrl Stream or URL to open as a stream 37 * @param string|null $mode Mode, only applicable if a URL is given 38 * @param null|string $logSeparator Log separator string 39 * @return Stream 40 * @throws Exception\InvalidArgumentException 41 * @throws Exception\RuntimeException 42 */ 43 public function __construct($streamOrUrl, $mode = null, $logSeparator = null) 44 { 45 if ($streamOrUrl instanceof Traversable) { 46 $streamOrUrl = iterator_to_array($streamOrUrl); 47 } 48 49 if (is_array($streamOrUrl)) { 50 parent::__construct($streamOrUrl); 51 $mode = isset($streamOrUrl['mode']) ? $streamOrUrl['mode'] : null; 52 $logSeparator = isset($streamOrUrl['log_separator']) ? $streamOrUrl['log_separator'] : null; 53 $streamOrUrl = isset($streamOrUrl['stream']) ? $streamOrUrl['stream'] : null; 54 } 55 56 // Setting the default mode 57 if (null === $mode) { 58 $mode = 'a'; 59 } 60 61 if (is_resource($streamOrUrl)) { 62 if ('stream' != get_resource_type($streamOrUrl)) { 63 throw new Exception\InvalidArgumentException(sprintf( 64 'Resource is not a stream; received "%s', 65 get_resource_type($streamOrUrl) 66 )); 67 } 68 69 if ('a' != $mode) { 70 throw new Exception\InvalidArgumentException(sprintf( 71 'Mode must be "a" on existing streams; received "%s"', 72 $mode 73 )); 74 } 75 76 $this->stream = $streamOrUrl; 77 } else { 78 ErrorHandler::start(); 79 $this->stream = fopen($streamOrUrl, $mode, false); 80 $error = ErrorHandler::stop(); 81 if (!$this->stream) { 82 throw new Exception\RuntimeException(sprintf( 83 '"%s" cannot be opened with mode "%s"', 84 $streamOrUrl, 85 $mode 86 ), 0, $error); 87 } 88 } 89 90 if (null !== $logSeparator) { 91 $this->setLogSeparator($logSeparator); 92 } 93 94 if ($this->formatter === null) { 95 $this->formatter = new SimpleFormatter(); 96 } 97 } 98 99 /** 100 * Write a message to the log. 101 * 102 * @param array $event event data 103 * @return void 104 * @throws Exception\RuntimeException 105 */ 106 protected function doWrite(array $event) 107 { 108 $line = $this->formatter->format($event) . $this->logSeparator; 109 fwrite($this->stream, $line); 110 } 111 112 /** 113 * Set log separator string 114 * 115 * @param string $logSeparator 116 * @return Stream 117 */ 118 public function setLogSeparator($logSeparator) 119 { 120 $this->logSeparator = (string) $logSeparator; 121 return $this; 122 } 123 124 /** 125 * Get log separator string 126 * 127 * @return string 128 */ 129 public function getLogSeparator() 130 { 131 return $this->logSeparator; 132 } 133 134 /** 135 * Close the stream resource. 136 * 137 * @return void 138 */ 139 public function shutdown() 140 { 141 if (is_resource($this->stream)) { 142 fclose($this->stream); 143 } 144 } 145} 146