Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/spikephpcoverage/src/reporter/HtmlCoverageReporter.php
Go to the documentation of this file.
00001 <?php
00002     /*
00003     *  $Id: HtmlCoverageReporter.php,v 1.3 2010/12/14 17:35:59 moodlerobot Exp $
00004     *  
00005     *  Copyright(c) 2004-2006, SpikeSource Inc. All Rights Reserved.
00006     *  Licensed under the Open Software License version 2.1
00007     *  (See http://www.spikesource.com/license.html)
00008     */
00009 ?>
00010 <?php
00011 
00012     if(!defined("__PHPCOVERAGE_HOME")) {
00013         define("__PHPCOVERAGE_HOME", dirname(dirname(__FILE__)));
00014     }
00015     require_once __PHPCOVERAGE_HOME . "/reporter/CoverageReporter.php";
00016     require_once __PHPCOVERAGE_HOME . "/parser/PHPParser.php";
00017     require_once __PHPCOVERAGE_HOME . "/util/Utility.php";
00018 
00026     class HtmlCoverageReporter extends CoverageReporter {
00027 
00028         /*{{{ Members */
00029 
00030         private $coverageData;
00031         private $htmlFile;
00032         private $body;
00033         private $header = "html/header.html";
00034         private $footer = "html/footer.html";
00035         private $indexHeader = "html/indexheader.html"; 
00036         private $indexFooter = "html/indexfooter.html";
00037 
00038         /*}}}*/
00039         /*{{{ public function __construct() */
00040 
00049         public function __construct(
00050             $heading="Coverage Report",
00051             $style="",
00052             $dir="report"
00053         ) {
00054             parent::__construct($heading, $style, $dir);
00055         }
00056 
00057         /*}}}*/
00058         /*{{{ public function generateReport() */
00059 
00068         public function generateReport(&$data) {
00069             if(!file_exists($this->outputDir)) {
00070                 mkdir($this->outputDir);
00071             }
00072             $this->coverageData =& $data;
00073             $this->grandTotalFiles = count($this->coverageData);
00074             $ret = $this->writeIndexFile();
00075             if($ret === FALSE) {
00076                 $this->logger->error("Error occured!!!", __FILE__, __LINE__);
00077             }
00078             $this->logger->debug(print_r($data, true), __FILE__, __LINE__);
00079         }
00080 
00081         /*}}}*/
00082         /*{{{ private function writeIndexFileHeader() */
00083 
00090         private function writeIndexFileHeader() {
00091             $str = false;
00092             $dir = realpath(dirname(__FILE__));
00093             if($dir !== false) {
00094                 $str = file_get_contents($dir . "/" . $this->indexHeader);
00095                 if($str == false) {
00096                     return $str;
00097                 }
00098                 $str = str_replace("%%heading%%", $this->heading, $str);
00099                 $str = str_replace("%%style%%", $this->style, $str);
00100             }
00101             return $str;
00102         }
00103 
00104         /*}}}*/
00105         /*{{{ private function writeIndexFileFooter() */
00106 
00113         private function writeIndexFileFooter() {
00114             $str = false;
00115             $dir = realpath(dirname(__FILE__));
00116             if($dir !== false) {
00117                 $str = file_get_contents($dir . "/" . $this->indexFooter);
00118                 if($str == false) {
00119                     return $str;
00120                 }
00121             }
00122             return $str;
00123         }
00124 
00125         /*}}}*/
00126         /*{{{ private function createJSDir() */
00127 
00133         private function createJSDir() {
00134             $jsDir = $this->outputDir . "/js";
00135             if(file_exists($this->outputDir) && !file_exists($jsDir)) {
00136                 mkdir($jsDir);
00137             }
00138             $jsSortFile = realpath(dirname(__FILE__)) . "/js/sort_spikesource.js";
00139             copy($jsSortFile, $jsDir . "/" . "sort_spikesource.js");
00140             return true;
00141         }
00142 
00143         /*}}}*/
00144         /*{{{ private function createImagesDir() */
00145 
00151         private function createImagesDir() {
00152             $imagesDir = $this->outputDir . "/images";
00153             if(file_exists($this->outputDir) && !file_exists($imagesDir)) {
00154                 mkdir($imagesDir);
00155             }
00156             $imagesSpikeDir = $imagesDir . "/spikesource";
00157             if(!file_exists($imagesSpikeDir)) {
00158                 mkdir($imagesSpikeDir);
00159             }
00160             $imagesArrowUpFile = realpath(dirname(__FILE__)) . "/images/arrow_up.gif";
00161             $imagesArrowDownFile = realpath(dirname(__FILE__)) . "/images/arrow_down.gif";
00162             $imagesPHPCoverageLogoFile = realpath(dirname(__FILE__)) . "/images/spikesource/phpcoverage.gif";
00163             $imagesSpacerFile = realpath(dirname(__FILE__)) . "/images/spacer.gif";
00164             copy($imagesArrowUpFile, $imagesDir . "/" . "arrow_up.gif");
00165             copy($imagesArrowDownFile, $imagesDir . "/" . "arrow_down.gif");
00166             copy($imagesSpacerFile, $imagesDir . "/" . "spacer.gif");
00167             copy($imagesPHPCoverageLogoFile, $imagesSpikeDir . "/" . "phpcoverage.gif");
00168             return true;
00169         }
00170 
00171         /*}}}*/
00172         /*{{{ private function createStyleDir() */
00173 
00174         private function createStyleDir() {
00175             if(isset($this->style)) {
00176                 $this->style = trim($this->style);
00177             }
00178             if(empty($this->style)) {
00179                 $this->style = "spikesource.css";
00180             }
00181             $styleDir = $this->outputDir . "/css";
00182             if(file_exists($this->outputDir) && !file_exists($styleDir)) {
00183                 mkdir($styleDir);
00184             }
00185             $styleFile = realpath(dirname(__FILE__)) . "/css/" . $this->style;
00186             copy($styleFile, $styleDir . "/" . $this->style);
00187             return true;
00188         }
00189 
00190         /*}}}*/
00191         /*{{{ protected function writeIndexFileTableHead() */
00192 
00199         protected function writeIndexFileTableHead() {
00200             $str = "";
00201             $str .= '<h1>Details</h1> <table class="spikeDataTable" cellpadding="4" cellspacing="0" border="0" id="table2sort" width="800">';
00202             $str .= '<thead>';
00203             // start moodle modification: xhtml links
00204             $str .= '<tr><td class="spikeDataTableHeadLeft" id="sortCell0" rowspan="2" style="white-space:nowrap" width="52%"><a id="sortCellLink0" class="headerlink" href="#" onclick="javascript:sort(0)" title="Sort Ascending">File Name </a></td>';
00205             // end moodle modification
00206             $str .= '<td colspan="4" class="spikeDataTableHeadCenter">Lines</td>';
00207             // start moodle modification: xhtml links
00208             $str .= '<td class="spikeDataTableHeadCenterLast" id="sortCell5" rowspan="2"  width="16%" style="white-space:nowrap"><a id="sortCellLink5" class="headerlink" href="#" onclick="javascript:sort(5, \'percentage\')" title="Sort Ascending">Code Coverage </a></td>';
00209             // end moodle modification
00210             $str .= '</tr>';
00211 
00212             // Second row - subheadings
00213             $str .= '<tr>';
00214             // start moodle modification: xhtml links
00215             $str .= '<td class="spikeDataTableSubHeadCenter" id="sortCell1" style="white-space:nowrap" width="8%"><a id="sortCellLink1" title="Sort Ascending" class="headerlink" href="#" onclick="javascript:sort(1, \'number\')">Total </a></td>';
00216             $str .= '<td class="spikeDataTableSubHeadCenter"  id="sortCell2" style="white-space:nowrap" width="9%"><a id="sortCellLink2" title="Sort Ascending" class="headerlink" href="#" onclick="javascript:sort(2, \'number\')">Covered </a></td>';
00217             $str .= '<td class="spikeDataTableSubHeadCenter" id="sortCell3" style="white-space:nowrap" width="8%"><a id="sortCellLink3" title="Sort Ascending" class="headerlink" href="#" onclick="javascript:sort(3, \'number\')">Missed </a></td>';
00218             $str .= '<td class="spikeDataTableSubHeadCenter" id="sortCell4" style="white-space:nowrap" width="10%"><a id="sortCellLink4" title="Sort Ascending" class="headerlink" href="#" onclick="javascript:sort(4, \'number\')">Executable </a></td>';
00219             // end moodle modification
00220             $str .= '</tr>';
00221             $str .= '</thead>';
00222             return $str;
00223         }
00224 
00225         /*}}}*/
00226         /*{{{ protected function writeIndexFileTableRow() */
00227 
00238         protected function writeIndexFileTableRow($fileLink, $realFile, $fileCoverage) {
00239 
00240             global $util;
00241             $fileLink = $this->makeRelative($fileLink);
00242             $realFileShort = $util->shortenFilename($realFile);
00243             $str = "";
00244 
00245             $str .= '<tr><td class="spikeDataTableCellLeft">';
00246             $str .= '<a class="contentlink" href="' . $util->unixifyPath($fileLink) . '" title="' 
00247             . $realFile .'">' . $realFileShort. '</a>' . '</td>';
00248             $str .= '<td class="spikeDataTableCellCenter">' . $fileCoverage['total'] . "</td>";
00249             $str .= '<td class="spikeDataTableCellCenter">' . $fileCoverage['covered'] . "</td>";
00250             $str .= '<td class="spikeDataTableCellCenter">' . $fileCoverage['uncovered'] . "</td>";
00251             $str .= '<td class="spikeDataTableCellCenter">' . ($fileCoverage['covered']+$fileCoverage['uncovered']) . "</td>";
00252             if($fileCoverage['uncovered'] + $fileCoverage['covered'] == 0) {
00253                 // If there are no executable lines, assume coverage to be 100%
00254                 $str .= '<td class="spikeDataTableCellCenter">100%</td></tr>';
00255             }
00256             else {
00257                 $str .= '<td class="spikeDataTableCellCenter">' 
00258                 . round(($fileCoverage['covered']/($fileCoverage['uncovered'] 
00259                 + $fileCoverage['covered']))*100.0, 2)
00260                 . '%</td></tr>';
00261             }
00262             return $str;
00263         }
00264 
00265         /*}}}*/
00266         /*{{{ protected function writeIndexFileGrandTotalPercentage() */
00267 
00274         protected function writeIndexFileGrandTotalPercentage() {
00275             $str = "";
00276 
00277             $str .= "<br/><h1>" . $this->heading . "</h1><br/>";
00278 
00279             $str .= '<table border="0" cellpadding="0" cellspacing="0" id="contentBox" width="800"> <tr>';
00280             $str .= '<td align="left" valign="top"><h1>Summary</h1>';
00281             $str .= '<table class="spikeVerticalTable" cellpadding="4" cellspacing="0" width="800" style="margin-bottom:10px" border="0">';
00282             // start moodle modification: xhtml
00283             $str .= '<tr>';
00284             $str .= '<td width="380" class="spikeVerticalTableHead" style="font-size:14px">Overall Code Coverage&nbsp;</td>';
00285             $str .= '<td class="spikeVerticalTableCell" style="font-size:14px" colspan="2"><strong>' . $this->getGrandCodeCoveragePercentage() . '%</strong></td>';
00286             // end moodle modification
00287 
00288             $str .= '</tr><tr>';
00289 
00290             $str .= '<td class="spikeVerticalTableHead">Total Covered Lines of Code&nbsp;</td>';
00291             $str .= '<td width="30" class="spikeVerticalTableCell"><span class="emphasis">' . $this->grandTotalCoveredLines.'</span></td>';
00292             $str .= '<td class="spikeVerticalTableCell"><span class="note">(' . TOTAL_COVERED_LINES_EXPLAIN . ')</span></td>';
00293 
00294             $str .= '</tr><tr>';
00295 
00296             $str .= '<td class="spikeVerticalTableHead">Total Missed Lines of Code&nbsp;</td>';
00297             $str .= '<td class="spikeVerticalTableCell"><span class="emphasis">' . $this->grandTotalUncoveredLines.'</span></td>';
00298             $str .= '<td class="spikeVerticalTableCell"><span class="note">(' . TOTAL_UNCOVERED_LINES_EXPLAIN . ')</span></td>';
00299 
00300             $str .= '</tr><tr>';
00301 
00302             $str .= '<td class="spikeVerticalTableHead">Total Lines of Code&nbsp;</td>';
00303             $str .= '<td class="spikeVerticalTableCell"><span class="emphasis">' . ($this->grandTotalCoveredLines + $this->grandTotalUncoveredLines) .'</span></td>';
00304             $str .= '<td class="spikeVerticalTableCell"><span class="note">(' . 
00305             TOTAL_LINES_OF_CODE_EXPLAIN . ')</span></td>';
00306 
00307             $str .= '</tr><tr>';
00308 
00309             $str .= '<td class="spikeVerticalTableHead" >Total Lines&nbsp;</td>';
00310             $str .= '<td class="spikeVerticalTableCell"><span class="emphasis">' . $this->grandTotalLines.'</span></td>';
00311             $str .= '<td class="spikeVerticalTableCell"><span class="note">(' . TOTAL_LINES_EXPLAIN . ')</span></td>';
00312 
00313             $str .= '</tr><tr>';
00314 
00315             $str .= '<td class="spikeVerticalTableHeadLast" >Total Files&nbsp;</td>';
00316             $str .= '<td class="spikeVerticalTableCellLast"><span class="emphasis">' . $this->grandTotalFiles.'</span></td>';
00317             $str .= '<td class="spikeVerticalTableCellLast"><span class="note">(' . TOTAL_FILES_EXPLAIN . ')</span></td>';
00318 
00319             $str .= '</tr></table>';
00320 
00321             return $str;
00322         }
00323 
00324         /*}}}*/
00325         /*{{{ protected function writeIndexFile() */
00326 
00333         protected function writeIndexFile() {
00334             global $util;
00335             $str = "";
00336             $this->createJSDir();
00337             $this->createImagesDir();
00338             $this->createStyleDir();
00339             $this->htmlFile = $this->outputDir . "/index.html";
00340             $indexFile = fopen($this->htmlFile, "w");
00341             if(empty($indexFile)) {
00342                 $this->logger->error("Cannot open file for writing: $this->htmlFile",
00343                     __FILE__, __LINE__);
00344                 return false;
00345             }
00346 
00347             $strHead = $this->writeIndexFileHeader();
00348             if($strHead == false) {
00349                 return false;
00350             }
00351             $str .= $this->writeIndexFileTableHead();
00352             $str .= '<tbody>';
00353             if(!empty($this->coverageData)) {
00354                 foreach($this->coverageData as $filename => &$lines) {
00355                     $realFile = realpath($filename);
00356                     $fileLink = $this->outputDir . $util->unixifyPath($realFile). ".html";
00357                     $fileCoverage = $this->markFile($realFile, $fileLink, $lines);
00358                     if(empty($fileCoverage)) {
00359                         return false;
00360                     }
00361                     $this->recordFileCoverageInfo($fileCoverage);
00362                     $this->updateGrandTotals($fileCoverage);
00363 
00364                     $str .= $this->writeIndexFileTableRow($fileLink, $realFile, $fileCoverage);
00365                     unset($this->coverageData[$filename]);
00366                 }
00367             }
00368             $str .= '</tbody>';
00369             $str .= "</table></td></tr>";
00370 
00371             $str .= "<tr><td><p align=\"right\" class=\"content\">Report Generated On: " . $util->getTimeStamp() . "<br/>";
00372             $str .= "Generated using Spike PHPCoverage " . $this->recorder->getVersion() . "</p></td></tr></table>";
00373 
00374             // Get the summary
00375             $strSummary = $this->writeIndexFileGrandTotalPercentage();
00376 
00377             // Merge them - with summary on top
00378             $str = $strHead . $strSummary . $str;
00379 
00380             $str .= $this->writeIndexFileFooter();
00381             fwrite($indexFile, $str);
00382             fclose($indexFile);
00383             return TRUE;
00384         }
00385 
00386         /*}}}*/
00387         /*{{{ private function writePhpFileHeader() */
00388 
00396         private function writePhpFileHeader($filename, $fileLink) {
00397             $fileLink = $this->makeRelative($fileLink);
00398             $str = false;
00399             $dir = realpath(dirname(__FILE__));
00400             if($dir !== false) {
00401                 $str = file_get_contents($dir . "/" . $this->header);
00402                 if($str == false) {
00403                     return $str;
00404                 }
00405                 $str = str_replace("%%filename%%", $filename, $str);
00406                 // Get the path to parent CSS directory
00407                 $relativeCssPath = $this->getRelativeOutputDirPath($fileLink);
00408                 $relativeCssPath .= "/css/" . $this->style;
00409                 $str = str_replace("%%style%%", $relativeCssPath, $str);
00410             }
00411             return $str;
00412         }
00413 
00414         /*}}}*/
00415         /*{{{ private function writePhpFileFooter() */
00416 
00423         private function writePhpFileFooter() {
00424             $str = false;
00425             $dir = realpath(dirname(__FILE__));
00426             if($dir !== false) {
00427                 $str = file_get_contents($dir . "/" . $this->footer);
00428                 if($str == false) {
00429                     return $str;
00430                 }
00431             }
00432             return $str;
00433         }
00434 
00435         /*}}}*/
00436         /*{{{ protected function markFile() */
00437 
00447         protected function markFile($phpFile, $fileLink, &$coverageLines) {
00448             global $util;
00449             $fileLink = $util->replaceBackslashes($fileLink);
00450             $parentDir = $util->replaceBackslashes(dirname($fileLink));
00451             if(!file_exists($parentDir)) {
00452                 //echo "\nCreating dir: $parentDir\n";
00453                 $util->makeDirRecursive($parentDir, 0755);
00454             }
00455             $writer = fopen($fileLink, "w");
00456 
00457             if(empty($writer)) {
00458                 $this->logger->error("Could not open file for writing: $fileLink",
00459                     __FILE__, __LINE__);
00460                 return false;
00461             }
00462 
00463             // Get the header for file
00464             $filestr = $this->writePhpFileHeader(basename($phpFile), $fileLink);
00465 
00466             // Add header for table
00467             $filestr .= '<table width="100%" border="0" cellpadding="2" cellspacing="0">';
00468             $filestr .= $this->writeFileTableHead();
00469 
00470             $lineCnt = $coveredCnt = $uncoveredCnt = 0;
00471             $parser = new PHPParser();
00472             $parser->parse($phpFile);
00473             $lastLineType = "non-exec";
00474             $fileLines = array();
00475             while(($line = $parser->getLine()) !== false) {
00476                 if (substr($line, -1) == "\n") {
00477                     $line = substr($line, 0, -1);
00478                 }
00479                 $lineCnt++;
00480                 $coverageLineNumbers = array_keys($coverageLines);
00481                 if(in_array($lineCnt, $coverageLineNumbers)) {
00482                     $lineType = $parser->getLineType();
00483                     if($lineType == LINE_TYPE_EXEC) {
00484                         $coveredCnt ++;
00485                         $type = "covered";
00486                     }
00487                     else if($lineType == LINE_TYPE_CONT) {
00488                         // XDebug might return this as covered - when it is
00489                         // actually merely a continuation of previous line
00490                         if($lastLineType == "covered" || $lastLineType == "covered_cont") {
00491                             unset($coverageLines[$lineCnt]);
00492                             $type = "covered_cont";
00493                             $coveredCnt ++;
00494                         }
00495                         else {
00496                            $ft = "uncovered_cont";
00497                            for($il = $lineCnt-1
00498                                   ; $il >=0
00499                                     && isset($fileLines[$lineCnt-1]["type"])
00500                                     && $ft == "uncovered_cont"
00501                                   ; $il--) {
00502                                 $ft = $fileLines[$il]["type"];
00503                                 $uncoveredCnt --;
00504                                 $coveredCnt ++;
00505                                 if($ft == "uncovered") {
00506                                     $fileLines[$il]["type"] = "covered";
00507                                 } else {
00508                                     $fileLines[$il]["type"] = "covered_cont";
00509                                 }
00510                             }
00511                             $coveredCnt ++;
00512                             $type = "covered_cont";
00513                         }
00514                     }
00515                     else {
00516                         $type = "non-exec";
00517                         $coverageLines[$lineCnt] = 0;
00518                     }
00519                 }
00520                 else if($parser->getLineType() == LINE_TYPE_EXEC) {
00521                     $uncoveredCnt ++;
00522                     $type = "uncovered";
00523                 }
00524                 else if($parser->getLineType() == LINE_TYPE_CONT) {
00525                     if($lastLineType == "uncovered" || $lastLineType == "uncovered_cont") {
00526                         $uncoveredCnt ++;
00527                         $type = "uncovered_cont";
00528                     } else if($lastLineType == "covered" || $lastLineType == "covered_cont") {
00529                         $coveredCnt ++;
00530                         $type = "covered_cont";
00531                     } else {
00532                         $type = $lastLineType;
00533                         $this->logger->debug("LINE_TYPE_CONT with lastLineType=$lastLineType",
00534                                              __FILE__, __LINE__);
00535                     }
00536                 }
00537                 else {
00538                     $type = "non-exec";
00539                 }
00540                 // Save line type 
00541                 $lastLineType = $type;
00542                 //echo $line . "\t[" . $type . "]\n";
00543 
00544                 if(!isset($coverageLines[$lineCnt])) {
00545                     $coverageLines[$lineCnt] = 0;
00546                 }
00547                 $fileLines[$lineCnt] = array("type" => $type, "lineCnt" => $lineCnt, "line" => $line, "coverageLines" => $coverageLines[$lineCnt]);
00548             }
00549             $this->logger->debug("File lines: ". print_r($fileLines, true),
00550                 __FILE__, __LINE__);
00551             for($i = 1; $i <= count($fileLines); $i++) {
00552                 $filestr .= $this->writeFileTableRow($fileLines[$i]["type"],
00553                     $fileLines[$i]["lineCnt"], 
00554                     $fileLines[$i]["line"],
00555                     $fileLines[$i]["coverageLines"]);
00556             }
00557             $filestr .= "</table>";
00558             $filestr .= $this->writePhpFileFooter();
00559             fwrite($writer, $filestr);
00560             fclose($writer);
00561             return array(
00562                 'filename' => $phpFile,
00563                 'covered' => $coveredCnt,
00564                 'uncovered' => $uncoveredCnt,
00565                 'total' => $lineCnt
00566             );
00567         }
00568 
00569         /*}}}*/
00570         /*{{{ protected function writeFileTableHead() */
00571 
00578         protected function writeFileTableHead() {
00579             $filestr = "";
00580 
00581             // start moodle modification: xhtml + column widths
00582             $filestr .= '<tr><td width="5%"class="coverageDetailsHead" >Line #</td>';
00583             $filestr .= '<td width="5%" class="coverageDetailsHead">Frequency</td>';
00584             $filestr .= '<td  width="90%" class="coverageDetailsHead">Source Line</td></tr>';
00585             // end moodle modification
00586             return $filestr;
00587         }
00588 
00589         /*}}}*/
00590         /*{{{ protected function writeFileTableRow() */
00591 
00603         protected function writeFileTableRow($type, $lineCnt, $line, $coverageLineCnt) {
00604             $spanstr = "";
00605             if($type == "covered" || $type == "covered_cont") {
00606                 $spanstr .= '<span class="codeExecuted">';
00607             }
00608             else if($type == "uncovered" || $type == "uncovered_cont") {
00609                 $spanstr .= '<span class="codeMissed">';
00610             }
00611             else {
00612                 $spanstr .= '<span>';
00613             }
00614 
00615             if(empty($coverageLineCnt)) {
00616                 $coverageLineCnt = "";
00617             }
00618 
00619             $filestr = '<tr>';
00620             $filestr .= '<td class="coverageDetails">' . $spanstr;
00621             if($type == "covered_cont" || $type == "uncovered_cont") {
00622               $filestr .= '+';
00623             }
00624             $filestr .= $lineCnt . '</span></td>';
00625             if(empty($coverageLineCnt)) {
00626                 $coverageLineCnt = "&nbsp;";
00627             }
00628             $filestr .= '<td class="coverageDetails">' . $spanstr . $coverageLineCnt . '</span></td>';
00629             $filestr .= '<td class="coverageDetailsCode"><code>' . $spanstr . $this->preserveSpacing($line) . '</span></code></td>';
00630             $filestr .= "</tr>";
00631             return $filestr;
00632         }
00633 
00634         /*}}}*/
00635         /*{{{ protected function preserveSpacing() */
00636 
00644         protected function preserveSpacing($string) {
00645             // start moodle modification: xhtml
00646             if (empty($string)) {
00647                 return '&nbsp;';
00648             }
00649             // end moodle modification
00650             $string = htmlspecialchars($string);
00651             $string = str_replace(" ", "&nbsp;", $string);
00652             $string = str_replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;", $string);
00653             return $string;
00654         }
00655 
00656         /*}}}*/
00657     }
00658 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations