Skip to content

Commit

Permalink
Fix: include honorific with new donors during donation form request (#…
Browse files Browse the repository at this point in the history
…7101)

Co-authored-by: Jon Waldstein <[email protected]>
  • Loading branch information
jonwaldstein and Jon Waldstein authored Nov 22, 2023
1 parent 21f163d commit 51e813a
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 70 deletions.
57 changes: 57 additions & 0 deletions src/DonationForms/Actions/GetOrCreateDonor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Give\DonationForms\Actions;

use Exception;
use Give\Donors\Models\Donor;

/**
* @unreleased
*/
class GetOrCreateDonor
{
public $donorCreated = false;

/**
* @unreleased
*
* @throws Exception
*/
public function __invoke(
?int $userId,
string $donorEmail,
string $firstName,
string $lastName,
?string $honorific
): Donor {
// first check if donor exists as a user
$donor = $userId ? Donor::whereUserId($userId) : null;

// If they exist as a donor & user then make sure they don't already own this email before adding to their additional emails list..
if ($donor && !$donor->hasEmail($donorEmail) && !Donor::whereEmail($donorEmail)) {
$donor->additionalEmails = array_merge($donor->additionalEmails ?? [], [$donorEmail]);
$donor->save();
}

// if donor is not a user than check for any donor matching this email
if (!$donor) {
$donor = Donor::whereEmail($donorEmail);
}

// if no donor exists then create a new one using their personal information from the form.
if (!$donor) {
$donor = Donor::create([
'name' => trim("$firstName $lastName"),
'firstName' => $firstName,
'lastName' => $lastName,
'email' => $donorEmail,
'userId' => $userId ?: null,
'prefix' => $honorific,
]);

$this->donorCreated = true;
}

return $donor;
}
}
52 changes: 17 additions & 35 deletions src/DonationForms/Controllers/DonateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
namespace Give\DonationForms\Controllers;

use Exception;
use Give\DonationForms\Actions\GetOrCreateDonor;
use Give\DonationForms\DataTransferObjects\DonateControllerData;
use Give\Donors\Models\Donor;
use Give\Framework\PaymentGateways\Controllers\GatewayPaymentController;
use Give\Framework\PaymentGateways\Controllers\GatewaySubscriptionController;
use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException;
use Give\Framework\PaymentGateways\PaymentGateway;
use Give\PaymentGateways\Actions\GetGatewayDataFromRequest;
use Give\Subscriptions\Models\Subscription;

