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->wpSegment = $wpSegment;
$this->referralDetector = $referralDetector; $this->referralDetector = $referralDetector;
$this->prefix = Env::$dbPrefix; $this->prefix = Env::$dbPrefix;
$this->models = [ $this->models = [];
'newsletter_option_fields',
];
$this->templates = [ $this->templates = [
'WelcomeBlank1Column', 'WelcomeBlank1Column',
'WelcomeBlank12Column', 'WelcomeBlank12Column',
@@ -169,6 +167,7 @@ class Populator {
$localizer->forceLoadWebsiteLocaleText(); $localizer->forceLoadWebsiteLocaleText();
array_map([$this, 'populate'], $this->models); array_map([$this, 'populate'], $this->models);
$this->populateNewsletterOptionFields();
$this->populateNewsletterTemplates(); $this->populateNewsletterTemplates();
$this->createDefaultSegment(); $this->createDefaultSegment();
@@ -382,7 +381,7 @@ class Populator {
return $defaultSegment; return $defaultSegment;
} }
protected function newsletterOptionFields() { private function populateNewsletterOptionFields() {
$optionFields = [ $optionFields = [
[ [
'name' => 'isScheduled', 'name' => 'isScheduled',
@@ -510,13 +509,33 @@ class Populator {
], ],
]; ];
return [ // 1. Load all existing option fields from the database.
'rows' => $optionFields, $tableName = $this->entityManager->getClassMetadata(NewsletterOptionFieldEntity::class)->getTableName();
'identification_columns' => [ $connection = $this->entityManager->getConnection();
'name', $existingOptionFields = $connection->createQueryBuilder()
'newsletter_type', ->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 { private function populateNewsletterTemplates(): void {

View File

@@ -3,13 +3,48 @@
namespace MailPoet\Test\Config; namespace MailPoet\Test\Config;
use MailPoet\Config\Populator; use MailPoet\Config\Populator;
use MailPoet\Entities\NewsletterOptionFieldEntity;
use MailPoet\Entities\NewsletterTemplateEntity; use MailPoet\Entities\NewsletterTemplateEntity;
use MailPoetTest; use MailPoetTest;
use MailPoetVendor\Doctrine\ORM\Query; use MailPoetVendor\Doctrine\ORM\Query;
class PopulatorTest extends MailPoetTest { class PopulatorTest extends MailPoetTest {
private const OPTION_FIELD_COUNT = 31;
private const TEMPLATE_COUNT = 76; 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 { public function testItInsertsTemplates(): void {
$populator = $this->diContainer->get(Populator::class); $populator = $this->diContainer->get(Populator::class);
@@ -86,6 +121,15 @@ class PopulatorTest extends MailPoetTest {
$this->assertSame(self::TEMPLATE_COUNT, count($templates)); $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 { private function getAllTemplates(): array {
return (array)$this->entityManager->createQueryBuilder() return (array)$this->entityManager->createQueryBuilder()
->select('t') ->select('t')