Optimize populating newsletter option fields

This commit is contained in:
Jan Jakes
2024-09-03 15:41:32 +02:00
committed by Jan Jakeš
parent 974add271a
commit a416cecddf
2 changed files with 74 additions and 11 deletions

View File

@@ -78,9 +78,7 @@ class Populator {
$this->wpSegment = $wpSegment;
$this->referralDetector = $referralDetector;
$this->prefix = Env::$dbPrefix;
$this->models = [
'newsletter_option_fields',
];
$this->models = [];
$this->templates = [
'WelcomeBlank1Column',
'WelcomeBlank12Column',
@@ -169,6 +167,7 @@ class Populator {
$localizer->forceLoadWebsiteLocaleText();
array_map([$this, 'populate'], $this->models);
$this->populateNewsletterOptionFields();
$this->populateNewsletterTemplates();
$this->createDefaultSegment();
@@ -382,7 +381,7 @@ class Populator {
return $defaultSegment;
}
protected function newsletterOptionFields() {
private function populateNewsletterOptionFields() {
$optionFields = [
[
'name' => 'isScheduled',
@@ -510,13 +509,33 @@ class Populator {
],
];
return [
'rows' => $optionFields,
'identification_columns' => [
'name',
'newsletter_type',
],
];
// 1. Load all existing option fields from the database.
$tableName = $this->entityManager->getClassMetadata(NewsletterOptionFieldEntity::class)->getTableName();
$connection = $this->entityManager->getConnection();
$existingOptionFields = $connection->createQueryBuilder()
->select('of.name, of.newsletter_type')
->from($tableName, 'of')
->executeQuery()
->fetchAllAssociative();
// 2. Insert new option fields using a single query (good for first installs).
$inserts = array_udiff(
$optionFields,
$existingOptionFields,
fn($a, $b) => [$a['name'], $a['newsletter_type']] <=> [$b['name'], $b['newsletter_type']]
);
if ($inserts) {
$placeholders = implode(',', array_fill(0, count($inserts), '(?, ?)'));
$connection->executeStatement(
"INSERT INTO $tableName (name, newsletter_type) VALUES $placeholders",
array_merge(
...array_map(
fn($of) => [$of['name'], $of['newsletter_type']],
$inserts
)
)
);
}
}
private function populateNewsletterTemplates(): void {

View File

@@ -3,13 +3,48 @@
namespace MailPoet\Test\Config;
use MailPoet\Config\Populator;
use MailPoet\Entities\NewsletterOptionFieldEntity;
use MailPoet\Entities\NewsletterTemplateEntity;
use MailPoetTest;
use MailPoetVendor\Doctrine\ORM\Query;
class PopulatorTest extends MailPoetTest {
private const OPTION_FIELD_COUNT = 31;
private const TEMPLATE_COUNT = 76;
public function testItInsertsOptionFields(): void {
$populator = $this->diContainer->get(Populator::class);
// no option fields
$this->entityManager->createQueryBuilder()
->delete(NewsletterOptionFieldEntity::class, 'f')
->getQuery()
->execute();
$optionFields = $this->getAllOptionFields();
$this->assertSame(0, count($optionFields));
// insert all option fields
$populator->up();
$optionFields = $this->getAllOptionFields();
$this->assertSame(self::OPTION_FIELD_COUNT, count($optionFields));
// delete only some fields
$this->entityManager->createQueryBuilder()
->delete(NewsletterOptionFieldEntity::class, 'f')
->where('f.id IN (:ids)')
->setParameter('ids', array_map(fn($field) => $field->getId(), array_slice($optionFields, 0, 10)))
->getQuery()
->execute();
$optionFields = $this->getAllOptionFields();
$this->assertSame(self::OPTION_FIELD_COUNT - 10, count($optionFields));
// insert new option fields
$populator->up();
$optionFields = $this->getAllOptionFields();
$this->assertSame(self::OPTION_FIELD_COUNT, count($optionFields));
}
public function testItInsertsTemplates(): void {
$populator = $this->diContainer->get(Populator::class);
@@ -86,6 +121,15 @@ class PopulatorTest extends MailPoetTest {
$this->assertSame(self::TEMPLATE_COUNT, count($templates));
}
private function getAllOptionFields(): array {
return (array)$this->entityManager->createQueryBuilder()
->select('f')
->from(NewsletterOptionFieldEntity::class, 'f')
->getQuery()
->setHint(Query::HINT_REFRESH, true)
->getResult();
}
private function getAllTemplates(): array {
return (array)$this->entityManager->createQueryBuilder()
->select('t')