/**
  * Sets a timer point before rendering a file.
  *
  * @param string $viewFile The view being rendered
  */
 public function beforeRenderFile($viewFile)
 {
     if ($this->_renderComplete) {
         return;
     }
     DebugTimer::start('render_' . basename($viewFile), __d('debug_kit', 'Rendering %s', Debugger::trimPath($viewFile)));
 }
Пример #2
0
 /**
  * Overload _render to capture filenames and time actual rendering of each view file
  *
  * @param string $___viewFn Filename of the view
  * @param array $___dataForView Data to include in rendered view
  * @return string Rendered output
  * @access protected
  */
 function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false)
 {
     if (!isset($___dataForView['disableTimer'])) {
         DebugKitDebugger::startTimer('render_' . basename($___viewFn), sprintf(__d('debug_kit', 'Rendering %s', true), Debugger::trimPath($___viewFn)));
     }
     $out = parent::_render($___viewFn, $___dataForView, $loadHelpers, $cached);
     if (!isset($___dataForView['disableTimer'])) {
         DebugKitDebugger::stopTimer('render_' . basename($___viewFn));
     }
     return $out;
 }
Пример #3
0
 public function testGetCallbacks()
 {
     $listeners = array(array('callable' => array('SomeClass', 'someStaticMethod')), array('callable' => array($this, 'someInstanceMethod')), array('callable' => function () {
         return 'Some Closure';
     }));
     $line = __LINE__;
     $path = Debugger::trimPath(__FILE__);
     $expected = array('SomeClass::someStaticMethod', 'CrudPanelTest::someInstanceMethod', $path . ':' . ($line - 5));
     $return = $this->callProtectedMethod('_getCallbacks', array($listeners), $this->Panel);
     $this->assertSame($expected, $return);
 }
Пример #4
0
 /**
  * Overload _render to capture filenames and time actual rendering of each view file
  *
  * @param string $___viewFn Filename of the view
  * @param array $___dataForView Data to include in rendered view
  * @return string Rendered output
  */
 protected function _render($___viewFn, $___dataForView = array())
 {
     if (!isset($___dataForView['disableTimer'])) {
         DebugTimer::start('render_' . basename($___viewFn), __d('debug_kit', 'Rendering %s', Debugger::trimPath($___viewFn)));
     }
     $out = parent::_render($___viewFn, $___dataForView);
     if (!isset($___dataForView['disableTimer'])) {
         DebugTimer::stop('render_' . basename($___viewFn));
     }
     return $out;
 }
Пример #5
0
 /**
  * Overload _render to capture filenames and time actual rendering of each view file
  *
  * @param string $___viewFn Filename of the view
  * @param array $___dataForView Data to include in rendered view
  * @return string Rendered output
  * @access protected
  */
 function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false)
 {
     if (isset($this->_oldExtension) && strstr($___viewFn, '.debug_view')) {
         $___viewFn = substr($___viewFn, 0, -10) . $this->_oldExtension;
     }
     if (!isset($___dataForView['disableTimer'])) {
         DebugKitDebugger::startTimer('render_' . basename($___viewFn), sprintf(__('Rendering %s', true), Debugger::trimPath($___viewFn)));
     }
     $out = parent::_render($___viewFn, $___dataForView, $loadHelpers, $cached);
     if (!isset($___dataForView['disableTimer'])) {
         DebugKitDebugger::stopTimer('render_' . basename($___viewFn));
     }
     return $out;
 }
Пример #6
0
 /**
  * Read a config file and return its contents.
  *
  * Keys with `.` will be treated as values in plugins.  Instead of reading from
  * the initialized path, plugin keys will be located using App::pluginPath().
  *
  *
  * @param string $key The identifier to read from.  If the key has a . it will be treated
  *   as a plugin prefix. path extension is not needed by default, but possible to specify
  *   your own extension, e.g. Configure::load('Hoge.yaml', new YamlReader);
  * @return array Parsed configuration values.
  * @throws ConfigureException when files doesn't exist or when files contain '..' as this could lead to abusive reads.
  */
 public function read($key)
 {
     App::uses('Spyc', 'vendors');
     if (!class_exists('Spyc')) {
         App::uses('Spyc', 'YamlReader.vendors');
     }
     $filePath = $this->_getFilePath($key);
     if (!file_exists($filePath)) {
         $filePath .= ".{$this->ext}";
         if (!file_exists($filePath)) {
             throw new ConfigureException(__('Could not load configuration file: ') . Debugger::trimPath($filePath));
         }
     }
     $config = Spyc::YAMLLoad($filePath);
     if ($this->baseKey) {
         $config = array($key => $config);
     }
     return $config;
 }
