db->getQueryBuilder(); $selectQueryBuilder->select('accounts.id') ->from('mail_accounts', 'accounts') ->leftJoin( 'accounts', 'mail_mailboxes', 'mailboxes', $selectQueryBuilder->expr()->eq( "accounts.{$mailboxType}_mailbox_id", 'mailboxes.id', IQueryBuilder::PARAM_INT ) ) ->where($selectQueryBuilder->expr()->isNull('mailboxes.id')) ->andWhere($selectQueryBuilder->expr()->isNotNull("accounts.{$mailboxType}_mailbox_id")); try { $affectedRows = $selectQueryBuilder->executeQuery()->fetchAll(); foreach ($affectedRows as $row) { $updateQueryBuilder = $this->db->getQueryBuilder(); $updateQueryBuilder->update('mail_accounts') ->set( "{$mailboxType}_mailbox_id", $updateQueryBuilder->createNamedParameter(null, IQueryBuilder::PARAM_NULL) ) ->where( $updateQueryBuilder->expr()->eq( 'id', $updateQueryBuilder->createNamedParameter($row['id'], IQueryBuilder::PARAM_INT) ) ); $updateQueryBuilder->executeStatement(); } } catch (Exception $e) { $this->logger->error("Emptying inconsistent {$mailboxType}_mailbox_id field failed", [ 'exception' => $e ]); } } /** * @param Table $accountsTable * @param Table $mailboxesTable * @param string $mailboxType * @return void */ private function addMailboxKey(Table $accountsTable, Table $mailboxesTable, string $mailboxType): void { $accountsTable->addForeignKeyConstraint( $mailboxesTable, ["{$mailboxType}_mailbox_id"], ['id'], [ 'onDelete' => 'SET NULL', ], ); } /** * @param IOutput $output * @param Closure(): ISchemaWrapper $schemaClosure * @param array $options */ #[Override] public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { $this->removeInconsistentMailboxEntries('drafts'); $this->removeInconsistentMailboxEntries('sent'); $this->removeInconsistentMailboxEntries('trash'); $this->removeInconsistentMailboxEntries('junk'); $this->removeInconsistentMailboxEntries('archive'); $this->removeInconsistentMailboxEntries('snooze'); } /** * @param IOutput $output * @param Closure(): ISchemaWrapper $schemaClosure * @param array $options * @return null|ISchemaWrapper */ #[Override] public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { $schema = $schemaClosure(); if ($schema->hasTable('mail_accounts')) { $accountsTable = $schema->getTable('mail_accounts'); $mailboxesTable = $schema->getTable('mail_mailboxes'); $this->addMailboxKey($accountsTable, $mailboxesTable, 'drafts'); $this->addMailboxKey($accountsTable, $mailboxesTable, 'sent'); $this->addMailboxKey($accountsTable, $mailboxesTable, 'trash'); $this->addMailboxKey($accountsTable, $mailboxesTable, 'junk'); $this->addMailboxKey($accountsTable, $mailboxesTable, 'archive'); $this->addMailboxKey($accountsTable, $mailboxesTable, 'snooze'); } return $schema; } }