<?php
/**
* Copyright (C) 2010 Kai Dorschner
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Kai Dorschner <the-hide@address.com>
* @copyright Copyright 2010, Kai Dorschner
* @license http://www.gnu.org/licenses/gpl.html GPLv3
* @package mocovi
* @subpackage helpers
*/
/**
* Require MVC Exception
*/
class_exists('MvcException') or require $GLOBALS['library'].'autoload/MvcException.php';
interface_exists('EventListener') or require $GLOBALS['library'].'autoload/EventListener.php';
/**
* Modifies HTTP Header
*
* @package mocovi
*/
class Header implements EventListener
{
protected $statuscodes = array
( 100 => 'Continue'
, 101 => 'Switching Protocols'
, 200 => 'OK'
, 201 => 'Created'
, 202 => 'Accepted'
, 203 => 'Non-Authoritative Information'
, 204 => 'No Content'
, 205 => 'Reset Content'
, 206 => 'Partial Content'
, 300 => 'Multiple Choices'
, 301 => 'Moved Permanently'
, 302 => 'Found'
, 303 => 'See Other'
, 304 => 'Not Modified'
, 305 => 'Use Proxy'
, 307 => 'Temporary Redirect'
, 400 => 'Bad Request'
, 401 => 'Unauthorized'
, 402 => 'Payment Required'
, 403 => 'Forbidden'
, 404 => 'Not Found'
, 405 => 'Method Not Allowed'
, 406 => 'Not Acceptable'
, 407 => 'Proxy Authentication Required'
, 408 => 'Request Timeout'
, 409 => 'Conflict'
, 410 => 'Gone'
, 411 => 'Length Required'
, 412 => 'Precondition Failed'
, 413 => 'Request Entity Too Large'
, 414 => 'Request-URI Too Long'
, 415 => 'Unsupported Media Type'
, 416 => 'Requested Range Not Satisfiable'
, 417 => 'Expectation Failed'
, 500 => 'Internal Server Error'
, 501 => 'Not Implemented'
, 502 => 'Bad Gateway'
, 503 => 'Service Unavailable'
, 504 => 'Gateway Timeout'
, 505 => 'HTTP Version Not Supported'
);
/**
* Var containing the singleton instance.
*/
protected static $instance;
/**
* Flag which indicated wether the header has already been sent.
*
* @access private
*/
protected $sent = false;
/**
* Internal header buffer.
*
* Saves all header strings.
*
* @access protected
*/
protected $buffer = array();
protected $cookiesBuffer = array();
/**
* Singleton-pattern constructor set protected to deny direct access.
*/
protected function __construct()
{
$this->sent = headers_sent();
}
public function __destruct() {return $this->sendHeader();}
/**
* Singleton-pattern method to get instance.
*/
public static function getInstance()
{
if(!isset($instance))
self::$instance = new Header();
return self::$instance;
}
public function sendHeader()
{
if(!$this->sent && !headers_sent())
{
foreach($this->buffer as $part)
if(strlen($part[1]) > 0)
header($part[0].': '.$part[1]);
else
header($part[0]);
$this->sendCookies();
return true;
}
$this->sent = true;
return false;
}
public function sendCookies()
{
$return = true;
foreach($this->cookiesBuffer as $cookie)
$return &= setcookie($cookie['name'], $cookie['value'], $cookie['expire']);
return $return;
}
public function addCookie($name, $value, $expire)
{
$this->cookiesBuffer[] = array
( 'name' => $name
, 'value' => $value
, 'expire' => $expire
);
}
public function notModified()
{
$this->status(304);
}
public function location($location)
{
$this->add('Location', $location);
}
public function contentType($media, $charset = '')
{
$this->add('Content-Type', $media.(empty($charset) ? '': '; charset='.$charset));
}
public function contentDisposition($filename, $disposition = 'inline')
{
$this->add('Content-Disposition', $disposition.'; filename="'.$filename.'"');
}
public function contentLength($length)
{
$this->add('Content-Length', (int)$length);
}
public function status($statuscode)
{
$this->add('HTTP/1.1 '.$statuscode.' '.$this->statuscodes[$statuscode]);
}
public function lastModified($date)
{
$this->add('Last-Modified', $date);
}
public function etag($etag)
{
$this->add('Etag', $etag);
}
public function triggerEvent(&$context)
{
$this->sendHeader();
}
protected function add($type, $value = '')
{
if(!($this->sent = headers_sent()))
{
$type[0] = strtoupper($type[0]);
$this->buffer[] = array($type, $value);
}
else
throw new MvcException('Cannot add a buffer. Header already sent.');
}
}