extract.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: extract_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Short description for file.
00005  *
00006  * Long description for file
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.console.libs
00023  * @since           CakePHP(tm) v 1.2.0.5012
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 /**
00030  * Only used when -debug option
00031  */
00032     ob_start();
00033 
00034     $singularReturn = __('Singular string  return __()', true);
00035     $singularEcho = __('Singular string  echo __()');
00036 
00037     $pluralReturn = __n('% apple in the bowl (plural string return __n())', '% apples in the blowl (plural string 2 return __n())', 3, true);
00038     $pluralEcho = __n('% apple in the bowl (plural string 2 echo __n())', '% apples in the blowl (plural string 2 echo __n()', 3);
00039 
00040     $singularDomainReturn = __d('controllers', 'Singular string domain lookup return __d()', true);
00041     $singularDomainEcho = __d('controllers', 'Singular string domain lookup echo __d()');
00042 
00043     $pluralDomainReturn = __dn('controllers', '% pears in the bowl (plural string domain lookup return __dn())', '% pears in the blowl (plural string domain lookup return __dn())', 3, true);
00044     $pluralDomainEcho = __dn('controllers', '% pears in the bowl (plural string domain lookup echo __dn())', '% pears in the blowl (plural string domain lookup echo __dn())', 3);
00045 
00046     $singularDomainCategoryReturn = __dc('controllers', 'Singular string domain and category lookup return __dc()', 5, true);
00047     $singularDomainCategoryEcho = __dc('controllers', 'Singular string domain and category lookup echo __dc()', 5);
00048 
00049     $pluralDomainCategoryReturn = __dcn('controllers', '% apple in the bowl (plural string 1 domain and category lookup return __dcn())', '% apples in the blowl (plural string 2 domain and category lookup return __dcn())', 3, 5, true);
00050     $pluralDomainCategoryEcho = __dcn('controllers', '% apple in the bowl (plural string 1 domain and category lookup echo __dcn())', '% apples in the blowl (plural string 2 domain and category lookup echo __dcn())', 3, 5);
00051 
00052     $categoryReturn = __c('Category string lookup line return __c()', 5, true);
00053     $categoryEcho = __c('Category string  lookup line echo __c()', 5);
00054 
00055     ob_end_clean();
00056 /**
00057  * Language string extractor
00058  *
00059  * @package     cake
00060  * @subpackage  cake.cake.console.libs
00061  */
00062 class ExtractTask extends Shell{
00063 /**
00064  * Path to use when looking for strings
00065  *
00066  * @var string
00067  * @access public
00068  */
00069     var $path = null;
00070 /**
00071  * Files from where to extract
00072  *
00073  * @var array
00074  * @access public
00075  */
00076     var $files = array();
00077 /**
00078  * Filename where to deposit translations
00079  *
00080  * @var string
00081  * @access private
00082  */
00083     var $__filename = 'default';
00084 /**
00085  * True if all strings should be merged into one file
00086  *
00087  * @var boolean
00088  * @access private
00089  */
00090     var $__oneFile = true;
00091 /**
00092  * Current file being processed
00093  *
00094  * @var string
00095  * @access private
00096  */
00097     var $__file = null;
00098 /**
00099  * Extracted tokens
00100  *
00101  * @var array
00102  * @access private
00103  */
00104     var $__tokens = array();
00105 /**
00106  * Extracted strings
00107  *
00108  * @var array
00109  * @access private
00110  */
00111     var $__strings = array();
00112 /**
00113  * History of file versions
00114  *
00115  * @var array
00116  * @access private
00117  */
00118     var $__fileVersions = array();
00119 /**
00120  * Destination path
00121  *
00122  * @var string
00123  * @access private
00124  */
00125     var $__output = null;
00126 /**
00127  * Execution method always used for tasks
00128  *
00129  * @access public
00130  */
00131     function execute() {
00132         if (isset($this->params['files']) && !is_array($this->params['files'])) {
00133             $this->files = explode(',', $this->params['files']);
00134         }
00135         if (isset($this->params['path'])) {
00136             $this->path = $this->params['path'];
00137         } else {
00138             $response = '';
00139             while ($response == '') {
00140                 $response = $this->in("What is the full path you would like to extract?\nExample: " . $this->params['root'] . DS . "myapp\n[Q]uit", null, 'Q');
00141                 if (strtoupper($response) === 'Q') {
00142                     $this->out('Extract Aborted');
00143                     $this->_stop();
00144                 }
00145             }
00146 
00147             if (is_dir($response)) {
00148                 $this->path = $response;
00149             } else {
00150                 $this->err('The directory path you supplied was not found. Please try again.');
00151                 $this->execute();
00152             }
00153         }
00154 
00155         if (isset($this->params['debug'])) {
00156             $this->path = ROOT;
00157             $this->files = array(__FILE__);
00158         }
00159 
00160         if (isset($this->params['output'])) {
00161             $this->__output = $this->params['output'];
00162         } else {
00163             $response = '';
00164             while ($response == '') {
00165                 $response = $this->in("What is the full path you would like to output?\nExample: " . $this->path . DS . "locale\n[Q]uit", null, $this->path . DS . "locale");
00166                 if (strtoupper($response) === 'Q') {
00167                     $this->out('Extract Aborted');
00168                     $this->_stop();
00169                 }
00170             }
00171 
00172             if (is_dir($response)) {
00173                 $this->__output = $response . DS;
00174             } else {
00175                 $this->err('The directory path you supplied was not found. Please try again.');
00176                 $this->execute();
00177             }
00178         }
00179 
00180         if (empty($this->files)) {
00181             $this->files = $this->__searchDirectory();
00182         }
00183         $this->__extract();
00184     }
00185 /**
00186  * Extract text
00187  *
00188  * @access private
00189  */
00190     function __extract() {
00191         $this->out('');
00192         $this->out('');
00193         $this->out(__('Extracting...', true));
00194         $this->hr();
00195         $this->out(__('Path: ', true). $this->path);
00196         $this->out(__('Output Directory: ', true). $this->__output);
00197         $this->hr();
00198 
00199         $response = '';
00200         $filename = '';
00201         while ($response == '') {
00202             $response = $this->in(__('Would you like to merge all translations into one file?', true), array('y','n'), 'y');
00203             if (strtolower($response) == 'n') {
00204                 $this->__oneFile = false;
00205             } else {
00206                 while ($filename == '') {
00207                     $filename = $this->in(__('What should we name this file?', true), null, $this->__filename);
00208                     if ($filename == '') {
00209                         $this->out(__('The filesname you supplied was empty. Please try again.', true));
00210                     }
00211                 }
00212                 $this->__filename = $filename;
00213             }
00214         }
00215         $this->__extractTokens();
00216     }
00217 /**
00218  * Show help options
00219  *
00220  * @access public
00221  */
00222     function help() {
00223         $this->out(__('CakePHP Language String Extraction:', true));
00224         $this->hr();
00225         $this->out(__('The Extract script generates .pot file(s) with translations', true));
00226         $this->out(__('By default the .pot file(s) will be place in the locale directory of -app', true));
00227         $this->out(__('By default -app is ROOT/app', true));
00228         $this->hr();
00229         $this->out(__('usage: cake i18n extract [command] [path...]', true));
00230         $this->out('');
00231         $this->out(__('commands:', true));
00232         $this->out(__('   -app [path...]: directory where your application is located', true));
00233         $this->out(__('   -root [path...]: path to install', true));
00234         $this->out(__('   -core [path...]: path to cake directory', true));
00235         $this->out(__('   -path [path...]: Full path to directory to extract strings', true));
00236         $this->out(__('   -output [path...]: Full path to output directory', true));
00237         $this->out(__('   -files: [comma separated list of files, full path to file is needed]', true));
00238         $this->out(__('   cake i18n extract help: Shows this help message.', true));
00239         $this->out(__('   -debug: Perform self test.', true));
00240         $this->out('');
00241     }
00242 /**
00243  * Extract tokens out of all files to be processed
00244  *
00245  * @access private
00246  */
00247     function __extractTokens() {
00248         foreach ($this->files as $file) {
00249             $this->__file = $file;
00250             $this->out(sprintf(__('Processing %s...', true), $file));
00251 
00252             $code = file_get_contents($file);
00253 
00254             $this->__findVersion($code, $file);
00255             $allTokens = token_get_all($code);
00256             $this->__tokens = array();
00257             $lineNumber = 1;
00258 
00259             foreach ($allTokens as $token) {
00260                 if ((!is_array($token)) || (($token[0] != T_WHITESPACE) && ($token[0] != T_INLINE_HTML))) {
00261                     if (is_array($token)) {
00262                         $token[] = $lineNumber;
00263                     }
00264                     $this->__tokens[] = $token;
00265                 }
00266 
00267                 if (is_array($token)) {
00268                     $lineNumber += count(split("\n", $token[1])) - 1;
00269                 } else {
00270                     $lineNumber += count(split("\n", $token)) - 1;
00271                 }
00272             }
00273             unset($allTokens);
00274             $this->basic();
00275             $this->basic('__c');
00276             $this->extended();
00277             $this->extended('__dc', 2);
00278             $this->extended('__n', 0, true);
00279             $this->extended('__dn', 2, true);
00280             $this->extended('__dcn', 4, true);
00281         }
00282         $this->__buildFiles();
00283         $this->__writeFiles();
00284         $this->out('Done.');
00285     }
00286 /**
00287  * Will parse  __(), __c() functions
00288  *
00289  * @param string $functionName Function name that indicates translatable string (e.g: '__')
00290  * @access public
00291  */
00292     function basic($functionName = '__') {
00293         $count = 0;
00294         $tokenCount = count($this->__tokens);
00295 
00296         while (($tokenCount - $count) > 3) {
00297             list($countToken, $parenthesis, $middle, $right) = array($this->__tokens[$count], $this->__tokens[$count + 1], $this->__tokens[$count + 2], $this->__tokens[$count + 3]);
00298             if (!is_array($countToken)) {
00299                 $count++;
00300                 continue;
00301             }
00302 
00303             list($type, $string, $line) = $countToken;
00304             if (($type == T_STRING) && ($string == $functionName) && ($parenthesis == '(')) {
00305 
00306                 if (in_array($right, array(')', ','))
00307                 && (is_array($middle) && ($middle[0] == T_CONSTANT_ENCAPSED_STRING))) {
00308 
00309                     if ($this->__oneFile === true) {
00310                         $this->__strings[$this->__formatString($middle[1])][$this->__file][] = $line;
00311                     } else {
00312                         $this->__strings[$this->__file][$this->__formatString($middle[1])][] = $line;
00313                     }
00314                 } else {
00315                     $this->__markerError($this->__file, $line, $functionName, $count);
00316                 }
00317             }
00318             $count++;
00319         }
00320     }
00321 /**
00322  * Will parse __d(), __dc(), __n(), __dn(), __dcn()
00323  *
00324  * @param string $functionName Function name that indicates translatable string (e.g: '__')
00325  * @param integer $shift Number of parameters to shift to find translateable string
00326  * @param boolean $plural Set to true if function supports plural format, false otherwise
00327  * @access public
00328  */
00329     function extended($functionName = '__d', $shift = 0, $plural = false) {
00330         $count = 0;
00331         $tokenCount = count($this->__tokens);
00332 
00333         while (($tokenCount - $count) > 7) {
00334             list($countToken, $firstParenthesis) = array($this->__tokens[$count], $this->__tokens[$count + 1]);
00335             if (!is_array($countToken)) {
00336                 $count++;
00337                 continue;
00338             }
00339 
00340             list($type, $string, $line) = $countToken;
00341             if (($type == T_STRING) && ($string == $functionName) && ($firstParenthesis == '(')) {
00342                 $position = $count;
00343                 $depth = 0;
00344 
00345                 while ($depth == 0) {
00346                     if ($this->__tokens[$position] == '(') {
00347                         $depth++;
00348                     } elseif ($this->__tokens[$position] == ')') {
00349                         $depth--;
00350                     }
00351                     $position++;
00352                 }
00353 
00354                 if ($plural) {
00355                     $end = $position + $shift + 7;
00356 
00357                     if ($this->__tokens[$position + $shift + 5] === ')') {
00358                         $end = $position + $shift + 5;
00359                     }
00360 
00361                     if (empty($shift)) {
00362                         list($singular, $firstComma, $plural, $seoncdComma, $endParenthesis) = array($this->__tokens[$position], $this->__tokens[$position + 1], $this->__tokens[$position + 2], $this->__tokens[$position + 3], $this->__tokens[$end]);
00363                         $condition = ($seoncdComma == ',');
00364                     } else {
00365                         list($domain, $firstComma, $singular, $seoncdComma, $plural, $comma3, $endParenthesis) = array($this->__tokens[$position], $this->__tokens[$position + 1], $this->__tokens[$position + 2], $this->__tokens[$position + 3], $this->__tokens[$position + 4], $this->__tokens[$position + 5], $this->__tokens[$end]);
00366                         $condition = ($comma3 == ',');
00367                     }
00368                     $condition = $condition &&
00369                         (is_array($singular) && ($singular[0] == T_CONSTANT_ENCAPSED_STRING)) &&
00370                         (is_array($plural) && ($plural[0] == T_CONSTANT_ENCAPSED_STRING));
00371                 } else {
00372                     if ($this->__tokens[$position + $shift + 5] === ')') {
00373                         $comma = $this->__tokens[$position + $shift + 3];
00374                         $end = $position + $shift + 5;
00375                     } else {
00376                         $comma = null;
00377                         $end = $position + $shift + 3;
00378                     }
00379 
00380                     list($domain, $firstComma, $text, $seoncdComma, $endParenthesis) = array($this->__tokens[$position], $this->__tokens[$position + 1], $this->__tokens[$position + 2], $comma, $this->__tokens[$end]);
00381                     $condition = ($seoncdComma == ',' || $seoncdComma === null) &&
00382                         (is_array($domain) && ($domain[0] == T_CONSTANT_ENCAPSED_STRING)) &&
00383                         (is_array($text) && ($text[0] == T_CONSTANT_ENCAPSED_STRING));
00384                 }
00385 
00386                 if (($endParenthesis == ')') && $condition) {
00387                     if ($this->__oneFile === true) {
00388                         if ($plural) {
00389                             $this->__strings[$this->__formatString($singular[1]) . "\0" . $this->__formatString($plural[1])][$this->__file][] = $line;
00390                         } else {
00391                             $this->__strings[$this->__formatString($text[1])][$this->__file][] = $line;
00392                         }
00393                     } else {
00394                         if ($plural) {
00395                             $this->__strings[$this->__file][$this->__formatString($singular[1]) . "\0" . $this->__formatString($plural[1])][] = $line;
00396                         } else {
00397                             $this->__strings[$this->__file][$this->__formatString($text[1])][] = $line;
00398                         }
00399                     }
00400                 } else {
00401                     $this->__markerError($this->__file, $line, $functionName, $count);
00402                 }
00403             }
00404             $count++;
00405         }
00406     }
00407 /**
00408  * Build the translate template file contents out of obtained strings
00409  *
00410  * @access private
00411  */
00412     function __buildFiles() {
00413         foreach ($this->__strings as $str => $fileInfo) {
00414             $output = '';
00415             $occured = $fileList = array();
00416 
00417             if ($this->__oneFile === true) {
00418                 foreach ($fileInfo as $file => $lines) {
00419                     $occured[] = "$file:" . join(';', $lines);
00420 
00421                     if (isset($this->__fileVersions[$file])) {
00422                         $fileList[] = $this->__fileVersions[$file];
00423                     }
00424                 }
00425                 $occurances = join("\n#: ", $occured);
00426                 $occurances = str_replace($this->path, '', $occurances);
00427                 $output = "#: $occurances\n";
00428                 $filename = $this->__filename;
00429 
00430                 if (strpos($str, "\0") === false) {
00431                     $output .= "msgid \"$str\"\n";
00432                     $output .= "msgstr \"\"\n";
00433                 } else {
00434                     list($singular, $plural) = explode("\0", $str);
00435                     $output .= "msgid \"$singular\"\n";
00436                     $output .= "msgid_plural \"$plural\"\n";
00437                     $output .= "msgstr[0] \"\"\n";
00438                     $output .= "msgstr[1] \"\"\n";
00439                 }
00440                 $output .= "\n";
00441             } else {
00442                 foreach ($fileInfo as $file => $lines) {
00443                     $filename = $str;
00444                     $occured = array("$str:" . join(';', $lines));
00445 
00446                     if (isset($this->__fileVersions[$str])) {
00447                         $fileList[] = $this->__fileVersions[$str];
00448                     }
00449                     $occurances = join("\n#: ", $occured);
00450                     $occurances = str_replace($this->path, '', $occurances);
00451                     $output .= "#: $occurances\n";
00452 
00453                     if (strpos($file, "\0") === false) {
00454                         $output .= "msgid \"$file\"\n";
00455                         $output .= "msgstr \"\"\n";
00456                     } else {
00457                         list($singular, $plural) = explode("\0", $file);
00458                         $output .= "msgid \"$singular\"\n";
00459                         $output .= "msgid_plural \"$plural\"\n";
00460                         $output .= "msgstr[0] \"\"\n";
00461                         $output .= "msgstr[1] \"\"\n";
00462                     }
00463                     $output .= "\n";
00464                 }
00465             }
00466             $this->__store($filename, $output, $fileList);
00467         }
00468     }
00469 /**
00470  * Prepare a file to be stored
00471  *
00472  * @param string $file Filename
00473  * @param string $input What to store
00474  * @param array $fileList File list
00475  * @param integer $get Set to 1 to get files to store, false to set
00476  * @return mixed If $get == 1, files to store, otherwise void
00477  * @access private
00478  */
00479     function __store($file = 0, $input = 0, $fileList = array(), $get = 0) {
00480         static $storage = array();
00481 
00482         if (!$get) {
00483             if (isset($storage[$file])) {
00484                 $storage[$file][1] = array_unique(array_merge($storage[$file][1], $fileList));
00485                 $storage[$file][] = $input;
00486             } else {
00487                 $storage[$file] = array();
00488                 $storage[$file][0] = $this->__writeHeader();
00489                 $storage[$file][1] = $fileList;
00490                 $storage[$file][2] = $input;
00491             }
00492         } else {
00493             return $storage;
00494         }
00495     }
00496 /**
00497  * Write the files that need to be stored
00498  *
00499  * @access private
00500  */
00501     function __writeFiles() {
00502         $output = $this->__store(0, 0, array(), 1);
00503         $output = $this->__mergeFiles($output);
00504 
00505         foreach ($output as $file => $content) {
00506             $tmp = str_replace(array($this->path, '.php','.ctp','.thtml', '.inc','.tpl' ), '', $file);
00507             $tmp = str_replace(DS, '.', $tmp);
00508             $file = str_replace('.', '-', $tmp) .'.pot';
00509             $fileList = $content[1];
00510 
00511             unset($content[1]);
00512 
00513             $fileList = str_replace(array($this->path), '', $fileList);
00514 
00515             if (count($fileList) > 1) {
00516                 $fileList = "Generated from files:\n#  " . join("\n#  ", $fileList);
00517             } elseif (count($fileList) == 1) {
00518                 $fileList = 'Generated from file: ' . join('', $fileList);
00519             } else {
00520                 $fileList = 'No version information was available in the source files.';
00521             }
00522 
00523             if (is_file($this->__output . $file)) {
00524                 $response = '';
00525                 while ($response == '') {
00526                     $response = $this->in("\n\nError: ".$file . ' already exists in this location. Overwrite?', array('y','n', 'q'), 'n');
00527                     if (strtoupper($response) === 'Q') {
00528                         $this->out('Extract Aborted');
00529                         $this->_stop();
00530                     } elseif (strtoupper($response) === 'N') {
00531                         $response = '';
00532                         while ($response == '') {
00533                             $response = $this->in("What would you like to name this file?\nExample: new_" . $file, null, "new_" . $file);
00534                             $file = $response;
00535                         }
00536                     }
00537                 }
00538             }
00539             $fp = fopen($this->__output . $file, 'w');
00540             fwrite($fp, str_replace('--VERSIONS--', $fileList, join('', $content)));
00541             fclose($fp);
00542         }
00543     }
00544 /**
00545  * Merge output files
00546  *
00547  * @param array $output Output to merge
00548  * @return array Merged output
00549  * @access private
00550  */
00551     function __mergeFiles($output) {
00552         foreach ($output as $file => $content) {
00553             if (count($content) <= 1 && $file != $this->__filename) {
00554                 @$output[$this->__filename][1] = array_unique(array_merge($output[$this->__filename][1], $content[1]));
00555 
00556                 if (!isset($output[$this->__filename][0])) {
00557                     $output[$this->__filename][0] = $content[0];
00558                 }
00559                 unset($content[0]);
00560                 unset($content[1]);
00561 
00562                 foreach ($content as $msgid) {
00563                     $output[$this->__filename][] = $msgid;
00564                 }
00565                 unset($output[$file]);
00566             }
00567         }
00568         return $output;
00569     }
00570 /**
00571  * Build the translation template header
00572  *
00573  * @return string Translation template header
00574  * @access private
00575  */
00576     function __writeHeader() {
00577         $output  = "# LANGUAGE translation of CakePHP Application\n";
00578         $output .= "# Copyright YEAR NAME <EMAIL@ADDRESS>\n";
00579         $output .= "# --VERSIONS--\n";
00580         $output .= "#\n";
00581         $output .= "#, fuzzy\n";
00582         $output .= "msgid \"\"\n";
00583         $output .= "msgstr \"\"\n";
00584         $output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
00585         $output .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
00586         $output .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
00587         $output .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
00588         $output .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
00589         $output .= "\"MIME-Version: 1.0\\n\"\n";
00590         $output .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
00591         $output .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
00592         $output .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n\n";
00593         return $output;
00594     }
00595 /**
00596  * Find the version number of a file looking for SVN commands
00597  *
00598  * @param string $code Source code of file
00599  * @param string $file File
00600  * @access private
00601  */
00602     function __findVersion($code, $file) {
00603         $header = '$Id' . ':';
00604         if (preg_match('/\\' . $header . ' [\\w.]* ([\\d]*)/', $code, $versionInfo)) {
00605             $version = str_replace(ROOT, '', 'Revision: ' . $versionInfo[1] . ' ' .$file);
00606             $this->__fileVersions[$file] = $version;
00607         }
00608     }
00609 /**
00610  * Format a string to be added as a translateable string
00611  *
00612  * @param string $string String to format
00613  * @return string Formatted string
00614  * @access private
00615  */
00616     function __formatString($string) {
00617         $quote = substr($string, 0, 1);
00618         $string = substr($string, 1, -1);
00619         if ($quote == '"') {
00620             $string = stripcslashes($string);
00621         } else {
00622             $string = strtr($string, array("\\'" => "'", "\\\\" => "\\"));
00623         }
00624         return addcslashes($string, "\0..\37\\\"");
00625     }
00626 /**
00627  * Indicate an invalid marker on a processed file
00628  *
00629  * @param string $file File where invalid marker resides
00630  * @param integer $line Line number
00631  * @param string $marker Marker found
00632  * @param integer $count Count
00633  * @access private
00634  */
00635     function __markerError($file, $line, $marker, $count) {
00636         $this->out("Invalid marker content in $file:$line\n* $marker(", true);
00637         $count += 2;
00638         $tokenCount = count($this->__tokens);
00639         $parenthesis = 1;
00640 
00641         while ((($tokenCount - $count) > 0) && $parenthesis) {
00642             if (is_array($this->__tokens[$count])) {
00643                 $this->out($this->__tokens[$count][1], false);
00644             } else {
00645                 $this->out($this->__tokens[$count], false);
00646                 if ($this->__tokens[$count] == '(') {
00647                     $parenthesis++;
00648                 }
00649 
00650                 if ($this->__tokens[$count] == ')') {
00651                     $parenthesis--;
00652                 }
00653             }
00654             $count++;
00655         }
00656         $this->out("\n", true);
00657     }
00658 /**
00659  * Search the specified path for files that may contain translateable strings
00660  *
00661  * @param string $path Path (or set to null to use current)
00662  * @return array Files
00663  * @access private
00664  */
00665     function __searchDirectory($path = null) {
00666         if ($path === null) {
00667             $path = $this->path .DS;
00668         }
00669         $files = glob("$path*.{php,ctp,thtml,inc,tpl}", GLOB_BRACE);
00670         $dirs = glob("$path*", GLOB_ONLYDIR);
00671 
00672         foreach ($dirs as $dir) {
00673             if (!preg_match("!(^|.+/)(CVS|.svn)$!", $dir)) {
00674                 $files = array_merge($files, $this->__searchDirectory("$dir" . DS));
00675                 if (($id = array_search($dir . DS . 'extract.php', $files)) !== FALSE) {
00676                     unset($files[$id]);
00677                 }
00678             }
00679         }
00680         return $files;
00681     }
00682 }
00683 ?>