Browse Source

Adding test for find('list') with composite keys

Jose Lorenzo Rodriguez 12 years ago
parent
commit
deec394b68
2 changed files with 92 additions and 0 deletions
  1. 42 0
      src/ORM/Table.php
  2. 50 0
      tests/TestCase/ORM/CompositeKeysTest.php

+ 42 - 0
src/ORM/Table.php

@@ -779,6 +779,10 @@ class Table implements EventListener {
 			'valueField' => $this->displayField(),
 			'groupField' => null
 		];
+		$options = $this->_setFieldMatchers(
+			$options,
+			['idField', 'valueField', 'groupField']
+		);
 
 		return $query->formatResults(function($results) use ($options) {
 			return $results->combine(
@@ -817,6 +821,7 @@ class Table implements EventListener {
 			'idField' => $this->primaryKey(),
 			'parentField' => 'parent_id',
 		];
+		$options = $this->_setFieldMatchers($options, ['idField', 'parentField']);
 
 		return $query->formatResults(function($results) use ($options) {
 			return $results->nest($options['idField'], $options['parentField']);
@@ -824,6 +829,43 @@ class Table implements EventListener {
 	}
 
 /**
+ * Out of an options array, check if the keys described in `$keys` are arrays
+ * and change the values for closures that will concatenate the each of the
+ * properties in the value array when passed a row.
+ *
+ * This is an auxiliary function used for result formatters that can accept
+ * composite keys when comparing values.
+ *
+ * @param array $options the original options passed to a finder
+ * @param array $keys the keys to check in $options to build matchers from
+ * the associated value
+ * @return array
+ */
+	protected function _setFieldMatchers($options, $keys) {
+		foreach ($keys as $field) {
+			if (!is_array($options[$field])) {
+				continue;
+			}
+
+			if (count($options[$field]) === 1) {
+				$options[$field] = current($options[$field]);
+				continue;
+			}
+
+			$fields = $options[$field];
+			$options[$field] = function($row) use ($fields) {
+				$matches = [];
+				foreach ($fields as $field) {
+					$matches[] = $row[$field];
+				}
+				return implode(';', $matches);
+			};
+		}
+
+		return $options;
+	}
+
+/**
  * Returns a single record after finding it by its primary key, if no record is
  * found this method throws an exception.
  *

+ 50 - 0
tests/TestCase/ORM/CompositeKeysTest.php

@@ -350,4 +350,54 @@ class CompositeKeyTest extends TestCase {
 		$this->assertEmpty($result->tags);
 	}
 
+/**
+ * Tests find('list') with composite keys
+ *
+ * @return void
+ */
+	public function testFindCompositeKeys() {
+		$table = new Table([
+			'table' => 'site_authors',
+			'connection' => $this->connection,
+		]);
+		$table->displayField('name');
+		$query = $table->find('list')
+			->hydrate(false)
+			->order('id');
+		$expected = [
+			'1;1' => 'mark',
+			'2;2' => 'juan',
+			'3;2' => 'jose',
+			'4;1' => 'andy'
+		];
+		$this->assertEquals($expected, $query->toArray());
+
+		$table->displayField(['name', 'site_id']);
+		$query = $table->find('list')
+			->hydrate(false)
+			->order('id');
+		$expected = [
+			'1;1' => 'mark;1',
+			'2;2' => 'juan;2',
+			'3;2' => 'jose;2',
+			'4;1' => 'andy;1'
+		];
+		$this->assertEquals($expected, $query->toArray());
+
+		$query = $table->find('list', ['groupField' => ['site_id', 'site_id']])
+			->hydrate(false)
+			->order('id');
+		$expected = [
+			'1;1' => [
+				'1;1' => 'mark;1',
+				'4;1' => 'andy;1'
+			],
+			'2;2' => [
+				'2;2' => 'juan;2',
+				'3;2' => 'jose;2'
+			]
+		];
+		$this->assertEquals($expected, $query->toArray());
+	}
+
 }