From c9c7146ef1ae9d2d0e6fa502430cb5ffa976ad4d Mon Sep 17 00:00:00 2001 From: Rostislav Wolny Date: Mon, 6 Nov 2023 16:49:38 +0100 Subject: [PATCH] Improve table prefixing to allow Doctrine entities for WP tables WordPress tables use only the DB prefix, but MailPoet tables use DB prefix + plugin prefix (mailpoet). This commit changes TablePrefixMetadataFactory to be able to distiguish WP table for posts and adds proper prefix. [MAILPOET-5646] --- mailpoet/lib/Config/Env.php | 4 +++ .../Doctrine/TablePrefixMetadataFactory.php | 27 +++++++++++++++++-- .../TablePrefixMetadataFactoryTest.php | 15 +++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 mailpoet/tests/integration/Doctrine/TablePrefixMetadataFactoryTest.php diff --git a/mailpoet/lib/Config/Env.php b/mailpoet/lib/Config/Env.php index b31b5920dc..8a016b0f56 100644 --- a/mailpoet/lib/Config/Env.php +++ b/mailpoet/lib/Config/Env.php @@ -23,7 +23,10 @@ class Env { public static $languagesPath; public static $libPath; public static $pluginPrefix; + /** @var string WP DB prefix + plugin prefix */ public static $dbPrefix; + /** @var string WP DB prefix only */ + public static $wpDbPrefix; public static $dbHost; public static $dbIsIpv6; public static $dbSocket; @@ -78,6 +81,7 @@ class Env { global $wpdb; self::$dbPrefix = $wpdb->prefix . self::$pluginPrefix; + self::$wpDbPrefix = $wpdb->prefix; self::$dbHost = $host; self::$dbIsIpv6 = $isIpv6; self::$dbPort = $port; diff --git a/mailpoet/lib/Doctrine/TablePrefixMetadataFactory.php b/mailpoet/lib/Doctrine/TablePrefixMetadataFactory.php index f6204b1c17..a4226fb508 100644 --- a/mailpoet/lib/Doctrine/TablePrefixMetadataFactory.php +++ b/mailpoet/lib/Doctrine/TablePrefixMetadataFactory.php @@ -11,9 +11,17 @@ use MailPoetVendor\Doctrine\ORM\Mapping\ClassMetadataInfo; // because we need to add prefix at runtime, not at metadata dump (which is included in builds). // @see https://www.doctrine-project.org/projects/doctrine-orm/en/2.5/cookbook/sql-table-prefixes.html class TablePrefixMetadataFactory extends ClassMetadataFactory { + // WordPress tables that are used by MailPoet via Doctrine + const WP_TABLES = [ + 'posts', + ]; + /** @var string */ private $prefix; + /** @var string */ + private $wpDbPrefix; + /** @var array */ private $prefixedMap = []; @@ -22,6 +30,7 @@ class TablePrefixMetadataFactory extends ClassMetadataFactory { throw new \RuntimeException('DB table prefix not initialized'); } $this->prefix = Env::$dbPrefix; + $this->wpDbPrefix = Env::$wpDbPrefix; $this->setProxyClassNameResolver(new ProxyClassNameResolver()); } @@ -51,15 +60,29 @@ class TablePrefixMetadataFactory extends ClassMetadataFactory { public function addPrefix(ClassMetadata $classMetadata) { if (!$classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName() === $classMetadata->rootEntityName) { $classMetadata->setPrimaryTable([ - 'name' => $this->prefix . $classMetadata->getTableName(), + 'name' => $this->createPrefixedName($classMetadata->getTableName()), ]); } foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) { if ($mapping['type'] === ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) { + /** @var string $mappedTableName */ $mappedTableName = $mapping['joinTable']['name']; - $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName; + $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->createPrefixedName($mappedTableName); } } } + + /** + * MailPoet tables are prefixed by WP prefix + plugin prefix. + * For entities for WP tables we use WP prefix only. + */ + private function createPrefixedName(string $tableName): string { + // Use WP prefix for WP tables + if (in_array($tableName, self::WP_TABLES, true)) { + return $this->wpDbPrefix . $tableName; + } + // Use WP + plugin prefix for MailPoet tables + return $this->prefix . $tableName; + } } diff --git a/mailpoet/tests/integration/Doctrine/TablePrefixMetadataFactoryTest.php b/mailpoet/tests/integration/Doctrine/TablePrefixMetadataFactoryTest.php new file mode 100644 index 0000000000..157240d6a4 --- /dev/null +++ b/mailpoet/tests/integration/Doctrine/TablePrefixMetadataFactoryTest.php @@ -0,0 +1,15 @@ +entityManager->getClassMetadata(WpPostEntity::class); + $newslettersMetadata = $this->entityManager->getClassMetadata(NewsletterEntity::class); + verify($wpPostMetadata->getTableName())->equals('mp_posts'); + verify($newslettersMetadata->getTableName())->equals('mp_mailpoet_newsletters'); + } +}