/**
* @since 3.0.0
Expand All @@ -33,7 +33,8 @@ public function donate(DonateControllerData $formData, PaymentGateway $gateway)
$formData->wpUserId,
$formData->email,
$formData->firstName,
$formData->lastName
$formData->lastName,
$formData->honorific
);

if ($formData->donationType->isSingle()) {
Expand Down Expand Up @@ -78,49 +79,30 @@ public function donate(DonateControllerData $formData, PaymentGateway $gateway)
}

/**
* @unreleased Added $formId to the signature for passing to do_action hooks.
* @unreleased Added $formId to the signature for passing to do_action hooks. Added honorific and use GetOrCreateDonor action
* @since 3.0.0
*
* @param int $formId
* @param int|null $userId
* @param string $donorEmail
* @param string $firstName
* @param string $lastName
*
* @return Donor
* @throws Exception
*/
private function getOrCreateDonor(
int $formId,
int $userId,
?int $userId,
string $donorEmail,
string $firstName,
string $lastName
string $lastName,
?string $honorific
): Donor {
// first check if donor exists as a user
$donor = Donor::whereUserId($userId);

// If they exist as a donor & user then make sure they don't already own this email before adding to their additional emails list..
if ($donor && !$donor->hasEmail($donorEmail)) {
$donor->additionalEmails = array_merge($donor->additionalEmails ?? [], [$donorEmail]);
$donor->save();
}

// if donor is not a user than check for any donor matching this email
if (!$donor) {
$donor = Donor::whereEmail($donorEmail);
}

// if no donor exists then create a new one using their personal information from the form.
if (!$donor) {
$donor = Donor::create([
'name' => trim("$firstName $lastName"),
'firstName' => $firstName,
'lastName' => $lastName,
'email' => $donorEmail,
'userId' => $userId ?: null
]);
$getOrCreateDonorAction = new GetOrCreateDonor();

$donor = $getOrCreateDonorAction(
$userId,
$donorEmail,
$firstName,
$lastName,
$honorific
);

if ($getOrCreateDonorAction->donorCreated) {
/**
* @unreleased Add a new do_action hook to differentiate when a v3 form creates a new donor.
* @param Donor $donor
Expand Down
49 changes: 14 additions & 35 deletions src/LegacyPaymentGateways/Adapters/LegacyPaymentGatewayAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Give\LegacyPaymentGateways\Adapters;

use Exception;
use Give\DonationForms\Actions\GetOrCreateDonor;
use Give\DonationForms\V2\Models\DonationForm;
use Give\Donations\Models\Donation;
use Give\Donations\ValueObjects\DonationType;
Expand Down Expand Up @@ -70,7 +71,8 @@ public function handleBeforeGateway(array $legacyDonationData, PaymentGateway $r
$formData->donorInfo->wpUserId,
$formData->donorInfo->email,
$formData->donorInfo->firstName,
$formData->donorInfo->lastName
$formData->donorInfo->lastName,
$formData->donorInfo->honorific
);

$donation = $formData->toDonation($donor->id);
Expand Down Expand Up @@ -279,48 +281,25 @@ private function setSession($donationId)
}

/**
* @unreleased add honorific and use GetOrCreateDonor action
* @since 2.21.0
*
* @param int|null $userId
* @param string $donorEmail
* @param string $firstName
* @param string $lastName
*
* @return Donor
* @throws Exception
*/
private function getOrCreateDonor(
int $userId,
?int $userId,
string $donorEmail,
string $firstName,
string $lastName
string $lastName,
?string $honorific
): Donor {
// first check if donor exists as a user
$donor = Donor::whereUserId($userId);

// If they exist as a donor & user then make sure they don't already own this email before adding to their additional emails list..
if ($donor && !$donor->hasEmail($donorEmail)) {
$donor->additionalEmails = array_merge($donor->additionalEmails ?? [], [$donorEmail]);
$donor->save();
}

// if donor is not a user than check for any donor matching this email
if (!$donor) {
$donor = Donor::whereEmail($donorEmail);
}

// if no donor exists then create a new one using their personal information from the form.
if (!$donor) {
$donor = Donor::create([
'name' => trim("$firstName $lastName"),
'firstName' => $firstName,
'lastName' => $lastName,
'email' => $donorEmail,
'userId' => $userId ?: null,
]);
}

return $donor;
return (new GetOrCreateDonor())(
$userId,
$donorEmail,
$firstName,
$lastName,
$honorific
);
}

/**
Expand Down
94 changes: 94 additions & 0 deletions tests/Unit/DonationForms/Actions/TestGetOrCreateDonor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Give\Tests\Unit\DonationForms\Actions;

use Exception;
use Give\DonationForms\Actions\GetOrCreateDonor;
use Give\Donors\Models\Donor;
use Give\Tests\TestCase;
use Give\Tests\TestTraits\RefreshDatabase;

class TestGetOrCreateDonor extends TestCase
{
use RefreshDatabase;

/**
* @unreleased
*
* @throws Exception
*/
public function testShouldReturnExistingDonorWithMatchingEmail(): void
{
$donor = Donor::factory()->create(['userId' => 1]);
$action = new GetOrCreateDonor();
$donorFromActionWithMatchingEmail = $action(null, $donor->email, $donor->firstName, $donor->lastName, $donor->prefix);

$this->assertEquals($donor->toArray(), $donorFromActionWithMatchingEmail->toArray());
$this->assertFalse($action->donorCreated);
}

/**
* @unreleased
*
* @throws Exception
*/
public function testShouldReturnExistingDonorWithMatchingUserId(): void
{
$donor = Donor::factory()->create(['userId' => 1]);
$action = new GetOrCreateDonor();
$donorFromActionWithMatchingUserId = $action($donor->userId, $donor->email, 'billing first name', 'billing last name', null);

$this->assertEquals($donor->toArray(), $donorFromActionWithMatchingUserId->toArray());
$this->assertFalse($action->donorCreated);
}

/**
* @unreleased
* @throws Exception
*/
public function testShouldReturnExistingDonorWithUserIdAndUpdateAdditionalEmails(): void
{
$donor = Donor::factory()->create(['userId' => 1]);
$action = new GetOrCreateDonor();
$donorFromActionWithMatchingUserId = $action($donor->userId, '[email protected]', 'billing first name', 'billing last name', null);
$donor->additionalEmails = array_merge($donor->additionalEmails ?? [], ['[email protected]']);
$donor->save();

$this->assertEquals($donor->toArray(), $donorFromActionWithMatchingUserId->toArray());
$this->assertFalse($action->donorCreated);
}

/**
* @unreleased
*
* @throws Exception
*/
public function testShouldReturnExistingDonorWithUserIdAndNotUpdateAdditionalEmails(): void
{
$donor = Donor::factory()->create(['userId' => 1]);
$donorWithExistingEmail = Donor::factory()->create();
$action = new GetOrCreateDonor();
$donorFromActionWithMatchingUserId = $action($donor->userId, $donorWithExistingEmail->email, 'billing first name', 'billing last name', null);

$this->assertEquals($donor->toArray(), $donorFromActionWithMatchingUserId->toArray());
$this->assertFalse($action->donorCreated);
}

/**
* @unreleased
*
* @throws Exception
*/
public function testShouldReturnNewDonor(): void
{
$action = new GetOrCreateDonor();
$donorFromAction = $action(null, '[email protected]', 'Bill', 'Murray', 'Mr.');

$this->assertSame('Bill Murray', $donorFromAction->name);
$this->assertSame('Bill', $donorFromAction->firstName);
$this->assertSame('Murray', $donorFromAction->lastName);
$this->assertSame('Mr.', $donorFromAction->prefix);
$this->assertSame('[email protected]', $donorFromAction->email);
$this->assertTrue($action->donorCreated);
}
}

0 comments on commit 51e813a

Please sign in to comment.