home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / HTML / Page2.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  53.9 KB  |  1,627 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | HTML_Page2                                                           |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997 - 2004 The PHP Group                              |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
  17. // |          Klaus Guenther <klaus@capitalfocus.org>                     |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Page2.php,v 1.7 2004/06/07 19:48:00 thesaur Exp $
  21.  
  22. /**
  23.  * The PEAR::HTML_Page2 package provides a simple interface for generating an XHTML compliant page
  24.  * 
  25.  * Features:
  26.  * - supports virtually all HTML doctypes, from HTML 2.0 through XHTML 1.1 and 
  27.  *   XHTML Basic 1.0 plus preliminary support for XHTML 2.0
  28.  * - namespace support
  29.  * - global language declaration for the document
  30.  * - line ending styles
  31.  * - full META tag support
  32.  * - support for stylesheet declaration in the head section
  33.  * - support for script declaration in the head section
  34.  * - support for linked stylesheets and scripts
  35.  * - full support for header <link> tags
  36.  * - body can be a string, object with toHtml or toString methods or an array 
  37.  *   (can be combined)
  38.  * 
  39.  * Ideas for use:
  40.  * - Use to validate the output of a class for XHTML compliance
  41.  * - Quick prototyping using PEAR packages is now a breeze
  42.  * @category HTML
  43.  * @package  HTML_Page2
  44.  * @version  2.0.0
  45.  * @license  http://www.php.net/license/3_0.txt PHP License 3.0
  46.  * @author   Adam Daniel <adaniel1@eesus.jnj.com>
  47.  * @author   Klaus Guenther <klaus@capitalfocus.org>
  48.  * @since   PHP 4.0.3pl1
  49.  */
  50.  
  51. /**
  52.  * Include PEAR core
  53.  */
  54. require_once 'PEAR.php';
  55.  
  56. /**
  57.  * Include HTML_Common class
  58.  * 
  59.  * <p>Additional required files:</p>
  60.  * 
  61.  * <p>HTML/Page2/Doctypes.php is required in private method 
  62.  * _getDoctype()</p>
  63.  * 
  64.  * <p>HTML/Page2/Namespaces.php is required in private method 
  65.  * _getNamespace()</p>
  66.  */
  67. require_once 'HTML/Common.php';
  68.  
  69. /**#@+
  70.  * Determines how content is added to the body.
  71.  *
  72.  * @var        integer
  73.  * @since      2.0.0
  74.  */
  75. define('HTML_PAGE2_APPEND',  0);
  76. define('HTML_PAGE2_PREPEND', 1);
  77. define('HTML_PAGE2_REPLACE', 2);
  78. /**#@-*/
  79.  
  80. /**
  81.  * (X)HTML Page generation class
  82.  * 
  83.  * <p>This class handles the details for creating a properly constructed XHTML page.
  84.  * Page caching, stylesheets, client side script, and Meta tags can be
  85.  * managed using this class.</p>
  86.  * 
  87.  * <p>The body may be a string, object, or array of objects or strings. Objects with
  88.  * toHtml() and toString() methods are supported.</p>
  89.  * 
  90.  * <p><b>XHTML Examples:</b></p>
  91.  * 
  92.  * <p>Simplest example:</p>
  93.  * <code>
  94.  * // the default doctype is XHTML 1.0 Transitional
  95.  * // All doctypes and defaults are set in HTML/Page/Doctypes.php
  96.  * $p = new HTML_Page2();
  97.  *
  98.  * //add some content
  99.  * $p->addBodyContent("<p>some text</p>");
  100.  * 
  101.  * // print to browser
  102.  * $p->display();
  103.  * ?>
  104.  * </code>
  105.  * 
  106.  * <p>Complex XHTML example:</p>
  107.  * <code>
  108.  * <?php
  109.  * // The array takes an array of attributes that determine many important
  110.  * // aspects of the page generations.
  111.  * 
  112.  * // Possible attributes are: charset, mime, lineend, tab, doctype, namespace,
  113.  * // language and cache
  114.  * 
  115.  * $p = new HTML_Page2(array (
  116.  *
  117.  *                          // Sets the charset encoding (default: utf-8)
  118.  *                          'charset'  => 'utf-8',
  119.  *
  120.  *                          // Sets the line end character (default: unix (\n))
  121.  *                          'lineend'  => 'unix',
  122.  *
  123.  *                          // Sets the tab string for autoindent (default: tab (\t))
  124.  *                          'tab'  => '  ',
  125.  *
  126.  *                          // This is where you define the doctype
  127.  *                          'doctype'  => "XHTML 1.0 Strict",
  128.  *
  129.  *                          // Global page language setting
  130.  *                          'language' => 'en',
  131.  *
  132.  *                          // If cache is set to true, the browser may cache the output.
  133.  *                          'cache'    => 'false'
  134.  *                          ));
  135.  *
  136.  * // Here we go
  137.  *
  138.  * // Set the page title
  139.  * $p->setTitle("My page");
  140.  * 
  141.  * // Add optional meta data
  142.  * $p->setMetaData("author", "My Name");
  143.  * 
  144.  * // Put something into the body
  145.  * $p->addBodyContent("<p>some text</p>");
  146.  *
  147.  * // If at some point you want to clear the page content
  148.  * // and output an error message, you can easily do that
  149.  * // See the source for {@link toHtml} and {@link _getDoctype}
  150.  * // for more details
  151.  * if ($error) {
  152.  *     $p->setTitle("Error!");
  153.  *     $p->setBody("<p>Houston, we have a problem: $error</p>");
  154.  *     $p->display();
  155.  *     die;
  156.  * } // end error handling
  157.  *
  158.  * // print to browser
  159.  * $p->display();
  160.  * // output to file
  161.  * $p->toFile('example.html');
  162.  * ?>
  163.  * </code>
  164.  * 
  165.  * Simple XHTML declaration example:
  166.  * <code>
  167.  * <?php
  168.  * $p = new HTML_Page2();
  169.  * // An XHTML compliant page (with title) is automatically generated
  170.  *
  171.  * // This overrides the XHTML 1.0 Transitional default
  172.  * $p->setDoctype('XHTML 1.0 Strict');
  173.  * 
  174.  * // Put some content in here
  175.  * $p->addBodyContent("<p>some text</p>");
  176.  *
  177.  * // print to browser
  178.  * $p->display();
  179.  * ?>
  180.  * </code>
  181.  * 
  182.  * <p><b>HTML examples:</b></p>
  183.  * 
  184.  * <p>HTML 4.01 example:</p>
  185.  * <code>
  186.  * <?php
  187.  * $p = new HTML_Page2('doctype="HTML 4.01 Strict"');
  188.  * $p->addBodyContent = "<p>some text</p>";
  189.  * $p->display();
  190.  * ?>
  191.  * </code>
  192.  * 
  193.  * <p>nuke doctype declaration:</p>
  194.  *
  195.  * <code>
  196.  * <?php
  197.  * $p = new HTML_Page2('doctype="none"');
  198.  * $p->addBodyContent = "<p>some text</p>";
  199.  * $p->display();
  200.  * ?>
  201.  * </code>
  202.  * 
  203.  * 
  204.  * @version 2.0.0
  205.  * @package HTML_Page2
  206.  * @author   Adam Daniel <adaniel1@eesus.jnj.com>
  207.  * @author   Klaus Guenther <klaus@capitalfocus.org>
  208.  */
  209. class HTML_Page2 extends HTML_Common {
  210.     
  211.     /**
  212.      * Contains the content of the <body> tag.
  213.      * 
  214.      * @var     array
  215.      * @access  private
  216.      * @since   2.0
  217.      */
  218.     var $_body = array();
  219.     
  220.     /**
  221.      * Controls caching of the page
  222.      * 
  223.      * @var     bool
  224.      * @access  private
  225.      * @since   2.0
  226.      */
  227.     var $_cache = false;
  228.     
  229.     /**
  230.      * Contains the character encoding string
  231.      * 
  232.      * @var     string
  233.      * @access  private
  234.      * @since   2.0
  235.      */
  236.     var $_charset = 'utf-8';
  237.     
  238.     /**
  239.      * Contains the !DOCTYPE definition
  240.      * 
  241.      * @var array
  242.      * @access private
  243.      * @since   2.0
  244.      */
  245.     var $_doctype = array('type'=>'xhtml','version'=>'1.0','variant'=>'transitional');
  246.     
  247.     /**
  248.      * Contains the page language setting
  249.      * 
  250.      * @var     string
  251.      * @access  private
  252.      * @since   2.0
  253.      */
  254.     var $_language = 'en';
  255.     
  256.     /**
  257.      * Array of Header <link> tags
  258.      * 
  259.      * @var     array
  260.      * @access  private
  261.      * @since   2.0
  262.      */
  263.     var $_links = array();
  264.     
  265.     /**
  266.      * Array of meta tags
  267.      * 
  268.      * @var     array
  269.      * @access  private
  270.      * @since   2.0
  271.      */
  272.     var $_metaTags = array( 'standard' => array ( 'Generator' => 'PEAR HTML_Page' ) );
  273.     
  274.     /**
  275.      * Document mime type
  276.      * 
  277.      * @var      string
  278.      * @access   private
  279.      * @since   2.0
  280.      */
  281.     var $_mime = 'text/html';
  282.     
  283.     /**
  284.      * Document namespace
  285.      * 
  286.      * @var      string
  287.      * @access   private
  288.      * @since   2.0
  289.      */
  290.     var $_namespace = '';
  291.     
  292.     /**
  293.      * Document profile
  294.      * 
  295.      * @var      string
  296.      * @access   private
  297.      * @since   2.0
  298.      */
  299.     var $_profile = '';
  300.     
  301.     /**
  302.      * Array of linked scripts
  303.      * 
  304.      * @var      array
  305.      * @access   private
  306.      * @since   2.0
  307.      */
  308.     var $_scripts = array();
  309.     
  310.     /**
  311.      * Array of scripts placed in the header
  312.      * 
  313.      * @var  array
  314.      * @access   private
  315.      * @since   2.0
  316.      */
  317.     var $_script = array();
  318.     
  319.     /**
  320.      * Suppresses doctype
  321.      * 
  322.      * @var     boolean
  323.      * @access  private
  324.      * @since   2.0
  325.      */
  326.     var $_simple = false;
  327.     
  328.     /**
  329.      * Array of included style declarations
  330.      * 
  331.      * @var     array
  332.      * @access  private
  333.      * @since   2.0
  334.      */
  335.     var $_style = array();
  336.     
  337.     /**
  338.      * Array of linked style sheets
  339.      * 
  340.      * @var     array
  341.      * @access  private
  342.      * @since   2.0
  343.      */
  344.     var $_styleSheets = array();
  345.     
  346.     /**
  347.      * HTML page title
  348.      * 
  349.      * @var     string
  350.      * @access  private
  351.      * @since   2.0
  352.      */
  353.     var $_title = '';
  354.     
  355.     /**
  356.      * Defines whether XML prolog should be prepended to XHTML documents
  357.      * 
  358.      * @var  bool
  359.      * @access   private
  360.      * @since   2.0
  361.      */
  362.     var $_xmlProlog = true;
  363.     
  364.     /**
  365.      * Class constructor.
  366.      *
  367.      * <p>Accepts an array of attributes</p>
  368.      * 
  369.      * <p><b>General options:</b></p>
  370.      *     - "lineend" => "unix|win|mac" (Sets line ending style; defaults to 
  371.      *        unix.) See also {@link setLineEnd}. 
  372.      *     - "tab"     => string (Sets line ending style; defaults to \t.) See 
  373.      *        also {@link setTab}. 
  374.      *     - "cache"   => "false|true"  See also {@link setCache}. 
  375.      *     - "charset" => charset string (Sets charset encoding; defaults 
  376.      *       to utf-8) See also {@link setCharset} and {@link getCharset}. 
  377.      *     - "mime"    => mime encoding string (Sets document mime type; 
  378.      *       defaults to text/html)  See also {@link setMimeEncoding}. 
  379.      * <p><b>XHTML specific options:</b></p>
  380.      *     - "doctype"  => string (Sets XHTML doctype; defaults to 
  381.      *       XHTML 1.0 Transitional.)  See also {@link setDoctype}. 
  382.      *     - "language" => two letter language designation. (Defines global 
  383.      *       document language; defaults to "en".) See also {@link setLang}.
  384.      *     - "namespace"  => string (Sets document namespace; defaults to the 
  385.      *       W3C defined namespace.) See also {@link setNamespace}. 
  386.      *     - "profile" => string (Sets head section profile) See also
  387.      *       {@link setHeadProfile}.
  388.      *     - "prolog" => bool (Enables or disables the XML prolog. This is 
  389.      *       usually unwanted, as it makes the page invalid XHTML.) See also
  390.      *       {@link disableXmlProlog} and {@link enableXmlProlog}.
  391.      * 
  392.      * <p>For extensive usage examples, see {@link HTML_Page2 page-level} 
  393.      * documentation.</p>
  394.      * 
  395.      * @param   mixed   $attributes     Associative array of table tag 
  396.      *                                  attributes 
  397.      * @access  public
  398.      * @since   2.0
  399.      */
  400.     function HTML_Page2($attributes = array())
  401.     {
  402.         
  403.         if ($attributes) {
  404.             $attributes = $this->_parseAttributes($attributes);
  405.         }
  406.         
  407.         if (isset($attributes['lineend'])) {
  408.             $this->setLineEnd($attributes['lineend']);
  409.         }
  410.         
  411.         if (isset($attributes['charset'])) {
  412.             $this->setCharset($attributes['charset']);
  413.         }
  414.         
  415.         if (isset($attributes['doctype'])){
  416.             if ($attributes['doctype'] == 'none') {
  417.                 $this->_simple = true;
  418.             } elseif ($attributes['doctype']) {
  419.                 $this->setDoctype($attributes['doctype']);
  420.             }
  421.         }
  422.         
  423.         if (isset($attributes['language'])) {
  424.             $this->setLang($attributes['language']);
  425.         }
  426.         
  427.         if (isset($attributes['mime'])) {
  428.             $this->setMimeEncoding($attributes['mime']);
  429.         }
  430.         
  431.         if (isset($attributes['namespace'])) {
  432.             $this->setNamespace($attributes['namespace']);
  433.         }
  434.         
  435.         if (isset($attributes['profile'])) {
  436.             $this->setHeadProfile($attributes['profile']);
  437.         }
  438.         
  439.         if (isset($attributes['tab'])) {
  440.             $this->setTab($attributes['tab']);
  441.         }
  442.         
  443.         if (isset($attributes['cache'])) {
  444.             $this->setCache($attributes['cache']);
  445.         }
  446.         
  447.         if (isset($attributes['prolog'])) {
  448.             if ($attributes['prolog'] === false) {
  449.                 $this->disableXmlProlog();
  450.             } else {
  451.                 $this->enableXmlProlog();
  452.             }
  453.         }
  454.         
  455.     } // end class constructor
  456.  
  457.     /**
  458.      * Iterates through an array, returning an HTML string
  459.      * 
  460.      * <p>It also handles objects, calling the toHTML or toString methods
  461.      * and propagating the line endings and tabs for objects that
  462.      * extend HTML_Common.</p>
  463.      * 
  464.      * <p>For more details read the well-documented source.</p>
  465.      * 
  466.      * @access  protected
  467.      * @param   mixed       $element   The element to be processed
  468.      * @return  string
  469.      */
  470.     function _elementToHtml(&$element) // It's a reference just to save some memory.
  471.     {
  472.         
  473.         // get the special formatting settings
  474.         $lnEnd = $this->_getLineEnd();
  475.         $tab = $this->_getTab();
  476.         
  477.         // initialize the variable that will collect our generated HTML
  478.         $strHtml = ''; 
  479.         
  480.         // Attempt to generate HTML code for what is passed
  481.         if (is_object($element)) {
  482.             // If this is an object, attempt to generate the appropriate HTML 
  483.             // code.
  484.             
  485.             if (is_subclass_of($element, 'html_common')) {
  486.                 // For this special case, we set the appropriate indentation
  487.                 // and line end styles. That way uniform HTML is generated.
  488.                 
  489.                 // The reason this does not check for each method individually 
  490.                 // is that it could be that setTab, for example, could 
  491.                 // possibly refer to setTable, etc. And such ambiguity could
  492.                 // create a big mess. So this will simply bias  the HTML_Page 
  493.                 // class family toward other HTML_Common-based classes.
  494.                 
  495.                 // Of course, these features are not necessarily implemented
  496.                 // in all HTML_Common-based packages. But at least this makes 
  497.                 // it possible to propagate the settings.
  498.                 $element->setTabOffset(1);
  499.                 $element->setTab($tab);
  500.                 $element->setLineEnd($lnEnd);
  501.             }
  502.             
  503.             // Attempt to generate code using first toHtml and then toString 
  504.             // methods. The result is not parsed with _elementToHtml because
  505.             // it would improperly add one tab indentation to the initial line
  506.             // of each object's output.
  507.             if (method_exists($element, 'toHtml')) {
  508.                 $strHtml .= $element->toHtml() . $lnEnd;
  509.             } elseif (method_exists($element, 'toString')) {
  510.                 $strHtml .= $element->toString() . $lnEnd;
  511.             } else {
  512.                 // If the class does not have an appropriate method, an error 
  513.                 // should be returned rather than simply dying or outputting
  514.                 // the difficult to troubleshoot 'Object' output.
  515.                 $class = get_class($element);
  516.                 PEAR::raiseError("Error: Content object (class $class) " .
  517.                                  'does not support  methods toHtml() or ' .
  518.                                  'toString().',0,PEAR_ERROR_TRIGGER);
  519.             }
  520.         } elseif (is_array($element)) {
  521.             foreach ($element as $item) {
  522.                 // Parse each element individually
  523.                 $strHtml .= $this->_elementToHtml($item);
  524.             }
  525.         } else { 
  526.             // If we don't have an object or array, we can simply output
  527.             // the element after indenting it and properly ending the line.
  528.             $strHtml .= $tab . $element . $lnEnd;
  529.         }
  530.         
  531.         return $strHtml;
  532.         
  533.     } // end func _elementToHtml
  534.     
  535.     /**
  536.      * Generates the HTML string for the <body> tag
  537.      * 
  538.      * @access  private
  539.      * @return  string
  540.      */
  541.     function _generateBody()
  542.     {
  543.         
  544.         // get line endings
  545.         $lnEnd = $this->_getLineEnd();
  546.         
  547.         // If body attributes exist, add them to the body tag.
  548.         // Many attributes are depreciated because of CSS.
  549.         $strAttr = $this->_getAttrString($this->_attributes);
  550.         
  551.         if ($strAttr) {
  552.             $strHtml = "<body $strAttr>" . $lnEnd;
  553.         } else {
  554.             $strHtml = '<body>' . $lnEnd;
  555.         }
  556.  
  557.         // Allow for mixed content in the body array, recursing into inner
  558.         // array serching for non-array types.
  559.         $strHtml .= $this->_elementToHtml($this->_body);
  560.  
  561.         // Close tag
  562.         $strHtml .= '</body>' . $lnEnd;
  563.  
  564.         // Let's roll!
  565.         return $strHtml;
  566.     } // end func _generateHead
  567.     
  568.     /**
  569.      * Generates the HTML string for the <head> tag
  570.      * 
  571.      * @return string
  572.      * @access private
  573.      */
  574.     function _generateHead()
  575.     {
  576.         // Close empty tags if XHTML for XML compliance
  577.         if ($this->_doctype['type'] == 'html'){
  578.             $tagEnd = '>';
  579.         } else {
  580.             $tagEnd = ' />';
  581.         }
  582.         
  583.         // get line endings
  584.         $lnEnd = $this->_getLineEnd();
  585.         $tab = $this->_getTab();
  586.         
  587.         $strHtml  = '<head>' . $lnEnd;
  588.         
  589.         // Generate META tags
  590.         foreach ($this->_metaTags as $type => $tag) {
  591.             foreach ($tag as $name => $content) {
  592.                 if ($type == 'http-equiv') {
  593.                     $strHtml .= $tab . "<meta http-equiv=\"$name\" content=\"$content\"" . $tagEnd . $lnEnd;
  594.                 } elseif ($type == 'standard') {
  595.                     $strHtml .= $tab . "<meta name=\"$name\" content=\"$content\"" . $tagEnd . $lnEnd;
  596.                 }
  597.             }
  598.         }
  599.  
  600.         // Generate the title tag.
  601.         // Pre-XHTML compatibility:
  602.         //     This comes after meta tags because of possible
  603.         //     http-equiv character set declarations.
  604.         $strHtml .= $tab . '<title>' . $this->getTitle() . '</title>' . $lnEnd;
  605.         
  606.         // Generate link declarations
  607.         foreach ($this->_links as $link) {
  608.             $strHtml .= $tab . $link . $tagEnd . $lnEnd;
  609.         }
  610.         
  611.         // Generate stylesheet links
  612.         foreach ($this->_styleSheets as $strSrc => $strAttr ) {
  613.             $strHtml .= $tab . "<link rel=\"stylesheet\" href=\"$strSrc\" type=\"".$strAttr['mime'].'"';
  614.             if (!is_null($strAttr['media'])){
  615.                 $strHtml .= ' media="'.$strAttr['media'].'"';
  616.             }
  617.             $strHtml .= $tagEnd . $lnEnd;
  618.         }
  619.         
  620.         // Generate stylesheet declarations
  621.         foreach ($this->_style as $styledecl) {
  622.             foreach ($styledecl as $type => $content) {
  623.                 $strHtml .= $tab . '<style type="' . $type . '">' . $lnEnd;
  624.                 
  625.                 // This is for full XHTML support.
  626.                 if ($this->_mime == 'text/html' ) {
  627.                     $strHtml .= $tab . $tab . '<!--' . $lnEnd;
  628.                 } else {
  629.                     $strHtml .= $tab . $tab . '<![CDATA[' . $lnEnd;
  630.                 }
  631.                 
  632.                 if (is_object($content)) {
  633.                     
  634.                     // first let's propagate line endings and tabs for other HTML_Common-based objects
  635.                     if (is_subclass_of($content, "html_common")) {
  636.                         $content->setTab($tab);
  637.                         $content->setTabOffset(3);
  638.                         $content->setLineEnd($lnEnd);
  639.                     }
  640.                     
  641.                     // now let's get a string from the object
  642.                     if (method_exists($content, "toString")) {
  643.                         $strHtml .= $content->toString() . $lnEnd;
  644.                     } else {
  645.                         PEAR::raiseError('Error: Style content object does not support  method toString().',
  646.                                 0,PEAR_ERROR_TRIGGER);
  647.                     }
  648.                     
  649.                 } else {
  650.                     $strHtml .= $content . $lnEnd;
  651.                 }
  652.                 
  653.                 // See above note
  654.                 if ($this->_mime == 'text/html' ) {
  655.                     $strHtml .= $tab . $tab . '-->' . $lnEnd;
  656.                 } else {
  657.                     $strHtml .= $tab . $tab . ']]>' . $lnEnd;
  658.                 }
  659.                 $strHtml .= $tab . '</style>' . $lnEnd;
  660.             }
  661.         } // end generating stylesheet blocks
  662.         
  663.         // Generate script file links
  664.         foreach ($this->_scripts as $strSrc => $strType) {
  665.             $strHtml .= $tab . "<script type=\"$strType\" src=\"$strSrc\"></script>" . $lnEnd;
  666.         }
  667.         
  668.         // Generate script declarations
  669.         foreach ($this->_script as $script) {
  670.             foreach ($script as $type => $content) {
  671.                 $strHtml .= $tab . '<script type="' . $type . '">' . $lnEnd;
  672.                 
  673.                 // This is for full XHTML support.
  674.                 if ($this->_mime == 'text/html' ) {
  675.                     $strHtml .= $tab . $tab . '// <!--' . $lnEnd;
  676.                 } else {
  677.                     $strHtml .= $tab . $tab . '<![CDATA[' . $lnEnd;
  678.                 }
  679.                 
  680.                 if (is_object($content)) {
  681.                     
  682.                     // first let's propagate line endings and tabs for other HTML_Common-based objects
  683.                     if (is_subclass_of($content, "html_common")) {
  684.                         $content->setTab($tab);
  685.                         $content->setTabOffset(3);
  686.                         $content->setLineEnd($lnEnd);
  687.                     }
  688.                     
  689.                     // now let's get a string from the object
  690.                     if (method_exists($content, "toString")) {
  691.                         $strHtml .= $content->toString() . $lnEnd;
  692.                     } else {
  693.                         PEAR::raiseError('Error: Script content object does not support  method toString().',
  694.                                 0,PEAR_ERROR_TRIGGER);
  695.                     }
  696.                     
  697.                 } else {
  698.                     $strHtml .= $content . $lnEnd;
  699.                 }
  700.                 
  701.                 // See above note
  702.                 if ($this->_mime == 'text/html' ) {
  703.                     $strHtml .= $tab . $tab . '// -->' . $lnEnd;
  704.                 } else {
  705.                     $strHtml .= $tab . $tab . '// ]]>' . $lnEnd;
  706.                 }
  707.                 $strHtml .= $tab . '</script>' . $lnEnd;
  708.             }
  709.         } // end generating script blocks
  710.         
  711.         // Close tag
  712.         $strHtml .=  '</head>' . $lnEnd;
  713.         
  714.         // Let's roll!
  715.         return $strHtml;
  716.     } // end func _generateHead
  717.     
  718.     /**
  719.      * Returns the doctype declaration
  720.      *
  721.      * @return string
  722.      * @access private
  723.      */
  724.     function _getDoctype()
  725.     {
  726.         require('HTML/Page2/Doctypes.php');
  727.         
  728.         if (isset($this->_doctype['type'])) {
  729.             $type = $this->_doctype['type'];
  730.         }
  731.         
  732.         if (isset($this->_doctype['version'])) {
  733.             $version = $this->_doctype['version'];
  734.         }
  735.         
  736.         if (isset($this->_doctype['variant'])) {
  737.             $variant = $this->_doctype['variant'];
  738.         }
  739.         
  740.         $strDoctype = '';
  741.         
  742.         if (isset($variant)) {
  743.             if (isset($doctype[$type][$version][$variant][0])) {
  744.                 foreach ( $doctype[$type][$version][$variant] as $string) {
  745.                     $strDoctype .= $string.$this->_getLineEnd();
  746.                 }
  747.             }
  748.         } elseif (isset($version)) {
  749.             if (isset($doctype[$type][$version][0])) {
  750.                 foreach ( $doctype[$type][$version] as $string) {
  751.                     $strDoctype .= $string.$this->_getLineEnd();
  752.                 }
  753.             } else {
  754.                 if (isset($default[$type][$version][0])) {
  755.                     $this->_doctype = $this->_parseDoctypeString($default[$type][$version][0]);
  756.                     $strDoctype = $this->_getDoctype();
  757.                 }
  758.             }
  759.         } elseif (isset($type)) {
  760.             if (isset($default[$type][0])){
  761.                 $this->_doctype = $this->_parseDoctypeString($default[$type][0]);
  762.                 $strDoctype = $this->_getDoctype();
  763.             }
  764.         } else {
  765.             $this->_doctype = $this->_parseDoctypeString($default['default'][0]);
  766.             $strDoctype = $this->_getDoctype();
  767.         }
  768.         
  769.         if ($strDoctype) {
  770.             return $strDoctype;
  771.         } else {
  772.             PEAR::raiseError('Error: "'.$this->getDoctypeString().'" is an unsupported or illegal document type.',
  773.                                     0,PEAR_ERROR_TRIGGER);
  774.             $this->_simple = true;
  775.             return false;
  776.         }
  777.         
  778.     } // end func _getDoctype
  779.     
  780.     /**
  781.      * Retrieves the document namespace
  782.      *
  783.      * @return string
  784.      * @access private
  785.      */
  786.     function _getNamespace()
  787.     {
  788.         
  789.         require('HTML/Page2/Namespaces.php');
  790.         
  791.         if (isset($this->_doctype['type'])) {
  792.             $type = $this->_doctype['type'];
  793.         }
  794.         
  795.         if (isset($this->_doctype['version'])) {
  796.             $version = $this->_doctype['version'];
  797.         }
  798.         
  799.         if (isset($this->_doctype['variant'])) {
  800.             $variant = $this->_doctype['variant'];
  801.         }
  802.         
  803.         $strNamespace = '';
  804.         
  805.         if (isset($variant)){
  806.             if (isset($namespace[$type][$version][$variant][0]) && is_string($namespace[$type][$version][$variant][0])) {
  807.                 $strNamespace = $namespace[$type][$version][$variant][0];
  808.             } elseif (isset($namespace[$type][$version][0]) && is_string($namespace[$type][$version][0]) ) {
  809.                 $strNamespace = $namespace[$type][$version][0];
  810.             } elseif (isset($namespace[$type][0]) && is_string($namespace[$type][0]) ) {
  811.                 $strNamespace = $namespace[$type][0];
  812.             }
  813.         } elseif (isset($version)) {
  814.             if (isset($namespace[$type][$version][0]) && is_string($namespace[$type][$version][0]) ) {
  815.                 $strNamespace = $namespace[$type][$version][0];
  816.             } elseif (isset($namespace[$type][0]) && is_string($namespace[$type][0]) ) {
  817.                 $strNamespace = $namespace[$type][0];
  818.             }
  819.         } else {
  820.             if (isset($namespace[$type][0]) && is_string($namespace[$type][0]) ) {
  821.                 $strNamespace = $namespace[$type][0];
  822.             }
  823.         }
  824.         
  825.         if ($strNamespace) {
  826.             return $strNamespace;
  827.         } else {
  828.             PEAR::raiseError('Error: "' . $this->getDoctypeString() .
  829.                                     '" does not have a default namespace.' .
  830.                                     ' Use setNamespace() to define your namespace.',
  831.                                     0, PEAR_ERROR_TRIGGER);
  832.             return false;
  833.         }
  834.         
  835.     } // end func _getNamespace
  836.     
  837.     /**
  838.      * Parses a doctype declaration like "XHTML 1.0 Strict" to an array
  839.      *
  840.      * @param   string  $string     The string to be parsed
  841.      * @return array
  842.      * @access private
  843.      */
  844.     function _parseDoctypeString($string)
  845.     {
  846.         
  847.         $split = explode(' ',strtolower($string));
  848.         $elements = count($split);
  849.         
  850.         if (isset($split[2])){
  851.             $array = array('type'=>$split[0],'version'=>$split[1],'variant'=>$split[2]);
  852.         } elseif (isset($split[1])){
  853.             $array = array('type'=>$split[0],'version'=>$split[1]);
  854.         } else {
  855.             $array = array('type'=>$split[0]);
  856.         }
  857.         
  858.         return $array;
  859.         
  860.     } // end func _parseDoctypeString
  861.     
  862.     /**
  863.      * Sets the content of the <body> tag
  864.      * 
  865.      * <p>It is possible to add objects, strings or an array of strings 
  866.      * and/or objects. Objects must have a toHtml or toString method.</p>
  867.      * 
  868.      * <p>By default, if content already exists, the new content is appended.
  869.      * If you wish to overwrite whatever is in the body, use {@link setBody}; 
  870.      * {@link unsetBody} completely empties the body without inserting new 
  871.      * content. You can also use {@link prependBodyContent} to prepend content 
  872.      * to whatever is currently in the array of body elements.</p>
  873.      * 
  874.      * <p>The following constants are defined to be passed as the flag
  875.      * attribute: HTML_PAGE2_APPEND, HTML_PAGE2_PREPEND and HTML_PAGE2_REPLACE.
  876.      * Their usage should be quite clear from their names.</p> 
  877.      * 
  878.      * @param mixed $content  New <body> tag content (may be passed as a 
  879.      *                        reference)
  880.      * @param int   $flag     Determines whether to prepend, append or replace 
  881.      *                        the content. Use pre-defined constants.
  882.      * @access public
  883.      */
  884.     function addBodyContent($content, $flag = HTML_PAGE2_APPEND)
  885.     {
  886.         
  887.         if ($flag == HTML_PAGE2_REPLACE) {       // replaces any content in body 
  888.             $this->unsetBody();
  889.             $this->_body[] =& $content;
  890.         } elseif ($flag == HTML_PAGE2_PREPEND) { // prepends content to the body 
  891.             array_unshift($this->_body, $content);
  892.         } else {                                // appends content to the body
  893.             $this->_body[] =& $content;
  894.         }
  895.         
  896.     } // end addBodyContent    
  897.     
  898.     /**
  899.      * Adds a linked script to the page
  900.      * 
  901.      * @param    string  $url        URL to the linked script
  902.      * @param    string  $type       Type of script. Defaults to 'text/javascript'
  903.      * @access   public
  904.      */
  905.     function addScript($url, $type="text/javascript")
  906.     {
  907.         $this->_scripts[$url] = $type;
  908.     } // end func addScript
  909.     
  910.     /**
  911.      * Adds a script to the page
  912.      *
  913.      * <p>Content can be a string or an object with a toString method.
  914.      * Defaults to text/javascript.</p>
  915.      * 
  916.      * @access   public
  917.      * @param    mixed   $content   Script (may be passed as a reference)
  918.      * @param    string  $type      Scripting mime (defaults to 'text/javascript')
  919.      * @return   void
  920.      */
  921.     function addScriptDeclaration($content, $type = 'text/javascript')
  922.     {
  923.         $this->_script[][strtolower($type)] =& $content;
  924.     } // end func addScriptDeclaration
  925.     
  926.     /**
  927.      * Adds a linked stylesheet to the page
  928.      * 
  929.      * @param    string  $url    URL to the linked style sheet
  930.      * @param    string  $type   Mime encoding type
  931.      * @param    string  $media  Media type that this stylesheet applies to
  932.      * @access   public
  933.      * @return   void
  934.      */
  935.     function addStyleSheet($url, $type = 'text/css', $media = null)
  936.     {
  937.         $this->_styleSheets[$url]['mime']  = $type;
  938.         $this->_styleSheets[$url]['media'] = $media;
  939.     } // end func addStyleSheet
  940.     
  941.     /**
  942.      * Adds a stylesheet declaration to the page
  943.      * 
  944.      * <p>Content can be a string or an object with a toString method.
  945.      * Defaults to text/css.</p>
  946.      * 
  947.      * @access   public
  948.      * @param    mixed   $content   Style declarations (may be passed as a reference)
  949.      * @param    string  $type      Type of stylesheet (defaults to 'text/css')
  950.      * @return   void
  951.      */
  952.     function addStyleDeclaration($content, $type = 'text/css')
  953.     {
  954.         $this->_style[][strtolower($type)] =& $content;
  955.     } // end func addStyleDeclaration
  956.     
  957.     /**
  958.      * Adds a shortcut icon (favicon)
  959.      * 
  960.      * <p>This adds a link to the icon shown in the favorites list or on 
  961.      * the left of the url in the address bar. Some browsers display 
  962.      * it on the tab, as well.</p>
  963.      * 
  964.      * @access    public
  965.      * @param     string  $href        The link that is being related.
  966.      * @param     string  $type        File type
  967.      * @param     string  $relation    Relation of link
  968.      * @return    void
  969.      */
  970.     function addFavicon($href, $type = 'image/x-icon', $relation = 'shortcut icon') {
  971.         $this->_links[] = "<link href=\"$href\" rel=\"$relation\" type=\"$type\"";
  972.     } // end func addFavicon
  973.  
  974.     /**
  975.      * Adds <link> tags to the head of the document
  976.      * 
  977.      * <p>$relType defaults to 'rel' as it is the most common relation type used.
  978.      * ('rev' refers to reverse relation, 'rel' indicates normal, forward relation.)
  979.      * Typical tag: <link href="index.php" rel="Start"></p>
  980.      * 
  981.      * @access   public
  982.      * @param    string  $href       The link that is being related.
  983.      * @param    string  $relation   Relation of link.
  984.      * @param    string  $relType    Relation type attribute.  Either rel or rev (default: 'rel').
  985.      * @param    array   $attributes Associative array of remaining attributes.
  986.      * @return   void
  987.      */
  988.     function addHeadLink($href, $relation, $relType = 'rel', $attributes = array()) {
  989.         $attributes = $this->_parseAttributes($attributes);
  990.         $generatedTag = $this->_getAttrString($attributes);
  991.         $generatedTag = "<link href=\"$href\" $relType=\"$relation\"" . $generatedTag;
  992.         $this->_links[] = $generatedTag;
  993.     } // end func addHeadLink
  994.  
  995.     /**
  996.      * Returns the current API version
  997.      * 
  998.      * @access   public
  999.      * @return   double
  1000.      */
  1001.     function apiVersion()
  1002.     {
  1003.         return 2.0;
  1004.     } // end func apiVersion
  1005.     
  1006.     /**
  1007.      *  Disables prepending the XML prolog for XHTML documents
  1008.      * 
  1009.      * <p>Normally, XHTML documents require the XML prolog to be on the first 
  1010.      * line of each valid document:</p>
  1011.      * 
  1012.      * <code>
  1013.      * <?xml version="1.0" encoding="utf-8"?> 
  1014.      * <!DOCTYPE html
  1015.      *     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  1016.      *     "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  1017.      * 
  1018.      * <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  1019.      * <head>
  1020.      * ...
  1021.      * </code>
  1022.      * 
  1023.      * <p>However, some browsers, most noticeably Microsoft Internet Explorer, 
  1024.      * have difficulties properly displaying XHTML in compatibility mode with 
  1025.      * this. This method is for workaround solutions, such as the infamous CSS 
  1026.      * Box Hack.</p>
  1027.      * 
  1028.      * <p>The opposite (and default) effect can be achieved using the 
  1029.      * {@link enableXmlProlog} method.</p>
  1030.      * 
  1031.      * <p>Usage:</p>
  1032.      * 
  1033.      * <code>
  1034.      * $page->disableXmlProlog();
  1035.      * </code>
  1036.      * 
  1037.      * @access   public
  1038.      * @return  void
  1039.      */
  1040.     function disableXmlProlog()
  1041.     {
  1042.         $this->_xmlProlog = false;
  1043.     } // end func disableXmlProlog
  1044.     
  1045.     /**
  1046.      * Enables prepending the XML prolog for XHTML documents (default)
  1047.      * 
  1048.      * <p>This method enables the default XHTML output, with an XML prolog on 
  1049.      * the first line of the document. See {@link disableXmlProlog} for more 
  1050.      * details on why it may or may not be advantageous to have the XML prolog 
  1051.      * disabled.</p>
  1052.      * 
  1053.      * <p>Usage:</p>
  1054.      * 
  1055.      * <code>
  1056.      * $page->enableXmlProlog();
  1057.      * </code>
  1058.      * 
  1059.      * @access   public
  1060.      * @return   void
  1061.      */
  1062.     function enableXmlProlog()
  1063.     {
  1064.         $this->_xmlProlog = true;
  1065.     } // end func enableXmlProlog
  1066.     
  1067.     /**
  1068.      * Returns the document charset encoding.
  1069.      * 
  1070.      * @access public
  1071.      * @return string
  1072.      */
  1073.     function getCharset()
  1074.     {
  1075.         return $this->_charset;
  1076.     } // end setCache
  1077.     
  1078.     /**
  1079.      * Returns the document type string
  1080.      *
  1081.      * @access public
  1082.      * @return string
  1083.      */
  1084.     function getDoctypeString()
  1085.     {
  1086.         $strDoctype = strtoupper($this->_doctype['type']);
  1087.         $strDoctype .= ' '.ucfirst(strtolower($this->_doctype['version']));
  1088.         if ($this->_doctype['variant']) {
  1089.             $strDoctype .= ' ' . ucfirst(strtolower($this->_doctype['variant']));
  1090.         }
  1091.         return trim($strDoctype);
  1092.     } // end func getDoctypeString
  1093.     
  1094.     /**
  1095.      * Returns the document language.
  1096.      * 
  1097.      * @return string
  1098.      * @access public
  1099.      */
  1100.     function getLang()
  1101.     {
  1102.         return $this->_language;
  1103.     } // end func getLang
  1104.     
  1105.     /**
  1106.      * Return the title of the page.
  1107.      * 
  1108.      * @return   string
  1109.      * @access   public
  1110.      */
  1111.     function getTitle()
  1112.     {
  1113.         if (!$this->_title){
  1114.             if ($this->_simple) {
  1115.                 return 'New Page';
  1116.             } else {
  1117.                 return 'New '. $this->getDoctypeString() . ' Compliant Page';
  1118.             }
  1119.         } else {
  1120.             return $this->_title;
  1121.         }
  1122.     } // end func getTitle
  1123.     
  1124.     /**
  1125.      * Prepends content to the content of the <body> tag. Wrapper for {@link addBodyContent}
  1126.      * 
  1127.      * <p>If you wish to overwrite whatever is in the body, use {@link setBody};
  1128.      * {@link addBodyContent} provides full functionality including appending;
  1129.      * {@link unsetBody} completely empties the body without inserting new content.
  1130.      * It is possible to add objects, strings or an array of strings and/or objects
  1131.      * Objects must have a toString method.</p>
  1132.      *
  1133.      * @param mixed $content  New <body> tag content (may be passed as a reference)
  1134.      * @access public
  1135.      */
  1136.     function prependBodyContent($content)
  1137.     {
  1138.         $this->addBodyContent($content, HTML_PAGE2_PREPEND);
  1139.     } // end func prependBodyContent
  1140.     
  1141.     /**
  1142.      * Sets the content of the <body> tag.
  1143.      * 
  1144.      * <p>If content exists, it is overwritten. If you wish to use a "safe" 
  1145.      * version, use {@link addBodyContent}. Objects must have a toString 
  1146.      * method.</p>
  1147.      * 
  1148.      * <p>This function acts as a wrapper for {@link addBodyContent}. If you 
  1149.      * are using PHP 4.x and would like to pass an object by reference, this
  1150.      * is not the function to use. Use {@link addBodyContent} with the flag
  1151.      * HTML_PAGE2_REPLACE instead.</p>
  1152.      * 
  1153.      * @param mixed    $content   New <body> tag content. May be an object. 
  1154.      *                            (may be passed as a reference)
  1155.      * @access public
  1156.      */
  1157.     function setBody($content)
  1158.     {
  1159.         $this->addBodyContent($content, HTML_PAGE2_REPLACE);
  1160.     } // end setBody
  1161.     
  1162.     /**
  1163.      * Unsets the content of the <body> tag.
  1164.      * 
  1165.      * @access public
  1166.      */
  1167.     function unsetBody()
  1168.     {
  1169.         $this->_body = array();
  1170.     } // end unsetBody
  1171.     
  1172.     /**
  1173.      * Sets the attributes of the <body> tag
  1174.      * 
  1175.      * <p>If attributes exist, they are overwritten. In XHTML, all attribute 
  1176.      * names must be lowercase. As lowercase attributes are legal in SGML, all 
  1177.      * attributes are automatically lowercased. This also prevents accidentally
  1178.      * creating duplicate attributes when attempting to update one.</p>
  1179.      * 
  1180.      * @param  array   $attributes   <body> tag attributes.
  1181.      * @access public
  1182.      */
  1183.     function setBodyAttributes($attributes)
  1184.     {
  1185.         $this->setAttributes($attributes);
  1186.     } // end setBodyAttributes
  1187.  
  1188.     /**
  1189.      * Defines if the document should be cached by the browser
  1190.      * 
  1191.      * <p>Defaults to false.</p>
  1192.      * 
  1193.      * <p>A fully configurable cache header is in the works. for now, though 
  1194.      * if you would like to determine exactly what caching headers are sent to 
  1195.      * to the browser, set cache to true, and then output your own headers 
  1196.      * before calling {@link display}.</p>
  1197.      * 
  1198.      * @param  string   $cache  Options are currently 'true' or 'false'
  1199.      * @access public
  1200.      */
  1201.     function setCache($cache = 'false')
  1202.     {
  1203.         if ($cache == 'true'){
  1204.             $this->_cache = true;
  1205.         } else {
  1206.             $this->_cache = false;
  1207.         }
  1208.     } // end setCache
  1209.     
  1210.     /**
  1211.      * Sets the document charset
  1212.      * 
  1213.      * <p>By default, HTML_Page2 uses UTF-8 encoding. This is properly handled 
  1214.      * by PHP, but remember to use the htmlentities attribute for charset so 
  1215.      * that whatever you get from a database is properly handled by the 
  1216.      * browser.</p>
  1217.      * 
  1218.      * <p>The current most popular encoding: iso-8859-1. If it is used,
  1219.      * htmlentities and htmlspecialchars can be used without any special 
  1220.      * settings.</p>
  1221.      * 
  1222.      * @param   string   $type  Charset encoding string
  1223.      * @access  public
  1224.      * @return  void
  1225.      */
  1226.     function setCharset($type = 'utf-8')
  1227.     {
  1228.         $this->_charset = $type;
  1229.     } // end setCache
  1230.     
  1231.     /**
  1232.      * Sets or alters the !DOCTYPE declaration.
  1233.      * 
  1234.      * <p>Can be set to "strict", "transitional" or "frameset".
  1235.      * Defaults to "XHTML 1.0 Transitional".</p>
  1236.      * 
  1237.      * <p>This must come <i>after</i> declaring the character encoding with
  1238.      * {@link setCharset} or directly when the class is initiated 
  1239.      * {@link HTML_Page2}. Use in conjunction with {@link setMimeEncoding}</p>
  1240.      * 
  1241.      * <p>Framesets are not yet implemented.</p>
  1242.      * 
  1243.      * @param   string   $type  String containing a document type
  1244.      * @access  public
  1245.      * @return  void
  1246.      */
  1247.     function setDoctype($type = "XHTML 1.0 Transitional")
  1248.     {
  1249.         $this->_doctype = $this->_parseDoctypeString($type);
  1250.     } // end func setDoctype
  1251.     
  1252.     /**
  1253.      * Sets the <head> profile
  1254.      * 
  1255.      * <p>Profiles allow for adding various uncommented links, etc. to the 
  1256.      * head section. For more details, see the W3C documents 
  1257.      * ({@link http://www.w3.org/TR/html4/struct/global.html#h-7.4.4.3
  1258.      * http://www.w3.org/TR/html4/struct/global.html#h-7.4.4.3} and
  1259.      * {@link http://www.w3.org/TR/html401/types.html#type-links
  1260.      * http://www.w3.org/TR/html401/types.html#type-links})
  1261.      * detailing proper use.</p>
  1262.      * 
  1263.      * @param    string    $profile   URL to profile
  1264.      * @access   public
  1265.      * @return   void
  1266.      */
  1267.     function setHeadProfile($profile = '')
  1268.     {
  1269.         $this->_profile = $profile;
  1270.     } // end func setHeadProfile
  1271.     
  1272.     /**
  1273.      * Sets the global document language declaration. Default is English.
  1274.      * 
  1275.      * @access public
  1276.      * @param   string   $lang    Two-letter language designation
  1277.      */
  1278.     function setLang($lang = "en")
  1279.     {
  1280.         $this->_language = strtolower($lang);
  1281.     } // end setLang
  1282.     
  1283.     /**
  1284.      * Sets or alters a meta tag.
  1285.      * 
  1286.      * @param string  $name           Value of name or http-equiv tag
  1287.      * @param string  $content        Value of the content tag
  1288.      * @param bool    $http_equiv     META type "http-equiv" defaults to null
  1289.      * @return void
  1290.      * @access public
  1291.      */
  1292.     function setMetaData($name, $content, $http_equiv = false)
  1293.     {
  1294.         if ($content == '') {
  1295.             $this->unsetMetaData($name, $http_equiv);
  1296.         } else {
  1297.             if ($http_equiv == true) {
  1298.                 $this->_metaTags['http-equiv'][$name] = $content;
  1299.             } else {
  1300.                 $this->_metaTags['standard'][$name] = $content;
  1301.             }
  1302.         }
  1303.     } // end func setMetaData
  1304.     
  1305.     /**
  1306.      * Unsets a meta tag.
  1307.      *
  1308.      * @param string  $name           Value of name or http-equiv tag
  1309.      * @param bool    $http_equiv     META type "http-equiv" defaults to null
  1310.      * @return void
  1311.      * @access public
  1312.      */
  1313.     function unsetMetaData($name, $http_equiv = false)
  1314.     {
  1315.         if ($http_equiv == true) {
  1316.             unset($this->_metaTags['http-equiv'][$name]);
  1317.         } else {
  1318.             unset($this->_metaTags['standard'][$name]);
  1319.         }
  1320.     } // end func unsetMetaData
  1321.  
  1322.     /**
  1323.      * Sets an http-equiv Content-Type meta tag
  1324.      * 
  1325.      * @access   public
  1326.      * @return   void
  1327.      */
  1328.     function setMetaContentType()
  1329.     {
  1330.         $this->setMetaData('Content-Type', $this->_mime . '; charset=' . $this->_charset , true );
  1331.     } // end func setMetaContentType
  1332.     
  1333.     /**
  1334.      * Shortcut to set or alter a refresh meta tag 
  1335.      * 
  1336.      * <p>If no $url is passed, "self" is presupposed, and the appropriate URL
  1337.      * will be automatically generated. In this case, an optional third 
  1338.      * boolean parameter enables https redirects to self.</p>
  1339.      * 
  1340.      * @param int     $time    Time till refresh (in seconds)
  1341.      * @param string  $url     Absolute URL or "self"
  1342.      * @param bool    $https   If $url == self, this allows for the https 
  1343.      *                         protocol defaults to null
  1344.      * @return void
  1345.      * @access public
  1346.      */
  1347.     function setMetaRefresh($time, $url = 'self', $https = false)
  1348.     {
  1349.         if ($url == 'self') {
  1350.             if ($https) { 
  1351.                 $protocol = 'https://';
  1352.             } else {
  1353.                 $protocol = 'http://';
  1354.             }
  1355.             $url = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  1356.         }
  1357.         $this->setMetaData("Refresh", "$time; url=$url", true);
  1358.     } // end func setMetaRefresh
  1359.     
  1360.     /**
  1361.      * Sets the document MIME encoding that is sent to the browser.
  1362.      * 
  1363.      * <p>This usually will be text/html because most browsers cannot yet  
  1364.      * accept the proper mime settings for XHTML: application/xhtml+xml 
  1365.      * and to a lesser extent application/xml and text/xml. See the W3C note
  1366.      * ({@link http://www.w3.org/TR/xhtml-media-types/ 
  1367.      * http://www.w3.org/TR/xhtml-media-types/}) for more details.</p>
  1368.      * 
  1369.      * <p>Here is a possible way of automatically including the proper mime
  1370.      * type for XHTML 1.0 if the requesting browser supports it:</p>
  1371.      * 
  1372.      * <code>
  1373.      * <?php
  1374.      * // Initialize the HTML_Page2 object:
  1375.      * require 'HTML/Page2.php';
  1376.      * $page = new HTML_Page2();
  1377.      * 
  1378.      * // Check if browse can take the proper mime type
  1379.      * if ( strpos($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') ) {
  1380.      *     $page->setDoctype('XHTML 1.0 Strict');
  1381.      *     $page->setMimeEncoding('application/xhtml+xml');
  1382.      * } else {
  1383.      *     // HTML that qualifies for XHTML 1.0 Strict automatically
  1384.      *     // also complies with XHTML 1.0 Transitional, so if the
  1385.      *     // requesting browser doesn't take the necessary mime type
  1386.      *     // for XHTML 1.0 Strict, let's give it what it can take.
  1387.      *     $page->setDoctype('XHTML 1.0 Transitional');
  1388.      * }
  1389.      * 
  1390.      * // finish building your page here..
  1391.      * 
  1392.      * $page->display();
  1393.      * ?>
  1394.      * </code>
  1395.      * 
  1396.      * @param    string    $type
  1397.      * @access   public
  1398.      * @return   void
  1399.      */
  1400.     function setMimeEncoding($type = 'text/html')
  1401.     {
  1402.         $this->_mime = strtolower($type);
  1403.     } // end func setMimeEncoding
  1404.     
  1405.     /**
  1406.      * Sets the document namespace
  1407.      * 
  1408.      * <p>By default, W3C namespaces are used. However, if you need to define 
  1409.      * your own namespace, you can set it here.</p>
  1410.      * 
  1411.      * <p>Usage:<p>
  1412.      * 
  1413.      * <code>
  1414.      * // This is how you can set your own namespace:
  1415.      * $page->setNamespace('http://www.w3.org/1999/xhtml');
  1416.      * 
  1417.      * // This reverts to default setting and retrieves the appropriate 
  1418.      * // W3C namespace for the document type:
  1419.      * $page->setNamespace();
  1420.      * </code>
  1421.      * 
  1422.      * @param    string    $namespace  Optional. W3C namespaces are used by default.
  1423.      * @access   public
  1424.      * @return   void
  1425.      */
  1426.     function setNamespace($namespace = '')
  1427.     {
  1428.         if (isset($namespace)){
  1429.             $this->_namespace = $namespace;
  1430.         } else {
  1431.             $this->_namespace = $this->_getNamespace();
  1432.         }
  1433.     } // end func setTitle
  1434.     
  1435.     /**
  1436.      * Sets the title of the page
  1437.      * 
  1438.      * <p>Usage:</p>
  1439.      * 
  1440.      * <code>
  1441.      * $page->setTitle('My Page');
  1442.      * </code>
  1443.      * 
  1444.      * @param    string    $title
  1445.      * @access   public
  1446.      * @return   void
  1447.      */
  1448.     function setTitle($title)
  1449.     {
  1450.         $this->_title = $title;
  1451.     } // end func setTitle
  1452.     
  1453.     /**
  1454.      * Generates and returns the complete page as a string
  1455.      * 
  1456.      * <p>This is what you would call if you want to save the page in a
  1457.      * database. It creates a complete, valid HTML document, and returns
  1458.      * it as a string.</p>
  1459.      * 
  1460.      * <p>Usage example:</p>
  1461.      * <code>
  1462.      * <?php
  1463.      * require "HTML/Page2.php";
  1464.      * $page = new HTML_Page2();
  1465.      * $page->setTitle('My Page');
  1466.      * $page->addBodyContent('<h1>My Page</h1>');
  1467.      * $page->addBodyContent('<p>First Paragraph.</p>');
  1468.      * $page->addBodyContent('<p>Second Paragraph.</p>');
  1469.      * $html = $page->toHtml();
  1470.      * // here you insert HTML into a database
  1471.      * ?>
  1472.      * </code>
  1473.      * 
  1474.      * @return string
  1475.      * @access public
  1476.      */
  1477.     function toHtml()
  1478.     {
  1479.         
  1480.         // get line endings
  1481.         $lnEnd = $this->_getLineEnd();
  1482.         
  1483.         // get the doctype declaration
  1484.         $strDoctype = $this->_getDoctype();
  1485.         
  1486.         // This determines how the doctype is declared and enables various
  1487.         // features depending on whether the the document is XHTML, HTML or
  1488.         // if no doctype declaration is desired
  1489.         if ($this->_simple) {
  1490.             
  1491.             $strHtml = '<html>' . $lnEnd;
  1492.             
  1493.         } elseif ($this->_doctype['type'] == 'xhtml') {
  1494.             
  1495.             // get the namespace if not already set
  1496.             if (!$this->_namespace){
  1497.                 $this->_namespace = $this->_getNamespace();
  1498.             }
  1499.             
  1500.             $strHtml = $strDoctype . $lnEnd;
  1501.             $strHtml .= '<html xmlns="' . $this->_namespace . '" xml:lang="' . $this->_language . '"';
  1502.             
  1503.             // If a special profile is defined, make sure it is included
  1504.             // in the opening html tag. Normally this will not be the case.
  1505.             if ($this->_profile) {
  1506.                 $strHtml .= ' profile="'.$this->_profile.'"';
  1507.             }
  1508.             $strHtml .= '>' . $lnEnd;
  1509.             
  1510.             // check whether the XML prolog should be prepended
  1511.             if ($this->_xmlProlog){
  1512.                 $strHtml  = '<?xml version="1.0" encoding="' . $this->_charset . '"?>' . $lnEnd . $strHtml;
  1513.             }
  1514.             
  1515.         } else {
  1516.             
  1517.             $strHtml  = $strDoctype . $lnEnd;
  1518.             $strHtml .= '<html';
  1519.             
  1520.             // If a special profile is defined, make sure it is included
  1521.             // in the opening html tag. Normally this will not be the case.
  1522.             if ($this->_profile) {
  1523.                 $strHtml .= ' profile="'.$this->_profile.'"';
  1524.             }
  1525.             
  1526.             $strHtml .= '>' . $lnEnd;
  1527.             
  1528.         }
  1529.  
  1530.         $strHtml .= $this->_generateHead();
  1531.         $strHtml .= $this->_generateBody();
  1532.         $strHtml .= '</html>';
  1533.         return $strHtml;
  1534.     } // end func toHtml
  1535.     
  1536.     /**
  1537.      * Generates the document and outputs it to a file.
  1538.      * 
  1539.      * <p>Uses {@link file_put_content} when available. Includes a workaround 
  1540.      * for older versions of PHP.</p>
  1541.      * 
  1542.      * <p>Usage example:</p>
  1543.      * <code>
  1544.      * <?php
  1545.      * require "HTML/Page2.php";
  1546.      * $page = new HTML_Page2();
  1547.      * $page->setTitle('My Page');
  1548.      * $page->addBodyContent('<h1>My Page</h1>');
  1549.      * $page->addBodyContent('<p>First Paragraph.</p>');
  1550.      * $page->addBodyContent('<p>Second Paragraph.</p>');
  1551.      * $page->toFile('myPage.html');
  1552.      * ?>
  1553.      * </code>
  1554.      * 
  1555.      * @return  void
  1556.      * @since   2.0
  1557.      * @access  public
  1558.      */
  1559.     function toFile($filename)
  1560.     {
  1561.         
  1562.         if (function_exists('file_put_content')){
  1563.             file_put_content($filename, $this->toHtml());
  1564.         } else {
  1565.             $file = fopen($filename,'wb');
  1566.             fwrite($file, $this->toHtml());
  1567.             fclose($file);
  1568.         }
  1569.         
  1570.         if (!file_exists($filename)){
  1571.             PEAR::raiseError("HTML_Page::toFile() error: Failed to write to $filename",0,PEAR_ERROR_TRIGGER);
  1572.         }
  1573.         
  1574.     } // end func toFile
  1575.     
  1576.     /**
  1577.      * Outputs the HTML content to the browser
  1578.      * 
  1579.      * <p>This method outputs to the default display device. Normally that 
  1580.      * will be the browser.</p>
  1581.      * 
  1582.      * <p>If caching is turned off, which is the default case, this generates 
  1583.      * the appropriate headers:</p>
  1584.      * 
  1585.      * <code>
  1586.      * header("Expires: Tue, 1 Jan 1980 12:00:00 GMT");
  1587.      * header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  1588.      * header("Cache-Control: no-cache");
  1589.      * header("Pragma: no-cache");
  1590.      * </code>
  1591.      * 
  1592.      * <p>This functionality can be disabled:</p>
  1593.      * 
  1594.      * <code>
  1595.      * $page->setCache('true');
  1596.      * </code>
  1597.      * 
  1598.      * @return   void
  1599.      * @access   public
  1600.      */
  1601.     function display()
  1602.     {
  1603.         
  1604.         // If caching is to be implemented, this bit of code will need to be 
  1605.         // replaced with a private function. Else it may be possible to  
  1606.         // borrow from Cache or Cache_Lite.
  1607.         if(!$this->_cache) {
  1608.             header("Expires: Tue, 1 Jan 1980 12:00:00 GMT");
  1609.             header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  1610.             header("Cache-Control: no-cache");
  1611.             header("Pragma: no-cache");
  1612.         }
  1613.         
  1614.         // Set mime type and character encoding
  1615.         header('Content-Type: ' . $this->_mime .  '; charset=' . $this->_charset);
  1616.         
  1617.         // Generate HTML document
  1618.         $strHtml = $this->toHTML();
  1619.         
  1620.         // Output to browser, screen or other default device
  1621.         print $strHtml;
  1622.         
  1623.     } // end func display
  1624.     
  1625. }
  1626. ?>
  1627.