/** * Sets the views meta data, if available * * @param array $data * @return void */ public function set($data = array()) { $Model = $this->__controller->{$this->__controller->modelClass}; // assign the meta title variable, starting with data assigned // directly to MetaData, falling back next to the Model displayField // variable before falling again to the Model displayName variable if (!empty($data['MetaData']['title'])) { $metaTitle = $data['MetaData']['title']; } elseif (!empty($data[$Model->alias][$Model->displayField])) { $metaTitle = $data[$Model->alias][$Model->displayField]; } else { $metaTitle = Inflector::pluralize($data[$Model->alias][$Model->displayName]); } if (!empty($metaTitle)) { $this->Controller->set(compact('metaTitle')); } // assign the meta description variable, starting with data // assigned directly to MetaData, falling back to content // and then body fields from within the supplied data if (!empty($data['MetaData']['description'])) { $metaDescription = $data['MetaData']['description']; } elseif (!empty($data[$Model->alias]['body'])) { // truncate the content variable to a max of 160 characters // ref: https://moz.com/learn/seo/meta-description $metaDescription = CakeText::truncate($data['MetaData']['description'], 160, array('html' => false)); } elseif (!empty($data[$Model->alias]['content'])) { // truncate the content variable to a max of 160 characters // ref: https://moz.com/learn/seo/meta-description $metaDescription = CakeText::truncate($data[$Model->alias]['content'], 160, array('html' => false)); } if (!empty($metaDescription)) { $this->Controller->set(compact('metaDescription')); } return; }
public function testGenerate() { $data = ['url' => 'http://www.spiegel.de', 'start' => '2010-10-09 22:23:34', 'end' => '2010-10-09 23:23:34', 'summary' => 'xyz', 'description' => 'xyz hjdhfj dhfäöüp e', 'organizer' => 'CEO', 'class' => 'public', 'timestamp' => '2010-10-08 22:23:34', 'id' => CakeText::uuid(), 'location' => 'München']; $this->Ical->add($data); $this->Ical->add($data); $res = $this->Ical->generate(); //pr($res); }
/** * 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(""); }
/** * testAddWithPreSpecifiedId method * * @return void */ public function testAddWithPreSpecifiedId() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1'))); $id = CakeText::uuid(); $this->Tree->create(); $result = $this->Tree->save(array($modelClass => array('id' => $id, 'name' => 'testAddMiddle', $parentField => $data[$modelClass]['id']))); $expected = array_merge(array($modelClass => array('id' => $id, 'name' => 'testAddMiddle', $parentField => '2')), $result); $this->assertSame($expected, $result); $this->assertTrue($this->Tree->verify()); }
/** * Main execution function to indent a folder recursivly * * @return void */ public function folder() { if (!empty($this->params['extensions'])) { $this->settings['files'] = CakeText::tokenize($this->params['extensions']); } if (!empty($this->params['again'])) { $this->settings['againWithHalf'] = true; } if (!empty($this->args)) { if (!empty($this->args[0]) && $this->args[0] !== 'app') { $folder = $this->args[0]; if ($folder === '/') { $folder = APP; } $folder = realpath($folder); if (!file_exists($folder)) { return $this->error('folder not exists: ' . $folder . ''); } $this->_paths[] = $folder; } elseif ($this->args[0] === 'app') { $this->_paths[] = APP; } if (!empty($this->params['files'])) { $this->settings['files'] = explode(',', $this->params['files']); } $this->out($folder); $this->out('searching...'); $this->_searchFiles(); $this->out('found: ' . count($this->_files)); if (!empty($this->params['dry-run'])) { $this->out('TEST DONE'); } else { $continue = $this->in('Modifying files! Continue?', ['y', 'n'], 'n'); if (strtolower($continue) !== 'y' && strtolower($continue) !== 'yes') { return $this->error('...aborted'); } $this->_correctFiles(); $this->out('DONE'); } } else { $this->out('Usage: cake intend folder'); $this->out('"folder" is then intended recursivly'); $this->out('default file types are'); $this->out('[' . implode(', ', $this->settings['files']) . ']'); $this->out(''); $this->out('Specify file types manually:'); $this->out('-files php,js,css'); } }
/** * @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; }
protected function populateInfo($userid) { // Fetch user info if (is_array($userid)) { $userinfo = $userid; } else { $userinfo = $this->User->findById($userid); } if (empty($userinfo)) { throw new InternalErrorException('Unknown UserID.'); } // Destroy the current session (if any) $this->Session->destroy(); // Verify the account is enabled/not expired if ($userinfo['User']['active'] != 1) { $this->redirect('/?account_disabled'); } // Generate logout token $userinfo['User']['logout_token'] = Security::hash(CakeText::uuid()); // Clean the password (remove it from the array) unset($userinfo['User']['password']); // Set the new information $this->Session->write($userinfo); // Update our arrays $this->userinfo = $userinfo['User']; $this->groupinfo = $userinfo['Group']; }
protected function populateInfo($userid) { // Fetch user info $userinfo = $this->User->findById($userid); if (empty($userinfo)) { throw new InternalErrorException('Unknown UserID.'); } // Save specific info from the current session (if exists) $emulating = $this->Session->read('User.emulating'); $emulating_from = -1; if ($emulating) { $emulating_from = $this->Session->read('User.emulating_from'); } // Destroy the current session (if any) $this->Session->destroy(); // Verify the account is enabled/not expired if ($userinfo['User']['active'] != 1) { $this->redirect('/?account_disabled'); } if ($userinfo['User']['expires'] != 0 && $userinfo['User']['expires'] <= time()) { $this->redirect('/?account_expired'); } // Generate logout token $userinfo['User']['logout_token'] = Security::hash(CakeText::uuid()); // Generate refresh interval (5 minutes) $userinfo['User']['refresh_info'] = time() + self::REFRESH_INTERVAL; // Add the emulating information $userinfo['User']['emulating'] = $emulating; $userinfo['User']['emulating_from'] = $emulating_from; // Fetch the team/group info $teaminfo = $this->Team->findById($userinfo['User']['team_id']); // Clean the password (remove it from the array) unset($userinfo['User']['password']); // Set the new information $this->Session->write($userinfo); $this->Session->write($teaminfo); // Update our arrays $this->userinfo = $userinfo['User']; $this->teaminfo = $teaminfo['Team']; $this->groupinfo = $teaminfo['Group']; }
/** * Generate String representation of Records * * @param array $tableInfo Table schema array * @param int $recordCount The number of records to generate. * @return array Array of records to use in the fixture. */ protected function _generateRecords($tableInfo, $recordCount = 1) { $records = array(); for ($i = 0; $i < $recordCount; $i++) { $record = array(); foreach ($tableInfo as $field => $fieldInfo) { if (empty($fieldInfo['type'])) { continue; } $insert = ''; switch ($fieldInfo['type']) { case 'integer': case 'float': $insert = $i + 1; break; case 'string': case 'binary': $isPrimaryUuid = isset($fieldInfo['key']) && strtolower($fieldInfo['key']) === 'primary' && isset($fieldInfo['length']) && $fieldInfo['length'] == 36; if ($isPrimaryUuid) { $insert = CakeText::uuid(); } else { $insert = "Lorem ipsum dolor sit amet"; if (!empty($fieldInfo['length'])) { $insert = substr($insert, 0, (int) $fieldInfo['length'] - 2); } } break; case 'timestamp': $insert = time(); break; case 'datetime': $insert = date('Y-m-d H:i:s'); break; case 'date': $insert = date('Y-m-d'); break; case 'time': $insert = date('H:i:s'); break; case 'boolean': $insert = 1; break; case 'text': $insert = "Lorem ipsum dolor sit amet, aliquet feugiat."; $insert .= " Convallis morbi fringilla gravida,"; $insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin"; $insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla"; $insert .= " vestibulum massa neque ut et, id hendrerit sit,"; $insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus"; $insert .= " duis vestibulum nunc mattis convallis."; break; } $record[$field] = $insert; } $records[] = $record; } return $records; }
/** * test wrap() indenting * * @return void */ public function testWrapIndent() { $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.'; $result = CakeText::wrap($text, array('width' => 33, 'indent' => "\t", 'indentAt' => 1)); $expected = <<<TEXT This is the song that never ends. \tThis is the song that never ends. \tThis is the song that never ends. TEXT; $this->assertTextEquals($expected, $result); }
/** * Generate authorization hash. * * @return string Hash */ public static function generateAuthKey() { return Security::hash(CakeText::uuid()); }
/** * 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}"; }
/** * Get list of headers * * ### Includes: * * - `from` * - `replyTo` * - `readReceipt` * - `returnPath` * - `to` * - `cc` * - `bcc` * - `subject` * * @param array $include List of headers. * @return array */ public function getHeaders($include = array()) { if ($include == array_values($include)) { $include = array_fill_keys($include, true); } $defaults = array_fill_keys(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), false); $include += $defaults; $headers = array(); $relation = array('from' => 'From', 'replyTo' => 'Reply-To', 'readReceipt' => 'Disposition-Notification-To', 'returnPath' => 'Return-Path'); foreach ($relation as $var => $header) { if ($include[$var]) { $var = '_' . $var; $headers[$header] = current($this->_formatAddress($this->{$var})); } } if ($include['sender']) { if (key($this->_sender) === key($this->_from)) { $headers['Sender'] = ''; } else { $headers['Sender'] = current($this->_formatAddress($this->_sender)); } } foreach (array('to', 'cc', 'bcc') as $var) { if ($include[$var]) { $classVar = '_' . $var; $headers[ucfirst($var)] = implode(', ', $this->_formatAddress($this->{$classVar})); } } $headers += $this->_headers; if (!isset($headers['X-Mailer'])) { $headers['X-Mailer'] = static::EMAIL_CLIENT; } if (!isset($headers['Date'])) { $headers['Date'] = date(DATE_RFC2822); } if ($this->_messageId !== false) { if ($this->_messageId === true) { $headers['Message-ID'] = '<' . str_replace('-', '', CakeText::UUID()) . '@' . $this->_domain . '>'; } else { $headers['Message-ID'] = $this->_messageId; } } if ($include['subject']) { $headers['Subject'] = $this->_subject; } $headers['MIME-Version'] = '1.0'; if (!empty($this->_attachments)) { $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"'; } elseif ($this->_emailFormat === 'both') { $headers['Content-Type'] = 'multipart/alternative; boundary="' . $this->_boundary . '"'; } elseif ($this->_emailFormat === 'text') { $headers['Content-Type'] = 'text/plain; charset=' . $this->_getContentTypeCharset(); } elseif ($this->_emailFormat === 'html') { $headers['Content-Type'] = 'text/html; charset=' . $this->_getContentTypeCharset(); } $headers['Content-Transfer-Encoding'] = $this->_getContentTransferEncoding(); return $headers; }
/** * Gets a value from an array or object that is contained in a given path using an array path syntax, i.e.: * "{n}.Person.{[a-z]+}" - Where "{n}" represents a numeric key, "Person" represents a string literal, * and "{[a-z]+}" (i.e. any string literal enclosed in brackets besides {n} and {s}) is interpreted as * a regular expression. * * @param array $data Array from where to extract * @param string|array $path As an array, or as a dot-separated string. * @return mixed An array of matched items or the content of a single selected item or null in any of these cases: $path or $data are null, no items found. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::classicExtract */ public static function classicExtract($data, $path = null) { if (empty($path)) { return $data; } if (is_object($data)) { if (!($data instanceof ArrayAccess || $data instanceof Traversable)) { $data = get_object_vars($data); } } if (empty($data)) { return null; } if (is_string($path) && strpos($path, '{') !== false) { $path = CakeText::tokenize($path, '.', '{', '}'); } elseif (is_string($path)) { $path = explode('.', $path); } $tmp = array(); if (empty($path)) { return null; } foreach ($path as $i => $key) { if (is_numeric($key) && (int) $key > 0 || $key === '0') { if (isset($data[$key])) { $data = $data[$key]; } else { return null; } } elseif ($key === '{n}') { foreach ($data as $j => $val) { if (is_int($j)) { $tmpPath = array_slice($path, $i + 1); if (empty($tmpPath)) { $tmp[] = $val; } else { $tmp[] = Set::classicExtract($val, $tmpPath); } } } return $tmp; } elseif ($key === '{s}') { foreach ($data as $j => $val) { if (is_string($j)) { $tmpPath = array_slice($path, $i + 1); if (empty($tmpPath)) { $tmp[] = $val; } else { $tmp[] = Set::classicExtract($val, $tmpPath); } } } return $tmp; } elseif (strpos($key, '{') !== false && strpos($key, '}') !== false) { $pattern = substr($key, 1, -1); foreach ($data as $j => $val) { if (preg_match('/^' . $pattern . '/s', $j) !== 0) { $tmpPath = array_slice($path, $i + 1); if (empty($tmpPath)) { $tmp[$j] = $val; } else { $tmp[$j] = Set::classicExtract($val, $tmpPath); } } } return $tmp; } else { if (isset($data[$key])) { $data = $data[$key]; } else { return null; } } } return $data; }
/** * Gets the values from an array matching the $path expression. * The path expression is a dot separated expression, that can contain a set * of patterns and expressions: * * - `{n}` Matches any numeric key, or integer. * - `{s}` Matches any string key. * - `{*}` Matches any value. * - `Foo` Matches any key with the exact same value. * * There are a number of attribute operators: * * - `=`, `!=` Equality. * - `>`, `<`, `>=`, `<=` Value comparison. * - `=/.../` Regular expression pattern match. * * Given a set of User array data, from a `$User->find('all')` call: * * - `1.User.name` Get the name of the user at index 1. * - `{n}.User.name` Get the name of every user in the set of users. * - `{n}.User[id]` Get the name of every user with an id key. * - `{n}.User[id>=2]` Get the name of every user with an id key greater than or equal to 2. * - `{n}.User[username=/^paul/]` Get User elements with username matching `^paul`. * * @param array $data The data to extract from. * @param string $path The path to extract. * * @return array An array of the extracted values. Returns an empty array * if there are no matches. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::extract */ public static function extract(array $data, $path) { if (empty($path)) { return $data; } // Simple paths. if (!preg_match('/[{\\[]/', $path)) { return (array) static::get($data, $path); } if (strpos($path, '[') === FALSE) { $tokens = explode('.', $path); } else { $tokens = CakeText::tokenize($path, '.', '[', ']'); } $_key = '__set_item__'; $context = array($_key => array($data)); foreach ($tokens as $token) { $next = array(); list($token, $conditions) = static::_splitConditions($token); foreach ($context[$_key] as $item) { foreach ((array) $item as $k => $v) { if (static::_matchToken($k, $token)) { $next[] = $v; } } } // Filter for attributes. if ($conditions) { $filter = array(); foreach ($next as $item) { if (is_array($item) && static::_matches($item, $conditions)) { $filter[] = $item; } } $next = $filter; } $context = array($_key => $next); } return $context[$_key]; }
public function _fromList(Model $Model, $val) { extract($this->settings[$Model->alias]); return CakeText::tokenize($val, $separator, $leftBound, $rightBound); }
/** * Read database and Write schema object * accepts a connection as first arg or path to save as second arg * * @return void */ public function generate() { $this->out(__d('cake_console', 'Generating Schema...')); $options = array(); if ($this->params['force']) { $options['models'] = false; } elseif (!empty($this->params['models'])) { $options['models'] = CakeText::tokenize($this->params['models']); } $snapshot = false; if (isset($this->args[0]) && $this->args[0] === 'snapshot') { $snapshot = true; } if (!$snapshot && file_exists($this->Schema->path . DS . $this->params['file'])) { $snapshot = true; $prompt = __d('cake_console', "Schema file exists.\n [O]verwrite\n [S]napshot\n [Q]uit\nWould you like to do?"); $result = strtolower($this->in($prompt, array('o', 's', 'q'), 's')); if ($result === 'q') { return $this->_stop(); } if ($result === 'o') { $snapshot = false; } } $cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', true); $content = $this->Schema->read($options); $content['file'] = $this->params['file']; Configure::write('Cache.disable', $cacheDisable); if (!empty($this->params['exclude']) && !empty($content)) { $excluded = CakeText::tokenize($this->params['exclude']); foreach ($excluded as $table) { unset($content['tables'][$table]); } } if ($snapshot === true) { $fileName = basename($this->params['file'], '.php'); $Folder = new Folder($this->Schema->path); $result = $Folder->read(); $numToUse = false; if (isset($this->params['snapshot'])) { $numToUse = $this->params['snapshot']; } $count = 0; if (!empty($result[1])) { foreach ($result[1] as $file) { if (preg_match('/' . preg_quote($fileName) . '(?:[_\\d]*)?\\.php$/', $file)) { $count++; } } } if ($numToUse !== false) { if ($numToUse > $count) { $count = $numToUse; } } $content['file'] = $fileName . '_' . $count . '.php'; } if ($this->Schema->write($content)) { $this->out(__d('cake_console', 'Schema file: %s generated', $content['file'])); return $this->_stop(); } $this->err(__d('cake_console', 'Schema file: %s generated')); return $this->_stop(); }
/** * 改行処理 と テキストのブロックを決められた幅で折り返す * * @param string $text 文字列 * @return string 文字列 */ private function __textBrAndWrap($text) { $text = str_replace(array("\r\n", "\r"), "\n", $text); // テキストのブロックを決められた幅で折り返す(各行末空白も自動削除する) // http://book.cakephp.org/2.0/ja/core-utility-libraries/string.html#CakeText::wrap $text = CakeText::wrap($text, $this::MAX_LINE_LENGTH); return $text; }
/** * Looks for a skeleton template of a Cake application, * and if not found asks the user for a path. When there is a path * this method will make a deep copy of the skeleton to the project directory. * * @param string $path Project path * @param string $skel Path to copy from * @param string $skip array of directories to skip when copying * @return mixed */ public function bake($path, $skel = null, $skip = array('empty')) { if (!$skel && !empty($this->params['skel'])) { $skel = $this->params['skel']; } while (!$skel) { $skel = $this->in(__d('cake_console', "What is the path to the directory layout you wish to copy?"), null, CAKE . 'Console' . DS . 'Templates' . DS . 'skel'); if (!$skel) { $this->err(__d('cake_console', 'The directory path you supplied was empty. Please try again.')); } else { while (is_dir($skel) === false) { $skel = $this->in(__d('cake_console', 'Directory path does not exist please choose another:'), null, CAKE . 'Console' . DS . 'Templates' . DS . 'skel'); } } } $app = basename($path); $this->out(__d('cake_console', '<info>Skel Directory</info>: ') . $skel); $this->out(__d('cake_console', '<info>Will be copied to</info>: ') . $path); $this->hr(); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n', 'q'), 'y'); switch (strtolower($looksGood)) { case 'y': $Folder = new Folder($skel); if (!empty($this->params['empty'])) { $skip = array(); } if ($Folder->copy(array('to' => $path, 'skip' => $skip))) { $this->hr(); $this->out(__d('cake_console', '<success>Created:</success> %s in %s', $app, $path)); $this->hr(); } else { $this->err(__d('cake_console', "<error>Could not create</error> '%s' properly.", $app)); return false; } foreach ($Folder->messages() as $message) { $this->out(CakeText::wrap(' * ' . $message), 1, Shell::VERBOSE); } return true; case 'n': unset($this->args[0]); $this->execute(); return false; case 'q': $this->out(__d('cake_console', '<error>Bake Aborted.</error>')); return false; } }
/** * Remove data matching $path from the $data array. * You can use `{n}` and `{s}` to remove multiple elements * from $data. * * @param array $data The data to operate on * @param string $path A path expression to use to remove. * @return array The modified array. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::remove */ public static function remove(array $data, $path) { if (strpos($path, '[') === false) { $tokens = explode('.', $path); } else { $tokens = CakeText::tokenize($path, '.', '[', ']'); } if (strpos($path, '{') === false && strpos($path, '[') === false) { return static::_simpleOp('remove', $data, $tokens); } $token = array_shift($tokens); $nextPath = implode('.', $tokens); list($token, $conditions) = static::_splitConditions($token); foreach ($data as $k => $v) { $match = static::_matchToken($k, $token); if ($match && is_array($v)) { if ($conditions && static::_matches($v, $conditions)) { unset($data[$k]); continue; } $data[$k] = static::remove($v, $nextPath); if (empty($data[$k])) { unset($data[$k]); } } elseif ($match && empty($nextPath)) { unset($data[$k]); } } return $data; }
/** * Get the help as formatted text suitable for output on the command line. * * @param int $width The width of the help output. * @return string */ public function text($width = 72) { $parser = $this->_parser; $out = array(); $description = $parser->description(); if (!empty($description)) { $out[] = CakeText::wrap($description, $width); $out[] = ''; } $out[] = __d('cake_console', '<info>Usage:</info>'); $out[] = $this->_generateUsage(); $out[] = ''; $subcommands = $parser->subcommands(); if (!empty($subcommands)) { $out[] = __d('cake_console', '<info>Subcommands:</info>'); $out[] = ''; $max = $this->_getMaxLength($subcommands) + 2; foreach ($subcommands as $command) { $out[] = CakeText::wrap($command->help($max), array('width' => $width, 'indent' => str_repeat(' ', $max), 'indentAt' => 1)); } $out[] = ''; $out[] = __d('cake_console', 'To see help on a subcommand use <info>`cake %s [subcommand] --help`</info>', $parser->command()); $out[] = ''; } $options = $parser->options(); if (!empty($options)) { $max = $this->_getMaxLength($options) + 8; $out[] = __d('cake_console', '<info>Options:</info>'); $out[] = ''; foreach ($options as $option) { $out[] = CakeText::wrap($option->help($max), array('width' => $width, 'indent' => str_repeat(' ', $max), 'indentAt' => 1)); } $out[] = ''; } $arguments = $parser->arguments(); if (!empty($arguments)) { $max = $this->_getMaxLength($arguments) + 2; $out[] = __d('cake_console', '<info>Arguments:</info>'); $out[] = ''; foreach ($arguments as $argument) { $out[] = CakeText::wrap($argument->help($max), array('width' => $width, 'indent' => str_repeat(' ', $max), 'indentAt' => 1)); } $out[] = ''; } $epilog = $parser->epilog(); if (!empty($epilog)) { $out[] = CakeText::wrap($epilog, $width); $out[] = ''; } return implode("\n", $out); }
/** * 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); }
/** * Wrap a block of text. * Allows you to set the width, and indenting on a block of text. * * ### Options * * - `width` The width to wrap to. Defaults to 72 * - `wordWrap` Only wrap on words breaks (spaces) Defaults to true. * - `indent` Indent the text with the string provided. Defaults to null. * * @param string $text Text the text to format. * @param string|int|array $options Array of options to use, or an integer to wrap the text to. * @return string Wrapped / indented text * @see CakeText::wrap() * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::wrapText */ public function wrapText($text, $options = array()) { return CakeText::wrap($text, $options); }
/** * Handles the before/after filter logic for find('list') operations. Only called by Model::find(). * * @param string $state Either "before" or "after" * @param array $query Query. * @param array $results Results. * @return array Key/value pairs of primary keys/display field values of all records found * @see Model::find() */ protected function _findList($state, $query, $results = array()) { if ($state === 'before') { if (empty($query['fields'])) { $query['fields'] = array("{$this->alias}.{$this->primaryKey}", "{$this->alias}.{$this->displayField}"); $list = array("{n}.{$this->alias}.{$this->primaryKey}", "{n}.{$this->alias}.{$this->displayField}", null); } else { if (!is_array($query['fields'])) { $query['fields'] = CakeText::tokenize($query['fields']); } if (count($query['fields']) === 1) { if (strpos($query['fields'][0], '.') === false) { $query['fields'][0] = $this->alias . '.' . $query['fields'][0]; } $list = array("{n}.{$this->alias}.{$this->primaryKey}", '{n}.' . $query['fields'][0], null); $query['fields'] = array("{$this->alias}.{$this->primaryKey}", $query['fields'][0]); } elseif (count($query['fields']) === 3) { for ($i = 0; $i < 3; $i++) { if (strpos($query['fields'][$i], '.') === false) { $query['fields'][$i] = $this->alias . '.' . $query['fields'][$i]; } } $list = array('{n}.' . $query['fields'][0], '{n}.' . $query['fields'][1], '{n}.' . $query['fields'][2]); } else { for ($i = 0; $i < 2; $i++) { if (strpos($query['fields'][$i], '.') === false) { $query['fields'][$i] = $this->alias . '.' . $query['fields'][$i]; } } $list = array('{n}.' . $query['fields'][0], '{n}.' . $query['fields'][1], null); } } if (!isset($query['recursive']) || $query['recursive'] === null) { $query['recursive'] = -1; } list($query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath']) = $list; return $query; } if (empty($results)) { return array(); } return Hash::combine($results, $query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath']); }
/** * beforeFind Callback * * @param Model $Model Model find is being run on. * @param array $query Array of Query parameters. * @return array Modified query */ public function beforeFind(Model $Model, $query) { $this->runtime[$Model->alias]['virtualFields'] = $Model->virtualFields; $locale = $this->_getLocale($Model); if (empty($locale)) { return $query; } $db = $Model->getDataSource(); $RuntimeModel = $this->translateModel($Model); if (!empty($RuntimeModel->tablePrefix)) { $tablePrefix = $RuntimeModel->tablePrefix; } else { $tablePrefix = $db->config['prefix']; } $joinTable = new StdClass(); $joinTable->tablePrefix = $tablePrefix; $joinTable->table = $RuntimeModel->table; $joinTable->schemaName = $RuntimeModel->getDataSource()->getSchemaName(); $this->_joinTable = $joinTable; $this->_runtimeModel = $RuntimeModel; $query['group'] = $Model->alias . '.id'; //Modified for request only one per Id if (is_string($query['fields']) && $query['fields'] === "COUNT(*) AS {$db->name('count')}") { $query['fields'] = "COUNT(DISTINCT({$db->name($Model->escapeField())})) {$db->alias}count"; $query['joins'][] = array('type' => 'INNER', 'alias' => $RuntimeModel->alias, 'table' => $joinTable, 'conditions' => array($Model->escapeField() => $db->identifier($RuntimeModel->escapeField('foreign_key')), $RuntimeModel->escapeField('model') => $Model->name, $RuntimeModel->escapeField('locale') => array($locale, Configure::read('webConfig.default_language')))); $conditionFields = $this->_checkConditions($Model, $query); foreach ($conditionFields as $field) { $query = $this->_addJoin($Model, $query, $field, $field, $locale); } unset($this->_joinTable, $this->_runtimeModel); return $query; } elseif (is_string($query['fields'])) { $query['fields'] = CakeText::tokenize($query['fields']); } $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); $addFields = array(); if (empty($query['fields'])) { $addFields = $fields; } elseif (is_array($query['fields'])) { $isAllFields = in_array($Model->alias . '.' . '*', $query['fields']) || in_array($Model->escapeField('*'), $query['fields']); foreach ($fields as $key => $value) { $field = is_numeric($key) ? $value : $key; if ($isAllFields || in_array($Model->alias . '.' . $field, $query['fields']) || in_array($field, $query['fields'])) { $addFields[] = $field; } } } $this->runtime[$Model->alias]['virtualFields'] = $Model->virtualFields; if ($addFields) { foreach ($addFields as $_f => $field) { $aliasField = is_numeric($_f) ? $field : $_f; foreach (array($aliasField, $Model->alias . '.' . $aliasField) as $_field) { $key = array_search($_field, (array) $query['fields']); if ($key !== false) { unset($query['fields'][$key]); } } $query = $this->_addJoin($Model, $query, $field, $aliasField, $locale); } } $this->runtime[$Model->alias]['beforeFind'] = $addFields; unset($this->_joinTable, $this->_runtimeModel); return $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; $this->numRows = !empty($args['count']) ? $args['count'] : null; $query = preg_replace('@"ObjectId\\((.*?)\\)"@', 'ObjectId ("\\1")', $query); return parent::logQuery($query); }
/** * Cleans up a CakeText::insert() formatted string with given $options depending on the 'clean' key in * $options. The default method used is text but html is also available. The goal of this function * is to replace all whitespace and unneeded markup around placeholders that did not get replaced * by CakeText::insert(). * * @param string $str CakeText to clean. * @param array $options Options list. * @return string * @see CakeText::insert() */ public static function cleanInsert($str, $options) { $clean = $options['clean']; if (!$clean) { return $str; } if ($clean === true) { $clean = array('method' => 'text'); } if (!is_array($clean)) { $clean = array('method' => $options['clean']); } switch ($clean['method']) { case 'html': $clean = array_merge(array('word' => '[\\w,.]+', 'andText' => true, 'replacement' => ''), $clean); $kleenex = sprintf('/[\\s]*[a-z]+=(")(%s%s%s[\\s]*)+\\1/i', preg_quote($options['before'], '/'), $clean['word'], preg_quote($options['after'], '/')); $str = preg_replace($kleenex, $clean['replacement'], $str); if ($clean['andText']) { $options['clean'] = array('method' => 'text'); $str = CakeText::cleanInsert($str, $options); } break; case 'text': $clean = array_merge(array('word' => '[\\w,.]+', 'gap' => '[\\s]*(?:(?:and|or)[\\s]*)?', 'replacement' => ''), $clean); $kleenex = sprintf('/(%s%s%s%s|%s%s%s%s)/', preg_quote($options['before'], '/'), $clean['word'], preg_quote($options['after'], '/'), $clean['gap'], $clean['gap'], preg_quote($options['before'], '/'), $clean['word'], preg_quote($options['after'], '/')); $str = preg_replace($kleenex, $clean['replacement'], $str); break; } return $str; }
/** * Add an inline attachment as blob * * Options: * - contentDisposition * * @param binary $content: blob data * @param string $filename to attach it * @param string $mimeType (leave it empty to get mimetype from $filename) * @param string $contentId (optional) * @param array $options Options * @return mixed resource $EmailLib or string $contentId */ public function addEmbeddedBlobAttachment($content, $filename, $mimeType = null, $contentId = null, $options = []) { if ($mimeType === null) { $ext = pathinfo($filename, PATHINFO_EXTENSION); $mimeType = $this->_getMimeByExtension($ext); } $options['content'] = $content; $options['mimetype'] = $mimeType; $options['contentId'] = $contentId ? $contentId : str_replace('-', '', CakeText::uuid()) . '@' . $this->_domain; $file = [$filename => $options]; $res = $this->addAttachments($file); if ($contentId === null) { return $options['contentId']; } return $res; }
/** * 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); }
/** * 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); } }