Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Update Forms to Campaigns migration #7532

Merged
merged 12 commits into from
Sep 12, 2024
161 changes: 122 additions & 39 deletions src/Campaigns/Migrations/MigrateFormsToCampaignForms.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

namespace Give\Campaigns\Migrations;

use DateTime;
use Give\Campaigns\Models\Campaign;
use Give\Campaigns\ValueObjects\CampaignStatus;
use Give\Campaigns\ValueObjects\CampaignType;
use Give\DonationForms\Models\DonationForm;
use Give\DonationForms\ValueObjects\DonationFormStatus;
use Give\Framework\Database\DB;
use Give\Framework\Database\Exceptions\DatabaseQueryException;
use Give\Framework\Migrations\Contracts\Migration;
use Give\Framework\Migrations\Exceptions\DatabaseMigrationException;
use Give\Framework\QueryBuilder\JoinQueryBuilder;

/**
* @unreleased
Expand All @@ -29,66 +26,152 @@ public static function id(): string
*/
public static function timestamp(): int
{
return strtotime('2024-08-21');
return strtotime('2024-08-26 00:00:01');
}

/**
* @unreleased
* @inheritDoc
* @throws \Exception
*/
public function run()
kjohnson marked this conversation as resolved.
Show resolved Hide resolved
{
foreach(DonationForm::query()->getAll() ?? [] as $form) {
$this->createParentCampaignForDonationForm($form);
}
DB::transaction(function() {
try {
array_map([$this, 'createCampaignForForm'], $this->getFormData());
array_map([$this, 'addUpgradedFormToCampaign'], $this->getUpgradedFormData());
kjohnson marked this conversation as resolved.
Show resolved Hide resolved
} catch (DatabaseQueryException $exception) {
DB::rollback();
throw new DatabaseMigrationException('An error occurred while creating initial campaigns', 0, $exception);
}
});
}

/**
* @unreleased
*/
protected function getFormData(): array
{
$query = DB::table('posts', 'forms')
->select(
['forms.ID', 'id'],
['forms.post_title', 'title'],
['forms.post_status', 'status'],
['forms.post_date', 'createdAt']
)
->where('forms.post_type', 'give_forms');

$query->select(['formmeta.meta_value', 'settings'])
->join(function (JoinQueryBuilder $builder) {
$builder
->leftJoin('give_formmeta', 'formmeta')
->on('formmeta.form_id', 'forms.ID');
})
->where('formmeta.meta_key', 'formBuilderSettings');

// Exclude forms already associated with a campaign (ie Peer-to-peer).
$query->join(function (JoinQueryBuilder $builder) {
$builder
->leftJoin('give_campaigns', 'campaigns')
->on('campaigns.form_id', 'forms.ID');
})
->whereIsNull('campaigns.id');

// Exclude forms with an `upgraded` status, which are archived.
$query->where('forms.post_status', 'upgraded', '!=');

return $query->getAll();
}

/**
* @unreleased
* @return array [{formId, campaignId, migratedFormId}]
*/
public function createParentCampaignForDonationForm(DonationForm $form)
protected function getUpgradedFormData(): array
{
$campaign = Campaign::create([
'type' => CampaignType::CORE(),
'title' => $form->title,
'shortDescription' => $form->settings->formExcerpt,
'longDescription' => $form->settings->description,
'logo' => $form->settings->designSettingsLogoUrl,
'image' => $form->settings->designSettingsImageUrl,
'primaryColor' => $form->settings->primaryColor,
'secondaryColor' => $form->settings->secondaryColor,
'goal' => (int) $form->settings->goalAmount,
'status' => $this->mapFormStatusToCampaignStatus($form->status),
'startDate' => new DateTime($form->settings->goalStartDate),
'endDate' => new DateTime($form->settings->goalEndDate),
]);
return DB::table('posts', 'forms')
->select(['forms.ID', 'formId'], ['campaign_forms.campaign_id', 'campaignId'])
->attachMeta('give_formmeta', 'ID', 'form_id', 'migratedFormId')
->join(function (JoinQueryBuilder $builder) {
$builder
->rightJoin('give_campaign_forms', 'campaign_forms')
->on('campaign_forms.form_id', 'forms.ID');
})
->where('forms.post_type', 'give_forms')
->whereIsNotNull('give_formmeta_attach_meta_migratedFormId.meta_value')
->getAll();
}

/**
* @unreleased
*/
public function createCampaignForForm($formData): void
{
$formId = $formData->id;
$formTitle = $formData->title;
$formStatus = $formData->status;
$formCreatedAt = $formData->createdAt;
$formSettings = json_decode($formData->settings);

$campaignId = DB::table('give_campaigns')
->insert([
'campaign_type' => 'core',
'campaign_title' => $formTitle,
'status' => $this->mapFormToCampaignStatus($formStatus),
'short_desc' => $formSettings->formExcerpt,
'long_desc' => $formSettings->description,
'campaign_logo' => $formSettings->designSettingsLogoUrl,
'campaign_image' => $formSettings->designSettingsImageUrl,
'primary_color' => $formSettings->primaryColor,
'secondary_color' => $formSettings->secondaryColor,
'campaign_goal' => $formSettings->goalAmount,
'start_date' => $formSettings->goalStartDate,
'end_date' => $formSettings->goalEndDate,
'date_created' => $formCreatedAt,
]);

DB::table('give_campaign_forms')
->insert([
'form_id' => $form->id,
'campaign_id' => $campaign->id,
'form_id' => $formId,
'campaign_id' => $campaignId,
'is_default' => true,
]);
}

