AzuraCast/src/Entity/Migration/Version20201027130504.php

230 lines
7.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Entity\Migration;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20201027130504 extends AbstractMigration
{
public function getDescription(): string
{
return 'Song storage consolidation, part 2.';
}
public function preUp(Schema $schema): void
{
// Create temp index
$this->addSql(
'CREATE INDEX IF NOT EXISTS IDX_TEMP_CONVERT ON station_media (path, storage_location_id, station_id)'
);
// Create initial backup directory.
$this->connection->insert(
'storage_location',
[
'type' => 'backup',
'adapter' => 'local',
'path' => '/var/azuracast/backups',
]
);
$storageLocationId = $this->connection->lastInsertId();
$this->connection->update(
'settings',
[
'setting_value' => $storageLocationId,
],
[
'setting_key' => 'backup_storage_location',
]
);
// Migrate existing directories to new StorageLocation paradigm.
$stations = $this->connection->fetchAllAssociative(
'SELECT id, radio_base_dir, radio_media_dir, storage_quota FROM station WHERE media_storage_location_id IS NULL ORDER BY id ASC'
);
$directories = [];
foreach ($stations as $row) {
$stationId = $row['id'];
$baseDir = $row['radio_base_dir'];
$mediaDir = $row['radio_media_dir'];
if (empty($mediaDir)) {
$mediaDir = $baseDir . '/media';
}
if (isset($directories[$mediaDir])) {
$directories[$mediaDir]['stations'][] = $stationId;
} else {
$directories[$mediaDir] = [
'stations' => [$stationId],
'storageQuota' => $row['storage_quota'],
'albumArtDir' => $baseDir . '/album_art',
'waveformsDir' => $baseDir . '/waveforms',
];
}
// Create recordings dir.
$this->connection->insert(
'storage_location',
[
'type' => 'station_recordings',
'adapter' => 'local',
'path' => $baseDir . '/recordings',
'storage_quota' => $row['storage_quota'],
]
);
$recordingsStorageLocationId = $this->connection->lastInsertId();
$this->connection->update(
'station',
[
'recordings_storage_location_id' => $recordingsStorageLocationId,
],
[
'id' => $stationId,
]
);
}
foreach ($directories as $path => $dirInfo) {
$newAlbumArtDir = $path . '/.albumart';
rename($dirInfo['albumArtDir'], $newAlbumArtDir);
$newWaveformsDir = $path . '/.waveforms';
rename($dirInfo['waveformsDir'], $newWaveformsDir);
$this->connection->insert(
'storage_location',
[
'type' => 'station_media',
'adapter' => 'local',
'path' => $path,
'storage_quota' => $dirInfo['storageQuota'],
]
);
$mediaStorageLocationId = $this->connection->lastInsertId();
foreach ($dirInfo['stations'] as $stationId) {
$this->connection->update(
'station',
[
'media_storage_location_id' => $mediaStorageLocationId,
],
[
'id' => $stationId,
]
);
}
$firstStationId = array_shift($dirInfo['stations']);
$this->connection->executeQuery(
'UPDATE station_media SET storage_location_id=? WHERE station_id = ?',
[
$mediaStorageLocationId,
$firstStationId,
],
[
ParameterType::INTEGER,
ParameterType::INTEGER,
]
);
foreach ($dirInfo['stations'] as $stationId) {
$media = $this->connection->fetchAllAssociative(
'SELECT sm.id, sm.path FROM station_media AS sm WHERE sm.station_id = ?',
[
$stationId,
],
[
ParameterType::INTEGER,
]
);
foreach ($media as [$oldMediaId, $mediaPath]) {
$newMediaId = $this->connection->fetchOne(
'SELECT sm.id FROM station_media AS sm WHERE sm.path = ? AND sm.storage_location_id = ?',
[
$mediaPath,
$mediaStorageLocationId,
],
[
ParameterType::STRING,
ParameterType::INTEGER,
]
);
if ($newMediaId) {
$tablesToUpdate = [
'song_history' => 'media_id',
'station_playlist_media' => 'media_id',
'station_queue' => 'media_id',
'station_requests' => 'track_id',
];
foreach ($tablesToUpdate as $table => $fieldName) {
$this->connection->update(
$table,
[
$fieldName => $newMediaId,
],
[
$fieldName => $oldMediaId,
]
);
}
}
}
$this->connection->executeQuery(
'DELETE FROM station_media WHERE station_id = ?',
[
$stationId,
],
[
ParameterType::INTEGER,
]
);
}
}
// Drop temp index
$this->addSql('DROP INDEX IF EXISTS IDX_TEMP_CONVERT ON station_media');
}
public function up(Schema $schema): void
{
$this->addSql(
'ALTER TABLE station_media ADD CONSTRAINT FK_32AADE3ACDDD8AF FOREIGN KEY (storage_location_id) REFERENCES storage_location (id) ON DELETE CASCADE'
);
$this->addSql('CREATE INDEX IDX_32AADE3ACDDD8AF ON station_media (storage_location_id)');
$this->addSql('CREATE UNIQUE INDEX path_unique_idx ON station_media (path, storage_location_id)');
$this->addSql('ALTER TABLE station DROP radio_media_dir, DROP storage_quota, DROP storage_used');
$this->addSql('ALTER TABLE station_media DROP station_id');
}
public function down(Schema $schema): void
{
$this->addSql(
'ALTER TABLE station ADD radio_media_dir VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_general_ci`, ADD storage_quota BIGINT DEFAULT NULL, ADD storage_used BIGINT DEFAULT NULL'
);
$this->addSql('ALTER TABLE station_media ADD station_id INT NOT NULL');
$this->addSql('ALTER TABLE station_media DROP FOREIGN KEY FK_32AADE3ACDDD8AF');
$this->addSql('DROP INDEX IDX_32AADE3ACDDD8AF ON station_media');
$this->addSql('DROP INDEX path_unique_idx ON station_media');
}
}