Пример #7
0
 /**
  * override core one with the following enhancements/fixes:
  * - 404s log to a different domain
  * - IP, Referer and Browser-Infos are added for better error debugging/tracing
  * 2011-12-21 ms
  */
 public static function handleError($code, $description, $file = null, $line = null, $context = null)
 {
     if (error_reporting() === 0) {
         return false;
     }
     $errorConfig = Configure::read('Error');
     list($error, $log) = self::mapErrorCode($code);
     $debug = Configure::read('debug');
     if ($debug) {
         $data = array('level' => $log, 'code' => $code, 'error' => $error, 'description' => $description, 'file' => $file, 'line' => $line, 'context' => $context, 'start' => 2, 'path' => Debugger::trimPath($file));
         return Debugger::getInstance()->outputError($data);
     } else {
         $message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
         if (!empty($errorConfig['trace'])) {
             $trace = Debugger::trace(array('start' => 1, 'format' => 'log'));
             $message .= "\nTrace:\n" . $trace . "\n";
             $message .= self::traceDetails();
         }
         return CakeLog::write($log, $message);
     }
 }
Пример #8
0
 /**
  * testTrimPath method
  *
  * @return void
  */
 public function testTrimPath()
 {
     $this->assertEquals('APP' . DS, Debugger::trimPath(APP));
     $this->assertEquals('CORE', Debugger::trimPath(CAKE_CORE_INCLUDE_PATH));
     $this->assertEquals('ROOT', Debugger::trimPath(ROOT));
     $this->assertEquals('CORE' . DS . 'Cake' . DS, Debugger::trimPath(CAKE));
     $this->assertEquals('Some/Other/Path', Debugger::trimPath('Some/Other/Path'));
 }
Пример #9
0
/**
 * own shutdown function - also logs fatal errors (necessary until cake2.2)
 * 2010-10-17 ms
 */
