diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index fe93b1b..0b860d3 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -3,16 +3,19 @@ set -eu # Entrypoint for the Scriptor demo container. # -# On first start (no SQLite DB yet) we: -# 1. Apply schema migrations against a fresh DB file. -# 2. Run docker/seed-demo.php to create the canonical Pages/Users -# categories, an admin user (admin/scriptor) and one example page. +# On first start (no SQLite DB yet) we restore a snapshot of the +# scriptor-cms.dev demo content: +# 1. docker/seed-demo.sql — sqlite3 dump (schema + data, +# captured via `imanager dump`) +# 2. docker/seed-demo-uploads.tar.gz — public/uploads/ tarball # -# On every subsequent start the entrypoint is a no-op — the DB already -# exists and the seed script is idempotent anyway. +# On every start we then run schema:migrate, so a dump captured on +# an older schema gets caught up if the image carries newer migrations. APP_DIR=/var/www/scriptor DB_PATH="${APP_DIR}/data/imanager.db" +SEED_SQL="${APP_DIR}/docker/seed-demo.sql" +SEED_UPLOADS="${APP_DIR}/docker/seed-demo-uploads.tar.gz" cd "${APP_DIR}" @@ -25,19 +28,22 @@ if [ "$(id -u)" = "0" ]; then fi if [ ! -f "${DB_PATH}" ]; then - echo "[entrypoint] no database at ${DB_PATH} — bootstrapping demo data." - # Schema migrations are auto-applied on the first PDO resolve from - # DefaultBootstrap, so the seed script gets a fully-migrated DB for - # free. We run schema:migrate explicitly too so a future entrypoint - # change that doesn't open a container connection still applies - # pending migrations. - su -s /bin/sh -c "vendor/bin/imanager schema:migrate --db=${DB_PATH}" www-data - su -s /bin/sh -c "php docker/seed-demo.php" www-data - echo "[entrypoint] seed complete." -else - echo "[entrypoint] database present — applying any pending schema migrations." - su -s /bin/sh -c "vendor/bin/imanager schema:migrate --db=${DB_PATH}" www-data + if [ ! -f "${SEED_SQL}" ]; then + echo "[entrypoint] FATAL: no DB and no seed at ${SEED_SQL}" >&2 + exit 1 + fi + echo "[entrypoint] no database — restoring seed from ${SEED_SQL}." + su -s /bin/sh -c "sqlite3 ${DB_PATH} < ${SEED_SQL}" www-data + if [ -f "${SEED_UPLOADS}" ]; then + echo "[entrypoint] extracting ${SEED_UPLOADS} into public/." + su -s /bin/sh -c "tar xzf ${SEED_UPLOADS} -C public/" www-data + fi + echo "[entrypoint] seed restore complete." fi +# Always: apply any pending schema migrations (idempotent — no-op when +# the dump's schema matches the image's migrations). +su -s /bin/sh -c "vendor/bin/imanager schema:migrate --db=${DB_PATH}" www-data + # Hand control to whatever CMD was passed (php-fpm by default). exec "$@" diff --git a/docker/seed-demo-uploads.tar.gz b/docker/seed-demo-uploads.tar.gz new file mode 100644 index 0000000..6b7b389 Binary files /dev/null and b/docker/seed-demo-uploads.tar.gz differ diff --git a/docker/seed-demo.php b/docker/seed-demo.php deleted file mode 100644 index d7a8639..0000000 --- a/docker/seed-demo.php +++ /dev/null @@ -1,140 +0,0 @@ -get(CategoryRepository::class); -$fields = $container->get(FieldRepository::class); -$items = $container->get(ItemRepository::class); - -// Idempotency guard. -if ($categories->findBySlug('pages') !== null) { - fwrite(\STDOUT, "[seed] pages category already exists — skipping.\n"); - exit(0); -} - -// -- Pages category -- -fwrite(\STDOUT, "[seed] creating Pages category…\n"); -$pages = $categories->save(new Category(null, 'Pages', 'pages')); -\assert($pages->id !== null); - -$pageFieldDefs = [ - ['slug', FieldType::Slug, 0], - ['parent', FieldType::Integer, 1], - ['pagetype', FieldType::Text, 2], - ['menu_title', FieldType::Text, 3], - ['content', FieldType::LongText, 4], - ['template', FieldType::Text, 5], - ['images', FieldType::Imageupload, 6], -]; -foreach ($pageFieldDefs as [$name, $type, $position]) { - $fields->save(new Field( - id: null, - categoryId: $pages->id, - name: $name, - label: ucfirst(str_replace('_', ' ', $name)), - type: $type, - position: $position, - )); -} - -// -- Users category -- -fwrite(\STDOUT, "[seed] creating Users category…\n"); -$users = $categories->save(new Category(null, 'Users', 'users')); -\assert($users->id !== null); - -$userFieldDefs = [ - ['role', FieldType::Text, 0], - ['email', FieldType::Text, 1], - ['password', FieldType::Password, 2], -]; -foreach ($userFieldDefs as [$name, $type, $position]) { - $fields->save(new Field( - id: null, - categoryId: $users->id, - name: $name, - label: ucfirst($name), - type: $type, - position: $position, - )); -} - -// -- Admin user -- -// `ItemRepository::save()` writes `$data` verbatim — it does NOT run -// the registered FieldTypePlugin's validate() (that's the host editor's -// job). So we have to hash the password ourselves here, the same way -// `PasswordFieldType::validate()` would: bcrypt via `password_hash()`. -fwrite(\STDOUT, "[seed] creating admin user (admin/scriptor)…\n"); -$items->save(new Item( - id: null, - categoryId: $users->id, - name: 'admin', - label: 'Administrator', - data: [ - 'role' => 'admin', - 'email' => 'admin@example.com', - 'password' => password_hash('scriptor', \PASSWORD_BCRYPT), - ], -)); - -// -- Example page -- -fwrite(\STDOUT, "[seed] creating Hello-world example page…\n"); -$items->save(new Item( - id: null, - categoryId: $pages->id, - name: 'hello-world', - label: 'Hello, world', - data: [ - 'slug' => 'hello-world', - 'parent' => 0, - 'pagetype' => 'page', - 'menu_title' => 'Hello', - 'template' => 'default', - 'content' => << Mariti cur: ante *causa* rigorem errabant gravitate imagine quotiensque amor\r\n> secundi cruribus [adclivi sibi est](http:\/\/caelestia.com\/enim) apri dedimus\r\n> quinos. Mihi quoque gemelliparae factum gramen, alto nomina abest nostro,\r\n> illic extinctum regia, languescuntque. Anguis qui laesaque ciet nam lapsae,\r\n> *fortuna* manus at quam; in.\r\n\r\n### Highlighted code blocks\r\n\r\n```php\r\necho $page->parsedown->text(\r\n $page->content\r\n);\r\n```\r\n\r\n### Quibus sine velox\r\n\r\nEsse requiem pedes sub freta modo. Mortis **ieiunia furori animalia** credimus,\r\nterras per guttae paucaque coniuge in solas et illa sustinet? Antris proxima\r\ntantum lapidis Tonantis unde. Quoque sororis nivibus limine cognatumque\r\npingebat, matre concentu Aeolides Cancri, ipsa terrae semper feci sanguine\r\nexternos.\r\n\r\n- Acernas crescere et exitus\r\n- Silva deum Amphion tamen\r\n- Soror quondam contigit\r\n- Hamata modo quaerens ut velatam obmutuit decusque\r\n- Quam haererem aestatem ventos\r\n\r\nIncingere Aoniis celat imagine digitis et iram, cum est diu violave oculis passu\r\nmeo. Sume in Cinyran aerane altrice amnis nefas gerebat properatis **orbem**\r\nsicco honorem ille bis. Repulsa quantaque aderat in relictas memoraverat arma\r\ndesierant umerique, suo cum in nymphae signa praetemptatque suorum genetrici?\r\nFieres sequitur quaeris Diana una parens, *te origo*; quid. Capherea liquitur\r\nmediis deerat facies agat quercu donavi Clara: Erinys Dies. \r\n...","template":"default"}', 1519052101, 1778356441); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (2, 1, 'Articles', NULL, 2, 1, '{"menu_title":"Articles","slug":"articles","template":"blog","parent":0,"pagetype":"1","content":"","images":null}', 1625453680, 1777868475); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (3, 1, 'Get started with Scriptor', NULL, 3, 1, '{"slug":"get-started-with-scriptor","parent":2,"pagetype":"1","menu_title":"Get started","content":"preserved","template":"default","images":[]}', 1638895123, 1777876312); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (4, 1, 'Contact', NULL, 4, 1, '{"menu_title":"Contact","slug":"contact","template":"contact","parent":0,"pagetype":"1","content":"The basic theme comes with a built-in contact form, so that your site visitors can make all sorts of queries and contact. The contact form does not support SMTP by default, but you may easily extend it with e.g. Scriptor''s SMailer module, which does.","images":[]}', 1639166163, 1777956578); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (5, 1, 'Legal notice', NULL, 6, 1, '{"menu_title":"Legal notice","slug":"legal-notice","template":"","parent":6,"pagetype":"1","content":"...","images":null}', 1641119858, 1777793722); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (6, 1, 'Footer Pages', NULL, 5, 1, '{"menu_title":"Footer Pages","slug":"some-pages","template":"","parent":0,"pagetype":"1","content":"This page is a container for all pages that should appear in the footer navigation.","images":null}', 1641128288, 1777956578); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (7, 1, 'Privacy statement', NULL, 7, 1, '{"menu_title":"Privacy statement","slug":"privacy-statement","template":"","parent":6,"pagetype":"1","content":"...","images":null}', 1641501213, 1777793722); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (8, 1, 'Getting Help', NULL, 8, 1, '{"menu_title":"Help","slug":"help","template":"","parent":6,"pagetype":"1","content":"...","images":null}', 1641818049, 1777793722); +INSERT INTO "items" ("id", "category_id", "name", "label", "position", "active", "data", "created", "updated") VALUES (9, 2, 'admin', '', 1, 1, '{"role":"siteadmin","email":"gmail@chuck.norris.com","password":{"__class":"\\Imanager\\PasswordFieldValue","password":"$2y$10$gQdxIHrGm\/ia4RFzkoPXc.YmdpK87fbKGQIz.dXXhQuz0hwV4P\/C2","salt":""}}', 1519050932, 1777810723); + +-- Table: schema_version +CREATE TABLE schema_version ( + version INTEGER PRIMARY KEY, + description TEXT NOT NULL, + applied_at INTEGER NOT NULL + ); +INSERT INTO "schema_version" ("version", "description", "applied_at") VALUES (1, 'initial', 1777793722); +INSERT INTO "schema_version" ("version", "description", "applied_at") VALUES (2, 'fts', 1777793722); +INSERT INTO "schema_version" ("version", "description", "applied_at") VALUES (3, 'files', 1777793722); +INSERT INTO "schema_version" ("version", "description", "applied_at") VALUES (4, 'files title', 1777820911); + +COMMIT;