Page

<?php

include_once( "pagecentric.util/HelperFunctions.php" );
include_once( "pagecentric.util/Printer.php" );
include_once( "pagecentric.util/Input.php" );
include_once( "pagecentric.util/DBi.php" );

class Page
{
	var $request;
	var $out;
	var $debug;
	var $viva;

	private $requestURI;
	private $title;
	private $modals;
	private $pageId;
	private $pagePath;
	private $browser;
	private $classes;
	
    static function initialise_constant( $constant )
    {
        if ( '.php' == substr( $constant, -4 ) )
        {
            $constant = dirname( $constant );
        }

        if ( '/' != substr( $constant, -1 ) )
        {
            $constant .= "/";
        }

        return $constant;

    }

	static function initialise()
	{
		$redirect_url = array_key_exists( "REDIRECT_URL", $_SERVER ) ? $_SERVER["REDIRECT_URL"] : "";

		define( "REQUEST_URI",     Page::initialise_constant( $_SERVER["REQUEST_URI"]  ) );
		define( "REDIRECT_URL",    Page::initialise_constant( $redirect_url            ) );
		define( "HTTP_USER_AGENT", array_get( $_SERVER, "HTTP_USER_AGENT" ) );

		if ( ! defined( "DEBUG" ) ) define( "DEBUG", false );
	}

	function __construct()
	{
		$this->out = new Printer();
		$this->debug = ( DEBUG ) ? new Printer() : new NullPrinter();
		$this->debug->startBuffering();

		$this->classes  = "";
		$this->request  = Input::FilterInput( $_REQUEST, $this->debug );
		$this->pageId   = Page::_generatePageId();
		$this->pagePath = Page::generatePagePath();
		$this->browser  = Page::determineBrowser ( HTTP_USER_AGENT );
		$this->isMobile = Page::determineIfMobile( HTTP_USER_AGENT );

		$this->appendClass( $this->browser );

		$this->title = "";
		$this->modals = array();

		$this->isSupportedBrowser();

		//$this->visiting( $this->debug );
	}

	function addClass( $cls )
	{
		$this->appendClass( $cls );
	}

	function appendClass( $cls )
	{
		$this->classes = $this->classes ? $this->classes . " " . $cls : $cls;
	}

	function getBrowser()
	{
		return $this->browser;
	}

	function getClasses()
	{
		return $this->classes;
	}

	function isMobile()
	{
		return $this->isMobile;
	}

	function setTitle( $title )
	{
		$this->title = $title;
	}

	function getPageId()
	{
		return $this->pageId;
	}

	function getPagePath()
	{
		return $this->pagePath;
	}

	function getRequest( $name )
	{
		return array_get( $name, $this->request );
	}
	
	function isHomePage()
	{
		$this->debug->println( "<!-- " . $_SERVER["SCRIPT_NAME"] . "-->" );
	
		$ret = False;
	
		switch ( $_SERVER["SCRIPT_NAME"] )
		{
		case "/index.php":
			$ret = True;
			break;
		}
		return $ret;
	}

	function isSupportedBrowser()
	{
		$supported = true;
		
		if
		(
			string_contains( HTTP_USER_AGENT, "Trident/5"       )
		||	string_contains( HTTP_USER_AGENT, "Trident/4"       )
		||	string_contains( HTTP_USER_AGENT, "Trident/3"       )
		||	string_contains( HTTP_USER_AGENT, "Trident/2"       )
		||	string_contains( HTTP_USER_AGENT, "Trident/1"       )
		)
		{
			$supported = False;
		}

		if ( array_key_exists( "browser-warning-ignored", $_COOKIE ) )
		{
			$supported = True;
		}
		else
		{
			header( "Set-Cookie: browser-warning-ignored=; expires=Thu, 1-Jan-2100 01:01:01 GMT; path=/" );
		}

		return $supported;
	}