function shutDownFunction()
{
    $error = error_get_last();
    if (empty($error)) {
        return;
    }
    $matching = array(E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING', E_PARSE => 'E_', E_NOTICE => 'E_', E_CORE_ERROR => 'E_', E_COMPILE_ERROR => 'E_', E_COMPILE_WARNING => 'E_', E_STRICT => 'E_STRICT', E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', E_DEPRECATED => 'E_DEPRECATED');
    App::uses('CakeLog', 'Log');
    if (in_array($error['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR))) {
        $error['type_name'] = 'Fatal Error';
        $type = 'error';
    } elseif (Configure::read('Debug.log') && isset($matching[$error['type']])) {
        $error['type_name'] = 'Error';
        $type = 'notice';
    }
    if (!isset($type)) {
        return;
    }
    App::uses('Debugger', 'Utility');
    $trace = Debugger::trace(array('start' => 1, 'format' => 'log', 'args' => true));
    $path = Debugger::trimPath($error['file']);
    $message = $error['type_name'] . ' ' . $matching[$error['type']] . ' in ' . $path . ' (line ' . $error['line'] . '): ' . $error['message'];
    $message .= PHP_EOL . $trace;
    App::uses('MyErrorHandler', 'Tools.Error');
    $message .= MyErrorHandler::traceDetails();
    CakeLog::write($type, $message);
}
 /**
  * testTrimPath method
  *
  * @return void
  */
 public function testTrimPath()
 {
     $this->assertEquals(Debugger::trimPath(APP), 'APP' . DS);
     $this->assertEquals(Debugger::trimPath(CAKE_CORE_INCLUDE_PATH), 'CORE');
 }
Пример #11
0
 /**
  * Fix a trace for use in output
  *
  * @param mixed $trace Trace to fix
  * @return string
  */
 protected static function _escapeTrace($trace)
 {
     for ($i = 0, $len = count($trace); $i < $len; $i++) {
         if (isset($trace[$i]['file'])) {
             $trace[$i]['file'] = Debugger::trimPath($trace[$i]['file']);
         }
         if (isset($trace[$i]['args'])) {
             $trace[$i]['args'] = FireCake::stringEncode($trace[$i]['args']);
         }
     }
     return $trace;
 }
Пример #12
0
 /**
  * Set as the default error handler by CakePHP. Use Configure::write('Error.handler', $callback), to use your own
  * error handling methods. This function will use Debugger to display errors when debug > 0. And
  * will log errors to CakeLog, when debug == 0.
  *
  * You can use Configure::write('Error.level', $value); to set what type of errors will be handled here.
  * Stack traces for errors can be enabled with Configure::write('Error.trace', true);
  *
  * @param int $code Code of error
  * @param string $description Error description
  * @param string $file File on which error occurred
  * @param int $line Line that triggered the error
  * @param array $context Context
  * @return bool true if error was handled
  */
 public static function handleError($code, $description, $file = null, $line = null, $context = null)
 {
     if (error_reporting() === 0) {
         return false;
     }
     $errorConfig = Configure::read('Error');
     list($error, $log) = self::mapErrorCode($code);
     if ($log === LOG_ERR) {
         return self::handleFatalError($code, $description, $file, $line);
     }
     $debug = Configure::read('debug');
     if ($debug) {
         $data = array('level' => $log, 'code' => $code, 'error' => $error, 'description' => $description, 'file' => $file, 'line' => $line, 'context' => $context, 'start' => 2, 'path' => Debugger::trimPath($file));
         return Debugger::getInstance()->outputError($data);
     }
     $message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
     #mod blamoo@live.com
     $message .= "\nForwarded-For: " . (isset($_SERVER["HTTP_X_FORWARDED_FOR"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : '(None)');
     #MOD
     $message .= "\nReferer: " . (isset($_SERVER['HTTP_REFERER']) ? "<a href=\"{$_SERVER['HTTP_REFERER']}\">{$_SERVER['HTTP_REFERER']}</a>" : '(None)');
     #MOD
     $message .= "\nUA: " . (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '(None)');
     #MOD
     $message .= "\nMethod: " . (isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '(None)');
     #MOD
     if (count($_POST) !== 0) {
         $message .= "\nPost: <pre>" . var_export($_POST, true) . '</pre>';
         #MOD
     }
     #endmod
     if (!empty($errorConfig['trace'])) {
         $trace = Debugger::trace(array('start' => 1, 'format' => 'log'));
         $message .= "\nTrace:\n" . $trace . "\n";
     }
     return CakeLog::write($log, $message);
 }
Пример #13
0
 /**
  * Return where a closure has been defined
  *
  * If for some reason this doesn't work - it'll return the closure instance in the full knowledge
  * that it'll probably get dumped as the string "function"
  *
  * @param Closure $closure
  * @return mixed string or Closure
  */
 protected function _getClosureDefinition(Closure $closure)
 {
     $exported = ReflectionFunction::export($closure, true);
     preg_match('#@@ (.*) (\\d+) - (\\d+)#', $exported, $match);
     if (!$match) {
         return $closure;
     }
     list($m, $path, $start) = $match;
     $path = Debugger::trimPath($path);
     return "{$path}:{$start}";
 }
Пример #14
0
 /**
  * update method
  *
  * @return void
  * @access public
  */
 public function update()
 {
     if (!file_exists(CAKE . 'config' . DS . 'sources.txt')) {
         $File = new File(CAKE . 'config' . DS . 'sources.txt', true);
         $File->write('file://' . dirname(__FILE__) . DS . 'packages.txt');
     }
     $sources = file(CAKE . 'config' . DS . 'sources.txt');
     $packages = array();
     App::import('Core', 'HttpSocket');
     $Socket = new HttpSocket();
     foreach ($sources as &$source) {
         $source = trim($source);
         if (!$source || $source[0] === '#') {
             $source = false;
             continue;
         }
         if (strpos($source, 'file://') !== false) {
             $data = file($source);
         } else {
             $data = $Socket->get($source);
             if (!$data) {
                 $source .= ' (no response)';
                 continue;
             }
             $data = explode("\n", $data);
         }
         $packages = array_merge($packages, MiInstall::_parsePackages($data));
     }
     $File = new File(CAKE . 'config' . DS . 'packages.php', true);
     $File->write("<?php\n\$config = " . var_export($packages, true) . ';');
     $return[] = Debugger::trimPath($File->pwd()) . ' updated';
     $return['sources checked:'] = array_filter($sources);
     return $return;
 }
Пример #15
0
 /**
  * Set as the default error handler by CakePHP. Use Configure::write('Error.handler', $callback), to use your own
  * error handling methods. This function will use Debugger to display errors when debug > 0. And
  * will log errors to CakeLog, when debug == 0.
  *
  * You can use Configure::write('Error.level', $value); to set what type of errors will be handled here.
  * Stack traces for errors can be enabled with Configure::write('Error.trace', true);
  *
  * @param int $code Code of error
  * @param string $description Error description
  * @param string $file File on which error occurred
  * @param int $line Line that triggered the error
  * @param array $context Context
  * @return bool true if error was handled
  */
 public static function handleError($code, $description, $file = null, $line = null, $context = null)
 {
     if (error_reporting() === 0) {
         return false;
     }
     list($error, $log) = static::mapErrorCode($code);
     if ($log === LOG_ERR) {
         return static::handleFatalError($code, $description, $file, $line);
     }
     $debug = Configure::read('debug');
     if ($debug) {
         $data = array('level' => $log, 'code' => $code, 'error' => $error, 'description' => $description, 'file' => $file, 'line' => $line, 'context' => $context, 'start' => 2, 'path' => Debugger::trimPath($file));
         return Debugger::getInstance()->outputError($data);
     }
     $message = static::_getErrorMessage($error, $code, $description, $file, $line);
     return CakeLog::write($log, $message);
 }
Пример #16
0
 /**
  * Outputs a stack trace based on the supplied options.
  *
  * ### Options
  *
  * - `depth` - The number of stack frames to return. Defaults to 999
  * - `format` - The format you want the return.  Defaults to the currently selected format.  If
  *    format is 'array' or 'points' the return will be an array.
  * - `args` - Should arguments for functions be shown?  If true, the arguments for each method call
  *   will be displayed.
  * - `start` - The stack frame to start generating a trace from.  Defaults to 0
  *
  * @param array $options Format for outputting stack trace
  * @return mixed Formatted stack trace
  * @access public
  * @static
  * @link http://book.cakephp.org/view/1191/Using-the-Debugger-Class
  */
 function trace($options = array())
 {
     $_this =& Debugger::getInstance();
     $defaults = array('depth' => 999, 'format' => $_this->_outputFormat, 'args' => false, 'start' => 0, 'scope' => null, 'exclude' => null);
     $options += $defaults;
     $backtrace = debug_backtrace();
     $count = count($backtrace);
     $back = array();
     $_trace = array('line' => '??', 'file' => '[internal]', 'class' => null, 'function' => '[main]');
     for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) {
         $trace = array_merge(array('file' => '[internal]', 'line' => '??'), $backtrace[$i]);
         if (isset($backtrace[$i + 1])) {
             $next = array_merge($_trace, $backtrace[$i + 1]);
             $reference = $next['function'];
             if (!empty($next['class'])) {
                 $reference = $next['class'] . '::' . $reference . '(';
                 if ($options['args'] && isset($next['args'])) {
                     $args = array();
                     foreach ($next['args'] as $arg) {
                         $args[] = Debugger::exportVar($arg);
                     }
                     $reference .= join(', ', $args);
                 }
                 $reference .= ')';
             }
         } else {
             $reference = '[main]';
         }
         if (in_array($reference, array('call_user_func_array', 'trigger_error'))) {
             continue;
         }
         if ($options['format'] == 'points' && $trace['file'] != '[internal]') {
             $back[] = array('file' => $trace['file'], 'line' => $trace['line']);
         } elseif ($options['format'] == 'array') {
             $back[] = $trace;
         } else {
             if (isset($_this->_templates[$options['format']]['traceLine'])) {
                 $tpl = $_this->_templates[$options['format']]['traceLine'];
             } else {
                 $tpl = $_this->_templates['base']['traceLine'];
             }
             $trace['path'] = Debugger::trimPath($trace['file']);
             $trace['reference'] = $reference;
             unset($trace['object'], $trace['args']);
             $back[] = String::insert($tpl, $trace, array('before' => '{:', 'after' => '}'));
         }
     }
     if ($options['format'] == 'array' || $options['format'] == 'points') {
         return $back;
     }
     return implode("\n", $back);
 }
Пример #17
0
 /**
  * Assert that nested anonymous timers don't get mixed up.
  *
  * @return void
  **/
 function testNestedAnonymousTimers()
 {
     $this->assertTrue(DebugKitDebugger::startTimer());
     usleep(100);
     $this->assertTrue(DebugKitDebugger::startTimer());
     usleep(100);
     $this->assertTrue(DebugKitDebugger::stopTimer());
     $this->assertTrue(DebugKitDebugger::stopTimer());
     $timers = DebugKitDebugger::getTimers();
     $this->assertEqual(count($timers), 3, 'incorrect number of timers %s');
     $firstTimerLine = __LINE__ - 9;
     $secondTimerLine = __LINE__ - 8;
     $file = Debugger::trimPath(__FILE__);
     $this->assertTrue(isset($timers[$file . ' line ' . $firstTimerLine]), 'first timer is not set %s');
     $this->assertTrue(isset($timers[$file . ' line ' . $secondTimerLine]), 'second timer is not set %s');
     $firstTimer = $timers[$file . ' line ' . $firstTimerLine];
     $secondTimer = $timers[$file . ' line ' . $secondTimerLine];
     $this->assertTrue($firstTimer['time'] > $secondTimer['time']);
 }
Пример #18
0
 /**
  * Fix a trace for use in output
  *
  * @param mixed $trace Trace to fix
  * @access protected
  * @static
  * @return string
  **/
 function _escapeTrace($trace)
 {
     for ($i = 0, $len = count($trace); $i < $len; $i++) {
         if (isset($trace[$i]['file'])) {
             $trace[$i]['file'] = Debugger::trimPath($trace[$i]['file']);
         }
         if (isset($trace[$i]['args'])) {
             $trace[$i]['args'] = $this->stringEncode($trace[$i]['args']);
         }
     }
     return $trace;
 }
Пример #19
0
 /**
  * Outputs a stack trace based on the supplied options.
  *
  * @param array $options Format for outputting stack trace
  * @return string Formatted stack trace
  * @access public
  * @static
  * @link http://book.cakephp.org/view/460/Using-the-Debugger-Class
  */
 function trace($options = array())
 {
     $options = array_merge(array('depth' => 999, 'format' => '', 'args' => false, 'start' => 0, 'scope' => null, 'exclude' => null), $options);
     $backtrace = debug_backtrace();
     $back = array();
     $count = count($backtrace);
     for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) {
         $trace = array_merge(array('file' => '[internal]', 'line' => '??'), $backtrace[$i]);
         if (isset($backtrace[$i + 1])) {
             $next = array_merge(array('line' => '??', 'file' => '[internal]', 'class' => null, 'function' => '[main]'), $backtrace[$i + 1]);
             $function = $next['function'];
             if (!empty($next['class'])) {
                 $function = $next['class'] . '::' . $function . '(';
                 if ($options['args'] && isset($next['args'])) {
                     $args = array();
                     foreach ($next['args'] as $arg) {
                         $args[] = Debugger::exportVar($arg);
                     }
                     $function .= join(', ', $args);
                 }
                 $function .= ')';
             }
         } else {
             $function = '[main]';
         }
         if (in_array($function, array('call_user_func_array', 'trigger_error'))) {
             continue;
         }
         if ($options['format'] == 'points' && $trace['file'] != '[internal]') {
             $back[] = array('file' => $trace['file'], 'line' => $trace['line']);
         } elseif (empty($options['format'])) {
             $back[] = $function . ' - ' . Debugger::trimPath($trace['file']) . ', line ' . $trace['line'];
         } else {
             $back[] = $trace;
         }
     }
     if ($options['format'] == 'array' || $options['format'] == 'points') {
         return $back;
     }
     return join("\n", $back);
 }
Пример #20
0
 /**
  * log method
  *
  * If the message level is greater than the set logLevel - ignore it
  * If it's an error - don't echo it inline to prevent duplicate messages (once when found, and
  * once in the summary when all files are processed)
  *
  * @param string $string ''
  * @param mixed $ruleKey null
  * @param mixed $level 'info'
  * @param bool $isError false
  * @return void
  * @access protected
  */
 function _log($string = '', $ruleKey = null, $level = 'info', $isError = false)
 {
     if ($isError) {
         $this->returnValue = 1;
     }
     if ($this->_logLevel[$level] > $this->_logLevel[$this->settings['logLevel']]) {
         return;
     }
     if ($isError) {
         $this->returnValue = 1;
         $file = Debugger::trimPath($this->current['file']);
         if (!strpos($string, $file)) {
             $string .= ' in ' . $file;
             if ($this->current['lineNo'] !== '*') {
                 $string .= ' on line ' . $this->current['lineNo'];
             }
         }
         $this->errors[$this->current['file']][$this->current['rule']][$this->current['lineNo']] = $string;
         return;
     }
     if ($this->_logLevel[$level] === $this->_logLevel['err']) {
         $string = 'Error: ' . $string;
     } elseif ($this->_logLevel[$level] === $this->_logLevel['warning']) {
         $string = 'Warning: ' . $string;
     }
     if (!empty($this->settings['_supressMessages'])) {
         $this->messages[] = $string;
         return;
     }
     $this->out($string);
 }
 /**
  * Set as the default error handler by CakePHP. Use Configure::write('Error.handler', $callback), to use your own
  * error handling methods. This function will use Debugger to display errors when debug > 0. And
  * will log errors to CakeLog, when debug == 0.
  *
  * You can use Configure::write('Error.level', $value); to set what type of errors will be handled here.
  * Stack traces for errors can be enabled with Configure::write('Error.trace', true);
  *
  * @param int $code Code of error
  * @param string $description Error description
  * @param string $file File on which error occurred
  * @param int $line Line that triggered the error
  * @param array $context Context
  * @return bool true if error was handled
  */
 public static function handleError($code, $description, $file = null, $line = null, $context = null)
 {
     if (error_reporting() === 0) {
         return false;
     }
     $errorConfig = Configure::read('Error');
     list($error, $log) = static::mapErrorCode($code);
     if ($log === LOG_ERR) {
         return static::handleFatalError($code, $description, $file, $line);
     }
     $debug = Configure::read('debug');
     if ($debug) {
         $data = array('level' => $log, 'code' => $code, 'error' => $error, 'description' => $description, 'file' => $file, 'line' => $line, 'context' => $context, 'start' => 2, 'path' => Debugger::trimPath($file));
         return Debugger::getInstance()->outputError($data);
     }
     $message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
     if (!empty($errorConfig['trace'])) {
         // https://bugs.php.net/bug.php?id=65322
         if (version_compare(PHP_VERSION, '5.4.21', '<')) {
             if (!class_exists('Debugger')) {
                 App::load('Debugger');
             }
             if (!class_exists('CakeText')) {
                 App::uses('CakeText', 'Utility');
                 App::load('CakeText');
             }
         }
         $trace = Debugger::trace(array('start' => 1, 'format' => 'log'));
         $message .= "\nTrace:\n" . $trace . "\n";
     }
     return CakeLog::write($log, $message);
 }
Пример #22
0
 /**
  * jsPo method
  *
  * Parse js files for use of the (javascript) function __d('mi', ) and generate a javascript 'po' file.
  * will create app/vendors/i18n.<locale>.js files for each locale that exists in the app/locale dir
  *
  * @return void
  * @access protected
  */
 function _jsPo()
 {
     $Folder = new Folder(APP . 'locale');
     list($locales, $potFiles) = $Folder->read();
     if (!in_array('javascript.pot', $potFiles)) {
         $this->out(__d('mi', 'The javascript.pot file wasn\'t found - run cake mi_i18n to generate it', true));
         return;
     }
     if (defined('DEFAULT_LANGUAGE')) {
         $locales = array_unique(am(array(DEFAULT_LANGUAGE), $locales));
     }
     if (!class_exists('I18n')) {
         App::import('Core', 'i18n');
     }
     $messages = array();
     foreach ($locales as $locale) {
         if ($locale[0] === '.') {
             continue;
         }
         $data = Cache::read('javascript_' . $locale, '_cake_core_');
         if (!$data) {
             Configure::write('Config.language', $locale);
             __d('javascript', 'foo', true);
             $inst =& I18n::getInstance();
             Cache::write('javascript_' . $locale, array_filter($inst->__domains), '_cake_core_');
             $data = Cache::read('javascript_' . $locale, '_cake_core_');
             if (!$data) {
                 continue;
             }
         }
         foreach ($data as $type => $i) {
             foreach ($i[$locale]['javascript'] as $lookup => $string) {
                 if (!is_string($string)) {
                     continue;
                 }
                 if (!$string) {
                     $string = $lookup;
                 }
                 $messages[$lookup] = $string;
             }
         }
         ob_start();
         include dirname(__FILE__) . DS . 'templates' . DS . 'js' . DS . 'po.js';
         $contents = ob_get_clean();
         $targetFile = APP . 'vendors' . DS . 'js' . DS . 'i18n.' . $locale . '.js';
         $File = new File($targetFile);
         $File->write($contents);
         $this->out(Debugger::trimPath($targetFile) . ' written');
     }
 }