. ** ** UltraHTML 3000 tool layer. Create functions for html tags. ** ** new it_html; ** echo html(head('title' => 'hello'), body(h1('hello'), p('Hello world!'))); **/ /** * Parse an arg array (mixed key=>value pairs and strings) and return it * as array(0 => all numerical args concatenated, 1 => array(key=>value pairs) * php version if c extension is not loaded */ if (!function_exists("it_parse_args")) { function it_parse_args($args) { $p = array(); foreach ($args as $arg) { if (is_array($arg)) { foreach ($arg as $key => $value) { if (is_int($key)) $data .= it_taintcheck($value); else $p[$key] = $value; } } else $data .= it_taintcheck($arg); } return array($data, $p); } } class it_html { # these tags have no content and need no closing tag in html or can be shortened in xhtml static $voidtags = array('area' => 1, 'base' => 1, 'br' => 1, 'col' => 1, 'command' => 1, 'embed' => 1, 'hr' => 1, 'img' => 1, 'input' => 1, 'keygen' => 1, 'link' => 1, 'meta' => 1, 'param' => 1, 'source' => 1, 'track' => 1, 'wbr' => 1); var $p; # constructor params plus defaults /** * Create a HTML object and global functions for all methods (exlcluding * methods starting with '_') in this class plus the default tags (see below). * * @param $p Configuration settings. Can be set/overridden in constructor, configure(), html() or head(). * See source code for a list of supported values */ function __construct($p = array()) { # Default configuration of html class $this->p = $p + array( 'charset' => ini_get('default_charset') ?: 'iso-8859-1', 'doctype' => null, # Custom doctype (will usually be calculated from htmltype) 'head' => '', # Code to put into head() section 'htmltype' => 'html5', # 'html5', 'html' (=old-style), 'xhtml' or 'xhtml-mobile' for xhtml, or 'xml' for plain xml without magic 'lang' => 'de', # Language code to use in tag 'moretags' => '', # Comma-separated list of tag-functions to generate additionally to 'tags' 'name' => $p['htmltype'] == 'xml' ? 'it_html_xml' : 'it_html', # Name of global variable $this is assigned to (string), XXX Copy and paste in configure() 'nonewlinetags' => 'a,b,em,img,input,label,span,noscript', # tags that do not like newlines after them 'prettyprint' => it::is_devel(), # Should output be prettily indented? 'show_content_type' => true, # If true, add header 'show_favicon' => true, # If true, add tag to /favicon.ico if it exists 'favicon' => '', # If set, add favicon tag to this url 'staticallycallable' => 'Q,U,select', # Those methods are statically callable (have same arguments as global stubs) but are a bit slower 'tags' => "a,b,br,button,div,em,fieldset,form,h1,h2,h3,h4,h5,h6,hr,img,input,label,legend,li,meta,noscript,p,pre,span,style,table,tbody,td,textarea,tfoot,th,thead,tr,ul,ol,article,section", 'title' => '', # HTML title (default: no title added) 'srclines' => $GLOBALS['debug_srclines'], # append stackdump to each tag 'error_on_redefine' => false, # Generate it::error when trying to redefine function for a tag ); $this->p['notexported'] = trim($p['notexported'] . ',configure,sanitize,comment', ','); # We know these doctypes. If you need something else, supply 'doctype' in p $this->doctypes = array( 'html5' => '', 'html' => '', 'xhtml' => '', 'xhtml-mobile' => '', 'xml' => '' ); # @@@ Hack: Manually copy for new instance without custom value to keep setting from global auto_prepend instance if (!isset($p['error_on_redefine']) && isset($GLOBALS[$this->p['name']])) $this->p['error_on_redefine'] = $GLOBALS[$this->p['name']]->p['error_on_redefine']; # Since name is given as param, it is our duty to store it, not our caller's. $GLOBALS[$this->p['name']] =& $this; it_html::configure(array('name' => $this->p['name'])); $notexported = array_flip(explode(',', "dummy," . $this->p['notexported'])); # dummy keeps values > 0 # Create global functions for _tags foreach (array_keys($this->alltags) as $func) { if (!function_exists($func) && $func) $code[$func] = "function $func() { \$args = func_get_args(); return \$GLOBALS['{$this->p['name']}']->_tag('$func', \$args); }"; else if ($this->p['error_on_redefine']) it::error("Trying to redefine existing function '$func' in it_html"); } # Create global functions for it_html methods foreach (get_class_methods(get_class($this)) as $func) { if (!preg_match('/^_/', $func) && !is_a($this, $func) && $func && !function_exists($func) && !$notexported[$func]) $code[$func] = "function $func() { \$args = func_get_args(); return \$GLOBALS['{$this->p['name']}']->$func(\$args); }"; } # Create global functions for methods that are statically callable (have same arguments as global stubs) foreach (explode(',', $this->p['staticallycallable']) as $func) { if ($func && !function_exists($func)) $code[$func] = "function $func() { \$args = func_get_args(); return call_user_func_array(array(&\$GLOBALS['{$this->p['name']}'], '$func'), \$args); }"; } eval(join('', (array)$code)); } /** * Modify configuration of it_html, e.g. htmltype after it was instantiated. * @param $p Configuration settings. Can be set/overridden in constructor, configure(), html() or head(). * See constructor for a list of supported values */ static function configure($p) { $ithtml = $GLOBALS[$p['name'] ?: ($p['htmltype'] == 'xml' ? 'it_html_xml' : 'it_html')]; $ithtml->p = $p + (array)$ithtml->p; $ithtml->alltags = array_flip(explode(',', trim($ithtml->p['tags'] . ',' . $ithtml->p['moretags'], ','))); $ithtml->hasnonewline = array_flip(explode(',', $ithtml->p['nonewlinetags'])); } /** * Return doctype and entire HTML page. * Example application code to render page: * echo html(head(...), body(...)); * * @param any number of text args or array of key => value pairs * Defaults for key => value parameters are inherited from the it_html constructor and should be set there. * The parameters are $p['lang'], $p['htmltype'], $p['doctype'], $p['class'] and $p['manifest'] */ function html($args) { list($data, $p) = it_parse_args($args); $p += $this->p; foreach (array('class', 'manifest') as $attr) $attrs .= $p[$attr] ? " $attr=" . '"' . Q($p[$attr]) . '"' : ""; $html = ($p['doctype'] ? $p['doctype'] : $this->doctypes[$p['htmltype']]) . "\n" . '\n" . $data . ($p['omit_endhtml'] ? '' : "\n"); return EDC('upd') ? it::replace(array('' => ''), $html, array('singleline' => true)) : $html; } /** * Return HTML header on first call or empty string on subsequent calls * * @param args... any number of assoc arrays and strings. strings will be content of
* @param $p['content-type'] content type (default: "text/html; charset=iso-8859-1") * @param $p['headers'] Array of HTTP headers (e.g. [ 'Vary' => "User-Agent,Accept-Language" ]) * @param $p['cssinline'] stylesheet to be put in header * @param $p['description'] data for tag * @param $p['keywords'] data for tag * @param $p['stylesheets'] array mediatype => url of styleshests * @param $p['title'] content of