/** * Returns a callable to be used for each row in a query result set * for injecting the eager loaded rows * * @param \Cake\ORM\Query $fetchQuery the Query used to fetch results * @param array $resultMap an array with the foreignKey as keys and * the corresponding target table results as value. * @param array $options The options passed to the eagerLoader method * @return \Closure */ protected function _resultInjector($fetchQuery, $resultMap, $options) { $source = $this->source(); $sAlias = $source->alias(); $keys = $this->type() === $this::MANY_TO_ONE ? $this->foreignKey() : $this->bindingKey(); $sourceKeys = []; foreach ((array) $keys as $key) { $sourceKeys[] = key($fetchQuery->aliasField($key, $sAlias)); } $nestKey = $options['nestKey']; if (count($sourceKeys) > 1) { return $this->_multiKeysInjector($resultMap, $sourceKeys, $nestKey); } $sourceKey = $sourceKeys[0]; return function ($row) use($resultMap, $sourceKey, $nestKey) { if (isset($resultMap[$row[$sourceKey]])) { $row[$nestKey] = $resultMap[$row[$sourceKey]]; } return $row; }; }
/** * Helper function used to return the keys from the query records that will be used * to eagerly load associations. * * @param array $external the list of external associations to be loaded * @param \Cake\ORM\Query $query The query from which the results where generated * @param BufferedStatement $statement The statement to work on * @return array */ protected function _collectKeys($external, $query, $statement) { $collectKeys = []; foreach ($external as $meta) { $instance = $meta->instance(); if (!$instance->requiresKeys($meta->config())) { continue; } $source = $instance->source(); $keys = $instance->type() === Association::MANY_TO_ONE ? (array) $instance->foreignKey() : (array) $instance->bindingKey(); $alias = $source->alias(); $pkFields = []; foreach ($keys as $key) { $pkFields[] = key($query->aliasField($key, $alias)); } $collectKeys[$meta->aliasPath()] = [$alias, $pkFields, count($pkFields) === 1]; } if (empty($collectKeys)) { return [[], $statement]; } if (!$statement instanceof BufferedStatement) { $statement = new BufferedStatement($statement, $query->connection()->driver()); } return [$this->_groupKeys($statement, $collectKeys), $statement]; }
/** * Add translation fields to query * * If the query is using autofields (directly or implicitly) add the * main table's fields to the query first. * * Only add translations for fields that are in the main table, always * add the locale field though. * * @param \Cake\ORM\Query $query the query to check * @param array $config the config to use for adding fields * @return bool Whether a join to the translation table is required */ protected function _addFieldsToQuery(Query $query, array $config) { $select = $query->clause('select'); if (!$select) { return true; } $alias = $config['mainTableAlias']; $joinRequired = false; foreach ($this->_translationFields() as $field) { if (array_intersect($select, [$field, "{$alias}.{$field}"])) { $joinRequired = true; $query->select($query->aliasField($field, $config['hasOneAlias'])); } } if ($joinRequired) { $query->select($query->aliasField('locale', $config['hasOneAlias'])); } return $joinRequired; }