<?php
/**
* Class for generating head section of an web page. Elements
* that can be generated are title, meta-tags, CSS files paths,
* JavaScript files paths and path to the favicon image.
*
* @license GNU General Public License (GPL)
* @author Nikola Posa, www.nikolaposa.in.rs
*/
class HeadSection
{
const APPEND = 'APPEND';
const PREPEND = 'PREPEND';
const SET = 'SET';
/**
* Title of an web page.
*
* @var string
*/
protected $title = '';
/**
* Meta tags array which has meta-tag's names as indexes, and
* meta-tag's contents as values.
*
* @var array
*/
protected $meta = array();
/**
* This attribute can be a string or array of strings which
* represents paths to CSS files (i.e. files/style.css).
*
* @var mixed
*/
protected $css = array();
/**
* This attribute can be string or array of strings which
* represents paths to JavaScript files (i.e. files/test.js).
*
* @var mixed
*/
protected $js = array();
/**
* Path to the favicon image (i.e. images/favicon.ico).
*
* @var string
*/
protected $favicon;
/**
* Whether to generate opened and closed <head> tags.
*
* @var bool
*/
private $startingTags = true;
/**
* Content-Type meta-tag.
*
* @var string
*/
private $contentType = 'text/html; charset=UTF-8';
/**
* Indentation of output, this will usually be some spaces.
*
* @var string
*/
private $indent = '';
/**
* Constructor
*
* @param array Options (startingTags, contentType, indent).
* @param array Head section elements as key=>value pairs.
* @return HeadSection
*/
public function __construct($options = array(), $elements = array())
{
$this->setOptions($options);
$this->setElements($elements);
}
/**
* Sets values to head section elements.
*
* @param array Head section elements as key=>value pairs.
* @return void
*/
public function setElements(array $elements)
{
foreach ($elements as $key=>$value) {
$methodName = 'add' . ucfirst($key);
if (method_exists($this, $methodName)) {
$this->$methodName($value);
}
}
}
/**
* Sets values to head section elements.
*
* @param array Head section elements as key=>value pairs.
* @return void
*/
public function setOptions(array $options)
{
foreach ($options as $key=>$value) {
$methodName = 'set' . ucfirst($key);
if (method_exists($this, $methodName)) {
$this->$methodName($value);
}
}
}
/**
* Sets $startingTags flag.
*
* @param bool True or false.
* @return void
*/
public function setStartingTags($flag)
{
$this->startingTags = (bool)$flag;
}
/**
* Sets $contentType.
*
* @param string Content-type meta-tag content value.
* @return void
*/
public function setContentType($contentType)
{
if ($contentType !== null) {
$contentType = (string)$contentType;
}
$this->contentType = $contentType;
}
/**
* Sets indent.
*
* @param int|string True or false.
* @return void
*/
public function setIndent($indent)
{
$this->indent = $this->getWhitespace($indent);
}
/**
* Generate whitespace, based on $indent.
*
* @param int|string Indent (whitespaces or integer).
* @return string
*/
protected function getWhitespace($indent)
{
if (is_int($indent)) {
$indent = str_repeat(' ', $indent);
}
return (string) $indent;
}
/**
* Sets title in head section.
*
* @param string Head section title.
* @param string Mode (append, prepend, set).
* @param bool Whether to escape this head section element.
* @return void
*/
public function addTitle($value, $mode = 'APPEND', $escape = true)
{
$value = (string)$value;
$this->add('title', $value, $mode);
if ($escape === true) {
$this->title = $this->escape($this->title);
}
}
/**
* Function for adding meta-tags.
*
* @param array Meta-tags.
* @param string Mode (append, prepend, set).
* @param bool Whether to escape this head section element.
* @return void
*/
public function addMeta($value, $mode = 'APPEND', $escape = true)
{
if (is_array($value) && !isset($value['name'])) {
foreach ($value as $val) {
$this->add('meta', $val, $mode, false);
}
}
else {
if ($mode == self::SET) {
$this->meta = array($value);
}
else {
$this->add('meta', $value, $mode, false);
}
}
if ($escape === true) {
$this->meta = $this->escape($this->meta);
}
}
/**
* Function for adding path(s) to CSS files.
*
* @param mixed Path(s) to CSS files.
* @param string Mode (append, prepend, set).
* @return void
*/
public function addCss($value, $mode = 'APPEND')
{
$this->add('css', $value, $mode);
}
/**
* Function for adding path(s) to JS files.
*
* @param mixed Path(s) to JS files.
* @param string Mode (append, prepend, set).
* @return void
*/
public function addJs($value, $mode = 'APPEND')
{
$this->add('js', $value, $mode);
}
/**
* Sets path to favicon image.
*
* @param string Path to favicon image.
* @return void
*/
public function addFavicon($value)
{
$value = (string)$value;
$this->favicon = $value;
}
/**
* Used for adding title, meta-tags, css and js paths. This
* function appends, prepends or setts value to some of those
* elements, base on $mode parametar.
*
* @param string Name of an element in head section.
* @param string Value that will be added.
* @param string Mode (append, prepend, set).
* @param bool Whether to recursively pass through all values in case $value is an array.
* @return void
*/
protected function add($element, $value, $mode, $recursive = true)
{
if (is_array($value) && $mode != self::SET && $recursive == true) {
foreach ($value as $val) {
$this->add($element, $val, $mode, $recursive);
}
}
else {
$methodName = strtolower($mode);
if (method_exists($this, $methodName)) {
$this->$methodName($element, $value);
}
}
}
/**
* Appends value to some element of head section.
*
* @param string Name of an element in head section.
* @param string Value that will be added.
* @return void
*/
protected function append($element, $value)
{
if (is_string($this->$element)) {
$this->$element .= $value;
}
elseif (is_array($this->$element)) {
array_push($this->$element, $value);
}
}
/**
* Prepends value to some element of head section.
*
* @param string Name of an element in head section.
* @param string Value that will be added.
* @return void
*/
protected function prepend($element, $value)
{
if (is_string($this->$element)) {
$this->$element .= $value;
}
elseif (is_array($this->$element)) {
array_unshift($this->$element, $value);
}
}
/**
* Sets value to some element of head section.
*
* @param string Name of an element in head section.
* @param string Value that will be added.
* @return void
*/
protected function set($element, $value)
{
if (is_array($this->$element) && is_string($value)) {
$this->$element = array($value);
}
else {
$this->$element = $value;
}
}
/**
* Escapes some value.
*
* @param mixed String or array with strings to escape.
* @return string
*/
protected function escape($value)
{
if (is_array($value)) {
foreach ($value as &$val) {
$val = $this->escape($val);
}
}
elseif (is_string($value)) {
$value = htmlentities($value, null, 'UTF-8');
}
return $value;
}
/**
* Generates head section.
*
* @param string|int $indent
* @return string
*/
public function render($indent = null)
{
$output = '';
$indent = ($indent !== null) ? $this->getWhitespace($indent) : $this->indent;
//You can change this first $output .= if you want to.
if ($this->startingTags == true) {
$output .= '
<head>
';
}
if (strlen($this->title) > 0) {
$output .= $indent . '<title>' . $this->title . '</title>';
$output .= "\n\n";
}
if ($this->contentType !== null) {
$output .= $indent . '<meta http-equiv="Content-Type" content="' . $this->contentType . '" />';
$output .= "\n\n";
}
if (!empty($this->meta)) {
foreach ($this->meta as $tag) {
if (isset($tag['name']) && isset($tag['content'])) {
$output .= $indent . '<meta name= "' . $tag['name'] . '" content = "' . $tag['content'] . '" />';
$output .= "\n";
}
}
$output .= "\n";
}
if (!empty($this->css)) {
foreach($this->css as $path) {
$output .= $indent . '<link href = "' . $path . '" rel = "stylesheet" type = "text/css" />';
$output .= "\n";
}
$output .= "\n";
}
if (isset($this->favicon)) {
$output .= $indent . '<link href = "' . $this->favicon . '" rel = "shortcut icon" type = "image/x-icon" />';
$output .= "\n\n";
}
if (!empty($this->js)) {
foreach($this->js as $path) {
$output .= $indent . '<script type = "text/javascript" src = "' . $path . '"></script>';
$output .= "\n";
}
}
if ($this->startingTags == true) {
$output .= '</head>';
}
return $output;
}
/**
* Redefinded toString() method, that defines how object of
* this class will be outputed when it is converted to a string.
*
* @return string
*/
public function __toString()
{
return $this->render();
}
}
?>
|