feat: replace php migration with django migration
- keep latest legacy version in initial migration file - move propel schema to api legacy app - remove legacy upgrade tool
This commit is contained in:
parent
ee98387264
commit
0e4bc4cacd
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class LegacyConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "libretime_api.legacy"
|
||||
verbose_name = "LibreTime Legacy"
|
|
@ -0,0 +1,29 @@
|
|||
from pathlib import Path
|
||||
|
||||
from django.db import connection, migrations
|
||||
|
||||
from . import LEGACY_SCHEMA_VERSION
|
||||
from ._migrations import get_schema_version, set_schema_version
|
||||
|
||||
here = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def create_schema(_apps, _schema_editor):
|
||||
schema_version = get_schema_version()
|
||||
|
||||
# A schema already exists, don't overwrite !
|
||||
if schema_version is not None:
|
||||
return
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
for migration_filename in ("schema.sql", "data.sql"):
|
||||
raw = (here / "sql" / migration_filename).read_text(encoding="utf-8")
|
||||
cursor.execute(raw)
|
||||
|
||||
set_schema_version(cursor, LEGACY_SCHEMA_VERSION)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
dependencies = []
|
||||
operations = [migrations.RunPython(create_schema)]
|
|
@ -0,0 +1,28 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
-- Replacing system_version with schema_version
|
||||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('schema_version', '2.5.2');
|
||||
|
||||
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
|
||||
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0001_initial"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.2",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
-- DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
-- INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.3');
|
||||
|
||||
ALTER TABLE cc_files DROP COLUMN state;
|
||||
ALTER TABLE cc_files ADD import_status integer default 1; -- Default is "pending"
|
||||
UPDATE cc_files SET import_status=0; -- Existing files are already "imported"
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0003_2_5_2"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.3",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,61 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = None
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
def promote_admin_to_superadmin(cursor):
|
||||
# Ensure there are no superadmins already
|
||||
super_admin_count = cursor.execute(
|
||||
"""
|
||||
SELECT COUNT(id)
|
||||
FROM cc_subjs
|
||||
WHERE type = 'S'
|
||||
AND login != 'sourcefabric_admin';
|
||||
"""
|
||||
).fetchone()
|
||||
if super_admin_count != 0:
|
||||
return
|
||||
|
||||
# Promote the "admin" user to superadmin
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE cc_subjs SET type = 'S'
|
||||
WHERE login = 'admin';
|
||||
"""
|
||||
)
|
||||
if cursor.rowcount == 0:
|
||||
# Otherwise promote the administrator with the lowest ID
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE cc_subjs SET type = 'S'
|
||||
WHERE id = (
|
||||
SELECT id
|
||||
FROM cc_subjs
|
||||
WHERE type = 'A'
|
||||
ORDER BY id
|
||||
LIMIT 1
|
||||
);
|
||||
"""
|
||||
)
|
||||
if cursor.rowcount == 0:
|
||||
raise RuntimeError("Failed to find any users of type 'admin' ('A')")
|
||||
|
||||
# Ignoring the sourcefabric_admin user
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0004_2_5_3"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.4",
|
||||
before=promote_admin_to_superadmin,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
-- DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
-- INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.5');
|
||||
|
||||
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
|
||||
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0005_2_5_4"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.5",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
CREATE TABLE cloud_file
|
||||
(
|
||||
id serial NOT NULL,
|
||||
resource_id text NOT NULL,
|
||||
storage_backend text NOT NULL,
|
||||
cc_file_id integer NOT NULL,
|
||||
CONSTRAINT cloud_file_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT "cloud_file_FK_1" FOREIGN KEY (cc_file_id)
|
||||
REFERENCES cc_files (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION ON DELETE CASCADE
|
||||
)
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0006_2_5_5"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.9",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,24 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_files ADD COLUMN filesize integer NOT NULL
|
||||
CONSTRAINT filesize_default DEFAULT 0
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0007_2_5_9"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.10",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = None
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
def update_disk_usage(cursor):
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE cc_pref SET valstr = (
|
||||
SELECT SUM(filesize)
|
||||
FROM cc_files
|
||||
)
|
||||
WHERE keystr = 'disk_usage';
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0008_2_5_10"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.11",
|
||||
sql=update_disk_usage,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,24 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_show ALTER COLUMN description TYPE varchar(8192);
|
||||
ALTER TABLE cc_show_instances ALTER COLUMN description TYPE varchar(8192);
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0009_2_5_11"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.12",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -1,3 +1,8 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
-----------------------------------------------------------------------
|
||||
-- third_party_track_references
|
||||
-----------------------------------------------------------------------
|
||||
|
@ -40,3 +45,35 @@ ALTER TABLE "celery_tasks" ADD CONSTRAINT "celery_service_fkey"
|
|||
FOREIGN KEY ("track_reference")
|
||||
REFERENCES "third_party_track_references" ("id")
|
||||
ON DELETE CASCADE;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
-----------------------------------------------------------------------
|
||||
-- third_party_track_references
|
||||
-----------------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS "third_party_track_references" CASCADE;
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- celery_tasks
|
||||
-----------------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS "celery_tasks" CASCADE;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0010_2_5_12"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.13",
|
||||
sql=UP,
|
||||
),
|
||||
reverse_code=legacy_migration_factory(
|
||||
target="2.5.12",
|
||||
sql=DOWN,
|
||||
reverse=True,
|
||||
),
|
||||
)
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
# SAAS-923
|
||||
# Add a partial constraint to cc_pref so that keystrings must be unique
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_pref ALTER COLUMN subjid SET DEFAULT NULL;
|
||||
CREATE UNIQUE INDEX cc_pref_key_idx ON cc_pref (keystr) WHERE subjid IS NULL;
|
||||
ANALYZE cc_pref;
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0011_2_5_13"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.14",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,30 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
# SAAS-1071
|
||||
# Remove not null constraint from file_id fk in third_party_track_references
|
||||
# so that we can create track references for downloads (which won't have a
|
||||
# file ID until the task is run and the file is POSTed back to Airtime)
|
||||
|
||||
UP = """
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP NOT NULL;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET NOT NULL;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0012_2_5_14"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.15",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -1,3 +1,8 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_files ADD COLUMN description VARCHAR(512);
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
@ -88,3 +93,33 @@ ALTER TABLE "podcast_episodes" ADD CONSTRAINT "podcast_episodes_podcast_id_fkey"
|
|||
FOREIGN KEY ("podcast_id")
|
||||
REFERENCES "podcast" ("id")
|
||||
ON DELETE CASCADE;
|
||||
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_files DROP COLUMN description;
|
||||
|
||||
DELETE FROM cc_pref WHERE keystr = 'station_podcast_id';
|
||||
|
||||
DROP TABLE IF EXISTS "podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "imported_podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "station_podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "podcast_episodes" CASCADE;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0013_2_5_15"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.16",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_files ADD COLUMN artwork TYPE character varying(255);
|
||||
"""
|
||||
|
||||
DOWN = None
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0014_2_5_16"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="2.5.17",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_show ADD COLUMN has_autoplaylist boolean default 'f' NOT NULL;
|
||||
ALTER TABLE cc_show ADD COLUMN autoplaylist_id integer DEFAULT NULL;
|
||||
ALTER TABLE cc_show_instances ADD COLUMN autoplaylist_built boolean default 'f' NOT NULL;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_show_instances DROP COLUMN IF EXISTS autoplaylist_built;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS has_autoplaylist;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS autoplaylist_id;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0015_2_5_17"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,31 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE imported_podcast ADD COLUMN album_override boolean default 'f' NOT NULL;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET DEFAULT 0;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP NOT NULL;
|
||||
ALTER TABLE cc_show ADD COLUMN autoplaylist_repeat boolean default 'f' NOT NULL;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE imported_podcast DROP COLUMN IF EXISTS album_override;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP DEFAULT;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET NOT NULL;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS autoplaylist_repeat;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0016_3_0_0_alpha"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.1",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_service_register ALTER COLUMN ip TYPE character varying(45);
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_service_register ALTER COLUMN ip TYPE character varying(18);
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0017_3_0_0_alpha_1"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.6",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
# https://github.com/libretime/libretime/pull/636
|
||||
# Change dynamic smartblock to be default smartblock type
|
||||
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_block ALTER COLUMN type SET DEFAULT 'dynamic';
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_block ALTER COLUMN type SET DEFAULT 'static';
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0018_3_0_0_alpha_6"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.7",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,30 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
# https://github.com/libretime/libretime/pull/659
|
||||
# Add description and title to podcast episodes database table
|
||||
|
||||
UP = """
|
||||
ALTER TABLE podcast_episodes ADD COLUMN episode_title VARCHAR(4096);
|
||||
ALTER TABLE podcast_episodes ADD COLUMN episode_description VARCHAR(4096);
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE podcast_episodes DROP COLUMN IF EXISTS episode_title;
|
||||
ALTER TABLE podcast_episodes DROP COLUMN IF EXISTS episode_description;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0019_3_0_0_alpha_7"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.7.1",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
# https://github.com/libretime/libretime/pull/704
|
||||
# Add criteria group to smartblock table to enable database to store separately
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_blockcriteria ADD COLUMN criteriagroup integer;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_blockcriteria DROP COLUMN IF EXISTS criteriagroup;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0020_3_0_0_alpha_7_1"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.7.2",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE podcast_episodes ALTER COLUMN episode_description TYPE text;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE podcast_episodes ALTER COLUMN episode_description TYPE VARCHAR(4096);
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0021_3_0_0_alpha_7_2"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.7.3",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_files ADD COLUMN artwork VARCHAR(4096);
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_files DROP COLUMN IF EXISTS artwork;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0022_3_0_0_alpha_7_3"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.9.1",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -1,3 +1,8 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_files ADD COLUMN track_type VARCHAR(16);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "cc_track_types"
|
||||
|
@ -20,6 +25,27 @@ INSERT INTO cc_track_types VALUES (6, 'JIN', 'Jingle', 'A short song or tune, no
|
|||
INSERT INTO cc_track_types VALUES (7, 'PRO', 'Promo', 'For promotional use.', true);
|
||||
INSERT INTO cc_track_types VALUES (8, 'SHO', 'Shout Out', 'A message of congratulation, greeting. support, or appreciation. ', true);
|
||||
INSERT INTO cc_track_types VALUES (9, 'NWS', 'News', 'This is used for noteworthy information, announcements.', true);
|
||||
INSERT INTO cc_track_types VALUES (10, 'COM', 'Commercial', 'This is used for commerical advertising.', true);
|
||||
INSERT INTO cc_track_types VALUES (10, 'COM', 'Commercial', 'This is used for commercial advertising.', true);
|
||||
INSERT INTO cc_track_types VALUES (11, 'ITV', 'Interview', 'This is used for radio interviews', true);
|
||||
INSERT INTO cc_track_types VALUES (12, 'VTR', 'Voice Tracking', 'Also referred as robojock or taped. Make announcements without actually being in the station.', true);
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_files DROP COLUMN IF EXISTS track_type;
|
||||
|
||||
DROP TABLE IF EXISTS "cc_track_types" CASCADE;
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0023_3_0_0_alpha_9_1"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.9.2",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,34 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
DROP TABLE IF EXISTS "cc_smemb" CASCADE;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
CREATE TABLE "cc_smemb"
|
||||
(
|
||||
"id" INTEGER NOT NULL,
|
||||
"uid" INTEGER DEFAULT 0 NOT NULL,
|
||||
"gid" INTEGER DEFAULT 0 NOT NULL,
|
||||
"level" INTEGER DEFAULT 0 NOT NULL,
|
||||
"mid" INTEGER,
|
||||
PRIMARY KEY ("id"),
|
||||
CONSTRAINT "cc_smemb_id_idx" UNIQUE ("id")
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0024_3_0_0_alpha_9_2"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.9.3",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
from django.db import migrations
|
||||
|
||||
from ._migrations import legacy_migration_factory
|
||||
|
||||
UP = """
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_id;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_error_code;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_error_msg;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_link_to_file;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_upload_time;
|
||||
"""
|
||||
|
||||
DOWN = """
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_id INTEGER;
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_error_code INTEGER;
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_error_msg VARCHAR(512);
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_link_to_file VARCHAR(4096);
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_upload_time TIMESTAMP(6);
|
||||
"""
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("legacy", "0025_3_0_0_alpha_9_3"),
|
||||
]
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=legacy_migration_factory(
|
||||
target="3.0.0-alpha.9.4",
|
||||
sql=UP,
|
||||
)
|
||||
)
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
LEGACY_SCHEMA_VERSION = "3.0.0-alpha.9.4"
|
|
@ -0,0 +1,77 @@
|
|||
from typing import Callable, Optional
|
||||
|
||||
from django.db import connection
|
||||
|
||||
from ._version import parse_version
|
||||
|
||||
|
||||
def get_schema_version():
|
||||
"""
|
||||
Get the schema version from a legacy database.
|
||||
|
||||
Don't use django models as they might break in the future. Our concern is to upgrade
|
||||
the legacy database schema to the point where django is in charge of the migrations.
|
||||
"""
|
||||
|
||||
if "cc_pref" not in connection.introspection.table_names():
|
||||
return None
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT valstr FROM cc_pref WHERE keystr = 'schema_version'")
|
||||
row = cursor.fetchone()
|
||||
return row[0] if row else None
|
||||
|
||||
|
||||
def set_schema_version(cursor, version: str):
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE cc_pref
|
||||
SET valstr = %s
|
||||
WHERE keystr = 'schema_version';
|
||||
""",
|
||||
[version],
|
||||
)
|
||||
if not cursor.rowcount:
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO cc_pref (keystr, valstr)
|
||||
VALUES ('schema_version', %s);
|
||||
""",
|
||||
[version],
|
||||
)
|
||||
|
||||
|
||||
def legacy_migration_factory(
|
||||
target: str,
|
||||
before: Optional[Callable] = None,
|
||||
sql: Optional[str] = None,
|
||||
after: Optional[Callable] = None,
|
||||
reverse: bool = False,
|
||||
):
|
||||
target_version = parse_version(target)
|
||||
|
||||
def inner(_apps, _schema_editor):
|
||||
current = get_schema_version()
|
||||
if current is None:
|
||||
raise Exception("current schema version was not found!")
|
||||
|
||||
current_version = parse_version(current)
|
||||
if current_version >= target_version and not reverse:
|
||||
return
|
||||
|
||||
if current_version < target_version and reverse:
|
||||
return
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
if before is not None:
|
||||
before(cursor)
|
||||
|
||||
if sql is not None:
|
||||
cursor.execute(sql)
|
||||
|
||||
if after is not None:
|
||||
after(cursor)
|
||||
|
||||
set_schema_version(cursor, version=target)
|
||||
|
||||
return inner
|
|
@ -0,0 +1,38 @@
|
|||
import re
|
||||
|
||||
VERSION_RE = re.compile(
|
||||
r"""
|
||||
(?P<release>[0-9]+(?:\.[0-9]+)*)
|
||||
(?:
|
||||
-(?P<pre_l>(alpha|beta))
|
||||
(?:
|
||||
\.(?P<pre_n>[0-9]+
|
||||
(?:
|
||||
\.[0-9]+
|
||||
)?
|
||||
)
|
||||
)?
|
||||
)?
|
||||
""",
|
||||
re.VERBOSE | re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def parse_version(version: str):
|
||||
match = VERSION_RE.search(version)
|
||||
if not match:
|
||||
raise Exception(f"invalid version {version}")
|
||||
|
||||
major, minor, patch = map(int, match.group("release").split("."))
|
||||
|
||||
pre_mapping = {"alpha": -2, "beta": -1, None: 0, "": 0}
|
||||
pre = pre_mapping[match.group("pre_l")]
|
||||
|
||||
pre_major, pre_minor = 0, 0
|
||||
pre_version = match.group("pre_n")
|
||||
if pre_version:
|
||||
pre_version_list = pre_version.split(".")
|
||||
pre_major = int(pre_version_list.pop(0)) if len(pre_version_list) else 0
|
||||
pre_minor = int(pre_version_list.pop(0)) if len(pre_version_list) else 0
|
||||
|
||||
return (major, minor, patch, pre, pre_major, pre_minor)
|
|
@ -1,6 +1,3 @@
|
|||
-- Schema version
|
||||
INSERT INTO cc_pref("keystr", "valstr") VALUES('schema_version', '3.0.0-alpha');
|
||||
|
||||
INSERT INTO cc_subjs ("login", "type", "pass") VALUES ('admin', 'A', md5('admin'));
|
||||
-- added in 2.3
|
||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('off_air_meta', 'LibreTime - offline', 'string');
|
|
@ -0,0 +1,2 @@
|
|||
# Sqlfile -> Database map
|
||||
schema.sql=airtime
|
|
@ -0,0 +1,44 @@
|
|||
import pytest
|
||||
|
||||
from ...migrations._version import parse_version
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"version,expected",
|
||||
[
|
||||
# fmt: off
|
||||
("3.0.0-alpha", (3, 0, 0, -2, 0, 0)),
|
||||
("3.1.0-alpha.1", (3, 1, 0, -2, 1, 0)),
|
||||
("3.0.1-alpha.1.2", (3, 0, 1, -2, 1, 2)),
|
||||
("3.0.0-beta", (3, 0, 0, -1, 0, 0)),
|
||||
("3.0.0-beta.10", (3, 0, 0, -1, 10, 0)),
|
||||
("2.5.2", (2, 5, 2, 0, 0, 0)),
|
||||
("3.0.0", (3, 0, 0, 0, 0, 0)),
|
||||
# fmt: on
|
||||
],
|
||||
)
|
||||
def test_parse_version(version: str, expected):
|
||||
assert parse_version(version) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"before,after",
|
||||
[
|
||||
# fmt: off
|
||||
("3.0.0-alpha", "3.0.0-alpha.1"),
|
||||
("3.0.0-alpha.1", "3.0.0-alpha.2"),
|
||||
("3.0.0-alpha.1", "3.0.0-alpha.1.1"),
|
||||
("3.0.0-alpha", "3.0.0-beta"),
|
||||
("3.0.0-beta", "3.0.0"),
|
||||
("3.0.0", "3.0.1"),
|
||||
("3.0.0", "3.1.0"),
|
||||
("3.0.0", "4.0.0"),
|
||||
("2.5.3", "3.0.0"),
|
||||
("3.0.0", "3.0.0"),
|
||||
# fmt: on
|
||||
],
|
||||
)
|
||||
def test_version_compare(before: str, after: str):
|
||||
version_before = parse_version(before)
|
||||
version_after = parse_version(after)
|
||||
assert version_before <= version_after
|
|
@ -9,6 +9,7 @@ DEBUG = getenv("LIBRETIME_DEBUG", "false").lower() == "true"
|
|||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"libretime_api.legacy",
|
||||
"libretime_api.core",
|
||||
"libretime_api.history",
|
||||
"libretime_api.storage",
|
||||
|
|
|
@ -21,6 +21,9 @@ setup(
|
|||
},
|
||||
license="AGPLv3",
|
||||
packages=find_packages(),
|
||||
package_data={
|
||||
"libretime_api": ["legacy/migrations/sql/*.sql"],
|
||||
},
|
||||
include_package_data=True,
|
||||
python_requires=">=3.6",
|
||||
entry_points={
|
||||
|
|
|
@ -11,3 +11,4 @@ Welcome to the **LibreTime developer manual**, you should find guides to integra
|
|||
## Improve and contribute to LibreTime
|
||||
|
||||
- Learn about the [architecture of LibreTime](./design/architecture.md)
|
||||
- Learn about the [database migrations](./design/database-migrations.md)
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# Database schema creation and migrations
|
||||
|
||||
The method to maintain the database schema, is to write both a migration file for already installed databases and to update a `schema.sql` file for fresh databases. On fresh installation, the database is filled with the `schema.sql` and `data.sql` files and LibreTime won't run any sql migration on top of it. Previously, when LibreTime was upgraded, the missing migrations were run using a custom php based migration tool, those migrations are now handled by Django. The missing migrations are tracked using both a `schema_version` field in the `cc_pref` table and a Django migration id.
|
||||
|
||||
:::note
|
||||
|
||||
Since LibreTime forked, the `schema_version` in the `schema.sql` was locked on `3.0.0-alpha` and all the migrations were run during the first user connection. This has been fixed during the move to the Django based migrations.
|
||||
|
||||
:::
|
||||
|
||||
Django does not maintain a `schema.sql` file, it applies every migrations until it reaches the targeted schema represented by the code. The legacy `schema_version` has to be tracked until we remove the Propel schema generation and let Django handle all the schema migrations. Until then Propel generate the schema and Django handle migrations from already installed databases.
|
||||
|
||||
:::info
|
||||
|
||||
The first Django migration is the initial schema creation using the `schema.sql` and `data.sql` files.
|
||||
|
||||
:::
|
||||
|
||||
```
|
||||
stateDiagram-v2
|
||||
state is_django_migration_applied <<choice>>
|
||||
[*] --> is_django_migration_applied: Is the django migration ID in the DB ?
|
||||
|
||||
is_django_migration_applied --> [*]: Yes, ignoring...
|
||||
|
||||
state "Apply django migration" as apply_django_migration
|
||||
is_django_migration_applied --> apply_django_migration: No
|
||||
|
||||
state apply_django_migration {
|
||||
state is_legacy_migration <<choice>>
|
||||
[*] --> is_legacy_migration: Is it a legacy migration ?
|
||||
|
||||
state "Run django migration" as run_django_migration
|
||||
state "Apply changes" as run_django_migration
|
||||
state "Save migration ID in DB" as run_django_migration
|
||||
is_legacy_migration --> run_django_migration: No
|
||||
run_legacy_migration --> run_django_migration
|
||||
run_django_migration --> [*]
|
||||
|
||||
state is_legacy_migration_applied <<choice>>
|
||||
is_legacy_migration_applied --> [*]: Yes, ignoring...
|
||||
|
||||
state "Run legacy migration" as run_legacy_migration
|
||||
state "Apply changes" as run_legacy_migration
|
||||
state "Bump legacy schema version" as run_legacy_migration
|
||||
is_legacy_migration_applied --> run_legacy_migration: No
|
||||
is_legacy_migration --> is_legacy_migration_applied: Yes, is the DB schema version >= legacy migration schema version ?
|
||||
}
|
||||
|
||||
apply_django_migration --> [*]
|
||||
```
|
|
@ -180,32 +180,6 @@ interface AirtimeTask
|
|||
public function run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class UpgradeTask.
|
||||
*
|
||||
* Checks the current Airtime version and runs any outstanding upgrades
|
||||
*/
|
||||
class UpgradeTask implements AirtimeTask
|
||||
{
|
||||
/**
|
||||
* Check the current Airtime schema version to see if an upgrade should be run.
|
||||
*
|
||||
* @return bool true if an upgrade is needed
|
||||
*/
|
||||
public function shouldBeRun()
|
||||
{
|
||||
return UpgradeManager::checkIfUpgradeIsNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all upgrades above the current schema version.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
UpgradeManager::doUpgrade();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class CeleryTask.
|
||||
*
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
class UpgradeController extends Zend_Controller_Action
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!RestAuth::verifyAuth(true, false, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$didWePerformAnUpgrade = UpgradeManager::doUpgrade();
|
||||
|
||||
if (!$didWePerformAnUpgrade) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody('No upgrade was performed. The current schema version is ' . Application_Model_Preference::GetSchemaVersion() . '.<br>');
|
||||
} else {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody('Upgrade to Airtime schema version ' . Application_Model_Preference::GetSchemaVersion() . ' OK<br>');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function downgradeAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!RestAuth::verifyAuth(true, false, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $this->getRequest();
|
||||
$toVersion = $request->getParam('version');
|
||||
|
||||
try {
|
||||
$downgradePerformed = UpgradeManager::doDowngrade($toVersion);
|
||||
|
||||
if (!$downgradePerformed) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody('No downgrade was performed. The current schema version is ' . Application_Model_Preference::GetSchemaVersion() . '.<br>');
|
||||
} else {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody('Downgrade to Airtime schema version ' . Application_Model_Preference::GetSchemaVersion() . ' OK<br>');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
-----------------------------------------------------------------------
|
||||
-- third_party_track_references
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS "third_party_track_references" CASCADE;
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- celery_tasks
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS "celery_tasks" CASCADE;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET NOT NULL;
|
|
@ -1,11 +0,0 @@
|
|||
ALTER TABLE cc_files DROP COLUMN description;
|
||||
|
||||
DELETE FROM cc_pref WHERE keystr = 'station_podcast_id';
|
||||
|
||||
DROP TABLE IF EXISTS "podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "imported_podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "station_podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "podcast_episodes" CASCADE;
|
|
@ -1,4 +0,0 @@
|
|||
ALTER TABLE imported_podcast DROP COLUMN IF EXISTS album_override;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP DEFAULT;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET NOT NULL;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS autoplaylist_repeat;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_service_register ALTER COLUMN ip TYPE character varying(18);
|
|
@ -1,2 +0,0 @@
|
|||
ALTER TABLE podcast_episodes DROP COLUMN IF EXISTS episode_title;
|
||||
ALTER TABLE podcast_episodes DROP COLUMN IF EXISTS episode_description;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_blockcriteria DROP COLUMN IF EXISTS criteriagroup;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE podcast_episodes ALTER COLUMN episode_description TYPE VARCHAR(4096);
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_block ALTER COLUMN type SET DEFAULT 'static';
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_files DROP COLUMN IF EXISTS artwork;
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE cc_files DROP COLUMN IF EXISTS track_type;
|
||||
|
||||
DROP TABLE IF EXISTS "cc_track_types" CASCADE;
|
|
@ -1,10 +0,0 @@
|
|||
CREATE TABLE "cc_smemb"
|
||||
(
|
||||
"id" INTEGER NOT NULL,
|
||||
"uid" INTEGER DEFAULT 0 NOT NULL,
|
||||
"gid" INTEGER DEFAULT 0 NOT NULL,
|
||||
"level" INTEGER DEFAULT 0 NOT NULL,
|
||||
"mid" INTEGER,
|
||||
PRIMARY KEY ("id"),
|
||||
CONSTRAINT "cc_smemb_id_idx" UNIQUE ("id")
|
||||
);
|
|
@ -1,6 +0,0 @@
|
|||
-- we can restore the schema here but you'll need to restore data from a backup
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_id INTEGER;
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_error_code INTEGER;
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_error_msg VARCHAR(512);
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_link_to_file VARCHAR(4096);
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_upload_time TIMESTAMP(6);
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE cc_show_instances DROP COLUMN IF EXISTS autoplaylist_built;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS has_autoplaylist;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS autoplaylist_id;
|
|
@ -54,16 +54,10 @@ class PageLayoutInitPlugin extends Zend_Controller_Plugin_Abstract
|
|||
$this->_initViewHelpers();
|
||||
}
|
||||
|
||||
// Skip upgrades and task management when running unit tests
|
||||
// Skip task management when running unit tests
|
||||
if (getenv('AIRTIME_UNIT_TEST') != 1) {
|
||||
$taskManager = TaskManager::getInstance();
|
||||
|
||||
// Run the upgrade on each request (if it needs to be run)
|
||||
// We can't afford to wait 7 minutes to run an upgrade: users could
|
||||
// have several minutes of database errors while waiting for a
|
||||
// schema change upgrade to happen after a deployment
|
||||
$taskManager->runTask('UpgradeTask');
|
||||
|
||||
// Piggyback the TaskManager onto API calls. This provides guaranteed consistency
|
||||
// (there is at least one API call made from pypo to Airtime every 7 minutes) and
|
||||
// greatly reduces the chances of lock contention on cc_pref while the TaskManager runs
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
ALTER TABLE cc_files ADD COLUMN filesize integer NOT NULL
|
||||
CONSTRAINT filesize_default DEFAULT 0
|
|
@ -1,2 +0,0 @@
|
|||
ALTER TABLE cc_show ALTER COLUMN description TYPE varchar(8192);
|
||||
ALTER TABLE cc_show_instances ALTER COLUMN description TYPE varchar(8192);
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE cc_pref ALTER COLUMN subjid SET DEFAULT NULL;
|
||||
CREATE UNIQUE INDEX cc_pref_key_idx ON cc_pref (keystr) WHERE subjid IS NULL;
|
||||
ANALYZE cc_pref;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP NOT NULL;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_files ADD COLUMN artwork TYPE character varying(255);
|
|
@ -1,6 +0,0 @@
|
|||
-- Replacing system_version with schema_version
|
||||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('schema_version', '2.5.2');
|
||||
|
||||
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
|
||||
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';
|
|
@ -1,6 +0,0 @@
|
|||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.3');
|
||||
|
||||
ALTER TABLE cc_files DROP COLUMN state;
|
||||
ALTER TABLE cc_files ADD import_status integer default 1; -- Default is "pending"
|
||||
UPDATE cc_files SET import_status=0; -- Existing files are already "imported"
|
|
@ -1,5 +0,0 @@
|
|||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.5');
|
||||
|
||||
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
|
||||
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';
|
|
@ -1,11 +0,0 @@
|
|||
CREATE TABLE cloud_file
|
||||
(
|
||||
id serial NOT NULL,
|
||||
resource_id text NOT NULL,
|
||||
storage_backend text NOT NULL,
|
||||
cc_file_id integer NOT NULL,
|
||||
CONSTRAINT cloud_file_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT "cloud_file_FK_1" FOREIGN KEY (cc_file_id)
|
||||
REFERENCES cc_files (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION ON DELETE CASCADE
|
||||
)
|
|
@ -1,4 +0,0 @@
|
|||
ALTER TABLE imported_podcast ADD COLUMN album_override boolean default 'f' NOT NULL;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET DEFAULT 0;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP NOT NULL;
|
||||
ALTER TABLE cc_show ADD COLUMN autoplaylist_repeat boolean default 'f' NOT NULL;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_service_register ALTER COLUMN ip TYPE character varying(45);
|
|
@ -1,2 +0,0 @@
|
|||
ALTER TABLE podcast_episodes ADD COLUMN episode_title VARCHAR(4096);
|
||||
ALTER TABLE podcast_episodes ADD COLUMN episode_description VARCHAR(4096);
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_blockcriteria ADD COLUMN criteriagroup integer;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE podcast_episodes ALTER COLUMN episode_description TYPE text;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_block ALTER COLUMN type SET DEFAULT 'dynamic';
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE cc_files ADD COLUMN artwork VARCHAR(4096);
|
|
@ -1 +0,0 @@
|
|||
DROP TABLE IF EXISTS "cc_smemb" CASCADE;
|
|
@ -1,5 +0,0 @@
|
|||
ALTER TABLE cc_files DROP COLUMN soundcloud_id;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_error_code;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_error_msg;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_link_to_file;
|
||||
ALTER TABLE cc_files DROP COLUMN soundcloud_upload_time;
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE cc_show ADD COLUMN has_autoplaylist boolean default 'f' NOT NULL;
|
||||
ALTER TABLE cc_show ADD COLUMN autoplaylist_id integer DEFAULT NULL;
|
||||
ALTER TABLE cc_show_instances ADD COLUMN autoplaylist_built boolean default 'f' NOT NULL;
|
|
@ -1,726 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Check if a given classname belongs to a subclass of AirtimeUpgrader.
|
||||
*
|
||||
* @param $c string class name
|
||||
*
|
||||
* @return bool true if the $c is a subclass of AirtimeUpgrader
|
||||
*/
|
||||
function isUpgrade($c)
|
||||
{
|
||||
return is_subclass_of($c, 'AirtimeUpgrader');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter all declared classes to get all upgrade classes dynamically.
|
||||
*
|
||||
* @return array all upgrade classes
|
||||
*/
|
||||
function getUpgrades()
|
||||
{
|
||||
return array_filter(get_declared_classes(), 'isUpgrade');
|
||||
}
|
||||
|
||||
class UpgradeManager
|
||||
{
|
||||
/**
|
||||
* Used to determine if the database schema needs an upgrade in order for this version of the Airtime codebase to work correctly.
|
||||
*
|
||||
* @return array a list of schema versions that this version of the codebase supports
|
||||
*/
|
||||
public static function getSupportedSchemaVersions()
|
||||
{
|
||||
$config = Config::getConfig();
|
||||
// What versions of the schema does the code support today:
|
||||
return [$config['airtime_version']];
|
||||
}
|
||||
|
||||
public static function checkIfUpgradeIsNeeded()
|
||||
{
|
||||
$schemaVersion = Application_Model_Preference::GetSchemaVersion();
|
||||
$supportedSchemaVersions = self::getSupportedSchemaVersions();
|
||||
|
||||
return !in_array($schemaVersion, $supportedSchemaVersions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade the Airtime schema version to match the highest supported version.
|
||||
*
|
||||
* @return bool whether or not an upgrade was performed
|
||||
*/
|
||||
public static function doUpgrade()
|
||||
{
|
||||
// Get all upgrades dynamically (in declaration order!) so we don't have to add them explicitly each time
|
||||
// TODO: explicitly sort classnames by ascending version suffix for safety
|
||||
$upgraders = getUpgrades();
|
||||
$dir = (dirname(__DIR__) . '/controllers');
|
||||
$upgradePerformed = false;
|
||||
|
||||
foreach ($upgraders as $upgrader) {
|
||||
$upgradePerformed = self::_runUpgrade(new $upgrader($dir)) ? true : $upgradePerformed;
|
||||
}
|
||||
|
||||
return $upgradePerformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downgrade the Airtime schema version to match the given version.
|
||||
*
|
||||
* @param string $toVersion the version we want to downgrade to
|
||||
*
|
||||
* @return bool whether or not an upgrade was performed
|
||||
*/
|
||||
public static function doDowngrade($toVersion)
|
||||
{
|
||||
$downgraders = array_reverse(getUpgrades()); // Reverse the array because we're downgrading
|
||||
$dir = (dirname(__DIR__) . '/controllers');
|
||||
$downgradePerformed = false;
|
||||
|
||||
foreach ($downgraders as $downgrader) {
|
||||
/** @var AirtimeUpgrader $downgrader */
|
||||
$downgrader = new $downgrader($dir);
|
||||
if ($downgrader->getNewVersion() == $toVersion) {
|
||||
break; // We've reached the version we wanted to downgrade to, so break
|
||||
}
|
||||
$downgradePerformed = self::_runDowngrade($downgrader) ? true : $downgradePerformed;
|
||||
}
|
||||
|
||||
return $downgradePerformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given upgrade.
|
||||
*
|
||||
* @param $upgrader AirtimeUpgrader the upgrader class to be executed
|
||||
*
|
||||
* @return bool true if the upgrade was successful, otherwise false
|
||||
*/
|
||||
private static function _runUpgrade(AirtimeUpgrader $upgrader)
|
||||
{
|
||||
return $upgrader->checkIfUpgradeSupported() && $upgrader->upgrade();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given downgrade.
|
||||
*
|
||||
* @param $downgrader AirtimeUpgrader the upgrader class to be executed
|
||||
* @param $supportedVersions array array of supported versions
|
||||
*
|
||||
* @return bool true if the downgrade was successful, otherwise false
|
||||
*/
|
||||
private static function _runDowngrade(AirtimeUpgrader $downgrader)
|
||||
{
|
||||
return $downgrader->checkIfDowngradeSupported() && $downgrader->downgrade();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AirtimeUpgrader
|
||||
{
|
||||
protected $_dir;
|
||||
|
||||
protected $host;
|
||||
protected $port;
|
||||
protected $database;
|
||||
protected $username;
|
||||
protected $password;
|
||||
|
||||
/**
|
||||
* @param $dir string directory housing upgrade files
|
||||
*/
|
||||
public function __construct($dir)
|
||||
{
|
||||
$this->_dir = $dir;
|
||||
}
|
||||
|
||||
/** Schema versions that this upgrader class can upgrade from (an array of version strings). */
|
||||
abstract protected function getSupportedSchemaVersions();
|
||||
|
||||
/** The schema version that this upgrader class will upgrade to. (returns a version string) */
|
||||
abstract public function getNewVersion();
|
||||
|
||||
public static function getCurrentSchemaVersion()
|
||||
{
|
||||
return Application_Model_Preference::GetSchemaVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks to see if this class can perform an upgrade of your version of Airtime.
|
||||
*
|
||||
* @return bool true if we can upgrade your version of Airtime
|
||||
*/
|
||||
public function checkIfUpgradeSupported()
|
||||
{
|
||||
return in_array(static::getCurrentSchemaVersion(), $this->getSupportedSchemaVersions());
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks to see if this class can perform a downgrade of your version of Airtime.
|
||||
*
|
||||
* @return bool true if we can downgrade your version of Airtime
|
||||
*/
|
||||
public function checkIfDowngradeSupported()
|
||||
{
|
||||
return static::getCurrentSchemaVersion() == $this->getNewVersion();
|
||||
}
|
||||
|
||||
protected function toggleMaintenanceScreen($toggle)
|
||||
{
|
||||
if ($toggle) {
|
||||
// Disable Airtime UI
|
||||
// create a temporary maintenance notification file
|
||||
// when this file is on the server, zend framework redirects all
|
||||
// requests to the maintenance page and sets a 503 response code
|
||||
/* DISABLED because this does not work correctly
|
||||
$this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
|
||||
$file = fopen($this->maintenanceFile, 'w');
|
||||
fclose($file);
|
||||
*/
|
||||
}
|
||||
// delete maintenance.txt to give users access back to Airtime
|
||||
/* DISABLED because this does not work correctly
|
||||
if ($this->maintenanceFile) {
|
||||
unlink($this->maintenanceFile);
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this for each new version of Airtime
|
||||
* This function abstracts out the core upgrade functionality,
|
||||
* allowing child classes to overwrite _runUpgrade to reduce duplication.
|
||||
*/
|
||||
public function upgrade()
|
||||
{
|
||||
try {
|
||||
// $this->toggleMaintenanceScreen(true);
|
||||
|
||||
$this->_getDbValues();
|
||||
$this->_runUpgrade();
|
||||
|
||||
Application_Model_Preference::SetSchemaVersion($this->getNewVersion());
|
||||
|
||||
// $this->toggleMaintenanceScreen(false);
|
||||
} catch (Exception $e) {
|
||||
// $this->toggleMaintenanceScreen(false);
|
||||
Logging::error('Error in upgrade: ' . $e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this for each new version of Airtime
|
||||
* This function abstracts out the core downgrade functionality,
|
||||
* allowing child classes to overwrite _runDowngrade to reduce duplication.
|
||||
*/
|
||||
public function downgrade()
|
||||
{
|
||||
try {
|
||||
$this->_getDbValues();
|
||||
$this->_runDowngrade();
|
||||
|
||||
$highestSupportedVersion = null;
|
||||
foreach ($this->getSupportedSchemaVersions() as $v) {
|
||||
// version_compare returns 1 (true) if the second parameter is lower
|
||||
if (!$highestSupportedVersion || version_compare($v, $highestSupportedVersion)) {
|
||||
$highestSupportedVersion = $v;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the schema version to the highest supported version so we don't skip versions when downgrading
|
||||
Application_Model_Preference::SetSchemaVersion($highestSupportedVersion);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function _getDbValues()
|
||||
{
|
||||
$config = Config::getConfig();
|
||||
|
||||
$this->host = $config['dsn']['host'];
|
||||
$this->port = $config['dsn']['port'];
|
||||
$this->username = $config['dsn']['username'];
|
||||
$this->password = $config['dsn']['password'];
|
||||
$this->database = $config['dsn']['database'];
|
||||
}
|
||||
|
||||
protected function _runPsql($args)
|
||||
{
|
||||
$command = <<<"END"
|
||||
PGPASSWORD={$this->password} \\
|
||||
/usr/bin/psql --quiet \\
|
||||
--host={$this->host} \\
|
||||
--port={$this->port} \\
|
||||
--dbname={$this->database} \\
|
||||
--username={$this->username} \\
|
||||
{$args}
|
||||
END;
|
||||
passthru($command);
|
||||
}
|
||||
|
||||
protected function _runUpgrade()
|
||||
{
|
||||
$sqlFile = "{$this->_dir}/upgrade_sql/airtime_{$this->getNewVersion()}/upgrade.sql";
|
||||
$args = <<<"END"
|
||||
--file={$sqlFile} 2>&1 \\
|
||||
| grep -v -E "will create implicit sequence|will create implicit index"
|
||||
END;
|
||||
$this->_runPsql($args);
|
||||
}
|
||||
|
||||
protected function _runDowngrade()
|
||||
{
|
||||
$sqlFile = "{$this->_dir}/downgrade_sql/airtime_{$this->getNewVersion()}/downgrade.sql";
|
||||
$args = <<<"END"
|
||||
--file={$sqlFile} 2>&1 \\
|
||||
| grep -v -E "will create implicit sequence|will create implicit index"
|
||||
END;
|
||||
$this->_runPsql($args);
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader253 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return ['2.5.1', '2.5.2'];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.3';
|
||||
}
|
||||
|
||||
protected function _runUpgrade()
|
||||
{
|
||||
// Update disk_usage value in cc_pref
|
||||
$storDir = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE'] . 'srv/airtime/stor' : '/srv/airtime/stor';
|
||||
$diskUsage = shell_exec("du -sb {$storDir} | awk '{print $1}'");
|
||||
|
||||
Application_Model_Preference::setDiskUsage($diskUsage);
|
||||
|
||||
parent::_runUpgrade();
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader254 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return ['2.5.3'];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.4';
|
||||
}
|
||||
|
||||
protected function _runUpgrade()
|
||||
{
|
||||
// First, ensure there are no superadmins already.
|
||||
$numberOfSuperAdmins = CcSubjsQuery::create()
|
||||
->filterByDbType(UTYPE_SUPERADMIN)
|
||||
->filterByDbLogin('sourcefabric_admin', Criteria::NOT_EQUAL) // Ignore sourcefabric_admin users
|
||||
->count();
|
||||
|
||||
// Only create a super admin if there isn't one already.
|
||||
if ($numberOfSuperAdmins == 0) {
|
||||
// Find the "admin" user and promote them to superadmin.
|
||||
$adminUser = CcSubjsQuery::create()
|
||||
->filterByDbLogin('admin')
|
||||
->findOne();
|
||||
if (!$adminUser) {
|
||||
// Otherwise get the user with the lowest ID that is of type administrator:
|
||||
$adminUser = CcSubjsQuery::create()
|
||||
->filterByDbType(UTYPE_ADMIN)
|
||||
->orderByDbId(Criteria::ASC)
|
||||
->findOne();
|
||||
|
||||
if (!$adminUser) {
|
||||
throw new Exception("Failed to find any users of type 'admin' ('A').");
|
||||
}
|
||||
}
|
||||
|
||||
$adminUser = new Application_Model_User($adminUser->getDbId());
|
||||
$adminUser->setType(UTYPE_SUPERADMIN);
|
||||
$adminUser->save();
|
||||
Logging::info($_SERVER['HTTP_HOST'] . ': ' . $this->getNewVersion() . ' Upgrade: Promoted user ' . $adminUser->getLogin() . ' to be a Super Admin.');
|
||||
|
||||
// Also try to promote the sourcefabric_admin user
|
||||
$sofabAdminUser = CcSubjsQuery::create()
|
||||
->filterByDbLogin('sourcefabric_admin')
|
||||
->findOne();
|
||||
if ($sofabAdminUser) {
|
||||
$sofabAdminUser = new Application_Model_User($sofabAdminUser->getDbId());
|
||||
$sofabAdminUser->setType(UTYPE_SUPERADMIN);
|
||||
$sofabAdminUser->save();
|
||||
Logging::info($_SERVER['HTTP_HOST'] . ': ' . $this->getNewVersion() . ' Upgrade: Promoted user ' . $sofabAdminUser->getLogin() . ' to be a Super Admin.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader255 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.4',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.5';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader259 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.5',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.9';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader2510 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.9',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.10';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader2511 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.10',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.11';
|
||||
}
|
||||
|
||||
protected function _runUpgrade()
|
||||
{
|
||||
$queryResult = CcFilesQuery::create()
|
||||
->select(['disk_usage'])
|
||||
->withColumn('SUM(CcFiles.filesize)', 'disk_usage')
|
||||
->find();
|
||||
$disk_usage = $queryResult[0];
|
||||
Application_Model_Preference::setDiskUsage($disk_usage);
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader2512 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.10',
|
||||
'2.5.11',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.12';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AirtimeUpgrader2513 - Celery and SoundCloud upgrade.
|
||||
*
|
||||
* Adds third_party_track_references and celery_tasks tables for third party service
|
||||
* authentication and task architecture.
|
||||
*
|
||||
* <br/><b>third_party_track_references</b> schema:
|
||||
*
|
||||
* id -> int PK
|
||||
* service -> string internal service name
|
||||
* foreign_id -> int external unique service id
|
||||
* file_id -> int internal FK->cc_files track id
|
||||
* upload_time -> timestamp internal upload timestamp
|
||||
* status -> string external service status
|
||||
*
|
||||
* <br/><b>celery_tasks</b> schema:
|
||||
*
|
||||
* id -> int PK
|
||||
* task_id -> string external unique amqp results identifier
|
||||
* track_reference -> int internal FK->third_party_track_references id
|
||||
* name -> string external Celery task name
|
||||
* dispatch_time -> timestamp internal message dispatch time
|
||||
* status -> string external Celery task status
|
||||
*/
|
||||
class AirtimeUpgrader2513 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.12',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.13';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AirtimeUpgrader2514.
|
||||
*
|
||||
* SAAS-923 - Add a partial constraint to cc_pref so that keystrings must be unique
|
||||
*/
|
||||
class AirtimeUpgrader2514 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.13',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.14';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AirtimeUpgrader2515.
|
||||
*
|
||||
* SAAS-1071 - Remove not null constraint from file_id fk in third_party_track_references
|
||||
* so that we can create track references for downloads (which won't have a file
|
||||
* ID until the task is run and the file is POSTed back to Airtime)
|
||||
*/
|
||||
class AirtimeUpgrader2515 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.14',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.15';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader2516 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.15',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.16';
|
||||
}
|
||||
}
|
||||
class AirtimeUpgrader300alpha extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'2.5.16',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader300alpha1 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.1';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader300alpha6 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.1',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.6';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AirtimeUpgrader300alpha7.
|
||||
*
|
||||
* GH-#636 - https://github.com/libretime/libretime/pull/636 - Change dynamic smartblock to be default smartblock type
|
||||
*/
|
||||
class AirtimeUpgrader300alpha7 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.6',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.7';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AirtimeUpgrader300alpha7-1.
|
||||
*
|
||||
* GH-#659 - https://github.com/libretime/libretime/pull/659/ - Add description and title to podcast episodes database table
|
||||
*/
|
||||
class AirtimeUpgrader300alpha7_1 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.7',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.7.1';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AirtimeUpgrader300alpha7-2.
|
||||
*
|
||||
* GH-#704 - https://github.com/libretime/libretime/pull/704/ - Add criteria group to smartblock table to enable database to store separately
|
||||
*/
|
||||
class AirtimeUpgrader300alpha7_2 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.7.1',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.7.2';
|
||||
}
|
||||
}
|
||||
class AirtimeUpgrader300alpha7_3 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.7.2',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.7.3';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader300alpha9_1 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.7.3',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.9.1';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader300alpha9_2 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.9.1',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.9.2';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader200alpha9_3 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.9.2',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.9.3';
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader200alpha9_4 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedSchemaVersions()
|
||||
{
|
||||
return [
|
||||
'3.0.0-alpha.9.3',
|
||||
];
|
||||
}
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '3.0.0-alpha.9.4';
|
||||
}
|
||||
}
|
|
@ -18,7 +18,8 @@ propel.conf.dir = ${project.build}
|
|||
propel.output.dir = ${project.home}
|
||||
propel.php.dir = ${propel.output.dir}/application/models
|
||||
propel.phpconf.dir = ${propel.output.dir}/application/configs
|
||||
propel.sql.dir = ${project.build}/sql
|
||||
# propel.sql.dir = ${project.build}/sql
|
||||
propel.sql.dir = ${project.home}/../api/libretime_api/legacy/migrations/sql
|
||||
|
||||
# set the name for the configuration file
|
||||
# set the name for the configuration file
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
DROP SEQUENCE IF EXISTS schedule_group_id_seq CASCADE;
|
||||
|
||||
CREATE SEQUENCE schedule_group_id_seq;
|
||||
|
||||
DROP SEQUENCE IF EXISTS show_group_id_seq CASCADE;
|
||||
|
||||
CREATE SEQUENCE show_group_id_seq;
|
|
@ -1,6 +0,0 @@
|
|||
# Sqlfile -> Database map
|
||||
schema.sql=airtime
|
||||
sequences.sql=campcaster
|
||||
views.sql=campcaster
|
||||
triggers.sql=campcaster
|
||||
defaultdata.sql=campcaster
|
|
@ -1,6 +0,0 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- calculate_position()
|
||||
----------------------------------------------------------------------------------
|
||||
DROP FUNCTION IF EXISTS calculate_position CASCADE;
|
||||
|
||||
-- remove this trigger for group adds/delete
|
|
@ -1,5 +0,0 @@
|
|||
-------------------------------------------------------
|
||||
-- cc_playlisttimes
|
||||
-------------------------------------------------------
|
||||
|
||||
DROP VIEW IF EXISTS cc_playlisttimes;
|
|
@ -167,23 +167,17 @@ class DatabaseSetup extends Setup
|
|||
*/
|
||||
private function createDatabaseTables()
|
||||
{
|
||||
$sqlDir = dirname(__DIR__, 2) . '/build/sql/';
|
||||
$files = ['schema.sql', 'sequences.sql', 'views.sql', 'triggers.sql', 'defaultdata.sql'];
|
||||
foreach ($files as $f) {
|
||||
$sqlDir = dirname(ROOT_PATH) . '/api/libretime_api/legacy/migrations/sql/';
|
||||
$files = ['schema.sql', 'data.sql'];
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
/*
|
||||
* Unfortunately, we need to use exec here due to PDO's lack of support for importing
|
||||
* multi-line .sql files. PDO->exec() almost works, but any SQL errors stop the import,
|
||||
* so the necessary DROPs on non-existent tables make it unusable. Prepared statements
|
||||
* have multiple issues; they similarly die on any SQL errors, fail to read in multi-line
|
||||
* commands, and fail on any unescaped ? or $ characters.
|
||||
*/
|
||||
exec('export PGPASSWORD=' . self::$_properties['password'] . ' && /usr/bin/psql -U ' . self::$_properties['user']
|
||||
. ' --dbname ' . self::$_properties['name'] . ' -h ' . self::$_properties['host']
|
||||
. " -f {$sqlDir}{$f} 2>/dev/null", $out, $status);
|
||||
} catch (Exception $e) {
|
||||
$sql = file_get_contents($sqlDir . $file);
|
||||
self::$dbh->exec($sql);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
|
||||
throw new AirtimeDatabaseException(
|
||||
'There was an error setting up the Airtime schema!',
|
||||
'There was an error setting up the Airtime schema!: ' . $e->getMessage(),
|
||||
[self::DB_NAME]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -214,30 +214,22 @@ class AirtimeInstall
|
|||
public static function CreateDatabaseTables($dbuser, $dbpasswd, $dbname, $dbhost, $dbport)
|
||||
{
|
||||
echo ' * Creating database tables' . PHP_EOL;
|
||||
// Put Propel sql files in Database
|
||||
// $command = AirtimeInstall::CONF_DIR_WWW."/library/propel/generator/bin/propel-gen ".AirtimeInstall::CONF_DIR_WWW."/build/ insert-sql 2>/dev/null";
|
||||
$dir = self::GetAirtimeSrcDir() . '/build/sql/';
|
||||
$files = ['schema.sql', 'sequences.sql', 'views.sql', 'triggers.sql', 'defaultdata.sql'];
|
||||
foreach ($files as $f) {
|
||||
$command = <<<"END"
|
||||
PGPASSWORD={$dbpasswd} \\
|
||||
/usr/bin/psql \\
|
||||
--host={$dbhost} \\
|
||||
--port={$dbport} \\
|
||||
--dbname={$dbname} \\
|
||||
--username={$dbuser} \\
|
||||
--file {$dir}{$f} 2>&1
|
||||
END;
|
||||
@exec($command, $output, $results);
|
||||
$con = Propel::getConnection();
|
||||
$sqlDir = dirname(ROOT_PATH) . '/api/libretime_api/legacy/migrations/sql/';
|
||||
$files = ['schema.sql', 'data.sql'];
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
$sql = file_get_contents($sqlDir . $file);
|
||||
$con->exec($sql);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
AirtimeInstall::$databaseTablesCreated = true;
|
||||
}
|
||||
|
||||
final public static function UpdateDatabaseTables()
|
||||
{
|
||||
UpgradeManager::doUpgrade();
|
||||
}
|
||||
|
||||
public static function SetAirtimeVersion($p_version)
|
||||
{
|
||||
$con = Propel::getConnection();
|
||||
|
|
|
@ -126,7 +126,6 @@ class TestHelper
|
|||
} else {
|
||||
// Create all the database tables
|
||||
AirtimeInstall::CreateDatabaseTables($dbuser, $dbpasswd, $dbname, $dbhost, $dbport);
|
||||
AirtimeInstall::UpdateDatabaseTables();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue