Spaces:
No application file
No application file
| namespace Mautic\PluginBundle\Bundle; | |
| use Doctrine\DBAL\Schema\Comparator; | |
| use Doctrine\DBAL\Schema\Schema; | |
| use Doctrine\ORM\Tools\SchemaTool; | |
| use Mautic\CoreBundle\Factory\MauticFactory; | |
| use Mautic\PluginBundle\Entity\Plugin; | |
| use Symfony\Component\HttpKernel\Bundle\Bundle; | |
| /** | |
| * Base Bundle class which should be extended by addon bundles. | |
| */ | |
| abstract class PluginBundleBase extends Bundle | |
| { | |
| /** | |
| * @throws \Exception | |
| * | |
| * @deprecated To be removed in 5.0. Listen to PluginEvents::ON_PLUGIN_INSTALL instead | |
| */ | |
| public static function onPluginInstall(Plugin $plugin, MauticFactory $factory, $metadata = null, $installedSchema = null): void | |
| { | |
| if (null !== $metadata) { | |
| self::installPluginSchema($metadata, $factory, $installedSchema); | |
| } | |
| } | |
| /** | |
| * Install plugin schema based on Doctrine metadata. | |
| * | |
| * @throws \Exception | |
| */ | |
| public static function installPluginSchema(array $metadata, MauticFactory $factory, $installedSchema = null): void | |
| { | |
| if (null !== $installedSchema) { | |
| // Schema already exists, so no need to proceed | |
| return; | |
| } | |
| $db = $factory->getDatabase(); | |
| $schemaTool = new SchemaTool($factory->getEntityManager()); | |
| $installQueries = $schemaTool->getCreateSchemaSql($metadata); | |
| foreach ($installQueries as $q) { | |
| // Check if the query is a DDL statement | |
| if (self::isDDLStatement($q)) { | |
| // Execute DDL statements outside of a transaction | |
| $db->executeQuery($q); | |
| } else { | |
| // For non-DDL statements, use transactions | |
| try { | |
| $db->beginTransaction(); | |
| $db->executeQuery($q); | |
| $db->commit(); | |
| } catch (\Exception $e) { | |
| // Rollback only for non-DDL statements | |
| if ($db->isTransactionActive()) { | |
| $db->rollBack(); | |
| } | |
| throw $e; | |
| } | |
| } | |
| } | |
| } | |
| private static function isDDLStatement(string $query): bool|int | |
| { | |
| return preg_match('/^(CREATE|ALTER|DROP|RENAME|TRUNCATE|COMMENT)\s/i', $query); | |
| } | |
| /** | |
| * Called by PluginController::reloadAction when the addon version does not match what's installed. | |
| * | |
| * @throws \Exception | |
| * | |
| * @deprecated To be removed in 5.0. Listen to PluginEvents::ON_PLUGIN_UPDATE instead | |
| */ | |
| public static function onPluginUpdate( | |
| Plugin $plugin, | |
| MauticFactory $factory, | |
| $metadata = null, | |
| Schema $installedSchema = null | |
| ): void { | |
| // Not recommended although availalbe for simple schema changes - see updatePluginSchema docblock | |
| // self::updatePluginSchema($metadata, $installedSchema, $factory); | |
| } | |
| /** | |
| * Update plugin schema based on Doctrine metadata. | |
| * | |
| * WARNING - this is not recommended as Doctrine does not guarantee results. There is a risk | |
| * that Doctrine will generate an incorrect query leading to lost data. If using this method, | |
| * be sure to thoroughly test the queries Doctrine generates | |
| * | |
| * @throws \Doctrine\DBAL\ConnectionException | |
| * @throws \Exception | |
| */ | |
| public static function updatePluginSchema(array $metadata, Schema $installedSchema, MauticFactory $factory): void | |
| { | |
| $db = $factory->getDatabase(); | |
| $schemaTool = new SchemaTool($factory->getEntityManager()); | |
| $toSchema = $schemaTool->getSchemaFromMetadata($metadata); | |
| $comparator = (new Comparator())->compareSchemas($installedSchema, $toSchema); | |
| $databasePlatform = $db->getDatabasePlatform(); | |
| $queries = $databasePlatform->getAlterSchemaSQL($comparator); | |
| $db->beginTransaction(); | |
| try { | |
| foreach ($queries as $q) { | |
| $db->executeQuery($q); | |
| } | |
| $db->commit(); | |
| } catch (\Exception $e) { | |
| $db->rollback(); | |
| throw $e; | |
| } | |
| } | |
| /** | |
| * Not used yet :-). | |
| */ | |
| public static function onPluginUninstall(Plugin $plugin, MauticFactory $factory, $metadata = null): void | |
| { | |
| } | |
| /** | |
| * Drops plugin's tables based on Doctrine metadata. | |
| * | |
| * @throws \Doctrine\DBAL\ConnectionException | |
| * @throws \Exception | |
| */ | |
| public static function dropPluginSchema(array $metadata, MauticFactory $factory): void | |
| { | |
| $db = $factory->getDatabase(); | |
| $schemaTool = new SchemaTool($factory->getEntityManager()); | |
| $dropQueries = $schemaTool->getDropSchemaSQL($metadata); | |
| $db->beginTransaction(); | |
| try { | |
| foreach ($dropQueries as $q) { | |
| $db->executeQuery($q); | |
| } | |
| $db->commit(); | |
| } catch (\Exception $e) { | |
| $db->rollback(); | |
| throw $e; | |
| } | |
| } | |
| } | |