diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index f314d3d20c68015ae02c1b76234a32225a8e8b20..1b4bab55124f543d0f4fa009f0ef0950841f542d 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -48,6 +48,7 @@ class Autoload extends AutoloadConfig 'Modules\Auth' => ROOTPATH . 'modules/Auth/', 'Modules\Analytics' => ROOTPATH . 'modules/Analytics/', 'Modules\Install' => ROOTPATH . 'modules/Install/', + 'Modules\Update' => ROOTPATH . 'modules/Update/', 'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/', 'Modules\WebSub' => ROOTPATH . 'modules/WebSub/', 'Modules\Api\Rest\V1' => ROOTPATH . 'modules/Api/Rest/V1', diff --git a/app/Database/Migrations/2023-04-09-110000_testing_update.php b/app/Database/Migrations/2023-04-09-110000_testing_update.php new file mode 100644 index 0000000000000000000000000000000000000000..446811983f6b0da6ca67e37deab2adcc14d41e00 --- /dev/null +++ b/app/Database/Migrations/2023-04-09-110000_testing_update.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +/** + * Class AddCreatedByToPosts Adds created_by field to posts table in database + * + * @copyright 2020 Ad Aures + * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 + * @link https://castopod.org/ + */ + +namespace App\Database\Migrations; + +use CodeIgniter\Database\Migration; + +class AddTestingUpdate extends Migration +{ + public function up(): void + { + $this->forge->addColumn('podcasts', [ + 'cool_update' => [ + 'type' => 'INT', + 'unsigned' => true, + 'null' => true, + 'after' => 'custom_rss', + ], + ]); + } + + public function down(): void + { + $this->forge->dropColumn('podcasts', 'cool_update'); + } +} diff --git a/app/Resources/icons/information.svg b/app/Resources/icons/information.svg new file mode 100644 index 0000000000000000000000000000000000000000..39f02fbd91de77665a895b85242e36efe81de471 --- /dev/null +++ b/app/Resources/icons/information.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <path fill="none" d="M0 0h24v24H0z"/> + <path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z"/> +</svg> diff --git a/docs/src/getting-started/update.md b/docs/src/getting-started/update.md index 1f48e274922fd3affdc428ffd59a8d79909dcab7..98e019fbc7a9adefc88b183b9f166599709297e2 100644 --- a/docs/src/getting-started/update.md +++ b/docs/src/getting-started/update.md @@ -9,11 +9,13 @@ After installing Castopod, you may want to update your instance to the latest version in order to enjoy the latest features ✨, bug fixes 🛠and performance improvements âš¡. -## Automatic update instructions +## Update instructions -> Coming soon... 👀 +0. âš ï¸ Before any update, we highly recommend you backup your Castopod files and + database. -## Manual update instructions + - cf. + [Should I make a backup before updating?](#should-i-make-a-backup-before-updating) 1. Go to the [releases page](https://code.castopod.org/adaures/castopod/-/releases) and @@ -26,6 +28,8 @@ improvements âš¡. between the `zip` or `tar.gz` archives - âš ï¸ Make sure you download the Castopod Package and **NOT** the Source Code + - Note that you can also download the latest package from + [castopod.org](https://castopod.org/) 3. On your server: @@ -39,19 +43,31 @@ improvements âš¡. ::: -4. Releases may come with additional update instructions (see - [releases page](https://code.castopod.org/adaures/castopod/-/releases)). They - are usually database migration scripts in `.sql` format to update your - database schema. +4. Update your database schema from your `Castopod Admin` > `About` page or by + running: - - 👉 Make sure you run the scripts on your phpmyadmin panel or using command - line to update the database along with the package files! - - cf. - [I haven't updated my instance in a long time… What should I do?](#i-havent-updated-my-instance-in-a-long-time-what-should-i-do) + ```bash + php spark castopod:database-update + ``` -5. If you are using redis, clear your cache. +5. Clear your cache from your `Castopod Admin` > `Settings` > `general` > + `Housekeeping` 6. ✨ Enjoy your fresh instance, you're all done! +::: info Note + +Releases may come with additional update instructions (see +[releases page](https://code.castopod.org/adaures/castopod/-/releases)). + +- cf. + [I haven't updated my instance in a long time… What should I do?](#i-havent-updated-my-instance-in-a-long-time-what-should-i-do) + +::: + +## Fully Automated updates + +> Coming soon... 👀 + ## Frequently asked questions (FAQ) ### Where can I find my Castopod version? diff --git a/modules/Admin/Config/Routes.php b/modules/Admin/Config/Routes.php index 7bf22166899ae68703e5fad77a09a3dc4a91fccd..586272ead682d233ae862ffb12f40b4a7c77b73f 100644 --- a/modules/Admin/Config/Routes.php +++ b/modules/Admin/Config/Routes.php @@ -644,5 +644,15 @@ $routes->group( ]); }); }); + + $routes->get('about', 'AboutController', [ + 'as' => 'admin-about', + 'filter' => 'permission:admin.settings', + ]); + + $routes->post('update', 'AboutController::updateAction', [ + 'as' => 'update', + 'filter' => 'permission:admin.settings', + ]); }, ); diff --git a/modules/Admin/Controllers/AboutController.php b/modules/Admin/Controllers/AboutController.php new file mode 100644 index 0000000000000000000000000000000000000000..02be5c9e593c3f837ab7d944fce9b27062fbd141 --- /dev/null +++ b/modules/Admin/Controllers/AboutController.php @@ -0,0 +1,67 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright 2022 Ad Aures + * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 + * @link https://castopod.org/ + */ + +namespace Modules\Admin\Controllers; + +use CodeIgniter\HTTP\RedirectResponse; +use Config\Services; + +class AboutController extends BaseController +{ + public function index(): string + { + $instanceInfo = [ + 'host_name' => current_domain(), + 'version' => CP_VERSION, + 'php_version' => PHP_VERSION, + 'os' => PHP_OS, + 'languages' => implode(', ', config('App')->supportedLocales), + ]; + + return view('about', [ + 'info' => $instanceInfo, + ]); + } + + public function updateAction(): RedirectResponse + { + if ($this->request->getPost('action') === 'database') { + return $this->migrateDatabase(); + } + + return redirect()->back() + ->with('error', lang('Security.disallowedAction')); + } + + public function migrateDatabase(): RedirectResponse + { + $migrate = Services::migrations(); + + $migrate->setNamespace('CodeIgniter\Settings') + ->latest(); + $migrate->setNamespace('CodeIgniter\Shield') + ->latest(); + $migrate->setNamespace('Modules\Fediverse') + ->latest(); + $migrate->setNamespace(APP_NAMESPACE) + ->latest(); + $migrate->setNamespace('Modules\WebSub') + ->latest(); + $migrate->setNamespace('Modules\Auth') + ->latest(); + $migrate->setNamespace('Modules\PremiumPodcasts') + ->latest(); + $migrate->setNamespace('Modules\Analytics') + ->latest(); + + return redirect()->back() + ->with('message', lang('AboutCastopod.messages.databaseUpdateSuccess')); + } +} diff --git a/modules/Admin/Language/en/AboutCastopod.php b/modules/Admin/Language/en/AboutCastopod.php new file mode 100644 index 0000000000000000000000000000000000000000..3fb62afffecaf7007a17da81fbcb6f96d1917c76 --- /dev/null +++ b/modules/Admin/Language/en/AboutCastopod.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright 2020 Ad Aures + * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 + * @link https://castopod.org/ + */ + +return [ + 'title' => 'About Castopod', + 'host_name' => 'Host name', + 'version' => 'Castopod version', + 'php_version' => 'PHP version', + 'os' => 'Operating System', + 'languages' => 'Languages', + 'update_database' => 'Update database', + 'messages' => [ + 'databaseUpdateSuccess' => 'Database is up to date!', + ], +]; diff --git a/modules/Admin/Language/en/Breadcrumb.php b/modules/Admin/Language/en/Breadcrumb.php index 823ccd65acc88198e297aa574633fae9727067b9..b1742abfb12bcdc1e1d25458b53a63c2c496a7fe 100644 --- a/modules/Admin/Language/en/Breadcrumb.php +++ b/modules/Admin/Language/en/Breadcrumb.php @@ -19,6 +19,7 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', + 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', diff --git a/modules/Admin/Language/en/Navigation.php b/modules/Admin/Language/en/Navigation.php index 68d4609d5d94a5770f237ee23207ad47d1262c70..610f14345d427177b5bcbea0b56c1f56512b70ff 100644 --- a/modules/Admin/Language/en/Navigation.php +++ b/modules/Admin/Language/en/Navigation.php @@ -33,6 +33,7 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', + 'about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Update/Commands/DatabaseUpdate.php b/modules/Update/Commands/DatabaseUpdate.php new file mode 100644 index 0000000000000000000000000000000000000000..70a3ad0158c60414d69a7d989f0f1daadba96abe --- /dev/null +++ b/modules/Update/Commands/DatabaseUpdate.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace Modules\Update\Commands; + +use CodeIgniter\CLI\BaseCommand; + +class DatabaseUpdate extends BaseCommand +{ + /** + * @var string + */ + protected $group = 'maintenance'; + + /** + * @var string + */ + protected $name = 'castopod:database-update'; + + /** + * @var string + */ + protected $description = 'Runs all new database migrations for Castopod.'; + + public function run(array $params): void + { + $this->call('migrate', [ + 'all' => true, + ]); + } +} diff --git a/themes/cp_admin/_sidebar.php b/themes/cp_admin/_sidebar.php index f557e5e9b41820fa1ff52edf609674108b494d54..af54525097376157a5ada9590cfcf29726936d58 100644 --- a/themes/cp_admin/_sidebar.php +++ b/themes/cp_admin/_sidebar.php @@ -53,4 +53,8 @@ $navigation = [ </ul> </div> <?php endforeach; ?> + <a class="inline-flex items-center w-full px-4 py-1 font-semibold focus:ring-accent" href="<?= route_to('admin-about') ?>"> + <?= icon('information', 'opacity-60 text-2xl mr-4') ?> + <?= lang('Navigation.about') ?> + </a> </nav> diff --git a/themes/cp_admin/about.php b/themes/cp_admin/about.php new file mode 100644 index 0000000000000000000000000000000000000000..8df341bfdf910051609f4f437844114bbfc2dd96 --- /dev/null +++ b/themes/cp_admin/about.php @@ -0,0 +1,35 @@ +<?= $this->extend('_layout') ?> + +<?= $this->section('title') ?> +<?= lang('AboutCastopod.title') ?> +<?= $this->endSection() ?> + +<?= $this->section('pageTitle') ?> +<?= lang('AboutCastopod.title') ?> +<?= $this->endSection() ?> + +<?= $this->section('content') ?> + +<form action="<?= route_to('update') ?>" method="POST"> + <?= csrf_field() ?> + <button type="submit" name="action" value="database" class="inline-flex items-center px-4 py-2 text-lg font-semibold transition-colors rounded-full shadow group gap-x-2 bg-elevated hover:border-accent-hover focus:ring-accent border-3 border-subtle"> + <div class="relative"> + <Icon glyph="database" class="text-4xl text-accent-base" /> + <Icon glyph="refresh" class="absolute bottom-0 right-0 rounded-full bg-elevated text-accent-base motion-safe:group-hover:animate-spin motion-safe:group-focus:animate-spin" /> + </div> + <?= lang('AboutCastopod.update_database') ?> + </button> +</form> + +<?php foreach ($info as $key => $value): ?> +<div class="px-4 py-5"> + <dt class="text-sm font-medium leading-5 text-skin-muted"> + <?= lang('AboutCastopod.' . $key) ?> + </dt> + <dd class="mt-1 text-sm leading-5"> + <?= $value ?> + </dd> +</div> +<?php endforeach; ?> + +<?= $this->endSection() ?> diff --git a/themes/cp_install/_layout.php b/themes/cp_install/_layout.php index 6d35f502cc964caab1424a0810b139cd15c1e78d..1065c588c444f753d4ab62165ec2c8fa229d6aa0 100644 --- a/themes/cp_install/_layout.php +++ b/themes/cp_install/_layout.php @@ -6,8 +6,8 @@ <meta charset="UTF-8"/> <meta name="robots" content="noindex"> - <title>Castopod Install</title> - <meta name="description" content="Castopod is an open-source hosting platform made for podcasters who want engage and interact with their audience."/> + <title><?= lang('Install.title') ?></title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" /> <link rel="apple-touch-icon" href="/icon-180.png">