<?php
/**
* Set of base classes used by almost all pages of IS
* @package default
* @author Kamil Dudka <xdudka00@gmail.com>
*/
/**
* Abstraction of drawable page element
* package default
* @abstract
*/
interface Text {
public function draw();
};
/**
* Abstraction of an page element's drawable wrapper
* package default
* @abstract
*/
interface Wrapper {
public function drawBegin();
public function drawEnd();
};
/**
* An elementar class carrying simple text inside.
* The only behavor of this class is to write the text
* using echo command by calling draw() method.
* Useful, isn't it?
* @package default
*/
class SimpleText implements Text {
public function __construct ($szText)
{
$this->szText= $szText;
}
public function draw()
{
echo $this->szText;
}
private $szText;
};
/**
* This class makes possible to include any non-parsable file
* to page trough interface Text.
* @package default
*/
class SimpleInclude implements Text {
public function __construct ($szFilename)
{
$this->szFileName= $szFilename;
if (!file_exists ($this->szFileName))
throw new ErrFileNotFound;
}
public function draw()
{
readfile ($this->szFileName);
}
private $szFilename;
};
/**
* Encapsulated list of Text objects. It can draw all inserted objects to page
* using well-known Text interface
* @package default
*/
class TextList implements Text {
public function __construct() { $this->list= Array(); }
/**
* Append given Text object at end of list
* @param text Text object to add.
*/
public function add (Text $text) { $this->list []= $text; }
public function replace (Text $text) { $this->list= Array($text); }
/**
* Append SimpleText object at end of list using given text string.
* @param szText String to encapsulate and append to list.
*/
public function addText ($szText) { $this->add (new SimpleText ($szText)); }
public function replaceText ($szText) { $this->replace (new SimpleText ($szText)); }
/**
* Draw all inserted objects to page. Objects are drawn in the same order
* as thew were inserted to list. No parameters needed.
*/
public function draw ()
{
foreach ($this->list as $text)
if (NULL!=$text)
$text->draw();
}
private $list;
};
/**
* This abstract add Wrapper interface to class TextList. This make easy to
* encapsulate list of elements with some wrapper, e.g. xml tag
* @package default
* @abstract
*/
abstract class TextWrapper extends TextList {
abstract public function drawBegin ();
abstract public function drawEnd ();
/**
* Text interface method. Draw wrappered list of elements.
*/
public function draw ()
{
$this->drawBegin();
parent::draw();
$this->drawEnd();
}
};
/**
* Indentor is (x)html page source code indenting engine. This is useful for
* reading the page source code by people. Browsers do not need this ;-)
* Design patter singleton.
* @package default
*/
class Indentor {
/**
* @return Return pointer to singleton object.
*/
public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
/**
* Set this constant to any indentation string you like to use.
* Recomended values are a piece of spaces or an tabulator ("\t")
*/
const INDENT_STRING= " ";
/**
* You should call this method if you are about to nest.
*/
public function enter() { $this->iLevel ++; }
/**
* You should call this method if you are about to leave nested block.
*/
public function leave() { $this->iLevel --; }
/**
* @return Return current level of nest.
*/
public function level() { return $this->iLevel; }
/**
* @return Return string containing indentation for current level of nest.
*/
public function indent()
{
return str_repeat (self::INDENT_STRING, $this->level());
}
/**
* Put indentation string direct to document.
*/
public function indentDirect() { echo $this->indent(); }
/**
* Put indented given string direct to document.
* @param szText String tu put (indented) to the document.
*/
public function puts($szText)
{
echo $this->indent().$szText."\n";
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
private static $instance;
private $iLevel;
private function __construct()
{
$this->iLevel= 0;
}
};
class IndentedBlock implements Text {
public static function factory($parent, $szText)
{
return new self($parent, $szText);
}
public function __construct ($parent, $szText)
{
$this->szText= $szText;
if ($parent instanceof TextList)
$parent-> add($this);
}
public function draw()
{
$indentor= Indentor::singleton();
$list= explode("\n", $this->szText);
foreach ($list AS $line)
$indentor-> puts($line);
}
private $szText;
};
/**
* Encapsulation of associative array to store (x)html attributes with css support..
* @package default
*/
class HtAttrMap implements Text {
public function __construct ($attrArray= NULL)
{
$this->attrMap= Array();
if (!empty($attrArray))
foreach ($attrArray as $name => $value)
if (isset($value))
$this->attrMap [$name]= $value;
}
/**
* Set value of hovered attribute. Nothing happens if szValue is empty.
* @param szName Name of an attribute.
* @param szValut Value to set to. Nothing happens if empty.
*/
public function setAttr ($szName, $szValue)
{
if (!empty ($szValue))
$this->attrMap [$szName]= $szValue;
}
/**
* @param szName Name of attribute.
* @return Return value of attribute szName. Return empty string if value does not exist.
*/
public function getAttr ($szName)
{
return @$this->attrMap [$szName];
}
/**
* Method to set css style of element. Style can by added as 'id', 'class' or 'style' attribute.
* @param szStyle Style to set. Use prefix '#' to set element's id , '.' to set element's class or no prefix to set style inline.
*/
public function setStyle ($szStyle)// { $this->szStyle= $szStyle; }
{
if (empty ($szStyle))
return;
switch ($szStyle{0}) {
case '#': $this->setAttr ("id", substr ($szStyle, 1)); break;
case '.': $this->setAttr ("class", substr ($szStyle, 1)); break;
default: $this->setAttr ("style", $szStyle);
}
}
/**
* @return Return element's style. Style representaion is same as in setStyle method.
*/
public function draw()
{
//$this->initDraw();
foreach ($this->attrMap as $szName => $szValue)
echo " ".$szName."=\"".$szValue."\"";
}
private $attrMap;
/*private $szStyle;
private function initDraw()
{
if (empty ($this->szStyle))
return;
switch ($this->szStyle{0}) {
case '#': $this->setAttr ("id", substr ($this->szStyle, 1)); break;
case '.': $this->setAttr ("class", substr ($this->szStyle, 1)); break;
default: $this->setAttr ("style", $this->szStyle);
}
}*/
};
/**
* Abstraction for (x)html non-pair tag(markup). Implements Text interface.
* @package default
*/
class HtSingleToInline extends HtAttrMap {
/**
* @param szMarkup Name of (x)html markup.
* @param parent Reference to parent (x)html element. NULL if there is no parent. Any TextList based classes are allowed.
* @param szStyle Non obligatory parameter setting element css style. Css style can by set later. See setStyle method documentation.
* @param attrMap Associative array of element's attributes. This can be adjust later by setAttr method.
*/
public function __construct ($szMarkup, $parent, $szStyle="", $attrMap=NULL)
{
$this->szMarkup= $szMarkup;
parent::__construct ($attrMap);
$this->setStyle ($szStyle);
if (NULL!= $parent)
$parent-> add ($this);
}
/**
* Implementation of Text interface.
*/
public function draw()
{
echo
"<".$this->szMarkup;
parent::draw();
echo
" />";
}
private $szMarkup;
};
class HtSingleToBlock extends HtSingleToInline {
public function draw()
{
Indentor::singleton()-> indentDirect();
parent::draw();
echo
"\n";
}
};
/**
* This is an factory for HtSingle based elements creation.
* Design pattern factory.
* @package default
*/
class HtSingle {
/**
* Crate an instance of HtInline base object. This emulate design patter factory. It can be useful in future.
* @param szMarkup Name of (x)html markup.
* @param parent Reference to parent (x)html element. NULL if there is no parent. Any TextList based classes are allowed.
* @param szStyle Non obligatory parameter setting element css style. Css style can by set later. See setStyle method documentation.
* @param attrMap Associative array of element's attributes. This can be adjust later by setAttr method.
* @return Return an instance of HtInline based object.
* @static
*/
public static function factory ($szMarkup, $parent, $szStyle="", $attrMap=NULL)
{
$HtSingle= (!isset ($parent) || $parent instanceof HtBlock)?
"HtSingleToBlock":
"HtSingleToInline";
return new $HtSingle ($szMarkup, $parent, $szStyle, $attrMap);
}
};
/**
* Abstraction for (x)html tag(markup) pair.
* Implements Text and Wrapper interfaces.
* @package default
*/
class HtInlineToInline extends TextWrapper {
/**
* @param szMarkup Name of (x)html markup.
* @param parent Reference to parent (x)html element. NULL if there is no parent. Any TextList based classes are allowed.
* @param szStyle Non obligatory parameter setting element css style. Css style can by set later. See setStyle method documentation.
* @param attrMap Associative array of element's attributes. This can be adjust later by setAttr method.
*/
public function __construct ($szMarkup, $parent, $szStyle="", $attrMap=NULL)
{
parent::__construct();
$this->szMarkup= $szMarkup;
$this->attrs= new HtAttrMap ($attrMap);
$this->setStyle ($szStyle);
if (NULL!= $parent)
$parent-> add ($this);
}
public function __call ($szName, $args)
{
return $this->attrs->$szName (@$args[0], @$args[1]);
}
/**
* Draw the start markup before nested elements drawing.
* Wrapper interface implementation.
*/
public function drawBegin()
{
echo
"<".$this->szMarkup;
$this->attrs->draw();
echo
">";
}
/**
* Draw the end markup after nested elements drawing.
* Wrapper interface implementation.
*/
public function drawEnd()
{
echo
"</".$this->szMarkup.">";
}
private $szMarkup;
private $attrs;
};
/**
* This is an extension to HtInlineToInline.
* It is used to nest inline block to well-formed block of source code.
* @package default
*/
class HtInlineToBlock extends HtInlineToInline {
public function drawBegin()
{
Indentor::singleton()-> indentDirect();
parent::drawBegin();
}
public function drawEnd()
{
parent::drawEnd();
echo "\n";
}
};
/**
* This class stands for automatic (x)html blocks indentation.
* Design pattern factory, but not very efficient for this time :-)
* @package default
*/
class HtBlock extends HtInlineToInline {
/**
* Crate an instance of HtBlock. This emulate design patter factory. It can be useful in future.
* @param szMarkup Name of (x)html markup.
* @param parent Reference to parent (x)html element. NULL if there is no parent. Any TextList based classes are allowed.
* @param szStyle Non obligatory parameter setting element css style. Css style can by set later. See setStyle method documentation.
* @param attrMap Associative array of element's attributes. This can be adjust later by setAttr method.
* @return Return an instance of HtBlock.
*/
public static function factory ($szMarkup, $parent, $szStyle="", $attrMap=NULL)
{
return new self ($szMarkup, $parent, $szStyle, $attrMap);
}
public function drawBegin()
{
$indent= Indentor::singleton();
$indent-> indentDirect();
parent::drawBegin();
echo "\n";
$indent-> enter();
}
public function drawEnd()
{
$indent= Indentor::singleton();
$indent-> leave();
$indent-> indentDirect();
parent::drawEnd();
echo "\n";
}
};
/**
* This is an factory for HtInline based elements creation.
* Design pattern factory.
* @package default
*/
class HtInline {
/**
* Crate an instance of HtInline base object. This emulate design patter factory. It can be useful in future.
* @param szMarkup Name of (x)html markup.
* @param parent Reference to parent (x)html element. NULL if there is no parent. Any TextList based classes are allowed.
* @param szStyle Non obligatory parameter setting element css style. Css style can by set later. See setStyle method documentation.
* @param attrMap Associative array of element's attributes. This can be adjust later by setAttr method.
* @return Return an instance of HtInline based object.
*/
public static function factory ($szMarkup, $parent, $szStyle="", $attrMap=NULL)
{
$HtInline= (!isset ($parent) || $parent instanceof HtBlock)?
"HtInlineToBlock":
"HtInlineToInline";
return new $HtInline ($szMarkup, $parent, $szStyle, $attrMap);
}
};
/**
* This is an xhtml document wrapper.
* Implements interface Wrapper.
* @package default
*/
class HtXHTML implements Wrapper {
public function drawBegin()
{
echo
"<?xml version=\"1.0\" encoding=\"iso8859-2\" ?>\n".
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" ".
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n".
"<html>\n";
}
public function drawEnd()
{
echo
"</html>\n";
}
};
/**
* This is default html head. Implements interface Wrapper.
* Any other elements can be added to head using inherited add() method.
* @package default
*/
class HtHead extends TextWrapper {
public function drawBegin()
{
echo
"<head>\n".
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso8859-2\" />\n".
"<meta name=\"GENERATOR\" content=\"Quanta Plus\" />\n".
"<meta name=\"AUTHOR\" content=\"Kamil Dudka\" />\n";
}
public function drawEnd()
{
echo
"</head>\n";
}
};
/**
* Html title. Design pattern singleton.
* @package default
* @uses singleton Page
*/
class HtTitle extends HtInlineToBlock {
/**
* @return Return pointer to singleton object.
*/
public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
/**
* Use this constant to set title prefix.
* Title prefix is also used as title, if no title is set.
*/
const TITLE_PREFIX="T-shop";
/**
* Set document title to $szTitle. TITLE_PREFIX is added as prefix by default.
* @param szTitle Title to set.
* @param bAbsolute If true, no prefix is used.
*/
public function setTitle ($szTitle, $bAbsolute=false)
{
$this->szTitle= $szTitle;
$this->bAbsolute= $bAbsolute;
}
/**
* @return Return currently setted title without prefix.
*/
public function getTitle () { return $this->szTitle; }
public function __construct()
{
parent::__construct ("title", NULL);
Page::singleton()-> addToHead ($this);
}
public function draw()
{
$this->drawInit();
parent::draw();
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
private static $instance;
private function drawInit()
{
if (empty ($this->szTitle)) {
$this-> addText (self::TITLE_PREFIX);
return;
}
if (!$this->bAbsolute)
$this-> addText (self::TITLE_PREFIX.": ");
$this-> addText ($this->szTitle);
}
private $szTitle;
private $bAbsolute;
};
/**
* Inline css style definition, which will be automatically added to html head.
* @package default
* @uses singleton Page
*/
class HtStyle extends TextWrapper {
public function __construct()
{
parent::__construct();
Page::singleton()-> addToHead ($this);
}
public function drawBegin()
{
echo
"<style type=\"text/css\"><!--\n";
}
public function drawEnd()
{
echo
"--></style>\n";
}
};
/**
* Link to css style, which will be automatically added to html head.
* @package default
* @uses singleton Page
*/
class HtStyleLink extends HtSingleToBlock {
/**
* Support for user-style loading.
* STYLE_ID parametr from URL is used as style name.
* STYLE_DEFAUKT is used as default style name.
* It saves user preffered style using cookies.
* So this static method should be called before any drawing.
*/
public static function linkUserStyle ()
{
define ("STYLE_ID", "style");
define ("STYLE_DEFAULT", "default");
define ("STYLE_COOKIE_EXPIRATION", 155520000);
if (isset ($_GET[STYLE_ID]) &&self::styleExists ($_GET[STYLE_ID])) {
$style= $_GET[STYLE_ID];
setcookie (STYLE_ID, $style, time()+STYLE_COOKIE_EXPIRATION, "/");
}
else if (isset ($_COOKIE[STYLE_ID]) &&self::styleExists ($_COOKIE[STYLE_ID]))
$style= $_COOKIE[STYLE_ID];
else
$style= STYLE_DEFAULT;
return new HtStyleLink ($style);
}
/**
* @param szStyle Style file name, relative. Style in /style directory is expected.
*/
public function __construct ($szStyle)
{
parent::__construct ("link", NULL, "",
Array (
"rel" => "stylesheet",
"type" => "text/css",
"href" => (Page::singleton()->linkToWebRoot()."/style/".$szStyle.".css")
)
);
Page::singleton()->addToHead ($this);
}
private static function styleExists($szStyle) {
return file_exists ("style/".$szStyle.".css");
}
};
class HtJavaScript extends HtBlock {
public function __construct()
{
parent::__construct ('script', NULL, '', Array('type'=>'text/javascript'));
}
};
class JsFunction extends TextWrapper {
public function __construct($szFunction, HtJavaScript $script)
{
parent::__construct();
$this->szFunction= $szFunction;
$script-> add($this);
}
public function drawBegin()
{
$ind= Indentor::singleton();
$ind-> puts('function '.$this->szFunction);
$ind-> puts('{');
$ind-> enter();
}
public function drawEnd()
{
$ind= Indentor::singleton();
$ind-> leave();
$ind-> puts('}');
}
private $szFunction;
};
/**
* This singleton handle most of usual page requirements.
* I think each page of IS will use this.
* Design pattern singleton.
* @package default
*/
class Page implements Wrapper {
/**
* @return Return pointer to singleton object.
*/
public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
/**
* Add any Text based object to html head.
* @param text Object to add to head.
*/
public function addToHead (Text $text)
{
$this->htmlHead-> add ($text);
}
/**
* Add (x)html attribute to body element
* See HtAttrMap::setAttr() for more information.
*/
public function addBodyAttr ($szName, $szValue)
{
$this->htmlBody-> setAttr ($szName, $szValue);
}
/**
* @return Return (world visible) link to IS web root.
* This method mey be slight adjusted for stupid servers like eva.fit.vutbr.cz, ...
* @static
*/
public static function linkToWebRoot()
{
return "http://".$_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"]."/~xdudka00/IIS";
}
public static function phpFileExt()
{
return (ereg("fit.vutbr.cz", $_SERVER["SERVER_NAME"])) ? ".php.iso-8859-2" : ".php";
}
public static function redirTo($to)
{
Header ('Location: '.$to);
exit();
}
/**
* Wrapper interface implementation
*/
public function drawBegin()
{
HtTitle::singleton();
$this->htmlWrapper-> drawBegin();
$this->htmlHead-> draw();
$this->htmlBody-> drawBegin();
}
/**
* Wrapper interface implementation
*/
public function drawEnd()
{
$this->htmlBody-> drawEnd();
$this->htmlWrapper-> drawEnd();
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
private static $instance;
private $htmlWrapper;
private $htmlHead;
private $htmlBody;
private function __construct()
{
$this->htmlWrapper= new HtXHTML;
$this->htmlHead= new HtHead;
$this->htmlBody= new HtBlock ("body", NULL);
}
};
?>