/**
/**
* @param $data
*/
protected function addUpgradedFormToCampaign($data): void
{
DB::table('give_campaign_forms')
->insert([
'form_id' => $data->migratedFormId,
'campaign_id' => $data->campaignId,
]);
}

/**
* @unreleased
*/
public function mapFormStatusToCampaignStatus(DonationFormStatus $status)
public function mapFormToCampaignStatus(string $status): string
{
switch ($status) {
case DonationFormStatus::PUBLISHED():
case DonationFormStatus::UPGRADED(): // TODO: How do we handle upgraded, non-upgraded forms?
case DonationFormStatus::PRIVATE(): // TODO: How do we handle Private forms?
return CampaignStatus::ACTIVE();

case DonationFormStatus::PENDING():
return CampaignStatus::PENDING();
case 'pending':
return 'pending';

case 'draft':
return 'draft';

case 'trash':
return 'inactive';

case DonationFormStatus::DRAFT():
return CampaignStatus::DRAFT();
case 'publish':
case 'private':
return 'active';

case DonationFormStatus::TRASH():
return CampaignStatus::INACTIVE();
default: // TODO: How do we handle an unknown form status?
return 'inactive';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function run(): void
$sql = "CREATE TABLE $table (
campaign_id INT UNSIGNED NOT NULL,
form_id INT UNSIGNED NOT NULL,
is_default BOOLEAN NOT NULL DEFAULT 0,
KEY form_id (form_id),
KEY campaign_id (campaign_id),
PRIMARY KEY (campaign_id, form_id)
Expand Down
10 changes: 10 additions & 0 deletions src/Campaigns/Models/Campaign.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ class Campaign extends Model implements ModelCrud, ModelHasFactory
'createdAt' => DateTime::class,
];

/**
* @unreleased
*/
public function form(): DonationForm
{
return $this->forms()
->where('campaign_forms.is_default', true)
->get();
}

/**
* @unreleased
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Give\Campaigns\Migrations\MigrateFormsToCampaignForms;
use Give\Campaigns\Models\Campaign;
use Give\DonationForms\Models\DonationForm;
use Give\DonationForms\ValueObjects\DonationFormStatus;
use Give\Framework\Database\DB;
use Give\Tests\TestCase;
use Give\Tests\TestTraits\RefreshDatabase;
Expand All @@ -24,11 +25,82 @@ public function testCreatesParentCampaignForDonationForm()
$form = DonationForm::factory()->create();
$migration = new MigrateFormsToCampaignForms();

$migration->createParentCampaignForDonationForm($form);
$migration->run();

$relationship = DB::table('give_campaign_forms')->where('form_id', $form->id)->get();

$this->assertNotNull(Campaign::find($relationship->campaign_id));
$this->assertEquals($form->id, $relationship->form_id);
}

/**
* @unreleased
*/
public function testExistingPeerToPeerCampaignFormsAreNotMigrated()
{
$form = DonationForm::factory()->create();
DB::table('give_campaigns')->insert([
'form_id' => $form->id,
]);

$migration = new MigrateFormsToCampaignForms();
$migration->run();

$relationship = DB::table('give_campaign_forms')->where('form_id', $form->id)->get();

$this->assertNull($relationship);
$this->assertEquals(1, DB::table('give_campaigns')->count());
}

/**
* @unreleased
*/
public function testUpgradedFormsAreNotMigrated()
{
$form = DonationForm::factory()->create([
'status' => DonationFormStatus::UPGRADED(),
]);

$migration = new MigrateFormsToCampaignForms();
$migration->run();

$relationship = DB::table('give_campaign_forms')->where('form_id', $form->id)->get();

$this->assertNull($relationship);
$this->assertEquals(0, DB::table('give_campaigns')->count());
}

/**
* @unreleased
*/
public function testMigratedFormsAreDefault()
{
$form = DonationForm::factory()->create();

$migration = new MigrateFormsToCampaignForms();
$migration->run();

$relationship = DB::table('give_campaign_forms')->where('form_id', $form->id)->get();

$this->assertEquals(1, $relationship->is_default);
}

/**
* @unreleased
*/
public function testUpgradedFormsAreNotDefault()
{
$form1 = DonationForm::factory()->create([
'status' => DonationFormStatus::UPGRADED(),
]);
$form2 = DonationForm::factory()->create();
give_update_meta($form2->id, 'migratedFormId', $form1->id);

$migration = new MigrateFormsToCampaignForms();
$migration->run();

$relationship = DB::table('give_campaign_forms')->where('form_id', $form1->id)->get();

$this->assertEquals(0, $relationship->is_default);
}
}
16 changes: 16 additions & 0 deletions tests/Unit/Campaigns/Models/CampaignModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,20 @@ public function testCampaignHasManyForms()

$this->assertEquals(2, $campaign->forms()->count());
}

/**
* @unreleased
*/
public function testCampaignHasDefaultForm()
{
$campaign = Campaign::factory()->create();
$form1 = DonationForm::factory()->create();
$form2 = DonationForm::factory()->create();

$db = DB::table('give_campaign_forms');
$db->insert(['form_id' => $form1->id, 'campaign_id' => $campaign->id, 'is_default' => 1]);
$db->insert(['form_id' => $form2->id, 'campaign_id' => $campaign->id]);

$this->assertEquals($form1->id, $campaign->form()->id);
}
}
Loading