|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZTemplateDebugFunction class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package lib 00009 */ 00010 00011 /*! 00012 \class eZTemplateDebugFunction eztemplatedebugfunction.php 00013 \ingroup eZTemplateFunctions 00014 \brief Advanced debug handling 00015 00016 debug-timing-point 00017 Starts a timing point, executes body and ends the timing point. 00018 This is useful if you want to figure out how fast a piece of 00019 template code goes or to see all debug entries that occur 00020 between these two points. 00021 00022 \code 00023 {debug-timing-point id=""} 00024 {$item} - {$item2} 00025 {/debug-timing-point} 00026 \endcode 00027 00028 debug-accumulator 00029 Executes the body and performs statistics. 00030 The number of calls, total time and average time will be shown in debug. 00031 00032 \code 00033 {debug-accumulator} 00034 {section var=error loop=$errors}{$error}{/section} 00035 {/debug-accumulator} 00036 \endcode 00037 00038 debug-log 00039 Does exactly the same as eZDebug::writeDebug() method. 00040 Has two parameters: 00041 - var: variable to dump 00042 - msg: text message 00043 00044 \code 00045 {debug-log var=$object msg='object contents'} 00046 {debug-log msg='hello world'} 00047 {debug-log var=array(1,2,3)} 00048 \endcode 00049 00050 debug-trace 00051 Executes the body while tracing the result using XDebug. 00052 The result will a trace file made by XDebug which can be analyzed. 00053 Note: This will not do anything when XDebug is not available 00054 00055 \code 00056 {debug-trace id="loop"} 00057 {section var=error loop=$errors}{$error}{/section} 00058 {/debug-trace} 00059 \endcode 00060 */ 00061 00062 class eZTemplateDebugFunction 00063 { 00064 /*! 00065 Initializes the object with names. 00066 */ 00067 function eZTemplateDebugFunction( $timingPoint = 'debug-timing-point', 00068 $accumulator = 'debug-accumulator', 00069 $log = 'debug-log', 00070 $trace = 'debug-trace' ) 00071 { 00072 $this->TimingPointName = $timingPoint; 00073 $this->AccumulatorName = $accumulator; 00074 $this->LogName = $log; 00075 $this->TraceName = $trace; 00076 } 00077 00078 /*! 00079 Return the list of available functions. 00080 */ 00081 function functionList() 00082 { 00083 return array( $this->TimingPointName, $this->AccumulatorName, $this->LogName, $this->TraceName ); 00084 } 00085 00086 /*! 00087 * Returns the attribute list. 00088 * key: parameter name 00089 * value: can have children 00090 */ 00091 function attributeList() 00092 { 00093 return array( 00094 $this->TimingPointName => true, 00095 $this->AccumulatorName => true, 00096 $this->LogName => false, 00097 $this->TraceName => true 00098 ); 00099 } 00100 00101 function functionTemplateHints() 00102 { 00103 return array( $this->TimingPointName => array( 'parameters' => true, 00104 'static' => false, 00105 'transform-children' => true, 00106 'tree-transformation' => true, 00107 'transform-parameters' => true ), 00108 $this->AccumulatorName => array( 'parameters' => true, 00109 'static' => false, 00110 'transform-children' => true, 00111 'tree-transformation' => true, 00112 'transform-parameters' => true ), 00113 $this->LogName => array( 'parameters' => true, 00114 'static' => false, 00115 'transform-children' => true, 00116 'tree-transformation' => true, 00117 'transform-parameters' => true ), 00118 $this->TraceName => array( 'parameters' => true, 00119 'static' => false, 00120 'transform-children' => true, 00121 'tree-transformation' => true, 00122 'transform-parameters' => true ) ); 00123 } 00124 00125 function templateNodeTransformation( $functionName, &$node, 00126 $tpl, $parameters, $privateData ) 00127 { 00128 if ( $functionName == $this->TimingPointName ) 00129 { 00130 $id = false; 00131 if ( isset( $parameters['id'] ) ) 00132 { 00133 if ( !eZTemplateNodeTool::isConstantElement( $parameters['id'] ) ) 00134 return false; 00135 $id = eZTemplateNodeTool::elementConstantValue( $parameters['id'] ); 00136 } 00137 00138 $newNodes = array(); 00139 00140 $startDescription = "debug-timing-point START: $id"; 00141 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::addTimingPoint( " . var_export( $startDescription, true ) . " );" ); 00142 00143 $children = eZTemplateNodeTool::extractFunctionNodeChildren( $node ); 00144 $newNodes = array_merge( $newNodes, $children ); 00145 00146 $endDescription = "debug-timing-point END: $id"; 00147 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::addTimingPoint( " . var_export( $endDescription, true ) . " );" ); 00148 00149 return $newNodes; 00150 } 00151 else if ( $functionName == $this->AccumulatorName ) 00152 { 00153 $id = false; 00154 if ( isset( $parameters['id'] ) ) 00155 { 00156 if ( !eZTemplateNodeTool::isConstantElement( $parameters['id'] ) ) 00157 return false; 00158 $id = eZTemplateNodeTool::elementConstantValue( $parameters['id'] ); 00159 } 00160 00161 $name = false; 00162 if ( isset( $parameters['name'] ) ) 00163 { 00164 if ( !eZTemplateNodeTool::isConstantElement( $parameters['name'] ) ) 00165 return false; 00166 $name = eZTemplateNodeTool::elementConstantValue( $parameters['name'] ); 00167 } 00168 // Assign a name (as $functionName) which will be used in the debug output. 00169 $name = ( $name === false and $id === false ) ? $functionName : $name; 00170 // To uniquely identify this accumulator. 00171 $id = $id === false ? uniqID( $functionName . '_' ): $id; 00172 $newNodes = array(); 00173 00174 if ( $name ) 00175 { 00176 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::accumulatorStart( " . var_export( $id, true ) . ", 'Debug-Accumulator', " . var_export( $name, true ) . " );" ); 00177 } 00178 else 00179 { 00180 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::accumulatorStart( " . var_export( $id, true ) . ", 'Debug-Accumulator' );" ); 00181 } 00182 00183 $children = eZTemplateNodeTool::extractFunctionNodeChildren( $node ); 00184 $newNodes = array_merge( $newNodes, $children ); 00185 00186 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::accumulatorStop( " . var_export( $id, true ) . " );" ); 00187 00188 return $newNodes; 00189 } 00190 else if ( $functionName == $this->LogName ) 00191 { 00192 $nodePlacement = eZTemplateNodeTool::extractFunctionNodePlacement( $node ); 00193 $newNodes = array(); 00194 00195 $varIsSet = $msgIsSet = false; 00196 if ( isset( $parameters['var'] ) ) 00197 { 00198 $varIsSet = true; 00199 $var = $parameters['var']; 00200 } 00201 if ( isset( $parameters['msg'] ) ) 00202 { 00203 $msgIsSet = true; 00204 $msg = $parameters['msg']; 00205 } 00206 00207 $newNodes[]= eZTemplateNodeTool::createCodePieceNode( "// debug-log starts\n" ); 00208 00209 if ( $varIsSet ) 00210 $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $var, $nodePlacement, array( 'treat-value-as-non-object' => true ), 'debug_log_var' ); 00211 if ( $msgIsSet ) 00212 $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $msg, $nodePlacement, array( 'treat-value-as-non-object' => true ), 'debug_log_msg' ); 00213 00214 if ( $varIsSet && $msgIsSet ) 00215 $newNodes[]= eZTemplateNodeTool::createCodePieceNode( "eZDebug::writeDebug( \$debug_log_var, \$debug_log_msg );\n" ); 00216 elseif ( $msgIsSet ) 00217 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::writeDebug( \$debug_log_msg );\n" ); 00218 elseif ( $varIsSet ) 00219 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "eZDebug::writeDebug( \$debug_log_var );\n" ); 00220 00221 if ( $varIsSet ) 00222 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "unset( \$debug_log_var );" ); 00223 if ( $msgIsSet ) 00224 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "unset( \$debug_log_msg );" ); 00225 00226 $newNodes[]= eZTemplateNodeTool::createCodePieceNode( "// debug-log ends\n" ); 00227 00228 return $newNodes; 00229 } 00230 else if ( $functionName == $this->TraceName ) 00231 { 00232 $id = false; 00233 if ( isset( $parameters['id'] ) ) 00234 { 00235 if ( !eZTemplateNodeTool::isConstantElement( $parameters['id'] ) ) 00236 return false; 00237 $id = eZTemplateNodeTool::elementConstantValue( $parameters['id'] ); 00238 } 00239 00240 if ( !$id ) 00241 $id = 'template-debug'; 00242 00243 $newNodes = array(); 00244 00245 $code = ( "if ( extension_loaded( 'xdebug' ) )\n" . 00246 "{\n" . 00247 "if ( file_exists( " . var_export( $id . '.xt', true ) . " ) )\n" . 00248 "{\n" . 00249 "\$fd = fopen( " . var_export( $id . '.xt', true ) . ", 'w' ); fclose( \$fd ); unset( \$fd );\n" . 00250 "}\n" . 00251 "xdebug_start_trace( " . var_export( $id, true ) . " );\n" . 00252 "}\n" ); 00253 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( $code ); 00254 00255 $children = eZTemplateNodeTool::extractFunctionNodeChildren( $node ); 00256 $newNodes = array_merge( $newNodes, $children ); 00257 00258 $code = ( "if ( extension_loaded( 'xdebug' ) )\n" . 00259 "xdebug_stop_trace();\n" ); 00260 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( $code ); 00261 00262 return $newNodes; 00263 } 00264 return false; 00265 } 00266 00267 /*! 00268 Processes the function with all it's children. 00269 */ 00270 function process( $tpl, &$textElements, $functionName, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace ) 00271 { 00272 switch ( $functionName ) 00273 { 00274 case $this->TimingPointName: 00275 { 00276 $children = $functionChildren; 00277 $parameters = $functionParameters; 00278 00279 $id = false; 00280 if ( isset( $parameters["id"] ) ) 00281 { 00282 $id = $tpl->elementValue( $parameters["id"], $rootNamespace, $currentNamespace, $functionPlacement ); 00283 } 00284 00285 00286 $startDescription = "debug-timing-point START: $id"; 00287 eZDebug::addTimingPoint( $startDescription ); 00288 00289 if ( is_array( $children ) ) 00290 { 00291 foreach ( array_keys( $children ) as $childKey ) 00292 { 00293 $child =& $children[$childKey]; 00294 $tpl->processNode( $child, $textElements, $rootNamespace, $currentNamespace ); 00295 } 00296 } 00297 00298 $endDescription = "debug-timing-point END: $id"; 00299 eZDebug::addTimingPoint( $endDescription ); 00300 00301 } break; 00302 00303 case $this->AccumulatorName: 00304 { 00305 $children = $functionChildren; 00306 $parameters = $functionParameters; 00307 00308 $id = false; 00309 if ( isset( $parameters["id"] ) ) 00310 { 00311 $id = $tpl->elementValue( $parameters["id"], $rootNamespace, $currentNamespace, $functionPlacement ); 00312 } 00313 00314 $name = false; 00315 if ( isset( $parameters["name"] ) ) 00316 { 00317 $name = $tpl->elementValue( $parameters["name"], $rootNamespace, $currentNamespace, $functionPlacement ); 00318 } 00319 00320 // Assign a name (as $functionName) which will be used in the debug output. 00321 $name = ( $name === false and $id === false ) ? $functionName : $name; 00322 // To uniquely identify this accumulator. 00323 $id = $id === false ? uniqID( $functionName . '_' ): $id; 00324 00325 eZDebug::accumulatorStart( $id, 'Debug-Accumulator', $name ); 00326 00327 if ( is_array( $children ) ) 00328 { 00329 foreach ( array_keys( $children ) as $childKey ) 00330 { 00331 $child =& $children[$childKey]; 00332 $tpl->processNode( $child, $textElements, $rootNamespace, $currentNamespace ); 00333 } 00334 } 00335 00336 eZDebug::accumulatorStop( $id ); 00337 00338 } break; 00339 00340 case $this->LogName: 00341 { 00342 $parameters = $functionParameters; 00343 00344 if ( isset( $parameters['var'] ) ) 00345 $var = $tpl->elementValue( $parameters['var'], $rootNamespace, $currentNamespace, $functionPlacement ); 00346 if ( isset( $parameters['msg'] ) ) 00347 $msg = $tpl->elementValue( $parameters['msg'], $rootNamespace, $currentNamespace, $functionPlacement ); 00348 00349 if ( isset( $var ) && isset( $msg ) ) 00350 eZDebug::writeDebug( $var, $msg ); 00351 elseif ( isset( $msg ) ) 00352 eZDebug::writeDebug( $msg ); 00353 elseif ( isset( $var ) ) 00354 eZDebug::writeDebug( $var ); 00355 } break; 00356 00357 case $this->TraceName: 00358 { 00359 $children = $functionChildren; 00360 00361 $id = false; 00362 // If we have XDebug we start the trace, execute children and stop it 00363 // if not we just execute the children as normal 00364 if ( extension_loaded( 'xdebug' ) ) 00365 { 00366 $parameters = $functionParameters; 00367 if ( isset( $parameters["id"] ) ) 00368 { 00369 $id = $tpl->elementValue( $parameters["id"], $rootNamespace, $currentNamespace, $functionPlacement ); 00370 } 00371 00372 if ( !$id ) 00373 $id = 'template-debug'; 00374 00375 // If we already have a file, make sure it is truncated 00376 if ( file_exists( $id . '.xt' ) ) 00377 { 00378 $fd = fopen( $id, '.xt', 'w' ); fclose( $fd ); 00379 } 00380 xdebug_start_trace( $id ); 00381 00382 if ( is_array( $children ) ) 00383 { 00384 foreach ( array_keys( $children ) as $childKey ) 00385 { 00386 $child =& $children[$childKey]; 00387 $tpl->processNode( $child, $textElements, $rootNamespace, $currentNamespace ); 00388 } 00389 } 00390 00391 xdebug_stop_trace(); 00392 } 00393 elseif ( is_array( $children ) ) 00394 { 00395 foreach ( array_keys( $children ) as $childKey ) 00396 { 00397 $child =& $children[$childKey]; 00398 $tpl->processNode( $child, $textElements, $rootNamespace, $currentNamespace ); 00399 } 00400 } 00401 00402 } break; 00403 } 00404 } 00405 00406 /*! 00407 Returns true. 00408 */ 00409 function hasChildren() 00410 { 00411 return $this->attributeList(); 00412 } 00413 00414 /// \privatesection 00415 /// Name of the function 00416 public $DebugName; 00417 public $AppendDebugName; 00418 public $OnceName; 00419 } 00420 00421 ?>