APIv4 - Fix bug when using relative date filters in ON clause of a join
authorColeman Watts <coleman@civicrm.org>
Wed, 3 Feb 2021 13:18:36 +0000 (08:18 -0500)
committerColeman Watts <coleman@civicrm.org>
Wed, 3 Feb 2021 13:18:36 +0000 (08:18 -0500)
Civi/Api4/Query/Api4SelectQuery.php
tests/phpunit/api/v4/Action/DateTest.php

index c02568433a82620fbec688f9debc1893d62c3280..20b8286e6dd095d81f1bc014ade2efe3af9172e8 100644 (file)
@@ -412,9 +412,14 @@ class Api4SelectQuery {
       if (is_string($value)) {
         $valExpr = $this->getExpression($value);
         if ($fieldName && $valExpr->getType() === 'SqlString') {
-          FormattingUtil::formatInputValue($valExpr->expr, $fieldName, $this->apiFieldSpec[$fieldName], $operator);
+          $value = $valExpr->getExpr();
+          FormattingUtil::formatInputValue($value, $fieldName, $this->apiFieldSpec[$fieldName], $operator);
+          return \CRM_Core_DAO::createSQLFilter($fieldAlias, [$operator => $value]);
+        }
+        else {
+          $value = $valExpr->render($this->apiFieldSpec);
+          return sprintf('%s %s %s', $fieldAlias, $operator, $value);
         }
-        return sprintf('%s %s %s', $fieldAlias, $operator, $valExpr->render($this->apiFieldSpec));
       }
       elseif ($fieldName) {
         $field = $this->getField($fieldName);
index 3bc2636d6b420ed488773ce26dff584253255c6f..4361d17dd3bc609909c7702e3e0436deeeac740c 100644 (file)
@@ -21,6 +21,7 @@ namespace api\v4\Action;
 
 use Civi\Api4\Activity;
 use Civi\Api4\Contact;
+use Civi\Api4\Contribution;
 use Civi\Api4\Relationship;
 use api\v4\UnitTestCase;
 
@@ -143,4 +144,57 @@ class DateTest extends UnitTestCase {
     $this->assertNotContains($act[6], $result);
   }
 
+  public function testJoinOnRelativeDate() {
+    $c1 = Contact::create(FALSE)
+      ->addValue('first_name', 'Contributor')
+      ->addValue('last_name', 'One')
+      ->execute()
+      ->first()['id'];
+
+    // Contribution from last year
+    Contribution::create(FALSE)
+      ->addValue('contact_id', $c1)
+      ->addValue('receive_date', (date('Y') - 1) . '-06-01')
+      ->addValue('financial_type_id', 1)
+      ->addValue('total_amount', 12)
+      ->execute();
+
+    // Contribution from this year
+    Contribution::create(FALSE)
+      ->addValue('contact_id', $c1)
+      ->addValue('receive_date', date('Y') . '-06-01')
+      ->addValue('financial_type_id', 1)
+      ->addValue('total_amount', 6)
+      ->execute();
+
+    // Contribution from 2 years ago
+    Contribution::create(FALSE)
+      ->addValue('contact_id', $c1)
+      ->addValue('receive_date', (date('Y') - 2) . '-06-01')
+      ->addValue('financial_type_id', 1)
+      ->addValue('total_amount', 24)
+      ->execute();
+
+    // Find contribution from last year
+    $contact = \Civi\Api4\Contact::get()
+      ->addSelect('id', 'contribution.total_amount')
+      ->setJoin([
+        ['Contribution AS contribution', FALSE, NULL, ['contribution.receive_date', '=', '"previous.year"']],
+      ])
+      ->addWhere('id', '=', $c1)
+      ->execute();
+    $this->assertCount(1, $contact);
+    $this->assertEquals(12, $contact[0]['contribution.total_amount']);
+
+    // Find contributions not from last year
+    $contact = \Civi\Api4\Contact::get()
+      ->addSelect('id', 'contribution.total_amount')
+      ->setJoin([
+        ['Contribution AS contribution', FALSE, NULL, ['contribution.receive_date', '!=', '"previous.year"']],
+      ])
+      ->addWhere('id', '=', $c1)
+      ->execute();
+    $this->assertCount(2, $contact);
+  }
+
 }