2008-05-30 11:40:08 +00:00
< ? php
/**
2010-01-06 01:44:15 +00:00
* CakeHtmlReporter
2008-05-30 11:40:08 +00:00
*
2017-06-10 22:15:34 +00:00
* CakePHP ( tm ) Tests < https :// book . cakephp . org / 2.0 / en / development / testing . html >
2017-06-10 22:10:52 +00:00
* Copyright ( c ) Cake Software Foundation , Inc . ( https :// cakefoundation . org )
2008-05-30 11:40:08 +00:00
*
2010-10-03 16:31:21 +00:00
* Licensed under The MIT License
2013-02-08 12:22:51 +00:00
* For full copyright and license information , please see the LICENSE . txt
2010-10-03 16:31:21 +00:00
* Redistributions of files must retain the above copyright notice
2008-05-30 11:40:08 +00:00
*
2017-06-10 22:10:52 +00:00
* @ copyright Copyright ( c ) Cake Software Foundation , Inc . ( https :// cakefoundation . org )
2017-06-10 21:33:55 +00:00
* @ link https :// cakephp . org CakePHP ( tm ) Project
2008-10-30 17:30:26 +00:00
* @ since CakePHP ( tm ) v 1.2 . 0.4433
2017-06-10 22:23:14 +00:00
* @ license https :// opensource . org / licenses / mit - license . php MIT License
2008-05-30 11:40:08 +00:00
*/
2013-05-30 22:11:14 +00:00
2010-12-11 05:47:55 +00:00
App :: uses ( 'CakeBaseReporter' , 'TestSuite/Reporter' );
2010-01-06 01:44:15 +00:00
2008-05-30 11:40:08 +00:00
/**
2009-09-13 17:11:37 +00:00
* CakeHtmlReporter Reports Results of TestSuites and Test Cases
* in an HTML format / context .
2008-05-30 11:40:08 +00:00
*
2011-07-26 06:16:14 +00:00
* @ package Cake . TestSuite . Reporter
2008-05-30 11:40:08 +00:00
*/
2010-05-13 04:18:22 +00:00
class CakeHtmlReporter extends CakeBaseReporter {
2010-01-03 05:33:17 +00:00
2008-06-10 22:38:05 +00:00
/**
* Paints the top of the web page setting the
* title to the name of the starting test .
2009-09-13 17:11:37 +00:00
*
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-05-04 21:01:03 +00:00
public function paintHeader () {
2011-02-13 03:31:51 +00:00
$this -> _headerSent = true ;
2012-04-19 02:45:55 +00:00
$this -> sendContentType ();
2008-05-30 11:40:08 +00:00
$this -> sendNoCacheHeaders ();
2010-01-09 16:20:47 +00:00
$this -> paintDocumentStart ();
2010-01-07 03:42:35 +00:00
$this -> paintTestMenu ();
2008-06-10 22:38:05 +00:00
echo " <ul class='tests'> \n " ;
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2012-04-19 02:45:55 +00:00
/**
* Set the content - type header so it is in the correct encoding .
*
* @ return void
*/
public function sendContentType () {
if ( ! headers_sent ()) {
header ( 'Content-Type: text/html; charset=' . Configure :: read ( 'App.encoding' ));
}
}
2010-01-07 03:42:35 +00:00
/**
2010-01-09 16:20:47 +00:00
* Paints the document start content contained in header . php
2010-01-07 03:42:35 +00:00
*
* @ return void
*/
2010-04-15 02:56:51 +00:00
public function paintDocumentStart () {
2010-01-10 18:05:35 +00:00
ob_start ();
2015-09-30 01:41:33 +00:00
$baseDir = $this -> params [ 'baseDir' ];
2011-04-17 10:25:02 +00:00
include CAKE . 'TestSuite' . DS . 'templates' . DS . 'header.php' ;
2010-01-07 03:42:35 +00:00
}
/**
* Paints the menu on the left side of the test suite interface .
* Contains all of the various plugin , core , and app buttons .
*
* @ return void
*/
2010-04-15 02:56:51 +00:00
public function paintTestMenu () {
2015-09-30 01:41:33 +00:00
$cases = $this -> baseUrl () . '?show=cases' ;
2010-12-07 02:29:11 +00:00
$plugins = App :: objects ( 'plugin' , null , false );
2010-03-20 11:31:20 +00:00
sort ( $plugins );
2011-04-17 10:25:02 +00:00
include CAKE . 'TestSuite' . DS . 'templates' . DS . 'menu.php' ;
2010-01-07 04:02:37 +00:00
}
/**
* Retrieves and paints the list of tests cases in an HTML format .
*
* @ return void
*/
2010-04-15 02:56:51 +00:00
public function testCaseList () {
2010-01-09 15:55:58 +00:00
$testCases = parent :: testCaseList ();
2011-12-20 04:13:46 +00:00
$core = $this -> params [ 'core' ];
2010-01-09 15:55:58 +00:00
$plugin = $this -> params [ 'plugin' ];
2011-12-20 04:13:46 +00:00
$buffer = " <h3>App Test Cases:</h3> \n <ul> " ;
2010-01-09 15:55:58 +00:00
$urlExtra = null ;
2011-12-20 04:13:46 +00:00
if ( $core ) {
$buffer = " <h3>Core Test Cases:</h3> \n <ul> " ;
$urlExtra = '&core=true' ;
2010-01-09 15:55:58 +00:00
} elseif ( $plugin ) {
$buffer = " <h3> " . Inflector :: humanize ( $plugin ) . " Test Cases:</h3> \n <ul> " ;
$urlExtra = '&plugin=' . $plugin ;
}
2013-09-06 16:36:57 +00:00
if ( count ( $testCases ) < 1 ) {
2010-01-09 15:55:58 +00:00
$buffer .= " <strong>EMPTY</strong> " ;
}
2013-01-23 12:45:50 +00:00
foreach ( $testCases as $testCase ) {
2010-06-26 16:58:03 +00:00
$title = explode ( DS , str_replace ( '.test.php' , '' , $testCase ));
2010-01-09 15:55:58 +00:00
$title [ count ( $title ) - 1 ] = Inflector :: camelize ( $title [ count ( $title ) - 1 ]);
$title = implode ( ' / ' , $title );
2012-03-05 02:51:44 +00:00
$buffer .= " <li><a href=' " . $this -> baseUrl () . " ?case= " . urlencode ( $testCase ) . $urlExtra . " '> " . $title . " </a></li> \n " ;
2010-01-09 15:55:58 +00:00
}
$buffer .= " </ul> \n " ;
echo $buffer ;
2010-01-07 04:02:37 +00:00
}
2008-06-10 22:38:05 +00:00
/**
* Send the headers necessary to ensure the page is
* reloaded on every request . Otherwise you could be
* scratching your head over out of date test data .
2009-09-13 17:11:37 +00:00
*
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-04-05 03:19:38 +00:00
public function sendNoCacheHeaders () {
2008-06-10 22:38:05 +00:00
if ( ! headers_sent ()) {
header ( " Expires: Mon, 26 Jul 1997 05:00:00 GMT " );
header ( " Last-Modified: " . gmdate ( " D, d M Y H:i:s " ) . " GMT " );
header ( " Cache-Control: no-store, no-cache, must-revalidate " );
header ( " Cache-Control: post-check=0, pre-check=0 " , false );
header ( " Pragma: no-cache " );
}
}
2009-07-24 19:18:37 +00:00
2008-06-10 22:38:05 +00:00
/**
* Paints the end of the test with a summary of
* the passes and failures .
2009-09-13 17:11:37 +00:00
*
2010-05-13 04:18:22 +00:00
* @ param PHPUnit_Framework_TestResult $result Result object
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-05-04 18:21:25 +00:00
public function paintFooter ( $result ) {
2010-08-17 03:34:43 +00:00
ob_end_flush ();
2012-03-05 02:51:44 +00:00
$colour = ( $result -> failureCount () + $result -> errorCount () > 0 ? " red " : " green " );
2008-06-10 22:38:05 +00:00
echo " </ul> \n " ;
echo " <div style= \" " ;
echo " padding: 8px; margin: 1em 0; background-color: $colour ; color: white; " ;
echo " \" > " ;
2010-05-18 04:14:08 +00:00
echo ( $result -> count () - $result -> skippedCount ()) . " / " . $result -> count ();
2010-05-04 21:01:03 +00:00
echo " test methods complete: \n " ;
2010-05-04 18:21:25 +00:00
echo " <strong> " . count ( $result -> passed ()) . " </strong> passes, " ;
2010-05-04 21:01:03 +00:00
echo " <strong> " . $result -> failureCount () . " </strong> fails, " ;
echo " <strong> " . $this -> numAssertions . " </strong> assertions and " ;
2010-05-04 18:21:25 +00:00
echo " <strong> " . $result -> errorCount () . " </strong> exceptions. " ;
2008-06-10 22:38:05 +00:00
echo " </div> \n " ;
2009-09-13 17:29:44 +00:00
echo '<div style="padding:0 0 5px;">' ;
2011-02-13 20:01:00 +00:00
echo '<p><strong>Time:</strong> ' . $result -> time () . ' seconds</p>' ;
2011-12-16 06:52:07 +00:00
echo '<p><strong>Peak memory:</strong> ' . number_format ( memory_get_peak_usage ()) . ' bytes</p>' ;
2010-01-06 03:20:32 +00:00
echo $this -> _paintLinks ();
2009-09-13 17:29:44 +00:00
echo '</div>' ;
2010-05-08 21:14:47 +00:00
if ( isset ( $this -> params [ 'codeCoverage' ]) && $this -> params [ 'codeCoverage' ]) {
2011-11-05 21:46:32 +00:00
$coverage = $result -> getCodeCoverage ();
if ( method_exists ( $coverage , 'getSummary' )) {
$report = $coverage -> getSummary ();
echo $this -> paintCoverage ( $report );
}
if ( method_exists ( $coverage , 'getData' )) {
$report = $coverage -> getData ();
2011-11-12 03:13:20 +00:00
echo $this -> paintCoverage ( $report );
2011-11-05 21:46:32 +00:00
}
2010-01-10 03:35:29 +00:00
}
2010-01-07 03:52:04 +00:00
$this -> paintDocumentEnd ();
2008-06-10 22:38:05 +00:00
}
2009-07-24 19:18:37 +00:00
2010-05-08 21:14:47 +00:00
/**
* Paints a code coverage report .
*
2014-06-06 17:57:48 +00:00
* @ param array $coverage The coverage data
2010-05-08 21:14:47 +00:00
* @ return void
*/
2010-09-29 05:44:14 +00:00
public function paintCoverage ( array $coverage ) {
2011-03-12 06:36:50 +00:00
App :: uses ( 'HtmlCoverageReport' , 'TestSuite/Coverage' );
2011-11-12 03:13:20 +00:00
2010-05-08 22:12:03 +00:00
$reporter = new HtmlCoverageReport ( $coverage , $this );
2010-05-08 21:14:47 +00:00
echo $reporter -> report ();
}
2010-01-06 03:20:32 +00:00
/**
* Renders the links that for accessing things in the test suite .
*
* @ return void
*/
2010-04-15 02:56:51 +00:00
protected function _paintLinks () {
2010-01-06 03:20:32 +00:00
$show = $query = array ();
2010-06-26 16:58:03 +00:00
if ( ! empty ( $this -> params [ 'case' ])) {
2010-01-06 03:20:32 +00:00
$show [ 'show' ] = 'cases' ;
}
2011-12-20 04:13:46 +00:00
if ( ! empty ( $this -> params [ 'core' ])) {
$show [ 'core' ] = $query [ 'core' ] = 'true' ;
2010-01-06 03:20:32 +00:00
}
if ( ! empty ( $this -> params [ 'plugin' ])) {
$show [ 'plugin' ] = $query [ 'plugin' ] = $this -> params [ 'plugin' ];
}
if ( ! empty ( $this -> params [ 'case' ])) {
$query [ 'case' ] = $this -> params [ 'case' ];
2012-03-05 02:51:44 +00:00
}
2014-12-24 11:12:52 +00:00
list ( $show , $query ) = $this -> _getQueryLink ();
2010-01-06 03:20:32 +00:00
2012-08-27 18:48:07 +00:00
echo " <p><a href=' " . $this -> baseUrl () . $show . " '>Run more tests</a> | <a href=' " . $this -> baseUrl () . $query . " &show_passes=1'>Show Passes</a> | \n " ;
echo " <a href=' " . $this -> baseUrl () . $query . " &debug=1'>Enable Debug Output</a> | \n " ;
2014-12-24 11:12:52 +00:00
echo " <a href=' " . $this -> baseUrl () . $query . " &code_coverage=true'>Analyze Code Coverage</a> | \n " ;
2014-12-23 20:29:08 +00:00
echo " <a href=' " . $this -> baseUrl () . $query . " &code_coverage=true&show_passes=1&debug=1'>All options enabled</a></p> \n " ;
2010-01-06 03:20:32 +00:00
}
2010-01-07 03:52:04 +00:00
2010-01-06 03:20:32 +00:00
/**
* Convert an array of parameters into a query string url
*
* @ param array $url Url hash to be converted
* @ return string Converted url query string
*/
2010-04-15 02:56:51 +00:00
protected function _queryString ( $url ) {
2010-01-06 03:20:32 +00:00
$out = '?' ;
$params = array ();
foreach ( $url as $key => $value ) {
$params [] = " $key = $value " ;
}
$out .= implode ( '&' , $params );
return $out ;
}
2010-01-07 03:52:04 +00:00
/**
2010-01-09 16:20:47 +00:00
* Paints the end of the document html .
2010-01-07 03:52:04 +00:00
*
* @ return void
*/
2010-04-15 02:56:51 +00:00
public function paintDocumentEnd () {
2010-01-07 03:52:04 +00:00
$baseDir = $this -> params [ 'baseDir' ];
2011-04-17 10:25:02 +00:00
include CAKE . 'TestSuite' . DS . 'templates' . DS . 'footer.php' ;
2010-09-03 14:22:58 +00:00
if ( ob_get_length ()) {
ob_end_flush ();
}
2010-01-07 03:52:04 +00:00
}
2008-06-10 22:38:05 +00:00
/**
* Paints the test failure with a breadcrumbs
* trail of the nesting test suites below the
* top level test .
2009-09-13 17:11:37 +00:00
*
2010-05-04 18:21:25 +00:00
* @ param PHPUnit_Framework_AssertionFailedError $message Failure object displayed in
2009-09-13 17:11:37 +00:00
* the context of the other tests .
2014-06-06 17:57:48 +00:00
* @ param mixed $test The test case to paint a failure for .
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-07-15 02:58:42 +00:00
public function paintFail ( $message , $test ) {
$trace = $this -> _getStackTrace ( $message );
2014-12-24 11:40:56 +00:00
$className = get_class ( $test );
$testName = $className . '::' . $test -> getName () . '()' ;
2010-05-04 18:21:25 +00:00
2012-06-27 03:31:22 +00:00
$actualMsg = $expectedMsg = null ;
2013-01-01 19:25:22 +00:00
if ( method_exists ( $message , 'getComparisonFailure' )) {
$failure = $message -> getComparisonFailure ();
2012-07-21 13:23:54 +00:00
if ( is_object ( $failure )) {
2013-01-01 19:25:22 +00:00
$actualMsg = $failure -> getActualAsString ();
$expectedMsg = $failure -> getExpectedAsString ();
2012-07-21 13:23:54 +00:00
}
2012-06-26 03:12:54 +00:00
}
2008-06-10 22:38:05 +00:00
echo " <li class='fail'> \n " ;
echo " <span>Failed</span> " ;
2012-06-26 03:12:54 +00:00
echo " <div class='msg'><pre> " . $this -> _htmlEntities ( $message -> toString ());
if (( is_string ( $actualMsg ) && is_string ( $expectedMsg )) || ( is_array ( $actualMsg ) && is_array ( $expectedMsg ))) {
2014-04-12 11:37:36 +00:00
echo " <br /> " . $this -> _htmlEntities ( PHPUnit_Util_Diff :: diff ( $expectedMsg , $actualMsg ));
2012-06-26 03:12:54 +00:00
}
echo " </pre></div> \n " ;
2011-03-20 15:35:43 +00:00
echo " <div class='msg'> " . __d ( 'cake_dev' , 'Test case: %s' , $testName ) . " </div> \n " ;
2014-12-24 11:40:56 +00:00
if ( strpos ( $className , " PHPUnit_ " ) === false ) {
list ( $show , $query ) = $this -> _getQueryLink ();
echo " <div class='msg'><a href=' " . $this -> baseUrl () . $query . " &filter= " . $test -> getName () . " '> " . __d ( 'cake_dev' , 'Rerun only this test: %s' , $testName ) . " </a></div> \n " ;
}
2011-03-20 15:35:43 +00:00
echo " <div class='msg'> " . __d ( 'cake_dev' , 'Stack trace:' ) . '<br />' . $trace . " </div> \n " ;
2008-06-10 22:38:05 +00:00
echo " </li> \n " ;
}
2009-07-24 19:18:37 +00:00
2008-06-10 22:38:05 +00:00
/**
* Paints the test pass with a breadcrumbs
* trail of the nesting test suites below the
* top level test .
2009-09-13 17:11:37 +00:00
*
2014-06-06 17:57:48 +00:00
* @ param PHPUnit_Framework_Test $test Test method that just passed
2010-05-04 21:01:03 +00:00
* @ param float $time time spent to run the test method
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-05-04 21:01:03 +00:00
public function paintPass ( PHPUnit_Framework_Test $test , $time = null ) {
2011-07-09 09:40:22 +00:00
if ( isset ( $this -> params [ 'showPasses' ]) && $this -> params [ 'showPasses' ]) {
2008-06-10 22:38:05 +00:00
echo " <li class='pass'> \n " ;
echo " <span>Passed</span> " ;
2010-06-12 22:55:27 +00:00
2010-05-04 21:01:03 +00:00
echo " <br /> " . $this -> _htmlEntities ( $test -> getName ()) . " ( $time seconds) \n " ;
2008-06-10 22:38:05 +00:00
echo " </li> \n " ;
2008-05-30 11:40:08 +00:00
}
2008-06-10 22:38:05 +00:00
}
2009-07-24 19:18:37 +00:00
2008-06-10 22:38:05 +00:00
/**
* Paints a PHP exception .
2009-09-13 17:11:37 +00:00
*
2014-06-06 17:57:48 +00:00
* @ param Exception $message Exception to display .
* @ param mixed $test The test that failed .
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-07-27 02:36:34 +00:00
public function paintException ( $message , $test ) {
$trace = $this -> _getStackTrace ( $message );
$testName = get_class ( $test ) . '(' . $test -> getName () . ')' ;
2008-06-10 22:38:05 +00:00
echo " <li class='fail'> \n " ;
2011-02-04 22:11:49 +00:00
echo " <span> " . get_class ( $message ) . " </span> " ;
2010-07-27 02:36:34 +00:00
echo " <div class='msg'> " . $this -> _htmlEntities ( $message -> getMessage ()) . " </div> \n " ;
2011-03-20 15:35:43 +00:00
echo " <div class='msg'> " . __d ( 'cake_dev' , 'Test case: %s' , $testName ) . " </div> \n " ;
echo " <div class='msg'> " . __d ( 'cake_dev' , 'Stack trace:' ) . '<br />' . $trace . " </div> \n " ;
2008-06-10 22:38:05 +00:00
echo " </li> \n " ;
}
2009-07-24 19:18:37 +00:00
2008-06-10 22:38:05 +00:00
/**
* Prints the message for skipping tests .
2009-09-13 17:11:37 +00:00
*
2010-01-06 01:56:25 +00:00
* @ param string $message Text of skip condition .
2010-05-18 03:01:22 +00:00
* @ param PHPUnit_Framework_TestCase $test the test method skipped
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-05-18 03:01:22 +00:00
public function paintSkip ( $message , $test ) {
2008-06-10 22:38:05 +00:00
echo " <li class='skipped'> \n " ;
echo " <span>Skipped</span> " ;
2010-05-18 03:01:22 +00:00
echo $test -> getName () . ': ' . $this -> _htmlEntities ( $message -> getMessage ());
2008-06-10 22:38:05 +00:00
echo " </li> \n " ;
}
2009-07-24 19:18:37 +00:00
2008-06-10 22:38:05 +00:00
/**
* Paints formatted text such as dumped variables .
2009-09-13 17:11:37 +00:00
*
2008-06-10 22:38:05 +00:00
* @ param string $message Text to show .
2010-01-06 01:56:25 +00:00
* @ return void
2008-06-10 22:38:05 +00:00
*/
2010-04-05 03:19:38 +00:00
public function paintFormattedMessage ( $message ) {
2008-06-10 22:38:05 +00:00
echo '<pre>' . $this -> _htmlEntities ( $message ) . '</pre>' ;
}
2009-07-24 19:18:37 +00:00
2008-06-10 22:38:05 +00:00
/**
* Character set adjusted entity conversion .
2009-09-13 17:11:37 +00:00
*
2008-06-10 22:38:05 +00:00
* @ param string $message Plain text or Unicode message .
* @ return string Browser readable message .
*/
2010-04-05 03:21:28 +00:00
protected function _htmlEntities ( $message ) {
2010-01-09 16:20:47 +00:00
return htmlentities ( $message , ENT_COMPAT , $this -> _characterSet );
2008-05-30 11:40:08 +00:00
}
2010-05-04 18:21:25 +00:00
2010-07-15 02:58:42 +00:00
/**
* Gets a formatted stack trace .
*
* @ param Exception $e Exception to get a stack trace for .
* @ return string Generated stack trace .
*/
protected function _getStackTrace ( Exception $e ) {
$trace = $e -> getTrace ();
$out = array ();
foreach ( $trace as $frame ) {
2010-07-21 03:49:38 +00:00
if ( isset ( $frame [ 'file' ]) && isset ( $frame [ 'line' ])) {
$out [] = $frame [ 'file' ] . ' : ' . $frame [ 'line' ];
} elseif ( isset ( $frame [ 'class' ]) && isset ( $frame [ 'function' ])) {
$out [] = $frame [ 'class' ] . '::' . $frame [ 'function' ];
} else {
$out [] = '[internal]' ;
}
2010-07-15 02:58:42 +00:00
}
return implode ( '<br />' , $out );
}
2010-05-04 18:21:25 +00:00
/**
* A test suite started .
*
2014-06-06 17:57:48 +00:00
* @ param PHPUnit_Framework_TestSuite $suite The test suite to start .
2013-07-05 12:15:18 +00:00
* @ return void
2010-05-04 18:21:25 +00:00
*/
public function startTestSuite ( PHPUnit_Framework_TestSuite $suite ) {
2011-02-13 03:31:51 +00:00
if ( ! $this -> _headerSent ) {
echo $this -> paintHeader ();
}
2012-03-05 02:51:44 +00:00
echo '<h2>' . __d ( 'cake_dev' , 'Running %s' , $suite -> getName ()) . '</h2>' ;
2010-05-04 18:21:25 +00:00
}
2012-03-05 02:51:44 +00:00
2014-12-24 11:12:52 +00:00
/**
* Returns the query string formatted for ouput in links
*
* @ return string
*/
protected function _getQueryLink () {
$show = $query = array ();
if ( ! empty ( $this -> params [ 'case' ])) {
$show [ 'show' ] = 'cases' ;
}
if ( ! empty ( $this -> params [ 'core' ])) {
$show [ 'core' ] = $query [ 'core' ] = 'true' ;
}
if ( ! empty ( $this -> params [ 'plugin' ])) {
$show [ 'plugin' ] = $query [ 'plugin' ] = $this -> params [ 'plugin' ];
}
if ( ! empty ( $this -> params [ 'case' ])) {
$query [ 'case' ] = $this -> params [ 'case' ];
}
if ( ! empty ( $this -> params [ 'filter' ])) {
$query [ 'filter' ] = $this -> params [ 'filter' ];
}
$show = $this -> _queryString ( $show );
$query = $this -> _queryString ( $query );
2014-12-24 11:40:56 +00:00
return array ( $show , $query );
2014-12-24 11:12:52 +00:00
}
2011-04-17 10:25:02 +00:00
}