Browse Source

Completing the EagerLoader API to also have a function that returns
associations to be eager laoded

Jose Lorenzo Rodriguez 12 years ago
parent
commit
49f19d248c
1 changed files with 32 additions and 23 deletions
  1. 32 23
      src/ORM/EagerLoader.php

+ 32 - 23
src/ORM/EagerLoader.php

@@ -104,7 +104,7 @@ class EagerLoader {
 		}
 
 		$associations = $this->_reformatContain($associations, $this->_containments);
-		$this->_normalized = null;
+		$this->_normalized = $this->_loadExternal = null;
 		return $this->_containments = $associations;
 	}
 
@@ -149,7 +149,7 @@ class EagerLoader {
  */
 	public function normalized(Table $repository) {
 		if ($this->_normalized !== null || empty($this->_containments)) {
-			return $this->_normalized;
+			return (array)$this->_normalized;
 		}
 
 		$contain = [];
@@ -170,20 +170,6 @@ class EagerLoader {
 	}
 
 /**
- * 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
  * the new associations provided
@@ -277,6 +263,27 @@ class EagerLoader {
 	}
 
 /**
+ * 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()`
  *
@@ -329,7 +336,7 @@ class EagerLoader {
 				$result[$table] = $options;
 				$result += $this->_resolveJoins($options['associations']);
 			} else {
-				$this->_loadExternal[$table] = $options;
+				$this->_loadExternal[] = $options;
 			}
 		}
 		return $result;
@@ -345,13 +352,14 @@ class EagerLoader {
  * @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;
@@ -368,13 +376,14 @@ class EagerLoader {
  * 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();