| 
<?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();
 }
 }
 ?>
 |