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