3 * Dumps templates as HTML
5 * $Id: Html.php 440 2008-03-30 09:00:16Z fishbone $
9 * @author Sebastian Mordziol <argh@php-tools.net>
10 * @author Stephan Schmidt <schst@php.net>
14 * Dumps templates as HTML
16 * @package patTemplate
18 * @author Sebastian Mordziol <argh@php-tools.net>
19 * @author Stephan Schmidt <schst@php.net>
21 * @todo move this into patTemplate_Dump_Dhtml and keep it free from javascript
23 class patTemplate_Dump_Html extends patTemplate_Dump
26 'borders' => 'C8D3DA',
27 'headerFills' => 'E1E7EB',
28 'subHeaderFills' => 'F0F2F4',
30 'linkNormal' => '8CA0B4',
31 'linkHover' => '8BC3E0',
34 var $_useBorders = false;
41 function displayHeader()
45 echo ' <style type="text/css">';
47 echo ' font-family: Arial, Tahoma, sans-serif;';
48 echo ' font-size: 12px;';
50 echo ' TABLE.patTemplate{';
51 echo ' border-collapse:collapse;';
53 echo ' A.patTemplate{';
54 echo ' color:#'.$this->colors['linkNormal'].';';
56 echo ' A.patTemplate:hover{';
57 echo ' color:#'.$this->colors['linkHover'].';';
59 echo ' H1.patTemplate{';
61 echo ' padding: 4px;';
62 echo ' font-size: 18px;';
64 echo ' I.patTemplate{';
65 echo ' font-style:italic;';
66 echo ' color:#777777;';
68 echo ' H2.patTemplate{';
69 echo ' background-color: #'.$this->colors['headerFills'].';';
71 echo ' margin-bottom: 15px;';
72 echo ' padding: 4px;';
73 echo ' border-bottom: 1px dashed #'.$this->colors['borders'].';';
74 echo ' border-top: 1px dashed #'.$this->colors['borders'].';';
75 echo ' font-size: 14px;';
77 echo ' H3.patTemplate,H3.patTemplateSub{';
78 echo ' background-color: #'.$this->colors['headerFills'].';';
80 echo ' padding: 4px;';
81 echo ' border-bottom: 1px dashed #'.$this->colors['borders'].';';
82 echo ' border-top: 1px dashed #'.$this->colors['borders'].';';
83 echo ' font-size: 12px;';
84 echo ' font-weight: bold;';
86 echo ' H3.patTemplateSub{';
87 echo ' background-color: #'.$this->colors['subHeaderFills'].';';
88 echo ' border:1px dashed #'.$this->colors['borders'].';';
89 echo ' font-weight:normal;';
90 echo ' margin-bottom:3px;';
92 echo ' #patTemplateContent{';
94 echo ' background-color:#ffffff;';
95 echo ' border:dashed 1px #'.$this->colors['borders'].';';
98 echo ' .patTemplateSection{';
99 echo ' margin-bottom:20px;';
101 echo ' .patTemplateSubSection{';
102 echo ' margin-bottom:3px;';
104 echo ' .patTemplateData{';
105 echo ' display:none;';
107 echo ' .patTemplatePropBorder{';
108 echo ' white-space:nowrap;';
109 echo ' font-weight:bold;';
110 echo ' color:#333333;';
111 echo ' border:solid 1px #C8D3DA;';
113 echo ' .patTemplateProp{';
114 echo ' white-space:nowrap;';
115 echo ' font-weight:bold;';
116 echo ' color:#333333;';
118 echo ' .patTemplateSign{';
119 echo ' font-family:monospace;';
121 echo ' .patTemplateClick{';
122 echo ' cursor:pointer;';
124 echo ' .patTemplateCol{';
125 echo ' margin-bottom:8px;';
126 echo ' font-weight:bold;';
128 echo ' .patTemplateTblCol{';
129 echo ' padding:8px;';
130 echo ' padding-right:15px;';
131 echo ' border-right:dashed 1px #'.$this->colors['borders'].';';
133 echo ' .patTemplateTmplContent{';
134 echo ' padding:8px;';
135 echo ' border-top:dashed 1px #'.$this->colors['borders'].';';
137 echo ' .patTemplateSource{';
138 echo ' padding:5px;';
139 echo ' font-family:monospace;';
140 echo ' background-color:#'.$this->colors['source'].';';
141 echo ' margin-bottom:8px;';
143 echo ' .patTemplateVar{';
144 echo ' color: #009900;';
145 echo ' font-weight:bold;';
147 echo ' .patTemplateVarBorder{';
148 echo ' color: #009900;';
149 echo ' font-weight:bold;';
150 echo ' border:solid 1px #C8D3DA;';
152 echo ' .patTemplateVal{';
153 echo ' color:#333333;';
155 echo ' .patTemplateValBorder{';
156 echo ' color: #333333;';
157 echo ' border:solid 1px #C8D3DA;';
159 echo ' .patTemplateTmpl {';
160 echo ' color: #990000;';
161 echo ' font-weight:bold;';
162 echo ' cursor:pointer;';
165 echo ' <script language="JavaScript1.2" type="text/javascript">';
166 echo ' var tmpls = new Array();';
167 echo ' function patTemplateToggle( tmplName )';
169 echo ' var el = document.getElementById( \'tmpl-\' + tmplName );';
170 echo ' if( el.style.display == \'block\' )';
171 echo ' patTemplateCollapse( tmplName );';
173 echo ' patTemplateExpand( tmplName );';
175 echo ' function jump( tmplName )';
177 echo ' tmplName = tmplName.toLowerCase();';
178 echo ' patTemplateExpand( tmplName );';
179 echo ' document.location = \'#\' + tmplName';
181 echo ' function patTemplateExpandAll()';
183 echo ' for( var i = 0; i < tmpls.length; i++ )';
184 echo ' patTemplateExpand( tmpls[i] );';
186 echo ' function patTemplateCollapseAll()';
188 echo ' for( var i = 0; i < tmpls.length; i++ )';
189 echo ' patTemplateCollapse( tmpls[i] );';
191 echo ' function patTemplateExpand( tmplName )';
193 echo ' var el1 = document.getElementById( \'tmpl-\' + tmplName );';
194 echo ' var el2 = document.getElementById( \'tmpl-\' + tmplName + \'-sign\' );';
195 echo ' el1.style.display = \'block\';';
196 echo ' el2.innerHTML = \'[-]\';';
198 echo ' function patTemplateCollapse( tmplName )';
200 echo ' var el1 = document.getElementById( \'tmpl-\' + tmplName );';
201 echo ' var el2 = document.getElementById( \'tmpl-\' + tmplName + \'-sign\' );';
202 echo ' el1.style.display = \'none\';';
203 echo ' el2.innerHTML = \'[+]\';';
205 echo ' function patTemplateAddTmpl( tmplName )';
207 echo ' tmpls.push( tmplName );';
212 echo ' <div id="patTemplateContent">';
213 echo ' <h1 class="patTemplate">patTemplate Dump</h1>';
217 * dump the global variables
220 * @param array array containing all global variables
222 function dumpGlobals( $globals )
224 echo '<div class="patTemplateSection"><h2 class="patTemplate">Global template variables ('.count( $globals ).')</h2>';
225 if( !empty( $globals ) )
227 echo '<div class="patTemplateSubSection" style="padding:5px;">';
228 echo ' <table border="0" cellpadding="0" cellpadding="0" class="patTemplate">';
229 foreach( $globals as $key => $value )
231 $this->_displayLine( $key, $value );
242 * @param array templates
244 function dumpTemplates( $templates, $vars )
246 $templates = array_reverse( $templates );
248 echo '<div class="patTemplateSection"><h2 class="patTemplate">Templates ('.count( $templates ).') <span style="font-size:12px;font-weight:normal;"><a href="javascript:patTemplateExpandAll();" class="patTemplate">Expand all</a> | <a href="javascript:patTemplateCollapseAll();" class="patTemplate">Collapse all</a></span></h2>';
249 echo '<div class="patTemplateData">Dumping selected templates...</div>';
251 foreach( $templates as $name => $tmpl )
253 if( !isset( $vars[$name] ) )
254 $vars[$name] = array();
256 $vars[$name] = $this->_flattenVars( $vars[$name] );
258 echo '<div class="patTemplateSubSection">';
259 echo ' <h3 class="patTemplate" onclick="patTemplateToggle(\''.$name.'\');" style="cursor:pointer;"><span id="tmpl-'.$name.'-sign" class="patTemplateSign">[+]</span> Template <a name="'.$name.'">"'.$name.'"</a></h3>';
260 echo ' <div class="patTemplateData" id="tmpl-'.$name.'">';
261 echo ' <script language="JavaScript1.2" type="text/javascript">';
262 echo ' patTemplateAddTmpl( \''.$name.'\' );';
264 echo ' <table cellpadding="0" cellspacing="0" border="0">';
265 echo ' <tr valign="top">';
266 echo ' <td style="width:200px;" class="patTemplateTblCol">';
268 $this->_displayAttributes( $tmpl, $name );
271 echo ' <td class="patTemplateTblCol" style="width:130px;">';
273 $this->_displayTemplateState( $tmpl );
276 echo ' <td class="patTemplateTblCol" style="width:130px;">';
277 echo ' <div class="patTemplateCol">Dependencies</div>';
279 if( !empty( $tmpl['dependencies'] ) )
281 $dependencies = array();
282 foreach( $tmpl['dependencies'] as $dependency )
283 array_push( $dependencies, '<a href="javascript:jump( \''.$dependency.'\' );" class="patTemplate">'.$dependency.'</a>' );
285 echo implode( '<br>', $dependencies );
289 echo '<i class="patTemplate">[none]</i>';
298 * ------------------------------------------------------------------
301 $nestedTypes = array(
306 if( in_array( $tmpl['attributes']['type'], $nestedTypes ) )
310 foreach( $tmpl['subtemplates'] as $subName => $subDetails )
312 $content .= $subDetails['data'];
317 $content = $tmpl['content'];
320 $setVars = $this->_extractVars( $content );
322 echo '<div class="patTemplateTmplContent">';
323 echo ' <div class="patTemplateCol">Variables</div>';
324 $this->_displayVariables( $tmpl, $name, $setVars, $vars );
327 if( !empty( $tmpl['comments'] ) )
329 echo ' <div class="patTemplateTmplContent">';
330 echo ' <div class="patTemplateCol">Comments</div>';
331 echo ' <div style="margin-bottom:7px;">';
332 echo implode( '<br>', $tmpl['comments'] );
338 * ------------------------------------------------------------------
339 * display template content
341 echo ' <div class="patTemplateTmplContent">';
342 switch( $tmpl['attributes']['type'] )
346 $this->_displayConditions( $tmpl, $name, $vars );
350 echo ' <div class="patTemplateCol">Content</div>';
351 echo ' <div class="patTemplateSource"><pre>'.$this->_highlightVars( htmlspecialchars( $tmpl['content'] ), $vars[$name] ).'</pre></div>';
363 function _displayVariables( $tmpl, $tmplName, $setVars, $vars )
365 if( empty( $setVars ) )
367 echo '<i class="patTemplate">[none]</i>';
371 echo '<table border="0" cellpadding="3" cellpadding="0" class="patTemplate">';
372 $this->_useBorders( true );
373 $this->_displayHead( 'Name', 'Assigned value', 'Modifier' );
375 foreach( $setVars as $var )
377 if( isset( $vars[$tmplName][$var] ) )
378 $value = $vars[$tmplName][$var];
380 $value = '<i class="patTemplate">[no value set]</i>';
382 if( isset( $tmpl['modifyVars'][$var] ) )
385 foreach( $tmpl['modifyVars'][$var]['params'] as $n => $val )
387 array_push( $params, $n.'="'.$val.'"' );
389 $modifier = sprintf( '%s( %s )', $tmpl['modifyVars'][$var]['mod'], implode( ', ', $params ) );
393 $modifier = '<i class="patTemplate">[none]</i>';
396 $this->_displayLine( $var, $value, $modifier );
400 $this->_useBorders( false );
403 function _displayConditions( $tmpl, $tmplName, $vars )
405 foreach( $tmpl['subtemplates'] as $cond => $spec )
407 echo ' <h3 class="patTemplateSub" onclick="patTemplateToggle(\'Cond'.$cond.'\');" style="cursor:pointer;"><span id="tmpl-Cond'.$cond.'-sign" class="patTemplateSign">[+]</span> Subtemplate <a name="Cond'.$cond.'">"'.$cond.'"</a></h3>';
408 echo ' <div class="patTemplateData" id="tmpl-Cond'.$cond.'" style="margin-bottom:15px;">';
409 echo ' <script language="JavaScript1.2" type="text/javascript">';
410 echo ' patTemplateAddTmpl( \'Cond'.$cond.'\' );';
413 if( !empty( $spec['comments'] ) )
415 echo ' <div class="patTemplateCol">Comments</div>';
416 echo ' <div style="margin-bottom:7px;">';
417 echo implode( '<br>', $spec['comments'] );
421 echo ' <div class="patTemplateCol">Dependencies</div>';
422 echo ' <div style="margin-bottom:7px;">';
423 if( !empty( $spec['dependencies'] ) )
425 $dependencies = array();
426 foreach( $spec['dependencies'] as $dependency )
427 array_push( $dependencies, '<a href="javascript:jump( \''.$dependency.'\' );" class="patTemplate">'.$dependency.'</a>' );
429 echo implode( ', ', $dependencies );
433 echo '<i class="patTemplate">[none]</i>';
437 echo ' <div class="patTemplateCol">Content</div>';
438 echo ' <div class="patTemplateSource"><pre>'.$this->_highlightVars( htmlspecialchars( $spec['data'] ), $vars[$tmplName] ).'</pre></div>';
444 * display the attributes of a template
447 * @param array template data
448 * @param string name of the template
450 function _displayAttributes( $tmpl, $tmplName = null )
452 echo '<div class="patTemplateCol">Attributes</div>';
453 echo '<table border="0" cellpadding="0" cellpadding="0">';
458 switch( $tmpl['attributes']['type'] )
461 if( $tmpl['attributes']['modulo'] == 2 )
464 $type = 'modulo (' . $tmpl['attributes']['modulo'] . ')';
466 if( !isset( $type ) )
469 $this->_displayLine( 'Type', $tmpl['attributes']['type'] );
471 * condition variable, only used in condition templates
473 if( isset( $tmpl['attributes']['conditionvar'] ) )
475 if( isset( $tmpl['attributes']['conditiontmpl'] ) )
476 $this->_displayLine( 'ConditionVar', $tmpl['attributes']['conditiontmpl'].'.'.$tmpl['attributes']['conditionvar'] );
477 elseif( isset( $tmpl['attributes']['useglobals'] ) && $tmpl['attributes']['useglobals'] == 'yes' )
478 $this->_displayLine( 'ConditionVar', '__globals.'.$tmpl['attributes']['conditionvar'] );
480 $this->_displayLine( 'ConditionVar', $tmpl['attributes']['conditionvar'] );
484 case 'simplecondition':
485 $this->_displayLine( 'Type', 'simplecondition' );
486 $requiredvars = array();
487 foreach ($tmpl['attributes']['requiredvars'] as $tmp) {
488 if ($tmp[0] !== $tmplName) {
489 $var = $tmp[0] . '.' . $tmp[1];
493 if ($tmp[2] !== null) {
494 $var = $var . '='.$tmp[2];
496 array_push($requiredvars, $var);
499 $this->_displayLine( 'RequiredVars', implode( ', ', $requiredvars ) );
503 $this->_displayLine( 'Type', $tmpl['attributes']['type'] );
507 * standard attributes
509 $this->_displayLine( 'Visibility', $tmpl['attributes']['visibility'] );
510 $this->_displayLine( 'WhiteSpace', $tmpl['attributes']['whitespace'] );
511 $this->_displayLine( 'AddSystemVars', $tmpl['attributes']['addsystemvars'] );
512 $this->_displayLine( 'UnusedVars', $tmpl['attributes']['unusedvars'] );
517 if( isset( $tmpl['attributes']['src'] ) )
518 $this->_displayLine( 'External Src', $tmpl['attributes']['src'] );
522 if (isset($tmpl['attributes']['varscope'])) {
523 if (is_array($tmpl['attributes']['varscope'])) {
524 $this->_displayLine( 'Varscope', implode(', ', $tmpl['attributes']['varscope'] ) );
526 $this->_displayLine( 'Varscope', $tmpl['attributes']['varscope'] );
533 function _displayTemplateState( $tmpl )
535 echo ' <div class="patTemplateCol">States</div>';
536 echo ' <table border="0" cellpadding="0" cellpadding="0">';
537 $this->_displayLine( 'Loaded', $tmpl['loaded'] );
538 $this->_displayLine( 'Parsed', $tmpl['parsed'] );
543 * hilight variables in a template
546 * @param string template content
547 * @return string template content
549 function _highlightVars( $template, $vars )
551 $pattern = '/('.$this->_tmpl->getStartTag().'TMPL\:([^a-z]+)'.$this->_tmpl->getEndTag().')/U';
552 $template = preg_replace( $pattern, '<span class="patTemplateTmpl" onclick="jump(\'\2\')" title="Click to view the dependency \'\2\'.">\1</span>', $template );
554 $pattern = '/('.$this->_tmpl->getStartTag().'([^a-z:]+)'.$this->_tmpl->getEndTag().')/U';
556 preg_match_all( $pattern, $template, $matches );
557 for( $i = 0; $i < count( $matches[1] ); $i++ )
559 if( isset( $vars[$matches[2][$i]] ) )
561 $value = $vars[$matches[2][$i]];
565 $value = '[No value set]';
567 $replace = '<span class="patTemplateVar" title="'.$value.'">'.$matches[1][$i].'</span>';
568 $template = str_replace( $matches[1][$i], $replace, $template );
574 * display a table header
577 * @param string property
578 * @param mixed value, you may pass more than one value
580 function _displayHead()
582 $args = func_get_args();
584 echo ' <tr valign="top">';
585 foreach( $args as $head )
587 printf( ' <td class="'.$this->_getClassName( 'patTemplateProp' ).'">%s</td>', $head );
592 function _getClassName( $class )
594 if( !$this->_useBorders )
597 return $class .= 'Border';
601 * sets whether to draw borders in the tables generated via the
602 * {@link _displayHead()} and {@link _displayLine()} methods.
605 * @param bool $state Whether to draw the borders. true=draw, false=don't draw
607 function _useBorders( $state )
609 $this->_useBorders = $state;
613 * display a line in a table
616 * @param string property
617 * @param mixed value, you may pass more than one value
619 function _displayLine( $prop, $value )
621 $args = func_get_args();
622 $prop = array_shift( $args );
624 echo ' <tr valign="top">';
625 printf( ' <td class="'.$this->_getClassName( 'patTemplateProp' ).'">%s</td>', $prop );
626 if( count( $args ) == 1 )
628 echo ' <td class="'.$this->_getClassName( 'patTemplateVal' ).'"> : </td>';
631 foreach( $args as $value )
633 if( is_bool( $value ) )
635 $value = ( $value === true ) ? 'yes' : 'no';
638 printf( ' <td class="'.$this->_getClassName( 'patTemplateVal' ).'">%s</td>', $value );
648 function displayFooter()