	function setCookie( $name, $value, $path = "/", $httpOnly = TRUE )
	{
		$http_only = $httpOnly ? "HttpOnly" : "";
	
		$cookie = "Set-Cookie: $name=$value" . "; path=$path; $http_only";
		
		header( $cookie );
	}

//	function setJSCookie( $name, $value, $path = "/", $httpOnly = TRUE, $expiry = "" )
//	{
//		$cookie = "$name=$value" . "; path=$path";
//
//		if ( $expiry   ) $cookie .= "; $expiry";
//		if ( $httpOnly ) $cookie .= "; HttpOnly";
//
//		$this->out->inprint( "<script type='text/javascript'>" );
//		{
//			$this->out->println( "document.cookie=$cookie" );
//		}
//		$this->out->outprint( "</script>" );
//	}

	function render()
	{
		$this->redirect( $this->debug );

		$this->headers( $this->out );
		$this->doctype( $this->out );
		$this->html   ( $this->out );
	}
	
	function redirect( $debug )
	{
		//	This method may be overridden to redirect to another page.
	}

	function headers( $out )
	{
		header( "Content-type: text/html\n" );
	}

	function doctype( $out )
	{
		$out->println( "<!DOCTYPE html>" );
	}

	function html( $out )
	{
		$this->htmlStart( $out );
		$this->htmlContent( $out );
		$this->htmlEnd( $out );
	}

	function htmlStart( $out )
	{
		$out->println( "<html>" );
	}

	function htmlContent( $out )
	{
		$this->headStart( $out );
		$this->headContent( $out );
		$this->headEnd( $out );

		$this->debug->writeBuffer();

		$this->bodyStart    ( $out );
		$this->bodyContent  ( $out );
		$this->bodyEnd      ( $out );
	}

	function finalJavascript( $out )
	{}

	function htmlEnd( $out )
	{
		$out->println( "</html>" );
	}

	function headStart( $out )
	{
		$out->println( "<head>" );
	}

	function headContent( $out )
	{
		$this->title( $out );
		$this->meta( $out );
		$this->stylesheets( $out );
		$this->javascript( $out );
	}

	function headEnd( $out )
	{
		$out->println( "</head>" );
	}

		function title( $out )
		{
			$title = $this->getPageTitle();

			$out->println( "<title>" . $title . "</title>" );
		}

			function getPageTitle() { return $this->title; }

		function meta( $out )
		{
			//	This method may be overridden. This is it.
		}

		function stylesheets( $out ) {}

		function javascript( $out ) {}

	function bodyStart( $out )
	{
		$page_id     = $this->pageId;
		$pageyoffset = $this->getRequest( "pageyoffset" );
		$hostname    = $_SERVER["SERVER_NAME"];

		if ( ! array_key_exists( "no-modal", $this->request ) )
		{
			$show = $this->getRequest( "show-modal" );
			$show = isset( $this->showModal ) ? $this->showModal : $show;
		}
		$out->inprint( "<body data-class='Page' style='min-height:100vh;margin:0;overflow-y:scroll;' id='$page_id' data-show='$show' class='$this->classes' data-browser='$this->browser' data-hostname='$hostname' data-pageyoffset='$pageyoffset'>" );
	}

	function bodyContent( $out )
	{
		$this->bodyMain     ( $out );
		$this->bodyFooter   ( $out );
		$this->bodyHeader   ( $out );
		$this->bodyNav      ( $out );
		$this->bodyDialog   ( $out );
	}

	function bodyEnd( $out )
	{
		$out->outprint( "</body>" );
	}

	function bodyMain( $out )
	{
		$out->inprint( "<main id='main' style='min-height:100vh'>" );
		{
			$this->bodyMainContent( $out );
		}
		$out->outprint( "</main>" );
	}

		function bodyMainContent( $out ) {}

	function bodyFooter( $out )
	{
		$out->inprint( "<footer id='footer'>" );
		{
			$this->bodyFooterContent( $out );
		}
		$out->outprint( "</footer>" );
	}

		function bodyFooterContent( $out ) {}

	function bodyHeader( $out )
	{
		$out->inprint( "<header id='header'>" );
		{
			$this->bodyHeaderContent( $out );
		}
		$out->outprint( "</header>" );
	}

		function bodyHeaderContent( $out ) {}

