/** * Prints calculated results * * @param array $times Array of time values * @return void */ protected function _results($times) { $duration = array_sum($times); $requests = count($times); $this->out(CakeText::insert(__d('debug_kit', 'Total Requests made: :requests'), compact('requests'))); $this->out(CakeText::insert(__d('debug_kit', 'Total Time elapsed: :duration (seconds)'), compact('duration'))); $this->out(""); $this->out(CakeText::insert(__d('debug_kit', 'Requests/Second: :rps req/sec'), array('rps' => round($requests / $duration, 3)))); $this->out(CakeText::insert(__d('debug_kit', 'Average request time: :average-time seconds'), array('average-time' => round($duration / $requests, 3)))); $this->out(CakeText::insert(__d('debug_kit', 'Standard deviation of average request time: :std-dev'), array('std-dev' => round($this->_deviation($times, true), 3)))); $this->out(CakeText::insert(__d('debug_kit', 'Longest/shortest request: :longest sec/:shortest sec'), array('longest' => round(max($times), 3), 'shortest' => round(min($times), 3)))); $this->out(""); }
/** * @author Reed Dadoune * distanceQuery * A genral case distance query builder * Pass a number of options to this function and recieve a query * you can pass to either the find or paginate functions to get * objects back by distance * * Example: * $query = $this->Model->distanceQuery(array( * 'lat' => 34.2746405, * 'lng' => -119.2290053 * )); * $query['conditions']['published'] = true; * $results = $this->Model->find('all', $query); * * @param array $opts Options * - lat The latitude coordinate of the center point * - lng The longitude coordinate of the center point * - alias The model name of the query this is for * defaults to the current model alias * - radius The distance to at which to find objects at * defaults to false in which case distance is calculated * only for the sort order * @return array A query that can be modified and passed to find or paginate */ public function distanceQuery($opts = array()) { $defaults = array('lat' => 0, 'lng' => 0, 'alias' => $this->alias, 'radius' => false); $opts = Set::merge($defaults, $opts); $query = array('fields' => array(CakeText::insert('3956 * 2 * ASIN(SQRT( POWER(SIN((:lat - ABS(:alias.lat)) * PI() / 180 / 2), 2) + COS(:lat * PI() / 180) * COS(ABS(:alias.lat) * PI() / 180) * POWER(SIN((:lng - :alias.lng) * PI() / 180 / 2), 2) )) AS distance', array('alias' => $opts['alias'], 'lat' => $opts['lat'], 'lng' => $opts['lng']))), 'order' => array('distance' => 'ASC')); if ($opts['radius']) { $longitudeLower = $opts['lng'] - $opts['radius'] / abs(cos(deg2rad($opts['lat'])) * 69); $longitudeUpper = $opts['lng'] + $opts['radius'] / abs(cos(deg2rad($opts['lat'])) * 69); $latitudeLower = $opts['lat'] - $opts['radius'] / 69; $latitudeUpper = $opts['lat'] + $opts['radius'] / 69; $query['conditions'] = array(String::insert(':alias.lat BETWEEN ? AND ?', array('alias' => $opts['alias'])) => array($latitudeLower, $latitudeUpper), String::insert(':alias.lng BETWEEN ? AND ?', array('alias' => $opts['alias'])) => array($longitudeLower, $longitudeUpper)); $query['group'] = sprintf('%s.id HAVING distance < %f', $opts['alias'], $opts['radius']); } return $query; }
/** * 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 * @link http://book.cakephp.org/2.0/en/development/debugging.html#Debugger::trace */ public static function trace($options = array()) { $self = Debugger::getInstance(); $defaults = array('depth' => 999, 'format' => $self->_outputFormat, 'args' => FALSE, 'start' => 0, 'scope' => NULL, 'exclude' => array('call_user_func_array', 'trigger_error')); $options = Hash::merge($defaults, $options); $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]); $signature = $reference = '[main]'; if (isset($backtrace[$i + 1])) { $next = array_merge($_trace, $backtrace[$i + 1]); $signature = $reference = $next['function']; if (!empty($next['class'])) { $signature = $next['class'] . '::' . $next['function']; $reference = $signature . '('; if ($options['args'] && isset($next['args'])) { $args = array(); foreach ($next['args'] as $arg) { $args[] = Debugger::exportVar($arg); } $reference .= implode(', ', $args); } $reference .= ')'; } } if (in_array($signature, $options['exclude'])) { 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($self->_templates[$options['format']]['traceLine'])) { $tpl = $self->_templates[$options['format']]['traceLine']; } else { $tpl = $self->_templates['base']['traceLine']; } $trace['path'] = static::trimPath($trace['file']); $trace['reference'] = $reference; unset($trace['object'], $trace['args']); $back[] = CakeText::insert($tpl, $trace, array('before' => '{:', 'after' => '}')); } } if ($options['format'] === 'array' || $options['format'] === 'points') { return $back; } return implode("\n", $back); }
/** * testReplaceWithQuestionMarkInString method * * @return void */ public function testReplaceWithQuestionMarkInString() { $string = ':a, :b and :c?'; $expected = '2 and 3?'; $result = CakeText::insert($string, array('b' => 2, 'c' => 3), array('clean' => true)); $this->assertEquals($expected, $result); }
/** * Extracts a Model.field identifier and an SQL condition operator from a string, formats * and inserts values, and composes them into an SQL snippet. * * @param string $key An SQL key snippet containing a field and optional SQL operator * @param mixed $value The value(s) to be inserted in the string * @param Model $Model Model object initiating the query * @return string */ protected function _parseKey($key, $value, Model $Model = null) { $operatorMatch = '/^(((' . implode(')|(', $this->_sqlOps); $operatorMatch .= ')\\x20?)|<[>=]?(?![^>]+>)\\x20?|[>=!]{1,3}(?!<)\\x20?)/is'; $bound = strpos($key, '?') !== false || is_array($value) && strpos($key, ':') !== false; $key = trim($key); if (strpos($key, ' ') === false) { $operator = '='; } else { list($key, $operator) = explode(' ', $key, 2); if (!preg_match($operatorMatch, trim($operator)) && strpos($operator, ' ') !== false) { $key = $key . ' ' . $operator; $split = strrpos($key, ' '); $operator = substr($key, $split); $key = substr($key, 0, $split); } } $virtual = false; $type = null; if ($Model !== null) { if ($Model->isVirtualField($key)) { $key = $this->_quoteFields($Model->getVirtualField($key)); $virtual = true; } $type = $Model->getColumnType($key); } $null = $value === null || is_array($value) && empty($value); if (strtolower($operator) === 'not') { $data = $this->conditionKeysToString(array($operator => array($key => $value)), true, $Model); return $data[0]; } $value = $this->value($value, $type); if (!$virtual && $key !== '?') { $isKey = strpos($key, '(') !== false || strpos($key, ')') !== false || strpos($key, '|') !== false; $key = $isKey ? $this->_quoteFields($key) : $this->name($key); } if ($bound) { return CakeText::insert($key . ' ' . trim($operator), $value); } if (!preg_match($operatorMatch, trim($operator))) { $operator .= is_array($value) ? ' IN' : ' ='; } $operator = trim($operator); if (is_array($value)) { $value = implode(', ', $value); switch ($operator) { case '=': $operator = 'IN'; break; case '!=': case '<>': $operator = 'NOT IN'; break; } $value = "({$value})"; } elseif ($null || $value === 'NULL') { switch ($operator) { case '=': $operator = 'IS'; break; case '!=': case '<>': $operator = 'IS NOT'; break; } } if ($virtual) { return "({$key}) {$operator} {$value}"; } return "{$key} {$operator} {$value}"; }
/** * Takes a processed array of data from an error and displays it in the chosen format. * * @param string $data Data to output. * @return void */ public function outputError($data) { $defaults = array('level' => 0, 'error' => 0, 'code' => 0, 'description' => '', 'file' => '', 'line' => 0, 'context' => array(), 'start' => 2); $data += $defaults; $files = $this->trace(array('start' => $data['start'], 'format' => 'points')); $code = ''; $file = null; if (isset($files[0]['file'])) { $file = $files[0]; } elseif (isset($files[1]['file'])) { $file = $files[1]; } if ($file) { $code = $this->excerpt($file['file'], $file['line'] - 1, 1); } $trace = $this->trace(array('start' => $data['start'], 'depth' => '20')); $insertOpts = array('before' => '{:', 'after' => '}'); $context = array(); $links = array(); $info = ''; foreach ((array) $data['context'] as $var => $value) { $context[] = "\${$var} = " . $this->exportVar($value, 3); } switch ($this->_outputFormat) { case false: $this->_data[] = compact('context', 'trace') + $data; return; case 'log': $this->log(compact('context', 'trace') + $data); return; } $data['trace'] = $trace; $data['id'] = 'cakeErr' . uniqid(); $tpl = array_merge($this->_templates['base'], $this->_templates[$this->_outputFormat]); if (isset($tpl['links'])) { foreach ($tpl['links'] as $key => $val) { $links[$key] = CakeText::insert($val, $data, $insertOpts); } } if (!empty($tpl['escapeContext'])) { $context = h($context); } $infoData = compact('code', 'context', 'trace'); foreach ($infoData as $key => $value) { if (empty($value) || !isset($tpl[$key])) { continue; } if (is_array($value)) { $value = implode("\n", $value); } $info .= CakeText::insert($tpl[$key], array($key => $value) + $data, $insertOpts); } $links = implode(' ', $links); if (isset($tpl['callback']) && is_callable($tpl['callback'])) { return call_user_func($tpl['callback'], $data, compact('links', 'info')); } echo CakeText::insert($tpl['error'], compact('links', 'info') + $data, $insertOpts); }
/** * Callback used to display actions being performed * * @param CakeMigration &$Migration Migration being performed * @param string $type Type of action. i.e: create_table, drop_table, etc. * @param array $data Data to send to the callback * @return void */ public function beforeAction(&$Migration, $type, $data) { if (isset($this->_messages[$type])) { $message = CakeText::insert($this->_messages[$type], $data); $this->out(' > ' . $message); } }
/** * logQuery method * * Set timers, errors and refer to the parent * If there are arguments passed - inject them into the query * Show MongoIds in a copy-and-paste-into-mongo format * * * @param mixed $query * @param array $args array() * @return void * @access public */ public function logQuery($query, $args = array()) { if ($args) { $this->_stringify($args); $query = CakeText::insert($query, $args); } $this->took = round((microtime(true) - $this->_startTime) * 1000, 0); $this->affected = null; $this->numRows = !empty($args['count']) ? $args['count'] : null; $query = preg_replace('@"ObjectId\\((.*?)\\)"@', 'ObjectId ("\\1")', $query); return parent::logQuery($query); }
/** * logQuery method * * Set timers, errors and refer to the parent * If there are arguments passed - inject them into the query * Show MongoIds in a copy-and-paste-into-mongo format * * * @param mixed $query * @param array $args array() * @return void * @access public */ public function logQuery($query, $args = array()) { if ($args) { $this->_stringify($args); $query = CakeText::insert($query, $args); } $this->took = round((microtime(true) - $this->_startTime) * 1000, 0); $this->affected = null; if (empty($this->error['err'])) { $this->error = $this->_db->lastError(); if (!is_scalar($this->error)) { $this->error = json_encode($this->error); } } $this->numRows = !empty($args['count']) ? $args['count'] : null; $query = preg_replace('@"ObjectId\\((.*?)\\)"@', 'ObjectId ("\\1")', $query); return parent::logQuery($query); }
/** * Build url * * @return string url (full) */ protected function _url() { $params = ['host' => $this->options['host']]; $url = CakeText::insert(static::BASE_URL, $params, ['before' => '{', 'after' => '}', 'clean' => true]); return $url; }