Skip to content

Commit

Permalink
Completing the EagerLoader API to also have a function that returns
Browse files Browse the repository at this point in the history
associations to be eager laoded
  • Loading branch information
lorenzo committed Feb 9, 2014
1 parent 5556270 commit 49f19d2
Showing 1 changed file with 32 additions and 23 deletions.
55 changes: 32 additions & 23 deletions src/ORM/EagerLoader.php
Expand Up @@ -104,7 +104,7 @@ public function contain($associations = []) {
}

$associations = $this->_reformatContain($associations, $this->_containments);
$this->_normalized = null;
$this->_normalized = $this->_loadExternal = null;
return $this->_containments = $associations;
}

Expand Down Expand Up @@ -149,7 +149,7 @@ public function matching($assoc, callable $builder = null) {
*/
public function normalized(Table $repository) {
if ($this->_normalized !== null || empty($this->_containments)) {
return $this->_normalized;
return (array)$this->_normalized;
}

$contain = [];
Expand All @@ -169,20 +169,6 @@ public function normalized(Table $repository) {
return $this->_normalized = $contain;
}

/**
* Returns whether or not there are associations that need to be loaded by
* decorating results from a query and executing a separate one for injecting
* them.
*
* @param \Cake\ORM\Table $repository The table containing the associations described in
* the `contain` array
* @return boolean
*/
protected function _hasExternal(Table $repository) {
$this->normalized($repository);
return !empty($this->_loadExternal);
}

/**
* Formats the containments array so that associations are always set as keys
* in the array. This function merges the original associations array with
Expand Down Expand Up @@ -276,6 +262,27 @@ public function attachableAssociations(Table $repository) {
return $this->_resolveJoins($contain);
}

/**
* Returns an array with the associations that need to be fetched using a
* separate query, each array value will contain the following keys:
*
* - instance: the association object instance
* - config: the options set for fetching such association
*
* @param \Cake\ORM\Table $repository The table containing the associations
* to be loaded
* @return array
*/
public function externalAssociations(Table $repository) {
if ($this->_loadExternal) {
return $this->_loadExternal;
}

$contain = $this->normalized($repository);
$this->_resolveJoins($contain);
return $this->_loadExternal;
}

/**
* Auxiliary function responsible for fully normalizing deep associations defined
* using `contain()`
Expand Down Expand Up @@ -329,7 +336,7 @@ protected function _resolveJoins($associations) {
$result[$table] = $options;
$result += $this->_resolveJoins($options['associations']);
} else {
$this->_loadExternal[$table] = $options;
$this->_loadExternal[] = $options;
}
}
return $result;
Expand All @@ -345,13 +352,14 @@ protected function _resolveJoins($associations) {
* @return CallbackStatement $statement modified statement with extra loaders
*/
public function loadExternal($query, $statement) {
if (!$this->_hasExternal($query->repository())) {
$external = $this->externalAssociations($query->repository());
if (empty($external)) {
return $statement;
}

$driver = $query->connection()->driver();
list($collected, $statement) = $this->_collectKeys($query, $statement);
foreach ($this->_loadExternal as $meta) {
list($collected, $statement) = $this->_collectKeys($external, $query, $statement);
foreach ($external as $meta) {
$contain = $meta['associations'];
$alias = $meta['instance']->source()->alias();
$keys = isset($collected[$alias]) ? $collected[$alias] : null;
Expand All @@ -368,13 +376,14 @@ public function loadExternal($query, $statement) {
* Helper function used to return the keys from the query records that will be used
* to eagerly load associations.
*
* @param \Cake\ORM\Query $query
* @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
* @return array
*/
protected function _collectKeys($query, $statement) {
protected function _collectKeys($external, $query, $statement) {
$collectKeys = [];
foreach ($this->_loadExternal as $meta) {
foreach ($external as $meta) {
$source = $meta['instance']->source();
if ($meta['instance']->requiresKeys($meta['config'])) {
$alias = $source->alias();
Expand Down

0 comments on commit 49f19d2

Please sign in to comment.