APIv4 - Support pseudoconstant suffixes in orderBy clause
[civicrm-core.git] / tests / phpunit / api / v4 / Action / BasicActionsTest.php
index 21b181f7d444c1e9af7de18834c8d9549005e012..daf2b3470eab21374bdc9d995b1a503772a0aeb4 100644 (file)
@@ -49,22 +49,39 @@ class BasicActionsTest extends UnitTestCase {
     $this->assertEquals('new', $result->first()['foo']);
 
     $result = MockBasicEntity::save()
-      ->addRecord(['id' => $id1, 'foo' => 'one updated'])
-      ->addRecord(['id' => $id2])
+      ->addRecord(['id' => $id1, 'foo' => 'one updated', 'weight' => '5'])
+      ->addRecord(['id' => $id2, 'group:label' => 'Second'])
       ->addRecord(['foo' => 'three'])
       ->addDefault('color', 'pink')
       ->setReload(TRUE)
       ->execute()
       ->indexBy('id');
 
+    $this->assertTrue(5 === $result[$id1]['weight']);
     $this->assertEquals('new', $result[$id2]['foo']);
+    $this->assertEquals('two', $result[$id2]['group']);
     $this->assertEquals('three', $result->last()['foo']);
     $this->assertCount(3, $result);
     foreach ($result as $item) {
       $this->assertEquals('pink', $item['color']);
     }
 
-    $this->assertEquals('one updated', MockBasicEntity::get()->addWhere('id', '=', $id1)->execute()->first()['foo']);
+    $ent1 = MockBasicEntity::get()->addWhere('id', '=', $id1)->execute()->first();
+    $this->assertEquals('one updated', $ent1['foo']);
+    $this->assertFalse(isset($ent1['group:label']));
+
+    $ent2 = MockBasicEntity::get()->addWhere('group:label', '=', 'Second')->addSelect('group:label', 'group')->execute()->first();
+    $this->assertEquals('two', $ent2['group']);
+    $this->assertEquals('Second', $ent2['group:label']);
+    // We didn't select this
+    $this->assertFalse(isset($ent2['group:name']));
+
+    // With no SELECT, all fields should be returned but not suffixy stuff like group:name
+    $ent2 = MockBasicEntity::get()->addWhere('group:label', '=', 'Second')->execute()->first();
+    $this->assertEquals('two', $ent2['group']);
+    $this->assertFalse(isset($ent2['group:name']));
+    // This one wasn't selected but did get used by the WHERE clause; ensure it isn't returned
+    $this->assertFalse(isset($ent2['group:label']));
 
     MockBasicEntity::delete()->addWhere('id', '=', $id2);
     $result = MockBasicEntity::get()->execute();
@@ -128,23 +145,43 @@ class BasicActionsTest extends UnitTestCase {
   public function testGetFields() {
     $getFields = MockBasicEntity::getFields()->execute()->indexBy('name');
 
-    $this->assertCount(6, $getFields);
+    $this->assertCount(7, $getFields);
     $this->assertEquals('Id', $getFields['id']['title']);
     // Ensure default data type is "String" when not specified
     $this->assertEquals('String', $getFields['color']['data_type']);
 
     // Getfields should default to loadOptions = false and reduce them to bool
     $this->assertTrue($getFields['group']['options']);
+    $this->assertTrue($getFields['fruit']['options']);
     $this->assertFalse($getFields['id']['options']);
 
-    // Now load options
+    // Load simple options
     $getFields = MockBasicEntity::getFields()
-      ->addWhere('name', '=', 'group')
+      ->addWhere('name', 'IN', ['group', 'fruit'])
       ->setLoadOptions(TRUE)
       ->execute()->indexBy('name');
 
-    $this->assertCount(1, $getFields);
+    $this->assertCount(2, $getFields);
     $this->assertArrayHasKey('one', $getFields['group']['options']);
+    // Complex options should be reduced to simple array
+    $this->assertArrayHasKey(1, $getFields['fruit']['options']);
+    $this->assertEquals('Banana', $getFields['fruit']['options'][3]);
+
+    // Load complex options
+    $getFields = MockBasicEntity::getFields()
+      ->addWhere('name', 'IN', ['group', 'fruit'])
+      ->setLoadOptions(['id', 'name', 'label', 'color'])
+      ->execute()->indexBy('name');
+
+    // Simple options should be expanded to non-assoc array
+    $this->assertCount(2, $getFields);
+    $this->assertEquals('one', $getFields['group']['options'][0]['id']);
+    $this->assertEquals('First', $getFields['group']['options'][0]['name']);
+    $this->assertEquals('First', $getFields['group']['options'][0]['label']);
+    $this->assertFalse(isset($getFields['group']['options'][0]['color']));
+    // Complex options should give all requested properties
+    $this->assertEquals('Banana', $getFields['fruit']['options'][2]['label']);
+    $this->assertEquals('yellow', $getFields['fruit']['options'][2]['color']);
   }
 
   public function testItemsToGet() {
@@ -218,4 +255,42 @@ class BasicActionsTest extends UnitTestCase {
     $this->assertEquals(['shape', 'size', 'weight'], array_keys($result));
   }
 
+  public function testPseudoconstantMatch() {
+    MockBasicEntity::delete()->addWhere('id', '>', 0)->execute();
+
+    $records = [
+      ['group:label' => 'First', 'shape' => 'round', 'fruit:name' => 'banana'],
+      ['group:name' => 'Second', 'shape' => 'square', 'fruit:label' => 'Pear'],
+    ];
+    MockBasicEntity::save()->setRecords($records)->execute();
+
+    $results = MockBasicEntity::get()
+      ->addSelect('*', 'group:label', 'group:name', 'fruit:name', 'fruit:color', 'fruit:label')
+      ->addOrderBy('fruit:color', "DESC")
+      ->execute();
+
+    $this->assertEquals('round', $results[0]['shape']);
+    $this->assertEquals('one', $results[0]['group']);
+    $this->assertEquals('First', $results[0]['group:label']);
+    $this->assertEquals('First', $results[0]['group:name']);
+    $this->assertEquals(3, $results[0]['fruit']);
+    $this->assertEquals('Banana', $results[0]['fruit:label']);
+    $this->assertEquals('banana', $results[0]['fruit:name']);
+    $this->assertEquals('yellow', $results[0]['fruit:color']);
+
+    // Reverse order
+    $results = MockBasicEntity::get()
+      ->addOrderBy('fruit:color')
+      ->execute();
+    $this->assertEquals('two', $results[0]['group']);
+
+    // Cannot match to a non-unique option property like :color on create
+    try {
+      MockBasicEntity::create()->addValue('fruit:color', 'yellow')->execute();
+    }
+    catch (\API_Exception $createError) {
+    }
+    $this->assertContains('Illegal expression', $createError->getMessage());
+  }
+
 }