Files
myep-team/migrations/Version20260820000000.php
T

65 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Admin-edited mail bodies used to be plain text in which a single *asterisk* made a word
* bold. They are Markdown now (App\Email\MailBodyRenderer), where that is italic and bold
* is written **twice**, so every saved body is rewritten once.
*
* Only `body` is touched: `subject` never took markers, and `headline` is plain text under
* the new renderer, so a marker left in one is meant to stay the character it is.
*/
final class Version20260820000000 extends AbstractMigration
{
/**
* A single asterisk pair on one line. The lookarounds keep three things out: an already
* doubled **bold**, an escaped \* an admin wrote to get a literal asterisk, and a marker
* with whitespace next to it - "a * b * c" and "5 * 3" are arithmetic, not emphasis.
* That last rule is CommonMark's own, and slightly stricter than the renderer this
* replaces: a text that leant on the old, laxer matching loses its bold here rather
* than turning into something nobody wrote.
*/
private const SINGLE_EMPHASIS = '/(?<![\\\\*])\*(?!\*)(?!\s)([^*\n]+?)(?<![\s\\\\*])\*(?!\*)/u';
private const DOUBLE_EMPHASIS = '/(?<![\\\\*])\*\*(?!\*)(?!\s)([^*\n]+?)(?<![\s\\\\*])\*\*(?!\*)/u';
public function getDescription(): string
{
return 'Rewrite *bold* to **bold** in saved email texts, which are Markdown now';
}
public function up(Schema $schema): void
{
$this->rewriteBodies(self::SINGLE_EMPHASIS, '**$1**');
}
public function down(Schema $schema): void
{
$this->rewriteBodies(self::DOUBLE_EMPHASIS, '*$1*');
}
/**
* The rewrite happens in PHP, one row at a time: MySQL's REGEXP_REPLACE has no
* lookbehind, and getting this wrong would quietly mangle wording that goes out to
* every teamer. Only the read is done here and now - the writes go through addSql, so
* they are logged and rolled back like any other migration statement.
*/
private function rewriteBodies(string $pattern, string $replacement): void
{
foreach ($this->connection->fetchAllAssociative('SELECT id, body FROM email_text') as $row) {
$body = preg_replace($pattern, $replacement, (string) $row['body']);
if (null === $body || $body === $row['body']) {
continue;
}
$this->addSql('UPDATE email_text SET body = ? WHERE id = ?', [$body, $row['id']]);
}
}
}