Show:

File: platform/classes/Q/OutputBuffer.php

<?php

/**
 * @module Q
 */
class Q_OutputBuffer
{
	/**
	 * Allows use of output buffers that deal intelligently with exceptions.
	 * Constructor implicitly calls ob_start().
	 * The getClean() method calls ob_end_flush() repeatedly to flush buffers
	 * which have been started but not flushed yet, after this one.
	 * @class Q_OutputBuffer
	 * @constructor
	 * @param {string} [$handler=null] The output handler, such as 'ob_gzhandler'.
	 * @param {string} [$locale=null] Can be used to change the locale for a while, e.g. "en_GB"
	 * @param {boolean} [$throw_on_failure=false] If true, and throws an exception if failed
	 *  to create output buffer with this handler.
	 *  Otherwise, silently creates a "normal" output buffer.
	 * @throws {Exception}
	 */
	function __construct(
	 $handler = null, 
	 $locale = null,
	 $throw_on_failure = false)
	{
		if (empty($handler) or !is_string($handler)) {
			ob_start();
		} else {
			$started = ob_start($handler);
			if (!$started) {
				if (!$throw_on_failure) {
					throw new Exception(
						"Q_OutputBuffer with handler $handler could not be created"
					);
				}
				ob_start();
			}
		}
		$status = ob_get_status(false);
		$this->level = $status['level']; // nesting level of current buffer
		$this->pushLocale($locale);
	}
	
	/**
	 * Calls ob_get_clean().
	 * The getClean() method calls ob_end_flush() repeatedly to flush buffers
	 * which have been started but not flushed yet, after this one.
	 * @method getClean
	 * @return {string}
	 */
	function getClean()
	{
		$this->flushHigherBuffers();
		$this->popLocale();
		return ob_get_clean();
	}
	
	/**
	 * Calls ob_end_flush().
	 * The endFlush() method calls ob_end_flush() repeatedly to flush buffers
	 * which have been started but not flushed yet, after this one.
	 * @method endFlush
	 */
	function endFlush()
	{
		$this->flushHigherBuffers();
		$this->popLocale();
		return @ob_end_flush();
	}
	
	/**
	 * Calls ob_get_length().
	 * The getLength() method calls ob_end_flush() repeatedly to flush buffers
	 * which have been started but not flushed yet, after this one.
	 * @method getLength
	 */
	function getLength()
	{
		$this->flushHigherBuffers();
		return ob_get_length();
	}
	
	/**
	 * @method flushHigherBuffers
	 */
	function flushHigherBuffers()
	{
		$status = ob_get_status(false);
		$level = $status['level']; // nesting level of current buffer
		for ($i = $level; $i > $this->level; --$i) {
			@ob_end_flush();
		}
	}
	
	protected function pushLocale($locale)
	{
		if ($locale) {
			$this->lastLocale = $this->locales[$this->level] = $locale;
			setlocale($locale);
		} else {
			if (!$this->lastLocale) {
				$this->lastLocale = Q_Request::locale();
			}
			$this->locales[$this->level] = $this->lastLocale;
		}
	}
	
	protected function popLocale()
	{
		$locales = array();
		for ($i=0; $i<$this->level; ++$i) {
			if (isset($this->locales[$i])) {
				$locales = $this->locales[$i];
			}
		}
		$this->locales = $locales;
	}

	/**
	 * @property $level
	 * @type integer
	 */
	public $level;
	
	/**
	 * @property $locales
	 * @static
	 * @type array
	 */
	public $locales = array();
	
	/**
	 * @property $lastLocale
	 * @static
	 * @type string
	 */
	public $lastLocale = null;
}