	function bodyNav( $out )
	{
		$out->inprint( "<nav id='nav'>" );
		{
			$this->bodyNavContent( $out );
		}
		$out->outprint( "</nav>" );
	}

		function bodyNavContent( $out ) {}

	function bodyNotifications( $out )
	{
		$out->inprint( "<div class='hidden' id='notifications'>" );
		{
			$this->bodyNotificationsContent( $out );
		}
		$out->outprint( "</div>" );
	}

		function bodyNotificationsContent( $out ) {}

	function bodyDialog( $out )
	{
		$out->inprint( "<dialog class='hidden' id='dialog'>" );
		{
			$this->bodyDialogContent( $out );
		}
		$out->outprint( "</dialog>" );
	}

		function bodyDialogContent( $out ) {}

	/**************************************************************************
	 *  Below here are private helper methods.
	 **************************************************************************/

	/*
	 *  Converts uri to form 'page-subpage-index', used to uniquely identify pages.
	 */
	static function _generatePageId( $append_index = true )
	{
		$uri = REDIRECT_URL;
		$uri = substr( $uri, 1 );
		$uri = str_replace( "/", "-", $uri );

		if ( $append_index )
		{
			$uri = $uri . "index";
		}
		else
		if ( "" == $uri )
		{
			$uri = "index";
		}
		else
		{
			$uri = substr( $uri, 0, -1 );
		}
		
		return $uri;

		//$id  = (0 == stripos( $uri, "/page/" )) ? $uri : substr( $uri, stripos( $uri, "/page/" ) + 5 );

		//$page_id = substr( $uri, 1 );
		//return str_replace( "/", "-", $uri );
	}

	static function GeneratePageId( $uri )
	{
		$uri = substr( $uri, 1 );
		$uri = str_replace( "/", "-", $uri );
		$uri = $uri . "index";
		
		return $uri;

		//$id  = (0 == stripos( $uri, "/page/" )) ? $uri : substr( $uri, stripos( $uri, "/page/" ) + 5 );

		//$page_id = substr( $uri, 1 );
		//return str_replace( "/", "-", $uri );
	}

	/*
	 *  Converts each element of uri to Title Case e.g. 'Page/Subpage'.
	 */
	static function generatePagePath()
	{
		$path = "";
		{
			$uri  = REDIRECT_URL;
			$uri  = substr( $uri, 1, -1 );
		
			$bits = explode( "/", $uri );
			foreach ( $bits as $bit )
			{
				$path .= "/" . Page::toTitleCase( $bit );
			}
		}
		return $path;
	}
		
		static function toTitleCase( $string )
		{
			$ret = "";
		
			$bits = explode( "_", $string );
			foreach ( $bits as $bit )
			{
				if ( !empty( $bit ) ) $ret .= " " . strtoupper( $bit[0] ) . substr( $bit, 1 );
			}
			return substr( $ret, 1 );
		}

	static function determineIfMobile( $http_user_agent )
	{
		//	See:
		//	http://stackoverflow.com/questions/6636306/mobile-browser-detection
	
		return (bool)preg_match('#\b(ip(hone|od)|android\b.+\bmobile|opera m(ob|in)i|windows (phone|ce)|blackberry'.
                    '|s(ymbian|eries60|amsung)|p(alm|rofile/midp|laystation portable)|nokia|fennec|htc[\-_]'.
                    '|up\.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\b#i', HTTP_USER_AGENT );
	}

	static function determineBrowser( $http_user_agent )
	{
		$type = "XXX";
		if ( string_contains( $http_user_agent, "Trident" ) )
		{
			$type = "IE";
		}
		else
		if ( string_contains( $http_user_agent, "Chrome" ) )
		{
			if ( string_contains( $http_user_agent, "Windows" ) )
			{
				$type = "CHROME";
			}
			else
			{
				$type = "WEBKIT";
			}
		}
		else
		if ( string_contains( $http_user_agent, "WebKit" ) )
		{
			$type = "WEBKIT";
		}
		else
		{
			$type = "MOZ";
		}
		return $type;
	}
}