/** * ResetSlugs method. * * Regenerate all slugs. On large dbs this can take more than 30 seconds - a time * limit is set to allow a minimum 100 updates per second as a preventative measure. * * Note that you should use the Reset behavior if you need additional functionality such * as callbacks or timeouts. * * @param array $params * @return bool Success */ public function resetSlugs($params = []) { if (!$this->_table->hasField($this->_config['field'])) { throw new Exception('Table does not have field ' . $this->_config['field']); } $defaults = ['page' => 1, 'limit' => 100, 'fields' => array_merge([$this->_table->primaryKey()], $this->_config['label']), 'order' => $this->_table->displayField() . ' ASC', 'conditions' => $this->_config['scope'], 'overwrite' => true]; $params = array_merge($defaults, $params); $count = $this->_table->find('all', compact('conditions'))->count(); $max = ini_get('max_execution_time'); if ($max) { set_time_limit(max($max, $count / 100)); } $this->_table->behaviors()->Slugged->config($params, null, false); while ($records = $this->_table->find('all', $params)->toArray()) { foreach ($records as $record) { $record->isNew(true); $options = ['validate' => true, 'fieldList' => array_merge([$this->_table->primaryKey(), $this->_config['field']], $this->_config['label'])]; if (!$this->_table->save($record, $options)) { throw new Exception(print_r($this->_table->errors(), true)); } } $params['page']++; } return true; }
/** * Do some checks on the table which has been passed to make sure that it has what we need * * @param string $table The table * @return void */ protected function checkTable($table) { try { $this->Table = $this->loadModel($table); } catch (Exception $e) { $this->out(__('<error>' . $e->getMessage() . '</error>')); exit; } if (get_class($this->Table) === 'AppModel') { $this->out(__('<error>The table could not be found, instance of AppModel loaded.</error>')); exit; } if (!$this->Table->hasBehavior('Proffer')) { $out = __("<error>The table '" . $this->Table->alias() . "' does not have the Proffer behavior attached.</error>"); $this->out($out); exit; } $config = $this->Table->behaviors()->Proffer->config(); foreach ($config as $field => $settings) { if (!$this->Table->hasField($field)) { $out = __("<error>The table '" . $this->Table->alias() . "' does not have the configured upload field in it's schema.</error>"); $this->out($out); exit; } if (!$this->Table->hasField($settings['dir'])) { $out = __("<error>The table '" . $this->Table->alias() . "' does not have the configured dir field in it's schema.</error>"); $this->out($out); exit; } } }
/** * Gets the field(s) from the args and checks if they're present in the table. * * @param \Cake\ORM\Table $table Table object. * @return array Set of of fields explode()'ed from the args */ protected function _getFields(Table $table) { $fields = explode(',', $this->args[1]); foreach ($fields as $field) { if (!$table->hasField($field)) { $this->abort(sprintf('Table `%s` is missing the field `%s`.', $table->table(), $field)); } } return $fields; }
/** * Run before a model is saved. * * @param \Cake\Event\Event $event The event that was triggered * @param \Cake\ORM\Entity $entity The entity being saved * @param array $options Array of options for the save operation * @return bool True if save should proceed, false otherwise */ public function beforeSave(Event $event, $entity, $options = []) { if ($this->_table->hasField($this->config('createdByField')) || $this->_table->hasField($this->config('modifiedByField'))) { $userId = $this->_getUserId(); if ($userId > 0) { $entity->set($this->config('modifiedByField'), $userId); if ($entity->isNew()) { $entity->set($this->config('createdByField'), $userId); } } } return true; }
/** * Prefixes the field with the table alias if possible. * * @param \Cake\ORM\Table $object Table object. * @param array $order Order array. * @param bool $validate If field should be validated. Defaults to false. * @return array Final order array. */ protected function _prefix(Table $object, $order, $validate = false) { $tableAlias = $object->alias(); $tableOrder = []; foreach ($order as $key => $value) { $field = $key; $alias = $tableAlias; if (is_numeric($key)) { $tableOrder[] = $value; } else { if (strpos($key, '.') !== false) { list($alias, $field) = explode('.', $key); } $correctAlias = $tableAlias === $alias; if ($correctAlias && (!$validate || $object->hasField($field))) { $tableOrder[$tableAlias . '.' . $field] = $value; } } } return $tableOrder; }
/** * Validate that the desired sorting can be performed on the $object. Only fields or * virtualFields can be sorted on. The direction param will also be sanitized. Lastly * sort + direction keys will be converted into the model friendly order key. * * You can use the whitelist parameter to control which columns/fields are available for sorting. * This helps prevent users from ordering large result sets on un-indexed values. * * If you need to sort on associated columns or synthetic properties you will need to use a whitelist. * * Any columns listed in the sort whitelist will be implicitly trusted. You can use this to sort * on synthetic columns, or columns added in custom find operations that may not exist in the schema. * * @param Table $object The model being paginated. * @param array $options The pagination options being used for this request. * @return array An array of options with sort + direction removed and replaced with order if possible. */ public function validateSort(Table $object, array $options) { if (isset($options['sort'])) { $direction = null; if (isset($options['direction'])) { $direction = strtolower($options['direction']); } if (!in_array($direction, ['asc', 'desc'])) { $direction = 'asc'; } $options['order'] = [$options['sort'] => $direction]; } unset($options['sort'], $options['direction']); if (empty($options['order'])) { $options['order'] = []; } if (!is_array($options['order'])) { return $options; } if (!empty($options['sortWhitelist'])) { $field = key($options['order']); $inWhitelist = in_array($field, $options['sortWhitelist'], true); if (!$inWhitelist) { $options['order'] = []; } return $options; } $tableAlias = $object->alias(); $order = []; foreach ($options['order'] as $key => $value) { $field = $key; $alias = $tableAlias; if (is_numeric($key)) { $order[] = $value; } else { if (strpos($key, '.') !== false) { list($alias, $field) = explode('.', $key); } $correctAlias = $tableAlias === $alias; if ($correctAlias && $object->hasField($field)) { $order[$tableAlias . '.' . $field] = $value; } } } $options['order'] = $order; return $options; }
/** * Prefixes the field with the table alias if possible. * * @param \Cake\ORM\Table $object Table object. * @param array $order Order array. * @param bool $whitelisted Whether or not the field was whitelisted * @return array Final order array. */ protected function _prefix(Table $object, $order, $whitelisted = false) { $tableAlias = $object->alias(); $tableOrder = []; foreach ($order as $key => $value) { if (is_numeric($key)) { $tableOrder[] = $value; continue; } $field = $key; $alias = $tableAlias; if (strpos($key, '.') !== false) { list($alias, $field) = explode('.', $key); } $correctAlias = $tableAlias === $alias; if ($correctAlias && $whitelisted) { // Disambiguate fields in schema. As id is quite common. if ($object->hasField($field)) { $field = $alias . '.' . $field; } $tableOrder[$field] = $value; } elseif ($correctAlias && $object->hasField($field)) { $tableOrder[$tableAlias . '.' . $field] = $value; } elseif (!$correctAlias && $whitelisted) { $tableOrder[$alias . '.' . $field] = $value; } } return $tableOrder; }