APIv4 - Fix saving NULL as custom field value
[civicrm-core.git] / tests / phpunit / api / v4 / Action / BasicCustomFieldTest.php
index d22b3e041cb98ece69d90e74e8a0f1bb9a27332b..240ce3a9432f0ffe74e283f5e7f500f72c8e7d1e 100644 (file)
@@ -84,6 +84,18 @@ class BasicCustomFieldTest extends BaseCustomValueTest {
       ->first();
 
     $this->assertEquals('Blue', $contact['MyIndividualFields.FavColor']);
+
+    // Try setting to null
+    Contact::update()
+      ->addWhere('id', '=', $contactId)
+      ->addValue('MyIndividualFields.FavColor', NULL)
+      ->execute();
+    $contact = Contact::get(FALSE)
+      ->addSelect('MyIndividualFields.FavColor')
+      ->addWhere('id', '=', $contactId)
+      ->execute()
+      ->first();
+    $this->assertEquals(NULL, $contact['MyIndividualFields.FavColor']);
   }
 
   public function testWithTwoFields() {
@@ -247,6 +259,12 @@ class BasicCustomFieldTest extends BaseCustomValueTest {
       ->addValue('data_type', 'String')
       ->execute();
 
+    // Adding custom field to Relationship entity also adds it to RelationshipCache entity
+    $this->assertCount(1, RelationshipCache::getFields(FALSE)
+      ->addWhere('name', '=', "$cgName.PetName")
+      ->execute()
+    );
+
     $parent = Contact::create(FALSE)
       ->addValue('first_name', 'Parent')
       ->addValue('last_name', 'Tester')
@@ -261,13 +279,14 @@ class BasicCustomFieldTest extends BaseCustomValueTest {
       ->execute()
       ->first()['id'];
 
-    $relationship = Relationship::create(FALSE)
+    Relationship::create(FALSE)
       ->addValue('contact_id_a', $parent)
       ->addValue('contact_id_b', $child)
       ->addValue('relationship_type_id', 1)
       ->addValue("$cgName.PetName", 'Buddy')
       ->execute();
 
+    // Test get directly from relationshipCache entity
     $results = RelationshipCache::get(FALSE)
       ->addSelect("$cgName.PetName")
       ->addWhere("$cgName.PetName", '=', 'Buddy')
@@ -275,6 +294,72 @@ class BasicCustomFieldTest extends BaseCustomValueTest {
 
     $this->assertCount(2, $results);
     $this->assertEquals('Buddy', $results[0]["$cgName.PetName"]);
+
+    // Test get via bridge INNER join
+    $result = Contact::get(FALSE)
+      ->addSelect('relative.display_name', "relative.$cgName.PetName")
+      ->addJoin('Contact AS relative', 'INNER', 'RelationshipCache')
+      ->addWhere('id', '=', $parent)
+      ->addWhere('relative.relationship_type_id', '=', 1)
+      ->execute()->single();
+    $this->assertEquals('Child Tester', $result['relative.display_name']);
+    $this->assertEquals('Buddy', $result["relative.$cgName.PetName"]);
+
+    // Test get via bridge LEFT join
+    $result = Contact::get(FALSE)
+      ->addSelect('relative.display_name', "relative.$cgName.PetName")
+      ->addJoin('Contact AS relative', 'LEFT', 'RelationshipCache')
+      ->addWhere('id', '=', $parent)
+      ->addWhere('relative.relationship_type_id', '=', 1)
+      ->execute()->single();
+    $this->assertEquals('Child Tester', $result['relative.display_name']);
+    $this->assertEquals('Buddy', $result["relative.$cgName.PetName"]);
+  }
+
+  public function testMultipleJoinsToCustomTable() {
+    $cgName = uniqid('My');
+
+    CustomGroup::create(FALSE)
+      ->addValue('name', $cgName)
+      ->addValue('extends', 'Contact')
+      ->addChain('field1', CustomField::create()
+        ->addValue('label', 'FavColor')
+        ->addValue('custom_group_id', '$id')
+        ->addValue('html_type', 'Text')
+        ->addValue('data_type', 'String'))
+      ->execute();
+
+    $parent = Contact::create(FALSE)
+      ->addValue('first_name', 'Parent')
+      ->addValue('last_name', 'Tester')
+      ->addValue("$cgName.FavColor", 'Purple')
+      ->execute()
+      ->first()['id'];
+
+    $child = Contact::create(FALSE)
+      ->addValue('first_name', 'Child')
+      ->addValue('last_name', 'Tester')
+      ->addValue("$cgName.FavColor", 'Cyan')
+      ->execute()
+      ->first()['id'];
+
+    Relationship::create(FALSE)
+      ->addValue('contact_id_a', $parent)
+      ->addValue('contact_id_b', $child)
+      ->addValue('relationship_type_id', 1)
+      ->execute();
+
+    $results = Contact::get(FALSE)
+      ->addSelect('first_name', 'child.first_name', "$cgName.FavColor", "child.$cgName.FavColor")
+      ->addWhere('id', '=', $parent)
+      ->addJoin('Contact AS child', 'INNER', 'RelationshipCache', ['id', '=', 'child.far_contact_id'])
+      ->execute();
+
+    $this->assertCount(1, $results);
+    $this->assertEquals('Parent', $results[0]['first_name']);
+    $this->assertEquals('Child', $results[0]['child.first_name']);
+    $this->assertEquals('Purple', $results[0]["$cgName.FavColor"]);
+    $this->assertEquals('Cyan', $results[0]["child.$cgName.FavColor"]);
   }
 
   /**
@@ -312,4 +397,47 @@ class BasicCustomFieldTest extends BaseCustomValueTest {
     $this->assertEquals($optionGroupCount, OptionGroup::get(FALSE)->selectRowCount()->execute()->count());
   }
 
+  public function testUpdateWeights() {
+    $getValues = function($groupName) {
+      return CustomField::get(FALSE)
+        ->addWhere('custom_group_id.name', '=', $groupName)
+        ->addOrderBy('weight')
+        ->execute()->indexBy('name')->column('weight');
+    };
+
+    // Create 2 custom groups. Control group is to ensure updating one doesn't affect the other
+    foreach (['controlGroup', 'experimentalGroup'] as $groupName) {
+      $customGroups[$groupName] = CustomGroup::create(FALSE)
+        ->addValue('name', $groupName)
+        ->addValue('extends', 'Individual')
+        ->execute()->first();
+      $sampleData = [
+        ['label' => 'One'],
+        ['label' => 'Two'],
+        ['label' => 'Three'],
+        ['label' => 'Four'],
+      ];
+      CustomField::save(FALSE)
+        ->setRecords($sampleData)
+        ->addDefault('custom_group_id.name', $groupName)
+        ->addDefault('html_type', 'Text')
+        ->execute();
+      // Default weights should have been set during create
+      $this->assertEquals(['One' => 1, 'Two' => 2, 'Three' => 3, 'Four' => 4], $getValues($groupName));
+    }
+
+    // Ensure default weights were set for custom groups
+    $this->assertEquals($customGroups['controlGroup']['weight'] + 1, $customGroups['experimentalGroup']['weight']);
+
+    // Move third option to second position
+    CustomField::update(FALSE)
+      ->addWhere('custom_group_id.name', '=', 'experimentalGroup')
+      ->addWhere('name', '=', 'Three')
+      ->addValue('weight', 2)
+      ->execute();
+    // Experimental group should be updated, control group should not
+    $this->assertEquals(['One' => 1, 'Three' => 2, 'Two' => 3, 'Four' => 4], $getValues('experimentalGroup'));
+    $this->assertEquals(['One' => 1, 'Two' => 2, 'Three' => 3, 'Four' => 4], $getValues('controlGroup'));
+  }
+
 }