<?php
/**
 * A class for logging information to a stream.
 */
class log_writer_stream extends log_filter
{
    /**
     * @var resource The stream.
     */
    protected $stream;
    
    /**
     * @var string The logging template.
     */
    protected $template;

    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.

    /**
     * @param integer (optional) $filter The priority filter.
     * @param string (optional) $stream The stream.
     * @param string (optional) $mode The writing mode.
     * @param string (optional) $template The log template.
     */
    public function __construct($filter = log::DEBUG, $stream = 'php://output', $mode = 'a', $template = ":timestamp|:priority|:message\n")
    {
        parent::__construct($filter);
        $this->stream = array($stream, $mode); // Lazy.
        $this->template = $template;
    }

    /**
     * @throws unexpectedvalueexception If the stream could not be closed.
     */
    public function __destruct()
    {
        if (is_resource($this->stream))
        {
            if (!fclose($this->stream))
            {
                throw new unexpectedvalueexception('Stream could not be closed.');
            }
        }
        
        $this->stream = null;
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Overload functions.

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.

    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
    
    /**
     * Writes a log message to a file.
     *
     * @param string $message The message.
     * @param integer $priority The priority.
     * @param string $timestamp The date.
     * @throws unexpectedvalueexception If the stream could not be opened or
     * written to.
     * @return log_writer_stream A fluent interface.
     */
    protected function _write($message, $priority, $timestamp)
    {
        if (!is_resource($this->stream)) 
        {
            $stream = fopen($this->stream[0], $this->stream[1], false);
            
            if (!$stream)
            {
                throw new unexpectedvalueexception('Stream could not be opened.');
            }
            
            $this->stream = $stream;
        }
        
        $template = str_replace(array(':timestamp', ':priority', ':message'), array($timestamp, $priority, $message), $this->template);
        
        if (!fwrite($this->stream, $template))
        {
            throw new unexpectedvalueexception('Stream could not be written to.');
        }
        
        return $this;
    }
}
