/** * Initiate Tree behavior * * @param Model $Model instance of model * @param array $config array of configuration settings. * @return void */ public function setup(Model $Model, $config = array()) { if (isset($config[0])) { $config['type'] = $config[0]; unset($config[0]); } $settings = $config + $this->_defaults; if (in_array($settings['scope'], $Model->getAssociated('belongsTo'))) { $data = $Model->getAssociated($settings['scope']); $Parent = $Model->{$settings['scope']}; $settings['scope'] = $Model->escapeField($data['foreignKey']) . ' = ' . $Parent->escapeField(); $settings['recursive'] = 0; } $this->settings[$Model->alias] = $settings; }
/** * Initiate Tree behavior * * @param Model $Model instance of model * @param array $config array of configuration settings. * @return void */ public function setup($Model, $config = array()) { if (isset($config[0])) { $config['type'] = $config[0]; unset($config[0]); } $settings = array_merge($this->_defaults, $config); if (in_array($settings['scope'], $Model->getAssociated('belongsTo'))) { $data = $Model->getAssociated($settings['scope']); $parent = $Model->{$settings['scope']}; $settings['scope'] = $Model->alias . '.' . $data['foreignKey'] . ' = ' . $parent->alias . '.' . $parent->primaryKey; $settings['recursive'] = 0; } $this->settings[$Model->alias] = $settings; }
public function setup(Model $model, $config = array()) { if (empty($settings)) { $config = $model->getAssociated('hasAndBelongsToMany'); } foreach ((array) $config as $key) { $fieldName = $key; $this->settings[$model->alias][] = $fieldName; } }
/** * Setup HABTM relations * * @author Anthony Putignano <*****@*****.**> * @since 1.0 * @param Model $Model * @return void */ public function setupHabtmRelations(Model $Model) { $associated = $Model->getAssociated(); foreach ($this->__settings[$Model->alias]['fields'] as $field => $settings) { extract($settings); if (!array_key_exists($joinModel, $associated)) { // This relation takes care of deletions for us $Model->bindModel(array('hasMany' => array($joinModel => array('className' => $joinModel, 'foreignKey' => $foreignKey, 'dependent' => true, 'request' => true)))); } } }
/** * Is relation saveable or findeable? * * Checks to see if relation can be saved or fetched along with primary model * * @author Anthony Putignano <*****@*****.**> * @since 1.0 * @param Model $Model * @param string $relation Model alias of relation * @param string $operation `saveable` or `findable` * @return boolean */ private function __isRelationSaveableOrFindable(Model $Model, $relation = null, $operation = 'saveable') { $associations = $Model->getAssociated(); if (empty($associations[$relation])) { return false; } $settings = $Model->{$associations[$relation]}[$relation]; if (!array_key_exists($operation, $settings) || !empty($settings[$operation])) { return true; } return false; }
/** * Returns an array of SQL JOIN fragments from a model's associations * * @param Model $model * @return array */ protected function _getJoins($model) { $join = array(); $joins = array_merge($model->getAssociated('hasOne'), $model->getAssociated('belongsTo')); foreach ($joins as $assoc) { if (isset($model->{$assoc}) && $model->useDbConfig == $model->{$assoc}->useDbConfig && $model->{$assoc}->getDataSource()) { $assocData = $model->getAssociated($assoc); $join[] = $this->buildJoinStatement(array( 'table' => $model->{$assoc}, 'alias' => $assoc, 'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT', 'conditions' => trim($this->conditions( $this->_mergeConditions($assocData['conditions'], $this->getConstraint($assocData['association'], $model, $model->{$assoc}, $assoc, $assocData)), true, false, $model )) )); } } return $join; }
/** * Process a model recursively and pull out all the * model names converting them to fixture names. * * @param Model $subject A Model class to scan for associations and pull fixtures off of. * @return void * @access protected */ function _processModel(&$subject) { $this->_addFixture($subject->name); $associated = $subject->getAssociated(); foreach ($associated as $alias => $type) { $className = $subject->{$alias}->name; if (!isset($this->_fixtures[$className])) { $this->_processModel($subject->{$alias}); } if ($type == 'hasAndBelongsToMany') { $joinModel = Inflector::classify($subject->hasAndBelongsToMany[$alias]['joinTable']); if (!isset($this->_fixtures[$joinModel])) { $this->_processModel($subject->{$joinModel}); } } } }
/** * Returns an array of SQL JOIN conditions from a model's associations. * * @param Model $Model The model to get joins for.2 * @return array */ protected function _getJoins(Model $Model) { $join = array(); $joins = array_merge($Model->getAssociated('hasOne'), $Model->getAssociated('belongsTo')); foreach ($joins as $assoc) { if (!isset($Model->{$assoc})) { continue; } $LinkModel = $Model->{$assoc}; if ($Model->useDbConfig !== $LinkModel->useDbConfig) { continue; } $assocData = $Model->getAssociated($assoc); $join[] = $this->buildJoinStatement(array('table' => $LinkModel, 'alias' => $assoc, 'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT', 'conditions' => trim($this->conditions($this->_mergeConditions($assocData['conditions'], $this->getConstraint($assocData['association'], $Model, $LinkModel, $assoc, $assocData)), true, false, $Model)))); } return $join; }
/** * Parse the `contain` option of the query recursively * * @param Model $parent Parent model of the contained model * @param string $alias Alias of the contained model * @param array $contain Reformatted `contain` option for the deep associations * @param array|null $context Context * @return array * @throws InvalidArgumentException */ private function parseContain(Model $parent, $alias, array $contain, $context = null) { // @codingStandardsIgnoreLine if ($context === null) { $context = array('root' => $parent->alias, 'aliasPath' => $parent->alias, 'propertyPath' => '', 'forceExternal' => false); } $aliasPath = $context['aliasPath'] . '.' . $alias; $propertyPath = ($context['propertyPath'] ? $context['propertyPath'] . '.' : '') . $alias; $types = $parent->getAssociated(); if (!isset($types[$alias])) { throw new InvalidArgumentException(sprintf('Model "%s" is not associated with model "%s"', $parent->alias, $alias), E_USER_WARNING); } $parentAlias = $parent->alias; $target = $parent->{$alias}; $type = $types[$alias]; $relation = $parent->{$type}[$alias]; $options = $contain['options'] + array_intersect_key(Hash::filter($relation), $this->containOptions); $has = stripos($type, 'has') !== false; $many = stripos($type, 'many') !== false; $belong = stripos($type, 'belong') !== false; if ($has && $belong) { $parentKey = $parent->primaryKey; $targetKey = $target->primaryKey; $habtmAlias = $relation['with']; $habtm = $parent->{$habtmAlias}; $habtmParentKey = $relation['foreignKey']; $habtmTargetKey = $relation['associationForeignKey']; } elseif ($has) { $parentKey = $parent->primaryKey; $targetKey = $relation['foreignKey']; } else { $parentKey = $relation['foreignKey']; $targetKey = $target->primaryKey; } if (!empty($relation['external'])) { $external = true; } if (!empty($relation['finderQuery'])) { $finderQuery = $relation['finderQuery']; } $meta = compact('alias', 'parent', 'target', 'parentAlias', 'parentKey', 'targetKey', 'aliasPath', 'propertyPath', 'options', 'has', 'many', 'belong', 'external', 'finderQuery', 'habtm', 'habtmAlias', 'habtmParentKey', 'habtmTargetKey'); if ($this->isExternal($context, $meta)) { $meta['external'] = true; $context['root'] = $aliasPath; $context['propertyPath'] = $alias; $path = $context['aliasPath']; } else { $meta['external'] = false; if ($context['root'] !== $context['aliasPath']) { $meta['eager'] = true; } $context['propertyPath'] = $propertyPath; $path = $context['root']; } $this->metas[$path][] = $meta; $context['aliasPath'] = $aliasPath; $context['forceExternal'] = !empty($finderQuery); foreach ($contain['contain'] as $key => $val) { $this->parseContain($target, $key, $val, $context); } return $this->metas; }
/** * Revision uses the beforeSave callback to remember the old data for comparison in afterSave * * @param object $Model * @return boolean */ public function beforeSave(Model $Model, $options = array()) { if ($this->settings[$Model->alias]['auto'] === false) { return true; } if (!$Model->ShadowModel) { return true; } $Model->ShadowModel->create(); if (!isset($Model->data[$Model->alias][$Model->primaryKey]) && !$Model->id) { return true; } $habtm = array(); foreach ($Model->getAssociated('hasAndBelongsToMany') as $assocAlias) { if (isset($Model->ShadowModel->_schema[$assocAlias])) { $habtm[] = $assocAlias; } } $this->oldData[$Model->alias] = $Model->find('first', array('contain' => $habtm, 'conditions' => array($Model->alias . '.' . $Model->primaryKey => $Model->id))); return true; }
/** * Returns associations for controllers models. * * @param Model $model * @return array Associations for model */ protected function _associations(Model $model) { $associations = array(); $associated = $model->getAssociated(); foreach ($associated as $assocKey => $type) { if (!isset($associations[$type])) { $associations[$type] = array(); } $assocDataAll = $model->{$type}; $assocData = $assocDataAll[$assocKey]; $associatedModel = $model->{$assocKey}; $associations[$type][$assocKey]['primaryKey'] = $associatedModel->primaryKey; $associations[$type][$assocKey]['displayField'] = $associatedModel->displayField; $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey']; list($plugin, $modelClass) = pluginSplit($assocData['className']); if ($plugin) { $plugin = Inflector::underscore($plugin); } $associations[$type][$assocKey]['plugin'] = $plugin; $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($modelClass)); if ($type === 'hasAndBelongsToMany') { $associations[$type][$assocKey]['with'] = $assocData['with']; } } return $associations; }
/** * Check if the associated `modelName` to the `$model` * exists and if it has the field in question * * @param Model $model * @param string $modelName * @param string $fieldName * @return boolean */ protected function _associatedModelHasField(Model $model, $modelName, $fieldName) { $associated = $model->getAssociated(); if (!array_key_exists($modelName, $associated)) { return false; } if (!$this->_whitelistedAssociatedModel($modelName)) { return false; } return $model->{$modelName}->hasField($fieldName); }
/** * Returns a generic model that maps to the current $Model's shadow table. * * @param object $Model * @return boolean */ private function createShadowModel(Model $Model) { if (is_null($this->settings[$Model->alias]['useDbConfig'])) { $dbConfig = $Model->useDbConfig; } else { $dbConfig = $this->settings[$Model->alias]['useDbConfig']; } $db = ConnectionManager::getDataSource($dbConfig); if ($Model->useTable) { $shadow_table = $Model->useTable; } else { $shadow_table = Inflector::tableize($Model->name); } $shadow_table = $shadow_table . $this->revision_suffix; $prefix = $Model->tablePrefix ? $Model->tablePrefix : $db->config['prefix']; $full_table_name = $prefix . $shadow_table; $existing_tables = $db->listSources(); if (!in_array($full_table_name, $existing_tables)) { $Model->ShadowModel = false; return false; } $useShadowModel = $this->settings[$Model->alias]['model']; if (is_string($useShadowModel) && App::import('model', $useShadowModel)) { $Model->ShadowModel = new $useShadowModel(false, $shadow_table, $dbConfig); } else { $Model->ShadowModel = new Model(false, $shadow_table, $dbConfig); } if ($Model->tablePrefix) { $Model->ShadowModel->tablePrefix = $Model->tablePrefix; } $Model->ShadowModel->alias = 'Revision_' . $Model->alias; $Model->ShadowModel->primaryKey = 'version_id'; $Model->ShadowModel->order = array('version_created DESC', 'version_id DESC'); $assocBelongsTo = $Model->getAssociated('belongsTo'); //$fields=$Model->ShadowModel->schema(); foreach ($assocBelongsTo as $key => $assoc) { $field = $Model->belongsTo[$assoc]['foreignKey']; if ($field == $Model->belongsTo[$assoc]['foreignKey']) { $Model->ShadowModel->bindModel(array('belongsTo' => array($assoc => $Model->belongsTo[$assoc])), false); } } return true; }