/** * 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'); } }
/** * testTokenize method * * @return void */ public function testTokenize() { $result = CakeText::tokenize('A,(short,boring test)'); $expected = array('A', '(short,boring test)'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('A,(short,more interesting( test)'); $expected = array('A', '(short,more interesting( test)'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('A,(short,very interesting( test))'); $expected = array('A', '(short,very interesting( test))'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('"single tag"', ' ', '"', '"'); $expected = array('"single tag"'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('tagA "single tag" tagB', ' ', '"', '"'); $expected = array('tagA', '"single tag"', 'tagB'); $this->assertEquals($expected, $result); // Ideographic width space. $result = CakeText::tokenize("tagA \"single tag\" tagB", " ", '"', '"'); $expected = array('tagA', '"single tag"', 'tagB'); $this->assertEquals($expected, $result); $result = CakeText::tokenize(''); $expected = array(); $this->assertEquals($expected, $result); }
/** * 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; }
/** * Generates the fields list of an SQL query. * * @param Model $Model The model to get fields for. * @param string $alias Alias table name * @param mixed $fields The provided list of fields. * @param bool $quote If false, returns fields array unquoted * @return array */ public function fields(Model $Model, $alias = null, $fields = array(), $quote = true) { if (empty($alias)) { $alias = $Model->alias; } $virtualFields = $Model->getVirtualField(); $cacheKey = array($alias, get_class($Model), $Model->alias, $virtualFields, $fields, $quote, ConnectionManager::getSourceName($this), $Model->schemaName, $Model->table); $cacheKey = md5(serialize($cacheKey)); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } $allFields = empty($fields); if ($allFields) { $fields = array_keys($Model->schema()); } elseif (!is_array($fields)) { $fields = CakeText::tokenize($fields); } $fields = array_values(array_filter($fields)); $allFields = $allFields || in_array('*', $fields) || in_array($Model->alias . '.*', $fields); $virtual = array(); if (!empty($virtualFields)) { $virtualKeys = array_keys($virtualFields); foreach ($virtualKeys as $field) { $virtualKeys[] = $Model->alias . '.' . $field; } $virtual = $allFields ? $virtualKeys : array_intersect($virtualKeys, $fields); foreach ($virtual as $i => $field) { if (strpos($field, '.') !== false) { $virtual[$i] = str_replace($Model->alias . '.', '', $field); } $fields = array_diff($fields, array($field)); } $fields = array_values($fields); } if (!$quote) { if (!empty($virtual)) { $fields = array_merge($fields, $this->_constructVirtualFields($Model, $alias, $virtual)); } return $fields; } $count = count($fields); if ($count >= 1 && !in_array($fields[0], array('*', 'COUNT(*)'))) { for ($i = 0; $i < $count; $i++) { if (is_string($fields[$i]) && in_array($fields[$i], $virtual)) { unset($fields[$i]); continue; } if (is_object($fields[$i]) && isset($fields[$i]->type) && $fields[$i]->type === 'expression') { $fields[$i] = $fields[$i]->value; } elseif (preg_match('/^\\(.*\\)\\s' . $this->alias . '.*/i', $fields[$i])) { continue; } elseif (!preg_match('/^.+\\(.*\\)/', $fields[$i])) { $prepend = ''; if (strpos($fields[$i], 'DISTINCT') !== false) { $prepend = 'DISTINCT '; $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i])); } $dot = strpos($fields[$i], '.'); if ($dot === false) { $prefix = !(strpos($fields[$i], ' ') !== false || strpos($fields[$i], '(') !== false); $fields[$i] = $this->name(($prefix ? $alias . '.' : '') . $fields[$i]); } else { if (strpos($fields[$i], ',') === false) { $build = explode('.', $fields[$i]); if (!Hash::numeric($build)) { $fields[$i] = $this->name(implode('.', $build)); } } } $fields[$i] = $prepend . $fields[$i]; } elseif (preg_match('/\\(([\\.\\w]+)\\)/', $fields[$i], $field)) { if (isset($field[1])) { if (strpos($field[1], '.') === false) { $field[1] = $this->name($alias . '.' . $field[1]); } else { $field[0] = explode('.', $field[1]); if (!Hash::numeric($field[0])) { $field[0] = implode('.', array_map(array(&$this, 'name'), $field[0])); $fields[$i] = preg_replace('/\\(' . $field[1] . '\\)/', '(' . $field[0] . ')', $fields[$i], 1); } } } } } } if (!empty($virtual)) { $fields = array_merge($fields, $this->_constructVirtualFields($Model, $alias, $virtual)); } return $this->cacheMethod(__FUNCTION__, $cacheKey, array_unique($fields)); }
/** * 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']); }
/** * 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; }
/** * 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(); }
/** * Overwrite the schema.php file * * @return void */ protected function _overwriteSchema() { $options = array(); if ($this->params['force']) { $options['models'] = false; } elseif (!empty($this->params['models'])) { $options['models'] = CakeText::tokenize($this->params['models']); } $cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', true); $content = $this->Schema->read($options); $file = 'schema.php'; 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 ($this->Schema->write($content)) { $this->out(__d('cake_console', 'Schema file: %s generated', $file)); return $this->_stop(); } $this->err(__d('cake_console', 'Schema file: %s generated')); return $this->_stop(); }
/** * Generate ResultSet * * @param mixed $results The results to modify. * @return void */ public function resultSet($results) { $this->results = $results; $this->map = array(); $numFields = $results->columnCount(); $index = 0; $j = 0; // PDO::getColumnMeta is experimental and does not work with sqlite3, // so try to figure it out based on the querystring $querystring = $results->queryString; if (stripos($querystring, 'SELECT') === 0 && stripos($querystring, 'FROM') > 0) { $selectpart = substr($querystring, 7); $selects = array(); foreach (CakeText::tokenize($selectpart, ',', '(', ')') as $part) { $fromPos = stripos($part, ' FROM '); if ($fromPos !== false) { $selects[] = trim(substr($part, 0, $fromPos)); break; } $selects[] = $part; } } elseif (strpos($querystring, 'PRAGMA table_info') === 0) { $selects = array('cid', 'name', 'type', 'notnull', 'dflt_value', 'pk'); } elseif (strpos($querystring, 'PRAGMA index_list') === 0) { $selects = array('seq', 'name', 'unique'); } elseif (strpos($querystring, 'PRAGMA index_info') === 0) { $selects = array('seqno', 'cid', 'name'); } while ($j < $numFields) { if (!isset($selects[$j])) { $j++; continue; } if (preg_match('/\\bAS(?!.*\\bAS\\b)\\s+(.*)/i', $selects[$j], $matches)) { $columnName = trim($matches[1], '"'); } else { $columnName = trim(str_replace('"', '', $selects[$j])); } if (strpos($selects[$j], 'DISTINCT') === 0) { $columnName = str_ireplace('DISTINCT', '', $columnName); } $metaType = false; try { $metaData = (array) $results->getColumnMeta($j); if (!empty($metaData['sqlite:decl_type'])) { $metaType = trim($metaData['sqlite:decl_type']); } } catch (Exception $e) { } if (strpos($columnName, '.')) { $parts = explode('.', $columnName); $this->map[$index++] = array(trim($parts[0]), trim($parts[1]), $metaType); } else { $this->map[$index++] = array(0, $columnName, $metaType); } $j++; } }
/** * testTokenize method * * @return void */ public function testTokenize() { $result = CakeText::tokenize('A,(short,boring test)'); $expected = array('A', '(short,boring test)'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('A,(short,more interesting( test)'); $expected = array('A', '(short,more interesting( test)'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('A,(short,very interesting( test))'); $expected = array('A', '(short,very interesting( test))'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('"single tag"', ' ', '"', '"'); $expected = array('"single tag"'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('tagA "single tag" tagB', ' ', '"', '"'); $expected = array('tagA', '"single tag"', 'tagB'); $this->assertEquals($expected, $result); $result = CakeText::tokenize(''); $expected = array(); $this->assertEquals($expected, $result); }
/** * CakeText::tokenizeをSiteSetting用に修正 * * @param string $keyPath Hashクラスのpath * @return array */ protected static function _tokenize($keyPath) { $pathes = CakeText::tokenize($keyPath, '.', '[', ']'); $pathes = preg_replace('/[\\[\\]]/', '', $pathes); return $pathes; }
/** * Takes list of items and transforms it into an array * + cleaning (trim, no empty parts, etc). * Similar to CakeText::tokenize, but with more logic. * * //TODO: 3.4. parameter as array, move to Lib * * @deprecated Will be removed in 1.0. * @param string $string containing the parts * @param string $separator (defaults to ',') * @param bool $camelize (true/false): problems with äöüß etc! * @return array Results as list */ public function parseList($string, $separator = null, $camelize = false, $capitalize = true) { if ($separator === null) { $separator = ','; } // parses the list, but leaves tokens untouched inside () brackets $stringArray = CakeText::tokenize($string, $separator); $returnArray = []; if (empty($stringArray)) { return []; } foreach ($stringArray as $t) { $t = trim($t); if (!empty($t)) { if ($camelize === true) { $t = mb_strtolower($t); $t = Inflector::camelize(Inflector::underscore($t)); // problems with non-alpha chars! } elseif ($capitalize === true) { $t = ucwords($t); } $returnArray[] = $t; } } return $returnArray; }