Commit ceb46d28 authored by mattwire's avatar mattwire

Merge branch 'fix-get-billing-email' into 'master'

Fix get billing email

See merge request !3
parents 1dd5a61c 47691f58
......@@ -38,7 +38,7 @@ trait CRM_Core_Payment_MJWTrait {
*
* @return string|NULL
*/
protected function getBillingEmail($params, $contactId) {
public function getBillingEmail($params, $contactId) {
$billingLocationId = CRM_Core_BAO_LocationType::getBilling();
$emailAddress = CRM_Utils_Array::value("email-{$billingLocationId}", $params,
......@@ -47,15 +47,27 @@ trait CRM_Core_Payment_MJWTrait {
if (empty($emailAddress) && !empty($contactId)) {
// Try and retrieve an email address from Contact ID
try {
$emailAddress = civicrm_api3('Email', 'getvalue', [
'contact_id' => $contactId,
'return' => ['email'],
]);
$emailAddresses = civicrm_api3('Email', 'get', [
'contact_id' => $contactId,
'return' => ['email', 'location_type_id', 'is_primary'],
])['values'];
$other_options = [];
foreach ($emailAddresses as $row) {
if ($row['location_type_id'] == $billingLocationId) {
return $row['email'];
}
elseif ($row['is_primary']) {
array_unshift($other_options, $row['email']);
}
else {
$other_options[] = $row['email'];
}
}
catch (CiviCRM_API3_Exception $e) {
return NULL;
if ($other_options) {
return $other_options[0];
}
return NULL;
}
return $emailAddress;
}
......
<?xml version="1.0"?>
<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="tests/phpunit/bootstrap.php">
<testsuites>
<testsuite name="My Test Suite">
<directory>./tests/phpunit</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./</directory>
</whitelist>
</filter>
<listeners>
<listener class="Civi\Test\CiviTestListener">
<arguments/>
</listener>
</listeners>
</phpunit>
<?php
use CRM_Mjwshared_ExtensionUtil as E;
use Civi\Test\HeadlessInterface;
use Civi\Test\HookInterface;
use Civi\Test\TransactionalInterface;
/**
* Test trait functionalty
*
* Tips:
* - With HookInterface, you may implement CiviCRM hooks directly in the test class.
* Simply create corresponding functions (e.g. "hook_civicrm_post(...)" or similar).
* - With TransactionalInterface, any data changes made by setUp() or test****() functions will
* rollback automatically -- as long as you don't manipulate schema or truncate tables.
* If this test needs to manipulate schema or truncate tables, then either:
* a. Do all that using setupHeadless() and Civi\Test.
* b. Disable TransactionalInterface, and handle all setup/teardown yourself.
*
* @group headless
*/
class CRM_Core_Payment_MJWTraitTest extends \PHPUnit\Framework\TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
public function setUpHeadless() {
// Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
// See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
return \Civi\Test::headless()
->installMe(__DIR__)
->apply();
}
public function setUp() {
parent::setUp();
}
public function tearDown() {
parent::tearDown();
}
/**
* Test getEmail
*/
public function testGetEmail() {
$t = new TheTrait();
$billingLocationId = CRM_Core_BAO_LocationType::getBilling();
// First test selection logic when emails are provided in the input array.
$emails = [
"email" => 'other@example.com',
"email-Primary" => 'primary@example.com',
"email-$billingLocationId" => 'billing@example.com',
];
$this->assertEquals('billing@example.com',
$t->getBillingEmail($emails, NULL)
);
array_pop($emails);
$this->assertEquals('primary@example.com',
$t->getBillingEmail($emails, NULL)
);
array_pop($emails);
$this->assertEquals('other@example.com',
$t->getBillingEmail($emails, NULL)
);
// Test that without a contact nor emails, we return null.
$this->assertNull($t->getBillingEmail([], NULL));
// Next test selection logic when emails are not in the input array.
$contact_id = civicrm_api3('Contact', 'create', ['contact_type' => 'Individual', 'display_name' => 'test contact'])['id'];
// It should return NULL for a contact that has no emails.
$this->assertNull($t->getBillingEmail([], $contact_id));
// It should be able to find a single email.
$email_id_1 = civicrm_api3('Email', 'create', [
'contact_id' => $contact_id,
'email' => 'other@example.com',
])['id'];
$this->assertEquals('other@example.com',
$t->getBillingEmail([], $contact_id),
'Failed looking up a single email for a contact'
);
// It should be able to find an email if a contact has 2+
$email_id_2 = civicrm_api3('Email', 'create', [
'contact_id' => $contact_id,
'email' => 'another@example.com',
])['id'];
$this->assertRegexp(
'/^(an)?other@example.com$/',
$t->getBillingEmail([], $contact_id),
'Failed looking up an email for a contact that has more than one.'
);
// It should find a Primary email if one exists (and there's no billing one)
$email_id_3 = civicrm_api3('Email', 'create', [
'contact_id' => $contact_id,
'email' => 'primary@example.com',
'is_primary' => 1,
])['id'];
$this->assertEquals(
'primary@example.com',
$t->getBillingEmail([], $contact_id),
'Failed to find the primary email amongst others.'
);
// It should find a billing email if one exists.
$email_id_4 = civicrm_api3('Email', 'create', [
'contact_id' => $contact_id,
'email' => 'billing@example.com',
'location_type_id' => $billingLocationId,
])['id'];
$this->assertEquals(
'billing@example.com',
$t->getBillingEmail([], $contact_id),
'Failed to find the billing email amongst others.'
);
}
}
class TheTrait {
use CRM_Core_Payment_MJWTrait;
}
<?php
ini_set('memory_limit', '2G');
ini_set('safe_mode', 0);
// phpcs:ignore
eval(cv('php:boot --level=classloader', 'phpcode'));
// Allow autoloading of PHPUnit helper classes in this extension.
$loader = new \Composer\Autoload\ClassLoader();
$loader->add('CRM_', __DIR__);
$loader->add('Civi\\', __DIR__);
$loader->add('api_', __DIR__);
$loader->add('api\\', __DIR__);
$loader->register();
/**
* Call the "cv" command.
*
* @param string $cmd
* The rest of the command to send.
* @param string $decode
* Ex: 'json' or 'phpcode'.
* @return string
* Response output (if the command executed normally).
* @throws \RuntimeException
* If the command terminates abnormally.
*/
function cv($cmd, $decode = 'json') {
$cmd = 'cv ' . $cmd;
$descriptorSpec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => STDERR);
$oldOutput = getenv('CV_OUTPUT');
putenv("CV_OUTPUT=json");
// Execute `cv` in the original folder. This is a work-around for
// phpunit/codeception, which seem to manipulate PWD.
$cmd = sprintf('cd %s; %s', escapeshellarg(getenv('PWD')), $cmd);
$process = proc_open($cmd, $descriptorSpec, $pipes, __DIR__);
putenv("CV_OUTPUT=$oldOutput");
fclose($pipes[0]);
$result = stream_get_contents($pipes[1]);
fclose($pipes[1]);
if (proc_close($process) !== 0) {
throw new RuntimeException("Command failed ($cmd):\n$result");
}
switch ($decode) {
case 'raw':
return $result;
case 'phpcode':
// If the last output is /*PHPCODE*/, then we managed to complete execution.
if (substr(trim($result), 0, 12) !== "/*BEGINPHP*/" || substr(trim($result), -10) !== "/*ENDPHP*/") {
throw new \RuntimeException("Command failed ($cmd):\n$result");
}
return $result;
case 'json':
return json_decode($result, 1);
default:
throw new RuntimeException("Bad decoder format ($decode)");
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment