From a95de8bab010f6b01c598da72191abe97e473687 Mon Sep 17 00:00:00 2001
From: Yassine Doghri <yassine@doghri.fr>
Date: Fri, 27 Aug 2021 10:58:22 +0000
Subject: [PATCH] feat(components): add custom view renderer with
 ComponentRenderer adapted from bonfire2

- update Component class structure and remove component helper function and ComponentLoader
- update residual activitypub naming to fediverse
---
 .gitignore                                    |    3 +-
 app/Config/Autoload.php                       |   18 +-
 app/Config/Events.php                         |    2 +-
 app/Config/Filters.php                        |    4 +-
 app/Config/Services.php                       |   21 +
 app/Controllers/ActorController.php           |    4 +-
 app/Controllers/EpisodeCommentController.php  |    3 +
 app/Controllers/EpisodeController.php         |    2 +-
 app/Controllers/PostController.php            |   10 +-
 .../2020-05-30-101500_add_podcasts.php        |    2 +-
 ...1-02-23-100000_add_episode_id_to_posts.php |   18 +-
 ...1-03-09-113000_add_created_by_to_posts.php |   18 +-
 ...2021-08-12-150000_add_episode_comments.php |    6 +-
 .../2021-08-12-160000_add_likes.php           |    6 +-
 app/Database/Seeds/AuthSeeder.php             |    4 +-
 app/Entities/Actor.php                        |    4 +-
 app/Entities/EpisodeComment.php               |    2 +-
 app/Entities/Post.php                         |    4 +-
 app/Helpers/media_helper.php                  |    2 +-
 app/Language/en/ActivityPub.php               |   36 -
 app/Language/en/Admin.php                     |   15 -
 app/Language/en/Breadcrumb.php                |   44 -
 app/Language/en/Charts.php                    |   38 -
 app/Language/fr/ActivityPub.php               |   37 -
 app/Language/fr/Admin.php                     |   14 -
 app/Language/fr/Breadcrumb.php                |   44 -
 app/Language/fr/Charts.php                    |   51 -
 app/Libraries/NoteObject.php                  |    4 +-
 app/Libraries/View.php                        |  143 ++
 app/Libraries/ViewComponents/Component.php    |   30 +-
 .../ViewComponents/ComponentLoader.php        |   86 -
 .../ViewComponents/ComponentRenderer.php      |  264 +++
 .../ViewComponents/Config/Services.php        |    8 +-
 .../ViewComponents/Config/ViewComponents.php  |    6 +-
 .../Helpers/view_components_helper.php        |   28 -
 app/Models/ActorModel.php                     |    4 +-
 app/Models/EpisodeCommentModel.php            |    4 +-
 app/Models/PostModel.php                      |    4 +-
 app/View/Components/Button.php                |   12 +-
 app/View/Components/Forms/Input.php           |   15 -
 app/View/Components/Forms/Label.php           |   14 +-
 app/View/Components/Forms/MarkdownEditor.php  |    4 +-
 app/View/Components/Forms/MultiSelect.php     |   10 +
 app/View/Components/Forms/Toggler.php         |   17 +-
 app/View/Components/Forms/XMLEditor.php       |   11 +-
 app/View/Components/Icon.php                  |   17 +-
 app/Views/errors/html/error_404.php           |    6 +-
 .../podcast/_partials/comment_actions.php     |    2 +-
 .../comment_actions_authenticated.php         |    2 +-
 .../_partials/comment_actions_from_post.php   |    2 +-
 ...omment_actions_from_post_authenticated.php |    2 +-
 .../_partials/comment_reply_actions.php       |    2 +-
 .../comment_reply_actions_authenticated.php   |    2 +-
 app/Views/podcast/_partials/episode_card.php  |    2 +-
 app/Views/podcast/follow.php                  |    8 +-
 app/Views/podcast/post_remote_action.php      |   12 +-
 composer.json                                 |   26 +-
 composer.lock                                 | 1569 ++++++-----------
 ecs.php                                       |    5 +-
 .../Admin/Controllers/EpisodeController.php   |    3 -
 .../Controllers/PodcastPlatformController.php |    5 +-
 .../Admin}/Language/en/AdminNavigation.php    |    0
 .../Admin}/Language/fr/AdminNavigation.php    |    0
 modules/Admin/Views/contributor/add.php       |    6 +-
 modules/Admin/Views/contributor/edit.php      |    2 +-
 modules/Admin/Views/episode/create.php        |  152 +-
 modules/Admin/Views/episode/edit.php          |  155 +-
 modules/Admin/Views/episode/persons.php       |   25 +-
 modules/Admin/Views/episode/publish_edit.php  |    2 +-
 modules/Admin/Views/page/create.php           |   13 +-
 modules/Admin/Views/page/edit.php             |   12 +-
 modules/Admin/Views/podcast/create.php        |   92 +-
 modules/Admin/Views/podcast/edit.php          |  108 +-
 modules/Admin/Views/podcast/persons.php       |   14 +-
 modules/Admin/Views/podcast/platforms.php     |   36 +-
 modules/Admin/Views/user/edit.php             |    6 +-
 modules/Analytics/Config/Analytics.php        |    2 +-
 modules/Auth/Database/Seeds/AuthSeeder.php    |    4 +-
 modules/Fediverse/Config/Fediverse.php        |    4 +-
 modules/Fediverse/Config/Routes.php           |    2 +-
 .../Fediverse/Controllers/ActorController.php |   17 +-
 .../Fediverse/Controllers/BlockController.php |    2 +-
 .../Fediverse/Controllers/PostController.php  |    9 +-
 .../Controllers/SchedulerController.php       |    2 +-
 .../2018-01-01-010000_add_actors.php          |    6 +-
 .../2018-01-01-020000_add_posts.php           |   16 +-
 .../2018-01-01-100000_add_activities.php      |   16 +-
 .../2018-01-01-100000_add_favourites.php      |   14 +-
 .../2018-01-01-100000_add_follows.php         |   14 +-
 .../2018-01-01-100000_add_preview_cards.php   |    6 +-
 ...8-01-01-110000_add_posts_preview_cards.php |   13 +-
 .../2018-01-01-120000_add_blocked_domains.php |    6 +-
 modules/Fediverse/Entities/Post.php           |    2 +-
 ...ivityPubFilter.php => FediverseFilter.php} |    2 +-
 ...itypub_helper.php => fediverse_helper.php} |    0
 modules/Fediverse/Models/ActivityModel.php    |    5 +-
 modules/Fediverse/Models/ActorModel.php       |   13 +-
 modules/Fediverse/Models/BaseModel.php        |   26 +
 modules/Fediverse/Models/BaseUuidModel.php    |   20 +
 .../Fediverse/Models/BlockedDomainModel.php   |    4 +-
 modules/Fediverse/Models/FavouriteModel.php   |    5 +-
 modules/Fediverse/Models/FollowModel.php      |    4 +-
 modules/Fediverse/Models/PostModel.php        |   23 +-
 modules/Fediverse/Models/PreviewCardModel.php |   11 +-
 phpstan.neon                                  |    2 +-
 rector.php                                    |    7 +-
 106 files changed, 1482 insertions(+), 2139 deletions(-)
 delete mode 100644 app/Language/en/ActivityPub.php
 delete mode 100644 app/Language/en/Admin.php
 delete mode 100644 app/Language/en/Breadcrumb.php
 delete mode 100644 app/Language/en/Charts.php
 delete mode 100644 app/Language/fr/ActivityPub.php
 delete mode 100644 app/Language/fr/Admin.php
 delete mode 100644 app/Language/fr/Breadcrumb.php
 delete mode 100644 app/Language/fr/Charts.php
 create mode 100644 app/Libraries/View.php
 delete mode 100644 app/Libraries/ViewComponents/ComponentLoader.php
 create mode 100644 app/Libraries/ViewComponents/ComponentRenderer.php
 delete mode 100644 app/Libraries/ViewComponents/Helpers/view_components_helper.php
 delete mode 100644 app/View/Components/Forms/Input.php
 rename {app => modules/Admin}/Language/en/AdminNavigation.php (100%)
 rename {app => modules/Admin}/Language/fr/AdminNavigation.php (100%)
 rename modules/Fediverse/Filters/{ActivityPubFilter.php => FediverseFilter.php} (98%)
 rename modules/Fediverse/Helpers/{activitypub_helper.php => fediverse_helper.php} (100%)
 create mode 100644 modules/Fediverse/Models/BaseModel.php
 create mode 100644 modules/Fediverse/Models/BaseUuidModel.php

diff --git a/.gitignore b/.gitignore
index 2dd502f40b..47f4c37308 100644
--- a/.gitignore
+++ b/.gitignore
@@ -154,8 +154,7 @@ public/media/persons/*
 !public/media/persons/index.html
 
 # Generated files
-app/Language/en/PersonsTaxonomy.php
-app/Language/fr/PersonsTaxonomy.php
+modules/Admin/Language/*/PersonsTaxonomy.php
 
 #-------------------------
 # Docker volumes
diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php
index 2bc6ca8478..8a6ff73af5 100644
--- a/app/Config/Autoload.php
+++ b/app/Config/Autoload.php
@@ -43,16 +43,14 @@ class Autoload extends AutoloadConfig
      */
     public $psr4 = [
         APP_NAMESPACE => APPPATH,
-        'Modules' => ROOTPATH . 'modules',
-        'Modules\Admin' => ROOTPATH . 'modules/Admin',
-        'Modules\Auth' => ROOTPATH . 'modules/Auth',
-        'Modules\Analytics' => ROOTPATH . 'modules/Analytics',
-        'Modules\Install' => ROOTPATH . 'modules/Install',
-        'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse',
-        'Config' => APPPATH . 'Config',
-        'ActivityPub' => APPPATH . 'Libraries/ActivityPub',
-        'Analytics' => APPPATH . 'Libraries/Analytics',
-        'ViewComponents' => APPPATH . 'Libraries/ViewComponents',
+        'Modules' => ROOTPATH . 'modules/',
+        'Modules\Admin' => ROOTPATH . 'modules/Admin/',
+        'Modules\Auth' => ROOTPATH . 'modules/Auth/',
+        'Modules\Analytics' => ROOTPATH . 'modules/Analytics/',
+        'Modules\Install' => ROOTPATH . 'modules/Install/',
+        'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/',
+        'Config' => APPPATH . 'Config/',
+        'ViewComponents' => APPPATH . 'Libraries/ViewComponents/',
     ];
 
     /**
diff --git a/app/Config/Events.php b/app/Config/Events.php
index 5a5a5155e0..549ab27758 100644
--- a/app/Config/Events.php
+++ b/app/Config/Events.php
@@ -76,7 +76,7 @@ Events::on('logout', function (User $user): void {
 
 /*
  * --------------------------------------------------------------------
- * ActivityPub events
+ * Fediverse events
  * --------------------------------------------------------------------
  */
 /**
diff --git a/app/Config/Filters.php b/app/Config/Filters.php
index 397c496c3a..b65ed212a8 100644
--- a/app/Config/Filters.php
+++ b/app/Config/Filters.php
@@ -9,7 +9,7 @@ use CodeIgniter\Filters\CSRF;
 use CodeIgniter\Filters\DebugToolbar;
 use CodeIgniter\Filters\Honeypot;
 use Modules\Auth\Filters\PermissionFilter;
-use Modules\Fediverse\Filters\ActivityPubFilter;
+use Modules\Fediverse\Filters\FediverseFilter;
 use Myth\Auth\Filters\LoginFilter;
 use Myth\Auth\Filters\RoleFilter;
 
@@ -27,7 +27,7 @@ class Filters extends BaseConfig
         'login' => LoginFilter::class,
         'role' => RoleFilter::class,
         'permission' => PermissionFilter::class,
-        'activity-pub' => ActivityPubFilter::class,
+        'activity-pub' => FediverseFilter::class,
     ];
 
     /**
diff --git a/app/Config/Services.php b/app/Config/Services.php
index 0dc63ead8e..a0e120af63 100644
--- a/app/Config/Services.php
+++ b/app/Config/Services.php
@@ -7,11 +7,14 @@ namespace Config;
 use App\Libraries\Breadcrumb;
 use App\Libraries\Negotiate;
 use App\Libraries\Router;
+use App\Libraries\View;
 use App\Libraries\Vite;
 use CodeIgniter\Config\BaseService;
 use CodeIgniter\HTTP\Request;
 use CodeIgniter\HTTP\RequestInterface;
 use CodeIgniter\Router\RouteCollectionInterface;
+use Config\Services as AppServices;
+use Config\View as ViewConfig;
 
 /**
  * Services Configuration file.
@@ -46,6 +49,24 @@ class Services extends BaseService
         return new Router($routes, $request);
     }
 
+    /**
+     * The Renderer class is the class that actually displays a file to the user. The default View class within
+     * CodeIgniter is intentionally simple, but this service could easily be replaced by a template engine if the user
+     * needed to.
+     */
+    public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true): View
+    {
+        if ($getShared) {
+            return static::getSharedInstance('renderer', $viewPath, $config);
+        }
+
+        $viewPath = $viewPath ?: config('Paths')
+            ->viewDirectory;
+        $config = $config ?? config('View');
+
+        return new View($config, $viewPath, AppServices::locator(), CI_DEBUG, AppServices::logger());
+    }
+
     /**
      * The Negotiate class provides the content negotiation features for working the request to determine correct
      * language, encoding, charset, and more.
diff --git a/app/Controllers/ActorController.php b/app/Controllers/ActorController.php
index 75e8d8ffda..ff1dbae54b 100644
--- a/app/Controllers/ActorController.php
+++ b/app/Controllers/ActorController.php
@@ -11,9 +11,9 @@ declare(strict_types=1);
 namespace App\Controllers;
 
 use Modules\Analytics\AnalyticsTrait;
-use Modules\Fediverse\Controllers\ActorController as ActivityPubActorController;
+use Modules\Fediverse\Controllers\ActorController as FediverseActorController;
 
-class ActorController extends ActivityPubActorController
+class ActorController extends FediverseActorController
 {
     use AnalyticsTrait;
 
diff --git a/app/Controllers/EpisodeCommentController.php b/app/Controllers/EpisodeCommentController.php
index 964cb0f16e..4dcef86198 100644
--- a/app/Controllers/EpisodeCommentController.php
+++ b/app/Controllers/EpisodeCommentController.php
@@ -127,6 +127,9 @@ class EpisodeCommentController extends BaseController
             ->setBody($commentObject->toJSON());
     }
 
+    /**
+     * @noRector ReturnTypeDeclarationRector
+     */
     public function replies(): Response
     {
         /**
diff --git a/app/Controllers/EpisodeController.php b/app/Controllers/EpisodeController.php
index 5e584cfa59..9aacdc6848 100644
--- a/app/Controllers/EpisodeController.php
+++ b/app/Controllers/EpisodeController.php
@@ -222,7 +222,7 @@ class EpisodeController extends BaseController
         $episodeComments = model('PostModel')
             ->whereIn('in_reply_to_id', function (BaseBuilder $builder): BaseBuilder {
                 return $builder->select('id')
-                    ->from('activitypub_posts')
+                    ->from(config('Fediverse')->tablesPrefix . 'posts')
                     ->where('episode_id', $this->episode->id);
             })
             ->where('`published_at` <= NOW()', null, false)
diff --git a/app/Controllers/PostController.php b/app/Controllers/PostController.php
index 1cdafa464a..764477fcae 100644
--- a/app/Controllers/PostController.php
+++ b/app/Controllers/PostController.php
@@ -21,10 +21,10 @@ use CodeIgniter\HTTP\RedirectResponse;
 use CodeIgniter\HTTP\URI;
 use CodeIgniter\I18n\Time;
 use Modules\Analytics\AnalyticsTrait;
-use Modules\Fediverse\Controllers\PostController as ActivityPubPostController;
-use Modules\Fediverse\Entities\Post as ActivityPubPost;
+use Modules\Fediverse\Controllers\PostController as FediversePostController;
+use Modules\Fediverse\Entities\Post as FediversePost;
 
-class PostController extends ActivityPubPostController
+class PostController extends FediversePostController
 {
     use AnalyticsTrait;
 
@@ -35,7 +35,7 @@ class PostController extends ActivityPubPostController
     /**
      * @var string[]
      */
-    protected $helpers = ['auth', 'activitypub', 'svg', 'components', 'misc'];
+    protected $helpers = ['auth', 'fediverse', 'svg', 'components', 'misc'];
 
     public function _remap(string $method, string ...$params): mixed
     {
@@ -162,7 +162,7 @@ class PostController extends ActivityPubPostController
                 ->with('errors', $this->validator->getErrors());
         }
 
-        $newPost = new ActivityPubPost([
+        $newPost = new FediversePost([
             'actor_id' => interact_as_actor_id(),
             'in_reply_to_id' => $this->post->id,
             'message' => $this->request->getPost('message'),
diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
index c40b9c09cf..9243e7f386 100644
--- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
+++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
@@ -196,7 +196,7 @@ class AddPodcasts extends Migration
         $this->forge->addUniqueKey('handle');
         $this->forge->addUniqueKey('guid');
         $this->forge->addUniqueKey('actor_id');
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('actor_id', config('Fediverse')->tablesPrefix . 'actors', 'id', '', 'CASCADE');
         $this->forge->addForeignKey('category_id', 'categories', 'id');
         $this->forge->addForeignKey('language_code', 'languages', 'code');
         $this->forge->addForeignKey('created_by', 'users', 'id');
diff --git a/app/Database/Migrations/2021-02-23-100000_add_episode_id_to_posts.php b/app/Database/Migrations/2021-02-23-100000_add_episode_id_to_posts.php
index b34c801f50..1b3929cbb0 100644
--- a/app/Database/Migrations/2021-02-23-100000_add_episode_id_to_posts.php
+++ b/app/Database/Migrations/2021-02-23-100000_add_episode_id_to_posts.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddEpisodeIdToPosts Adds episode_id field to activitypub_posts table in database
+ * Class AddEpisodeIdToPosts Adds episode_id field to posts table in database
  *
  * @copyright  2020 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -19,18 +19,26 @@ class AddEpisodeIdToPosts extends Migration
     public function up(): void
     {
         $prefix = $this->db->getPrefix();
+        $fediverseTablesPrefix = config('Fediverse')
+            ->tablesPrefix;
 
         $createQuery = <<<CODE_SAMPLE
-            ALTER TABLE {$prefix}activitypub_posts
+            ALTER TABLE {$prefix}{$fediverseTablesPrefix}posts
             ADD COLUMN `episode_id` INT UNSIGNED NULL AFTER `replies_count`,
-            ADD FOREIGN KEY {$prefix}activitypub_posts_episode_id_foreign(episode_id) REFERENCES {$prefix}episodes(id) ON DELETE CASCADE;
+            ADD FOREIGN KEY {$prefix}{$fediverseTablesPrefix}posts_episode_id_foreign(episode_id) REFERENCES {$prefix}episodes(id) ON DELETE CASCADE;
         CODE_SAMPLE;
         $this->db->query($createQuery);
     }
 
     public function down(): void
     {
-        $this->forge->dropForeignKey('activitypub_posts', 'activitypub_posts_episode_id_foreign');
-        $this->forge->dropColumn('activitypub_posts', 'episode_id');
+        $fediverseTablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
+        $this->forge->dropForeignKey(
+            $fediverseTablesPrefix . 'posts',
+            $fediverseTablesPrefix . 'posts_episode_id_foreign'
+        );
+        $this->forge->dropColumn($fediverseTablesPrefix . 'posts', 'episode_id');
     }
 }
diff --git a/app/Database/Migrations/2021-03-09-113000_add_created_by_to_posts.php b/app/Database/Migrations/2021-03-09-113000_add_created_by_to_posts.php
index 9ccd81bde1..c10d9fb7a7 100644
--- a/app/Database/Migrations/2021-03-09-113000_add_created_by_to_posts.php
+++ b/app/Database/Migrations/2021-03-09-113000_add_created_by_to_posts.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddCreatedByToPosts Adds created_by field to activitypub_posts table in database
+ * Class AddCreatedByToPosts Adds created_by field to posts table in database
  *
  * @copyright  2020 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -19,18 +19,26 @@ class AddCreatedByToPosts extends Migration
     public function up(): void
     {
         $prefix = $this->db->getPrefix();
+        $fediverseTablesPrefix = config('Fediverse')
+            ->tablesPrefix;
 
         $createQuery = <<<CODE_SAMPLE
-            ALTER TABLE {$prefix}activitypub_posts
+            ALTER TABLE {$prefix}{$fediverseTablesPrefix}posts
             ADD COLUMN `created_by` INT UNSIGNED AFTER `episode_id`,
-            ADD FOREIGN KEY {$prefix}activitypub_posts_created_by_foreign(created_by) REFERENCES {$prefix}users(id) ON DELETE CASCADE;
+            ADD FOREIGN KEY {$prefix}{$fediverseTablesPrefix}posts_created_by_foreign(created_by) REFERENCES {$prefix}users(id) ON DELETE CASCADE;
         CODE_SAMPLE;
         $this->db->query($createQuery);
     }
 
     public function down(): void
     {
-        $this->forge->dropForeignKey('activitypub_posts', 'activitypub_posts_created_by_foreign');
-        $this->forge->dropColumn('activitypub_posts', 'created_by');
+        $fediverseTablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
+        $this->forge->dropForeignKey(
+            $fediverseTablesPrefix . 'posts',
+            $fediverseTablesPrefix . 'posts_created_by_foreign'
+        );
+        $this->forge->dropColumn($fediverseTablesPrefix . 'posts', 'created_by');
     }
 }
diff --git a/app/Database/Migrations/2021-08-12-150000_add_episode_comments.php b/app/Database/Migrations/2021-08-12-150000_add_episode_comments.php
index 1524d45679..156bd2f635 100644
--- a/app/Database/Migrations/2021-08-12-150000_add_episode_comments.php
+++ b/app/Database/Migrations/2021-08-12-150000_add_episode_comments.php
@@ -65,9 +65,13 @@ class AddEpisodeComments extends Migration
                 'null' => true,
             ],
         ]);
+
+        $fediverseTablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addPrimaryKey('id');
         $this->forge->addForeignKey('episode_id', 'episodes', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('actor_id', $fediverseTablesPrefix . 'actors', 'id', '', 'CASCADE');
         $this->forge->addForeignKey('created_by', 'users', 'id');
         $this->forge->createTable('episode_comments');
     }
diff --git a/app/Database/Migrations/2021-08-12-160000_add_likes.php b/app/Database/Migrations/2021-08-12-160000_add_likes.php
index 116fae4556..841037adf5 100644
--- a/app/Database/Migrations/2021-08-12-160000_add_likes.php
+++ b/app/Database/Migrations/2021-08-12-160000_add_likes.php
@@ -28,9 +28,13 @@ class AddLikes extends Migration
                 'constraint' => 16,
             ],
         ]);
+
+        $fediverseTablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
         $this->forge->addPrimaryKey(['actor_id', 'comment_id']);
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('actor_id', $fediverseTablesPrefix . 'actors', 'id', '', 'CASCADE');
         $this->forge->addForeignKey('comment_id', 'episode_comments', 'id', '', 'CASCADE');
         $this->forge->createTable('likes');
     }
diff --git a/app/Database/Seeds/AuthSeeder.php b/app/Database/Seeds/AuthSeeder.php
index 3a76e36215..2fb6fb6a28 100644
--- a/app/Database/Seeds/AuthSeeder.php
+++ b/app/Database/Seeds/AuthSeeder.php
@@ -238,13 +238,13 @@ class AuthSeeder extends Seeder
             [
                 'name' => 'block_actors',
                 'description' =>
-                    'Block an activitypub actors from interacting with the instance.',
+                    'Block fediverse actors from interacting with the instance.',
                 'has_permission' => ['superadmin'],
             ],
             [
                 'name' => 'block_domains',
                 'description' =>
-                    'Block an activitypub domains from interacting with the instance.',
+                    'Block fediverse domains from interacting with the instance.',
                 'has_permission' => ['superadmin'],
             ],
         ],
diff --git a/app/Entities/Actor.php b/app/Entities/Actor.php
index dc256a56a8..7b76b509f3 100644
--- a/app/Entities/Actor.php
+++ b/app/Entities/Actor.php
@@ -11,14 +11,14 @@ declare(strict_types=1);
 namespace App\Entities;
 
 use App\Models\PodcastModel;
-use Modules\Fediverse\Entities\Actor as ActivityPubActor;
+use Modules\Fediverse\Entities\Actor as FediverseActor;
 use RuntimeException;
 
 /**
  * @property Podcast|null $podcast
  * @property boolean $is_podcast
  */
-class Actor extends ActivityPubActor
+class Actor extends FediverseActor
 {
     protected ?Podcast $podcast = null;
 
diff --git a/app/Entities/EpisodeComment.php b/app/Entities/EpisodeComment.php
index a6fa142009..cb39152c55 100644
--- a/app/Entities/EpisodeComment.php
+++ b/app/Entities/EpisodeComment.php
@@ -134,7 +134,7 @@ class EpisodeComment extends UuidEntity
 
     public function setMessage(string $message): static
     {
-        helper('activitypub');
+        helper('fediverse');
 
         $messageWithoutTags = strip_tags($message);
 
diff --git a/app/Entities/Post.php b/app/Entities/Post.php
index 228c7efe2b..0f4c4654c9 100644
--- a/app/Entities/Post.php
+++ b/app/Entities/Post.php
@@ -11,14 +11,14 @@ declare(strict_types=1);
 namespace App\Entities;
 
 use App\Models\EpisodeModel;
-use Modules\Fediverse\Entities\Post as ActivityPubPost;
+use Modules\Fediverse\Entities\Post as FediversePost;
 use RuntimeException;
 
 /**
  * @property int|null $episode_id
  * @property Episode|null $episode
  */
-class Post extends ActivityPubPost
+class Post extends FediversePost
 {
     protected ?Episode $episode = null;
 
diff --git a/app/Helpers/media_helper.php b/app/Helpers/media_helper.php
index 827436f9eb..312af42a3b 100644
--- a/app/Helpers/media_helper.php
+++ b/app/Helpers/media_helper.php
@@ -18,7 +18,7 @@ if (! function_exists('save_media')) {
     /**
      * Saves a file to the corresponding podcast folder in `public/media`
      */
-    function save_media(File|UploadedFile $file, string $folder = '', string $filename = ''): string
+    function save_media(File | UploadedFile $file, string $folder = '', string $filename = ''): string
     {
         if (($extension = $file->getExtension()) !== '') {
             $filename = $filename . '.' . $extension;
diff --git a/app/Language/en/ActivityPub.php b/app/Language/en/ActivityPub.php
deleted file mode 100644
index 4c651894a5..0000000000
--- a/app/Language/en/ActivityPub.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'your_handle' => 'Your handle',
-    'your_handle_hint' => 'Enter the @username@domain you want to act from.',
-    'follow' => [
-        'label' => 'Follow',
-        'title' => 'Follow {actorDisplayName}',
-        'subtitle' => 'You are going to follow:',
-        'accountNotFound' => 'The account could not be found.',
-        'submit' => 'Proceed to follow',
-    ],
-    'favourite' => [
-        'title' => "Favourite {actorDisplayName}'s post",
-        'subtitle' => 'You are going to favourite:',
-        'submit' => 'Proceed to favourite',
-    ],
-    'reblog' => [
-        'title' => "Share {actorDisplayName}'s post",
-        'subtitle' => 'You are going to share:',
-        'submit' => 'Proceed to share',
-    ],
-    'reply' => [
-        'title' => "Reply to {actorDisplayName}'s post",
-        'subtitle' => 'You are going to reply to:',
-        'submit' => 'Proceed to reply',
-    ],
-];
diff --git a/app/Language/en/Admin.php b/app/Language/en/Admin.php
deleted file mode 100644
index 944e7af2b6..0000000000
--- a/app/Language/en/Admin.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'dashboard' => 'Admin dashboard',
-    'welcome_message' => 'Welcome to the admin area!',
-    'choose_interact' => 'Choose how to interact',
-];
diff --git a/app/Language/en/Breadcrumb.php b/app/Language/en/Breadcrumb.php
deleted file mode 100644
index a0fa5e44e7..0000000000
--- a/app/Language/en/Breadcrumb.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'label' => 'breadcrumb',
-    config('Admin')
-        ->gateway => 'Home',
-    'podcasts' => 'podcasts',
-    'episodes' => 'episodes',
-    'contributors' => 'contributors',
-    'pages' => 'pages',
-    'add' => 'add',
-    'new' => 'new',
-    'edit' => 'edit',
-    'persons' => 'persons',
-    'publish' => 'publish',
-    'publish-edit' => 'edit publication',
-    'unpublish' => 'unpublish',
-    'fediverse' => 'fediverse',
-    'block-lists' => 'block lists',
-    'users' => 'users',
-    'my-account' => 'my account',
-    'change-password' => 'change password',
-    'import' => 'feed import',
-    'platforms' => 'platforms',
-    'social' => 'social networks',
-    'funding' => 'funding',
-    'analytics' => 'analytics',
-    'locations' => 'locations',
-    'webpages' => 'web pages',
-    'unique-listeners' => 'unique listeners',
-    'players' => 'players',
-    'listening-time' => 'listening time',
-    'time-periods' => 'time periods',
-    'soundbites' => 'soundbites',
-    'embeddable-player' => 'embeddable player',
-];
diff --git a/app/Language/en/Charts.php b/app/Language/en/Charts.php
deleted file mode 100644
index 2bc933ef28..0000000000
--- a/app/Language/en/Charts.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'by_service_weekly' => 'Episode downloads by service (for the past week)',
-    'by_player_weekly' => 'Episode downloads by player (for the past week)',
-    'by_player_yearly' => 'Episode downloads by player (for the past year)',
-    'by_device_weekly' => 'Episode downloads by device (for the past week)',
-    'by_os_weekly' => 'Episode downloads by O.S. (for the past week)',
-    'podcast_by_region' => 'Episode downloads by region (for the past week)',
-    'unique_daily_listeners' => 'Daily unique listeners',
-    'unique_monthly_listeners' => 'Monthly unique listeners',
-    'by_browser' => 'Web pages usage by browser (for the past week)',
-    'podcast_by_day' => 'Episode daily downloads',
-    'podcast_by_month' => 'Episode monthly downloads',
-    'episode_by_day' => 'Episode daily downloads (first 60 days)',
-    'episode_by_month' => 'Episode monthly downloads',
-    'episodes_by_day' =>
-        '5 latest episodes downloads (during their first 60 days)',
-    'by_country_weekly' => 'Episode downloads by country (for the past week)',
-    'by_country_yearly' => 'Episode downloads by country (for the past year)',
-    'by_domain_weekly' => 'Web pages visits by source (for the past week)',
-    'by_domain_yearly' => 'Web pages visits by source (for the past year)',
-    'by_entry_page' => 'Web pages visits by landing page (for the past week)',
-    'podcast_bots' => 'Bots (crawlers)',
-    'daily_listening_time' => 'Daily cumulative listening time',
-    'monthly_listening_time' => 'Monthly cumulative listening time',
-    'by_weekday' => 'By week day (for the past 60 days)',
-    'by_hour' => 'By time of day (for the past 60 days)',
-    'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)',
-];
diff --git a/app/Language/fr/ActivityPub.php b/app/Language/fr/ActivityPub.php
deleted file mode 100644
index 8951919f2f..0000000000
--- a/app/Language/fr/ActivityPub.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'your_handle' => 'Votre pseudonyme',
-    'your_handle_hint' =>
-        'Entrez le @utilisateur@domaine avec lequel vous voulez interagir.',
-    'follow' => [
-        'label' => 'Suivre',
-        'title' => 'Suivre {actorDisplayName}',
-        'subtitle' => 'Vous allez suivre :',
-        'accountNotFound' => 'Le compte n’a pas pu être trouvé.',
-        'submit' => 'Poursuivre',
-    ],
-    'favourite' => [
-        'title' => 'Mettez la publication de {actorDisplayName} en favori',
-        'subtitle' => 'Vous allez mettre en favori :',
-        'submit' => 'Poursuivre',
-    ],
-    'reblog' => [
-        'title' => 'Partagez la publication de {actorDisplayName}',
-        'subtitle' => 'Vous allez partager :',
-        'submit' => 'Poursuivre',
-    ],
-    'reply' => [
-        'title' => 'Répondre à la publication de {actorDisplayName}',
-        'subtitle' => 'Vous allez répondre à :',
-        'submit' => 'Poursuivre',
-    ],
-];
diff --git a/app/Language/fr/Admin.php b/app/Language/fr/Admin.php
deleted file mode 100644
index 5c0d82e17b..0000000000
--- a/app/Language/fr/Admin.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'dashboard' => 'Tableau de bord',
-    'welcome_message' => 'Bienvenue dans l’administration !',
-];
diff --git a/app/Language/fr/Breadcrumb.php b/app/Language/fr/Breadcrumb.php
deleted file mode 100644
index 08d8d888ac..0000000000
--- a/app/Language/fr/Breadcrumb.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'label' => 'Fil d’Ariane',
-    config('Admin')
-        ->gateway => 'Accueil',
-    'podcasts' => 'podcasts',
-    'episodes' => 'épisodes',
-    'contributors' => 'contributeurs',
-    'pages' => 'pages',
-    'add' => 'ajouter',
-    'new' => 'créer',
-    'edit' => 'modifier',
-    'persons' => 'intervenants',
-    'publish' => 'publier',
-    'publish-edit' => 'modifier la publication',
-    'unpublish' => 'dépublier',
-    'fediverse' => 'fédiverse',
-    'block-lists' => 'listes de blocage',
-    'users' => 'utilisateurs',
-    'my-account' => 'mon compte',
-    'change-password' => 'changer le mot de passe',
-    'import' => 'importer un flux',
-    'platforms' => 'plateformes',
-    'social' => 'réseaux sociaux',
-    'funding' => 'financement',
-    'analytics' => 'mesures d’audience',
-    'locations' => 'localisations',
-    'webpages' => 'pages web',
-    'unique-listeners' => 'auditeurs uniques',
-    'players' => 'lecteurs',
-    'listening-time' => 'drée d’écoute',
-    'time-periods' => 'périodes',
-    'soundbites' => 'extraits sonores',
-    'embeddable-player' => 'lecteur intégré',
-];
diff --git a/app/Language/fr/Charts.php b/app/Language/fr/Charts.php
deleted file mode 100644
index 071918ae78..0000000000
--- a/app/Language/fr/Charts.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-return [
-    'by_service_weekly' =>
-        'Téléchargements d’épisodes par service (sur la dernière semaine)',
-    'by_player_weekly' =>
-        'Téléchargements d’épisodes par lecteur (sur la dernière semaine)',
-    'by_player_yearly' =>
-        'Téléchargements d’épisodes par lecteur (sur la dernière année)',
-    'by_device_weekly' =>
-        'Téléchargements d’épisodes par appareil (sur la dernière semaine)',
-    'by_os_weekly' =>
-        'Téléchargements d’épisodes par OS (sur la dernière semaine)',
-    'podcast_by_region' =>
-        'Téléchargements d’épisodes par région (sur la dernière semaine)',
-    'unique_daily_listeners' => 'Auditeurs uniques quotidiens',
-    'unique_monthly_listeners' => 'Auditeurs uniques mensuels',
-    'by_browser' =>
-        'Fréquentation des pages web par navigateur (sur la dernière semaine)',
-    'podcast_by_day' => 'Téléchargements quotidiens d’épisodes',
-    'podcast_by_month' => 'Téléchargements mensuels d’épisodes',
-    'episode_by_day' =>
-        'Téléchargements quotidiens de l’épisode (sur les 60 premiers jours)',
-    'episode_by_month' => 'Téléchargements mensuels de l’épisode',
-    'episodes_by_day' =>
-        'Téléchargements des 5 derniers épisodes (sur les 60 premiers jours)',
-    'by_country_weekly' =>
-        'Téléchargement d’épisodes par pays (sur la dernière semaine)',
-    'by_country_yearly' =>
-        'Téléchargement d’épisodes par pays (sur la dernière année)',
-    'by_domain_weekly' =>
-        'Fréquentation des pages web par origine (sur la dernière semaine)',
-    'by_domain_yearly' =>
-        'Fréquentation des pages web par origine (sur la dernière année)',
-    'by_entry_page' =>
-        'Fréquentation des pages web par page d’entrée (sur la dernière semaine)',
-    'podcast_bots' => 'Robots (bots)',
-    'daily_listening_time' => 'Durée quotidienne d’écoute cumulée',
-    'monthly_listening_time' => 'Durée mensuelle d’écoute cumulée',
-    'by_weekday' => 'Par jour de la semaine (sur les 60 derniers jours)',
-    'by_hour' => 'Par heure de la journée (sur les 60 derniers jours)',
-    'podcast_by_bandwidth' => 'Bande passante quotidienne consommée (en Mo)',
-];
diff --git a/app/Libraries/NoteObject.php b/app/Libraries/NoteObject.php
index 84af0c183f..71720ad747 100644
--- a/app/Libraries/NoteObject.php
+++ b/app/Libraries/NoteObject.php
@@ -11,9 +11,9 @@ declare(strict_types=1);
 namespace App\Libraries;
 
 use App\Entities\Post;
-use Modules\Fediverse\Objects\NoteObject as ActivityPubNoteObject;
+use Modules\Fediverse\Objects\NoteObject as FediverseNoteObject;
 
-class NoteObject extends ActivityPubNoteObject
+class NoteObject extends FediverseNoteObject
 {
     /**
      * @param Post $post
diff --git a/app/Libraries/View.php b/app/Libraries/View.php
new file mode 100644
index 0000000000..38fd82f9b1
--- /dev/null
+++ b/app/Libraries/View.php
@@ -0,0 +1,143 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Libraries;
+
+use CodeIgniter\Debug\Toolbar\Collectors\Views;
+use CodeIgniter\Filters\DebugToolbar;
+use CodeIgniter\View\Exceptions\ViewException;
+use CodeIgniter\View\View as CodeIgniterView;
+use Config\Toolbar;
+
+class View extends CodeIgniterView
+{
+    /**
+     * Builds the output based upon a file name and any
+     * data that has already been set.
+     *
+     * Valid $options:
+     *  - cache      Number of seconds to cache for
+     *  - cache_name Name to use for cache
+     *
+     * @param string     $view     File name of the view source
+     * @param array<string, mixed>|null $options  Reserved for 3rd-party uses since
+     *                             it might be needed to pass additional info
+     *                             to other template engines.
+     * @param bool|null  $saveData If true, saves data for subsequent calls,
+     *                             if false, cleans the data after displaying,
+     *                             if null, uses the config setting.
+     */
+    public function render(string $view, ?array $options = null, ?bool $saveData = null): string
+    {
+        $this->renderVars['start'] = microtime(true);
+
+        // Store the results here so even if
+        // multiple views are called in a view, it won't
+        // clean it unless we mean it to.
+        $saveData = $saveData ?? $this->saveData;
+        $fileExt = pathinfo($view, PATHINFO_EXTENSION);
+        $realPath = $fileExt === '' ? $view . '.php' : $view; // allow Views as .html, .tpl, etc (from CI3)
+        $this->renderVars['view'] = $realPath;
+        $this->renderVars['options'] = $options ?? [];
+
+        // Was it cached?
+        if (isset($this->renderVars['options']['cache'])) {
+            $cacheName = $this->renderVars['options']['cache_name'] ?? str_replace(
+                '.php',
+                '',
+                $this->renderVars['view']
+            );
+            $cacheName = str_replace(['\\', '/'], '', $cacheName);
+
+            $this->renderVars['cacheName'] = $cacheName;
+
+            if ($output = cache($this->renderVars['cacheName'])) {
+                $this->logPerformance($this->renderVars['start'], microtime(true), $this->renderVars['view']);
+
+                return $output;
+            }
+        }
+
+        $this->renderVars['file'] = $this->viewPath . $this->renderVars['view'];
+
+        if (! is_file($this->renderVars['file'])) {
+            $this->renderVars['file'] = $this->loader->locateFile(
+                $this->renderVars['view'],
+                'Views',
+                $fileExt === '' ? 'php' : $fileExt
+            );
+        }
+
+        // locateFile will return an empty string if the file cannot be found.
+        if ($this->renderVars['file'] === '') {
+            throw ViewException::forInvalidFile($this->renderVars['view']);
+        }
+
+        // Make our view data available to the view.
+        $this->tempData = $this->tempData ?? $this->data;
+
+        if ($saveData) {
+            $this->data = $this->tempData;
+        }
+
+        // Save current vars
+        $renderVars = $this->renderVars;
+
+        $output = (function (): string {
+            /** @phpstan-ignore-next-line */
+            extract($this->tempData);
+            ob_start();
+            include $this->renderVars['file'];
+
+            return ob_get_clean() ?: '';
+        })();
+
+        // Get back current vars
+        $this->renderVars = $renderVars;
+
+        // When using layouts, the data has already been stored
+        // in $this->sections, and no other valid output
+        // is allowed in $output so we'll overwrite it.
+        if ($this->layout !== null && $this->sectionStack === []) {
+            $layoutView = $this->layout;
+            $this->layout = null;
+            // Save current vars
+            $renderVars = $this->renderVars;
+            $output = $this->render($layoutView, $options, $saveData);
+            // Get back current vars
+            $this->renderVars = $renderVars;
+        }
+
+        $output = service('components')
+            ->setCurrentView($view)
+            ->render($output);
+
+        $this->logPerformance($this->renderVars['start'], microtime(true), $this->renderVars['view']);
+
+        if (($this->debug && (! isset($options['debug']) || $options['debug'] === true))
+            && in_array(DebugToolbar::class, service('filters')->getFiltersClass()['after'], true)
+        ) {
+            $toolbarCollectors = config(Toolbar::class)->collectors;
+
+            if (in_array(Views::class, $toolbarCollectors, true)) {
+                // Clean up our path names to make them a little cleaner
+                $this->renderVars['file'] = clean_path($this->renderVars['file']);
+                $this->renderVars['file'] = ++$this->viewsCount . ' ' . $this->renderVars['file'];
+
+                $output = '<!-- DEBUG-VIEW START ' . $this->renderVars['file'] . ' -->' . PHP_EOL
+                    . $output . PHP_EOL
+                    . '<!-- DEBUG-VIEW ENDED ' . $this->renderVars['file'] . ' -->' . PHP_EOL;
+            }
+        }
+
+        // Should we cache?
+        if (isset($this->renderVars['options']['cache'])) {
+            cache()->save($this->renderVars['cacheName'], $output, (int) $this->renderVars['options']['cache']);
+        }
+
+        $this->tempData = null;
+
+        return $output;
+    }
+}
diff --git a/app/Libraries/ViewComponents/Component.php b/app/Libraries/ViewComponents/Component.php
index 57873df5c9..81d08f1eb1 100644
--- a/app/Libraries/ViewComponents/Component.php
+++ b/app/Libraries/ViewComponents/Component.php
@@ -6,6 +6,8 @@ namespace ViewComponents;
 
 class Component implements ComponentInterface
 {
+    protected string $slot = '';
+
     /**
      * @var array<string, string>
      */
@@ -14,21 +16,33 @@ class Component implements ComponentInterface
     ];
 
     /**
-     * @param array<string, mixed> $properties
      * @param array<string, string> $attributes
      */
-    public function __construct(
-        protected array $properties,
-        array $attributes
-    ) {
-        // overwrite default properties if set
-        foreach ($properties as $key => $value) {
-            $this->{$key} = $value;
+    public function __construct(array $attributes)
+    {
+        if ($attributes !== []) {
+            $this->hydrate($attributes);
         }
+        // overwrite default attributes if set
 
         $this->attributes = array_merge($this->attributes, $attributes);
     }
 
+    /**
+     * @param array<string, string> $attributes
+     */
+    public function hydrate(array $attributes): void
+    {
+        foreach ($attributes as $name => $value) {
+            $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $name)));
+            if (is_callable([$this, $method])) {
+                $this->{$method}($value);
+            } else {
+                $this->{$name} = $value;
+            }
+        }
+    }
+
     public function render(): string
     {
         return static::class . ': RENDER METHOD NOT IMPLEMENTED';
diff --git a/app/Libraries/ViewComponents/ComponentLoader.php b/app/Libraries/ViewComponents/ComponentLoader.php
deleted file mode 100644
index 9ec75d7b87..0000000000
--- a/app/Libraries/ViewComponents/ComponentLoader.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace ViewComponents;
-
-use ViewComponents\Config\ViewComponents;
-use ViewComponents\Exceptions\ComponentNotFoundException;
-
-class ComponentLoader
-{
-    protected ViewComponents $config;
-
-    protected string $name;
-
-    /**
-     * @var array<string, mixed>
-     */
-    protected array $properties = [];
-
-    /**
-     * @var array<string, string>
-     */
-    protected array $attributes = [];
-
-    public function __construct()
-    {
-        $this->config = config('ViewComponents');
-    }
-
-    public function __get(string $property): mixed
-    {
-        if (property_exists($this, $property)) {
-            return $this->{$property};
-        }
-    }
-
-    // @phpstan-ignore-next-line
-    public function __set(string $property, mixed $value)
-    {
-        if (property_exists($this, $property)) {
-            $this->{$property} = $value;
-        }
-
-        return $this;
-    }
-
-    /**
-     * @throws ComponentNotFoundException
-     */
-    public function load(): string
-    {
-        // first, check if there exists a component class to load in class components path
-        if (file_exists("{$this->config->classComponentsPath}/{$this->name}.php")) {
-            return $this->loadComponentClass();
-        }
-
-        // check for the existence of a view file if no component class has been found
-        // component view files are camel case
-        $camelCaseName = strtolower(preg_replace('~(?<!^)(?<!\/)[A-Z]~', '_$0', $this->name) ?? '');
-
-        if (file_exists("{$this->config->componentsViewPath}/{$camelCaseName}.php")) {
-            return $this->loadComponentView($camelCaseName);
-        }
-
-        throw new ComponentNotFoundException("Could not find component \"{$this->name}\"");
-    }
-
-    private function loadComponentClass(): string
-    {
-        $classComponentsNamespace = $this->config->classComponentsNamespace;
-
-        $namespacedName = str_replace('/', '\\', $this->name);
-        $componentClassNamespace = "{$classComponentsNamespace}\\{$namespacedName}";
-
-        $component = new $componentClassNamespace($this->properties, $this->attributes);
-        return $component->render();
-    }
-
-    private function loadComponentView(string $name): string
-    {
-        $viewData = [...$this->properties, ...$this->attributes];
-
-        return view("components/{$name}", $viewData);
-    }
-}
diff --git a/app/Libraries/ViewComponents/ComponentRenderer.php b/app/Libraries/ViewComponents/ComponentRenderer.php
new file mode 100644
index 0000000000..c20d9d44bb
--- /dev/null
+++ b/app/Libraries/ViewComponents/ComponentRenderer.php
@@ -0,0 +1,264 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ViewComponents;
+
+use RuntimeException;
+use ViewComponents\Config\ViewComponents;
+
+/**
+ * Borrowed and adapted from https://github.com/lonnieezell/Bonfire2/
+ */
+class ComponentRenderer
+{
+    protected ViewComponents $config;
+
+    /**
+     * File name of the view source
+     */
+    protected string $currentView;
+
+    public function __construct()
+    {
+        $this->config = config('ViewComponents');
+    }
+
+    public function setCurrentView(string $view): self
+    {
+        $this->currentView = $view;
+
+        return $this;
+    }
+
+    public function render(string $output): string
+    {
+        // Try to locate any custom tags, with PascalCase names like: Button, Label, etc.
+        service('timer')
+            ->start('self-closing');
+        $output = $this->renderSelfClosingTags($output);
+        service('timer')
+            ->stop('self-closing');
+
+        service('timer')
+            ->start('paired-tags');
+        $output = $this->renderPairedTags($output);
+        service('timer')
+            ->stop('paired-tags');
+
+        return $output;
+    }
+
+    /**
+     * Finds and renders self-closing tags, i.e. <Foo />
+     */
+    private function renderSelfClosingTags(string $output): string
+    {
+        // Pattern borrowed and adapted from Laravel's ComponentTagCompiler
+        // Should match any Component tags <Component />
+        $pattern = "/
+            <
+                \s*
+                (?<name>[A-Z][A-Za-z0-9\.]*?)
+                \s*
+                (?<attributes>
+                    (?:
+                        \s+
+                        (?:
+                            (?:
+                                \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\}
+                            )
+                            |
+                            (?:
+                                [\w\-:.@]+
+                                (
+                                    =
+                                    (?:
+                                        \\\"[^\\\"]*\\\"
+                                        |
+                                        \'[^\']*\'
+                                        |
+                                        [^\'\\\"=<>]+
+                                    )
+                                )?
+                            )
+                        )
+                    )*
+                    \s*
+                )
+            \/>
+        /x";
+
+        /*
+            $matches[0] = full tags matched
+            $matches[name] = tag name
+            $matches[attributes] = array of attribute string (class="foo")
+         */
+        return preg_replace_callback($pattern, function ($match): string {
+            $view = $this->locateView($match['name']);
+            $attributes = $this->parseAttributes($match['attributes']);
+
+            $component = $this->factory($match['name'], $view, $attributes);
+
+            return $component instanceof Component
+                ? $component->render()
+                : $this->renderView($view, $attributes);
+        }, $output) ?? '';
+    }
+
+    private function renderPairedTags(string $output): string
+    {
+        $pattern = '/<\s*(?<name>[A-Z][A-Za-z0-9\.]*?)(?<attributes>[\s\S\=\'\"]*)>(?<slot>.*)<\/\s*\1\s*>/uUsm';
+
+        /*
+            $matches[0] = full tags matched and all of its content
+            $matches[name] = pascal cased tag name
+            $matches[attributes] = string of tag attributes (class="foo")
+            $matches[slot] = the content inside the tags
+         */
+        return preg_replace_callback($pattern, function ($match): string {
+            $view = $this->locateView($match['name']);
+            $attributes = $this->parseAttributes($match['attributes']);
+            $attributes['slot'] = $match['slot'];
+
+            $component = $this->factory($match['name'], $view, $attributes);
+
+            return $component instanceof Component
+                ? $component->render()
+                : $this->renderView($view, $attributes);
+        }, $output) ?? (string) preg_last_error();
+    }
+
+    /**
+     * Locate the view file used to render the component. The file's name must match the name of the component.
+     *
+     * Looks for class and view file components in the current module before checking the default app module
+     */
+    private function locateView(string $name): string
+    {
+        // TODO: Is there a better way to locate components local to current module?
+        $modulesToDiscover = [APPPATH];
+        foreach (config('Autoload')->psr4 as $namespace => $path) {
+            if (str_starts_with($this->currentView, $namespace)) {
+                array_unshift($modulesToDiscover, $path);
+            }
+        }
+
+        $namePath = str_replace('.', '/', $name);
+
+        foreach ($modulesToDiscover as $basePath) {
+            // Look for a class component first
+            $filePath = $basePath . $this->config->classComponentsPath . '/' . $namePath . '.php';
+
+            if (is_file($filePath)) {
+                return $filePath;
+            }
+
+            $camelCaseName = strtolower(preg_replace('~(?<!^)(?<!\/)[A-Z]~', '_$0', $namePath) ?? '');
+            $filePath = $basePath . $this->config->viewFileComponentsPath . '/' . $camelCaseName . '.php';
+
+            if (is_file($filePath)) {
+                return $filePath;
+            }
+        }
+
+        throw new RuntimeException("View not found for component: {$name}");
+    }
+
+    /**
+     * Parses a string to grab any key/value pairs, HTML attributes.
+     *
+     * @return array<string, string>
+     */
+    private function parseAttributes(string $attributeString): array
+    {
+        // Pattern borrowed from Laravel's ComponentTagCompiler
+        $pattern = '/
+            (?<attribute>[\w\-:.@]+)
+            (
+                =
+                (?<value>
+                    (
+                        \"[^\"]+\"
+                        |
+                        \'[^\']+\'
+                        |
+                        \\\'[^\\\']+\\\'
+                        |
+                        [^\s>]+
+                    )
+                )
+            )?
+        /x';
+
+        if (! preg_match_all($pattern, $attributeString, $matches, PREG_SET_ORDER)) {
+            return [];
+        }
+
+        $attributes = [];
+        /**
+         * @var array<string, string> $match
+         */
+        foreach ($matches as $match) {
+            $attributes[$match['attribute']] = $this->stripQuotes($match['value']);
+        }
+
+        return $attributes;
+    }
+
+    /**
+     * Attempts to locate the view and/or class that will be used to render this component. By default, the only thing
+     * that is needed is a view, but a Component class can also be found if more power is needed.
+     *
+     * If a class is used, the name is expected to be <viewName>Component.php
+     *
+     * @param array<string, mixed> $attributes
+     */
+    private function factory(string $name, string $view, array $attributes): ?Component
+    {
+        // Locate the class in the same folder as the view
+        $class = $name . '.php';
+        $filePath = str_replace($name . '.php', $class, $view);
+
+        if ($filePath === '') {
+            return null;
+        }
+
+        if (! file_exists($filePath)) {
+            return null;
+        }
+        $className = service('locator')
+            ->getClassname($filePath);
+
+        /** @phpstan-ignore-next-line */
+        if (! class_exists($className)) {
+            return null;
+        }
+
+        return new $className($attributes);
+    }
+
+    /**
+     * Renders the view when no corresponding class has been found.
+     *
+     * @param array<string, string> $data
+     */
+    private function renderView(string $view, array $data): string
+    {
+        return (function (string $view, $data): string {
+            /** @phpstan-ignore-next-line */
+            extract($data);
+            ob_start();
+            eval('?>' . file_get_contents($view));
+            return ob_get_clean() ?: '';
+        })($view, $data);
+    }
+
+    /**
+     * Removes surrounding quotes from a string.
+     */
+    private function stripQuotes(string $string): string
+    {
+        return trim($string, "\'\"");
+    }
+}
diff --git a/app/Libraries/ViewComponents/Config/Services.php b/app/Libraries/ViewComponents/Config/Services.php
index 1a50373108..bb9c1d2191 100644
--- a/app/Libraries/ViewComponents/Config/Services.php
+++ b/app/Libraries/ViewComponents/Config/Services.php
@@ -5,7 +5,7 @@ declare(strict_types=1);
 namespace ViewComponents\Config;
 
 use CodeIgniter\Config\BaseService;
-use ViewComponents\ComponentLoader;
+use ViewComponents\ComponentRenderer;
 
 /**
  * Services Configuration file.
@@ -19,12 +19,12 @@ use ViewComponents\ComponentLoader;
  */
 class Services extends BaseService
 {
-    public static function viewcomponents(bool $getShared = true): ComponentLoader
+    public static function components(bool $getShared = true): ComponentRenderer
     {
         if ($getShared) {
-            return self::getSharedInstance('viewcomponents');
+            return self::getSharedInstance('components');
         }
 
-        return new ComponentLoader();
+        return new ComponentRenderer();
     }
 }
diff --git a/app/Libraries/ViewComponents/Config/ViewComponents.php b/app/Libraries/ViewComponents/Config/ViewComponents.php
index 2131991288..efd459958c 100644
--- a/app/Libraries/ViewComponents/Config/ViewComponents.php
+++ b/app/Libraries/ViewComponents/Config/ViewComponents.php
@@ -8,9 +8,7 @@ use CodeIgniter\Config\BaseConfig;
 
 class ViewComponents extends BaseConfig
 {
-    public string $classComponentsNamespace = APP_NAMESPACE . '\View\Components';
+    public string $classComponentsPath = 'View/Components';
 
-    public string $classComponentsPath = APPPATH . 'View/Components';
-
-    public string $componentsViewPath = APPPATH . 'Views/components';
+    public string $viewFileComponentsPath = 'Views/components';
 }
diff --git a/app/Libraries/ViewComponents/Helpers/view_components_helper.php b/app/Libraries/ViewComponents/Helpers/view_components_helper.php
deleted file mode 100644
index d6a9625d89..0000000000
--- a/app/Libraries/ViewComponents/Helpers/view_components_helper.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-if (! function_exists('component')) {
-    /**
-     * Loads the specified class or view file component in the parameters
-     *
-     * @param array<string, array<string, mixed>> $properties
-     * @param array<string, array<string, mixed>> $attributes
-     */
-    function component(string $name, array $properties = [], array $attributes = []): string
-    {
-        $componentLoader = service('viewcomponents');
-
-        $componentLoader->name = $name;
-        $componentLoader->properties = $properties;
-        $componentLoader->attributes = $attributes;
-
-        return $componentLoader->load();
-    }
-}
diff --git a/app/Models/ActorModel.php b/app/Models/ActorModel.php
index 333722df21..ae519f5cd9 100644
--- a/app/Models/ActorModel.php
+++ b/app/Models/ActorModel.php
@@ -11,9 +11,9 @@ declare(strict_types=1);
 namespace App\Models;
 
 use App\Entities\Actor;
-use Modules\Fediverse\Models\ActorModel as ActivityPubActorModel;
+use Modules\Fediverse\Models\ActorModel as FediverseActorModel;
 
-class ActorModel extends ActivityPubActorModel
+class ActorModel extends FediverseActorModel
 {
     /**
      * @var string
diff --git a/app/Models/EpisodeCommentModel.php b/app/Models/EpisodeCommentModel.php
index c1f60dace8..cd950438e7 100644
--- a/app/Models/EpisodeCommentModel.php
+++ b/app/Models/EpisodeCommentModel.php
@@ -141,13 +141,13 @@ class EpisodeCommentModel extends UuidModel
             ])
             ->getCompiledSelect();
 
-        $episodePostsReplies = $this->db->table('activitypub_posts')
+        $episodePostsReplies = $this->db->table(config('Fediverse')->tablesPrefix . 'posts')
             ->select(
                 'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, favourites_count as likes_count, replies_count, published_at as created_at, created_by, 1 as is_from_post'
             )
             ->whereIn('in_reply_to_id', function (BaseBuilder $builder) use (&$episodeId): BaseBuilder {
                 return $builder->select('id')
-                    ->from('activitypub_posts')
+                    ->from(config('Fediverse')->tablesPrefix . 'posts')
                     ->where('episode_id', $episodeId);
             })
             ->where('`created_at` <= NOW()', null, false)
diff --git a/app/Models/PostModel.php b/app/Models/PostModel.php
index 201ad32741..9d6cd911a1 100644
--- a/app/Models/PostModel.php
+++ b/app/Models/PostModel.php
@@ -11,9 +11,9 @@ declare(strict_types=1);
 namespace App\Models;
 
 use App\Entities\Post;
-use Modules\Fediverse\Models\PostModel as ActivityPubPostModel;
+use Modules\Fediverse\Models\PostModel as FediversePostModel;
 
-class PostModel extends ActivityPubPostModel
+class PostModel extends FediversePostModel
 {
     /**
      * @var string
diff --git a/app/View/Components/Button.php b/app/View/Components/Button.php
index ac4416b237..b122395f90 100644
--- a/app/View/Components/Button.php
+++ b/app/View/Components/Button.php
@@ -25,7 +25,7 @@ class Button extends Component
     public function render(): string
     {
         $baseClass =
-            'inline-flex items-center font-semibold shadow-xs rounded-full focus:outline-none focus:ring';
+            'inline-flex items-center justify-center font-semibold shadow-xs rounded-full focus:outline-none focus:ring';
 
         $variantClass = [
             'default' => 'text-black bg-gray-300 hover:bg-gray-400',
@@ -73,11 +73,11 @@ class Button extends Component
         }
 
         if ($this->iconLeft !== '') {
-            $this->label = icon($this->iconLeft, 'mr-2') . $this->label;
+            $this->slot = '<Icon glyph="' . $this->iconLeft . '" class="mr-2" />' . $this->slot;
         }
 
         if ($this->iconRight !== '') {
-            $this->label .= icon($this->iconRight, 'ml-2');
+            $this->slot .= '<Icon glyph="' . $this->iconRight . '" class="ml-2" />';
         }
 
         if ($this->uri !== '') {
@@ -91,8 +91,8 @@ class Button extends Component
         ];
         $attributes = stringify_attributes(array_merge($defaultButtonAttributes, $this->attributes));
 
-        return <<<CODE_SAMPLE
-            <button class="{$buttonClass}" {$attributes}>{$this->label}</button>
-        CODE_SAMPLE;
+        return <<<HTML
+            <button class="{$buttonClass}" {$attributes}>{$this->slot}</button>
+        HTML;
     }
 }
diff --git a/app/View/Components/Forms/Input.php b/app/View/Components/Forms/Input.php
deleted file mode 100644
index 3dda5d57bf..0000000000
--- a/app/View/Components/Forms/Input.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\View\Components\Forms;
-
-use ViewComponents\Component;
-
-class Input extends Component
-{
-    public function render(): string
-    {
-        return '';
-    }
-}
diff --git a/app/View/Components/Forms/Label.php b/app/View/Components/Forms/Label.php
index ea43a51303..b2dfd00167 100644
--- a/app/View/Components/Forms/Label.php
+++ b/app/View/Components/Forms/Label.php
@@ -14,16 +14,18 @@ class Label extends Component
     protected array $attributes = [
         'for' => '',
         'name' => '',
-        'value' => '',
         'class' => '',
     ];
 
-    protected string $text = '';
-
     protected string $hint = '';
 
     protected bool $isOptional = false;
 
+    public function setIsOptional(string $value): void
+    {
+        $this->isOptional = $value === 'true';
+    }
+
     public function render(): string
     {
         $labelClass = $this->attributes['class'];
@@ -35,8 +37,8 @@ class Label extends Component
         ')</small>' : '';
         $hint = $this->hint !== '' ? hint_tooltip($this->hint, 'ml-1') : '';
 
-        return <<<CODE_SAMPLE
-            <label class="{$labelClass}" {$attributes}>{$this->text}{$optionalText}{$hint}</label>
-        CODE_SAMPLE;
+        return <<<HTML
+            <label class="{$labelClass}" {$attributes}>{$this->slot}{$optionalText}{$hint}</label>
+        HTML;
     }
 }
diff --git a/app/View/Components/Forms/MarkdownEditor.php b/app/View/Components/Forms/MarkdownEditor.php
index 48bb716540..6540e282ac 100644
--- a/app/View/Components/Forms/MarkdownEditor.php
+++ b/app/View/Components/Forms/MarkdownEditor.php
@@ -8,8 +8,6 @@ use ViewComponents\Component;
 
 class MarkdownEditor extends Component
 {
-    protected string $content = '';
-
     public function render(): string
     {
         $editorClass = 'w-full flex flex-col bg-white border border-gray-500 focus-within:ring-1 focus-within:ring-blue-600';
@@ -64,7 +62,7 @@ class MarkdownEditor extends Component
                 '</markdown-toolbar>' .
             '</header>' .
             '<div class="relative">' .
-                form_textarea($this->attributes, $this->content) .
+                form_textarea($this->attributes, $this->slot) .
                 '<markdown-preview for="' . $this->attributes['id'] . '" class="absolute top-0 left-0 hidden w-full h-full p-2 overflow-y-auto prose bg-gray-50" showClass="bg-white"></markdown-preview>' .
             '</div>' .
             '<footer class="flex px-2 py-1 bg-gray-100 border-t">' .
diff --git a/app/View/Components/Forms/MultiSelect.php b/app/View/Components/Forms/MultiSelect.php
index ea9374b63a..af7a24c3ce 100644
--- a/app/View/Components/Forms/MultiSelect.php
+++ b/app/View/Components/Forms/MultiSelect.php
@@ -18,6 +18,16 @@ class MultiSelect extends Component
      */
     protected array $selected = [];
 
+    public function setOptions(string $value): void
+    {
+        $this->options = json_decode(html_entity_decode($value), true);
+    }
+
+    public function setSelected(string $selected): void
+    {
+        $this->selected = json_decode($selected);
+    }
+
     public function render(): string
     {
         $defaultAttributes = [
diff --git a/app/View/Components/Forms/Toggler.php b/app/View/Components/Forms/Toggler.php
index f3421bfc17..eab1268a4e 100644
--- a/app/View/Components/Forms/Toggler.php
+++ b/app/View/Components/Forms/Toggler.php
@@ -29,21 +29,30 @@ class Toggler extends Component
 
     protected bool $checked = false;
 
+    public function setChecked(string $value): void
+    {
+        $this->checked = $value !== '';
+    }
+
     public function render(): string
     {
+        unset($this->attributes['checked']);
+
         $wrapperClass = $this->attributes['class'];
         unset($this->attributes['class']);
 
         $this->attributes['class'] = 'form-switch';
 
+        helper('form');
+
         $checkbox = form_checkbox($this->attributes, $this->attributes['value'], $this->checked);
-        $hint = $this->hint !== '' ? hint_tooltip(lang('Podcast.form.lock_hint'), 'ml-1') : '';
-        return <<<CODE_SAMPLE
+        $hint = $this->hint === '' ? '' : hint_tooltip($this->hint, 'ml-1');
+        return <<<HTML
             <label class="relative inline-flex items-center {$wrapperClass}">
                 {$checkbox}
                 <span class="form-switch-slider"></span>
-                <span class="ml-2">{$this->label}{$hint}</span>
+                <span class="ml-2">{$this->slot}{$hint}</span>
             </label>
-        CODE_SAMPLE;
+        HTML;
     }
 }
diff --git a/app/View/Components/Forms/XMLEditor.php b/app/View/Components/Forms/XMLEditor.php
index ef3406e47e..ac03f3d0b6 100644
--- a/app/View/Components/Forms/XMLEditor.php
+++ b/app/View/Components/Forms/XMLEditor.php
@@ -8,23 +8,22 @@ use ViewComponents\Component;
 
 class XMLEditor extends Component
 {
-    protected string $content = '';
-
     /**
      * @var array<string, string>
      */
     protected array $attributes = [
-        'slot' => 'textarea',
         'rows' => '5',
         'class' => 'textarea',
     ];
 
     public function render(): string
     {
-        $textarea = form_textarea($this->attributes, $this->content);
+        $content = $this->slot;
+        $this->attributes['slot'] = 'textarea';
+        $textarea = form_textarea($this->attributes, $content);
 
-        return <<<CODE_SAMPLE
+        return <<<HTML
             <xml-editor>{$textarea}</time-ago>
-        CODE_SAMPLE;
+        HTML;
     }
 }
diff --git a/app/View/Components/Icon.php b/app/View/Components/Icon.php
index b60051af44..7cd44991dc 100644
--- a/app/View/Components/Icon.php
+++ b/app/View/Components/Icon.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace App\View\Components;
 
+use Exception;
 use ViewComponents\Component;
 
 class Icon extends Component
@@ -12,16 +13,16 @@ class Icon extends Component
 
     public function render(): string
     {
-        $svgContents = file_get_contents('assets/icons/' . $this->glyph . '.svg');
-
-        if ($svgContents) {
-            if ($this->attributes['class'] !== '') {
-                $svgContents = str_replace('<svg', '<svg class="' . $this->attributes['class'] . '"', $svgContents);
-            }
+        try {
+            $svgContents = file_get_contents('assets/icons/' . $this->glyph . '.svg');
+        } catch (Exception) {
+            return 'â–¡';
+        }
 
-            return $svgContents;
+        if ($this->attributes['class'] !== '') {
+            $svgContents = str_replace('<svg', '<svg class="' . $this->attributes['class'] . '"', $svgContents);
         }
 
-        return 'â–¡';
+        return $svgContents;
     }
 }
diff --git a/app/Views/errors/html/error_404.php b/app/Views/errors/html/error_404.php
index fd5a841112..e26342668e 100644
--- a/app/Views/errors/html/error_404.php
+++ b/app/Views/errors/html/error_404.php
@@ -19,11 +19,7 @@
             Sorry! Cannot seem to find the page you were looking for.
         <?php endif; ?>
     </p>
-
-    <?= button(lang('Common.go_back'), previous_url(), [
-        'variant' => 'primary',
-        'iconLeft' => 'arrow-left',
-    ]) ?>
+    <button class="inline-flex items-center justify-center px-3 py-1 text-sm font-semibold text-white rounded-full shadow-xs focus:outline-none focus:ring md:px-4 md:py-2 md:text-base bg-pine-700 hover:bg-pine-800"><?= lang('Common.go_back') ?></button>
 </body>
 
 </html>
diff --git a/app/Views/podcast/_partials/comment_actions.php b/app/Views/podcast/_partials/comment_actions.php
index 3be7662517..f8c8048629 100644
--- a/app/Views/podcast/_partials/comment_actions.php
+++ b/app/Views/podcast/_partials/comment_actions.php
@@ -12,4 +12,4 @@
             ['class' => 'inline-flex items-center text-xs hover:underline']
         ) ?>
     <?php endif; ?>
-</footer>
\ No newline at end of file
+</footer>
diff --git a/app/Views/podcast/_partials/comment_actions_authenticated.php b/app/Views/podcast/_partials/comment_actions_authenticated.php
index ad55f02327..2f22f08951 100644
--- a/app/Views/podcast/_partials/comment_actions_authenticated.php
+++ b/app/Views/podcast/_partials/comment_actions_authenticated.php
@@ -21,4 +21,4 @@
             ['class' => 'inline-flex items-center text-xs hover:underline']
         ) ?>
     <?php endif; ?>
-</footer>
\ No newline at end of file
+</footer>
diff --git a/app/Views/podcast/_partials/comment_actions_from_post.php b/app/Views/podcast/_partials/comment_actions_from_post.php
index c7a23b0d2d..f483f8efa3 100644
--- a/app/Views/podcast/_partials/comment_actions_from_post.php
+++ b/app/Views/podcast/_partials/comment_actions_from_post.php
@@ -12,4 +12,4 @@
             ['class' => 'inline-flex items-center text-xs hover:underline']
         ) ?>
     <?php endif; ?>
-</footer>
\ No newline at end of file
+</footer>
diff --git a/app/Views/podcast/_partials/comment_actions_from_post_authenticated.php b/app/Views/podcast/_partials/comment_actions_from_post_authenticated.php
index 5d06650c38..e01936b6a7 100644
--- a/app/Views/podcast/_partials/comment_actions_from_post_authenticated.php
+++ b/app/Views/podcast/_partials/comment_actions_from_post_authenticated.php
@@ -21,4 +21,4 @@
             ['class' => 'inline-flex items-center text-xs hover:underline']
         ) ?>
     <?php endif; ?>
-</footer>
\ No newline at end of file
+</footer>
diff --git a/app/Views/podcast/_partials/comment_reply_actions.php b/app/Views/podcast/_partials/comment_reply_actions.php
index aa8a37b3ff..33d0d19e1c 100644
--- a/app/Views/podcast/_partials/comment_reply_actions.php
+++ b/app/Views/podcast/_partials/comment_reply_actions.php
@@ -17,4 +17,4 @@
         ],
     ) ?>
     <?php endif; ?>
-</footer>
\ No newline at end of file
+</footer>
diff --git a/app/Views/podcast/_partials/comment_reply_actions_authenticated.php b/app/Views/podcast/_partials/comment_reply_actions_authenticated.php
index a007c2b763..8ca81ce152 100644
--- a/app/Views/podcast/_partials/comment_reply_actions_authenticated.php
+++ b/app/Views/podcast/_partials/comment_reply_actions_authenticated.php
@@ -14,4 +14,4 @@
             ],
         ) ?>
     </form>
-</footer>
\ No newline at end of file
+</footer>
diff --git a/app/Views/podcast/_partials/episode_card.php b/app/Views/podcast/_partials/episode_card.php
index 01b5f412d4..9e40951cfb 100644
--- a/app/Views/podcast/_partials/episode_card.php
+++ b/app/Views/podcast/_partials/episode_card.php
@@ -40,4 +40,4 @@
             </div>
         </div>
     </div>
-</article>
\ No newline at end of file
+</article>
diff --git a/app/Views/podcast/follow.php b/app/Views/podcast/follow.php
index aef1249ad4..68de706e9a 100644
--- a/app/Views/podcast/follow.php
+++ b/app/Views/podcast/follow.php
@@ -30,7 +30,7 @@
 <body class="flex flex-col min-h-screen bg-pine-50">
     <header class="flex flex-col items-center mb-8">
         <h1 class="w-full pt-8 pb-32 text-center text-white bg-pine-900"><?= lang(
-            'ActivityPub.follow.subtitle',
+            'Fediverse.follow.subtitle',
         ) ?></h1>
         <div class="flex flex-col w-full max-w-xs -mt-24 overflow-hidden bg-white shadow rounded-xl">
             <img src="<?= $actor->cover_image_url ?>" alt="" class="object-cover w-full h-32 bg-pine-800" />
@@ -54,10 +54,10 @@
         <?= view('_message_block') ?>
 
         <?= form_label(
-            lang('ActivityPub.your_handle'),
+            lang('Fediverse.your_handle'),
             'handle',
             [],
-            lang('ActivityPub.your_handle_hint'),
+            lang('Fediverse.your_handle_hint'),
         ) ?>
         <?= form_input([
             'id' => 'handle',
@@ -68,7 +68,7 @@
         ]) ?>
 
         <?= button(
-            lang('ActivityPub.follow.submit'),
+            lang('Fediverse.follow.submit'),
             '',
             ['variant' => 'primary'],
             ['type' => 'submit', 'class' => 'self-end'],
diff --git a/app/Views/podcast/post_remote_action.php b/app/Views/podcast/post_remote_action.php
index 04a99bcc8b..8feeb6c31e 100644
--- a/app/Views/podcast/post_remote_action.php
+++ b/app/Views/podcast/post_remote_action.php
@@ -6,12 +6,12 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
     <link rel="shortcut icon" type="image/png" href="/favicon.ico" />
 
-    <title><?= lang('ActivityPub.' . $action . '.title', [
+    <title><?= lang('Fediverse.' . $action . '.title', [
         'actorDisplayName' => $post->actor->display_name,
     ]) ?></title>
     <meta name="description" content="<?= $post->message ?>"/>
     <meta property="og:title" content="<?= lang(
-        'ActivityPub.' . $action . '.title',
+        'Fediverse.' . $action . '.title',
         [
             'actorDisplayName' => $post->actor->display_name,
         ],
@@ -31,7 +31,7 @@
 <body class="min-h-screen mx-auto bg-pine-50">
     <header class="pt-8 pb-32 bg-pine-900">
         <h1 class="text-lg font-semibold text-center text-white"><?= lang(
-            'ActivityPub.' . $action . '.subtitle',
+            'Fediverse.' . $action . '.subtitle',
         ) ?></h1>
     </header>
     <main class="flex-1 max-w-xl px-4 pb-8 mx-auto -mt-24">
@@ -45,10 +45,10 @@
         <?= view('_message_block') ?>
 
         <?= form_label(
-            lang('ActivityPub.your_handle'),
+            lang('Fediverse.your_handle'),
             'handle',
             [],
-            lang('ActivityPub.your_handle_hint'),
+            lang('Fediverse.your_handle_hint'),
         ) ?>
         <?= form_input([
             'id' => 'handle',
@@ -59,7 +59,7 @@
         ]) ?>
 
         <?= button(
-            lang('ActivityPub.' . $action . '.submit'),
+            lang('Fediverse.' . $action . '.submit'),
             '',
             ['variant' => 'primary'],
             ['type' => 'submit', 'class' => 'self-end'],
diff --git a/composer.json b/composer.json
index 64ab014f1d..3ca24a4fc5 100644
--- a/composer.json
+++ b/composer.json
@@ -23,16 +23,16 @@
     "essence/essence": "^3.5.4"
   },
   "require-dev": {
-    "mikey179/vfsstream": "^1.6.9",
-    "phpunit/phpunit": "^9.5.8",
-    "rector/rector": "^0.11.46",
-    "captainhook/captainhook": "^5.10.1",
-    "phpstan/phpstan": "^0.12.94",
+    "mikey179/vfsstream": "^v1.6.8",
+    "phpunit/phpunit": "^9.5.4",
+    "rector/rector": "^0.11.5",
+    "captainhook/captainhook": "^5.10.0",
+    "phpstan/phpstan": "^0.12.85",
     "phpstan/extension-installer": "^1.1.0",
-    "symplify/phpstan-extensions": "^9.4.27",
-    "symplify/easy-coding-standard": "^9.4.27",
-    "symplify/coding-standard": "^9.4.27",
-    "rector/phpstan-rules": "^0.3.4"
+    "rector/rector-phpstan-rules": "^0.2.9",
+    "symplify/phpstan-extensions": "^v9.3.12",
+    "symplify/easy-coding-standard": "^v9.3.12",
+    "symplify/coding-standard": "^v9.3.12"
   },
   "autoload": {
     "psr-4": {
@@ -59,8 +59,8 @@
       "@php vendor/opawg/user-agents-php/src/UserAgentsGenerate.php >  vendor/opawg/user-agents-php/src/UserAgents.php",
       "@php vendor/opawg/user-agents-php/src/UserAgentsRSSGenerate.php >  vendor/opawg/user-agents-php/src/UserAgentsRSS.php",
       "@php vendor/podlibre/ipcat/IpDbGenerate.php >  vendor/podlibre/ipcat/IpDb.php",
-      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json >  app/Language/en/PersonsTaxonomy.php",
-      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json >  app/Language/fr/PersonsTaxonomy.php",
+      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json >  modules/Admin/Language/en/PersonsTaxonomy.php",
+      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json >  modules/Admin/Language/fr/PersonsTaxonomy.php",
       "@php vendor/podlibre/podcast-namespace/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json >  vendor/podlibre/podcast-namespace/src/ReversedTaxonomy.php"
     ],
     "post-update-cmd": [
@@ -68,8 +68,8 @@
       "@php vendor/opawg/user-agents-php/src/UserAgentsGenerate.php >  vendor/opawg/user-agents-php/src/UserAgents.php",
       "@php vendor/opawg/user-agents-php/src/UserAgentsRSSGenerate.php >  vendor/opawg/user-agents-php/src/UserAgentsRSS.php",
       "@php vendor/podlibre/ipcat/IpDbGenerate.php >  vendor/podlibre/ipcat/IpDb.php",
-      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json >  app/Language/en/PersonsTaxonomy.php",
-      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json >  app/Language/fr/PersonsTaxonomy.php",
+      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json >  modules/Admin/Language/en/PersonsTaxonomy.php",
+      "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json >  modules/Admin/Language/fr/PersonsTaxonomy.php",
       "@php vendor/podlibre/podcast-namespace/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json >  vendor/podlibre/podcast-namespace/src/ReversedTaxonomy.php"
     ]
   },
diff --git a/composer.lock b/composer.lock
index 7aeb745369..03baaec32b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -66,12 +66,12 @@
       "source": {
         "type": "git",
         "url": "https://github.com/codeigniter4/CodeIgniter4.git",
-        "reference": "5f09c247320c966f12a889a0821684daeb82f9bb"
+        "reference": "995c51f383844bc44a607026ea6ab85b06c7e87e"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/5f09c247320c966f12a889a0821684daeb82f9bb",
-        "reference": "5f09c247320c966f12a889a0821684daeb82f9bb",
+        "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/995c51f383844bc44a607026ea6ab85b06c7e87e",
+        "reference": "995c51f383844bc44a607026ea6ab85b06c7e87e",
         "shasum": ""
       },
       "require": {
@@ -80,7 +80,7 @@
         "ext-json": "*",
         "ext-mbstring": "*",
         "kint-php/kint": "^3.3",
-        "laminas/laminas-escaper": "^2.8",
+        "laminas/laminas-escaper": "^2.6",
         "php": "^7.3 || ^8.0",
         "psr/log": "^1.1"
       },
@@ -90,10 +90,10 @@
         "mikey179/vfsstream": "^1.6",
         "nexusphp/cs-config": "^3.1",
         "nexusphp/tachycardia": "^1.0",
-        "phpstan/phpstan": "^0.12.91",
+        "phpstan/phpstan": "0.12.88",
         "phpunit/phpunit": "^9.1",
         "predis/predis": "^1.1",
-        "rector/rector": "0.11.46",
+        "rector/rector": "0.11.16",
         "symplify/package-builder": "^9.3"
       },
       "suggest": {
@@ -135,7 +135,7 @@
         "slack": "https://codeigniterchat.slack.com",
         "issues": "https://github.com/codeigniter4/CodeIgniter4/issues"
       },
-      "time": "2021-08-09T17:55:41+00:00"
+      "time": "2021-06-10T06:40:05+00:00"
     },
     {
       "name": "composer/ca-bundle",
@@ -634,16 +634,16 @@
     },
     {
       "name": "laminas/laminas-escaper",
-      "version": "2.8.0",
+      "version": "2.7.0",
       "source": {
         "type": "git",
         "url": "https://github.com/laminas/laminas-escaper.git",
-        "reference": "2d6dce99668b413610e9544183fa10392437f542"
+        "reference": "5e04bc5ae5990b17159d79d331055e2c645e5cc5"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/2d6dce99668b413610e9544183fa10392437f542",
-        "reference": "2d6dce99668b413610e9544183fa10392437f542",
+        "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/5e04bc5ae5990b17159d79d331055e2c645e5cc5",
+        "reference": "5e04bc5ae5990b17159d79d331055e2c645e5cc5",
         "shasum": ""
       },
       "require": {
@@ -654,7 +654,7 @@
         "zendframework/zend-escaper": "^2.6.1"
       },
       "require-dev": {
-        "laminas/laminas-coding-standard": "~2.3.0",
+        "laminas/laminas-coding-standard": "~1.0.0",
         "phpunit/phpunit": "^9.3",
         "psalm/plugin-phpunit": "^0.12.2",
         "vimeo/psalm": "^3.16"
@@ -688,20 +688,20 @@
           "type": "community_bridge"
         }
       ],
-      "time": "2021-06-26T14:26:08+00:00"
+      "time": "2020-11-17T21:26:43+00:00"
     },
     {
       "name": "laminas/laminas-zendframework-bridge",
-      "version": "1.3.0",
+      "version": "1.2.0",
       "source": {
         "type": "git",
         "url": "https://github.com/laminas/laminas-zendframework-bridge.git",
-        "reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e"
+        "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/13af2502d9bb6f7d33be2de4b51fb68c6cdb476e",
-        "reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e",
+        "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6cccbddfcfc742eb02158d6137ca5687d92cee32",
+        "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32",
         "shasum": ""
       },
       "require": {
@@ -741,20 +741,20 @@
           "type": "community_bridge"
         }
       ],
-      "time": "2021-06-24T12:49:22+00:00"
+      "time": "2021-02-25T21:54:58+00:00"
     },
     {
       "name": "league/commonmark",
-      "version": "1.6.6",
+      "version": "1.6.2",
       "source": {
         "type": "git",
         "url": "https://github.com/thephpleague/commonmark.git",
-        "reference": "c4228d11e30d7493c6836d20872f9582d8ba6dcf"
+        "reference": "7d70d2f19c84bcc16275ea47edabee24747352eb"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c4228d11e30d7493c6836d20872f9582d8ba6dcf",
-        "reference": "c4228d11e30d7493c6836d20872f9582d8ba6dcf",
+        "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/7d70d2f19c84bcc16275ea47edabee24747352eb",
+        "reference": "7d70d2f19c84bcc16275ea47edabee24747352eb",
         "shasum": ""
       },
       "require": {
@@ -772,7 +772,7 @@
         "github/gfm": "0.29.0",
         "michelf/php-markdown": "~1.4",
         "mikehaertl/php-shellcommand": "^1.4",
-        "phpstan/phpstan": "^0.12.90",
+        "phpstan/phpstan": "^0.12",
         "phpunit/phpunit": "^7.5 || ^8.5 || ^9.2",
         "scrutinizer/ocular": "^1.5",
         "symfony/finder": "^4.2"
@@ -838,40 +838,37 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-17T17:13:23+00:00"
+      "time": "2021-05-12T11:39:41+00:00"
     },
     {
       "name": "league/html-to-markdown",
-      "version": "5.0.0",
+      "version": "4.10.0",
       "source": {
         "type": "git",
         "url": "https://github.com/thephpleague/html-to-markdown.git",
-        "reference": "c4dbebbebe0fe454b6b38e6c683a977615bd7dc2"
+        "reference": "0868ae7a552e809e5cd8f93ba022071640408e88"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/c4dbebbebe0fe454b6b38e6c683a977615bd7dc2",
-        "reference": "c4dbebbebe0fe454b6b38e6c683a977615bd7dc2",
+        "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/0868ae7a552e809e5cd8f93ba022071640408e88",
+        "reference": "0868ae7a552e809e5cd8f93ba022071640408e88",
         "shasum": ""
       },
       "require": {
         "ext-dom": "*",
         "ext-xml": "*",
-        "php": "^7.2.5 || ^8.0"
+        "php": ">=5.3.3"
       },
       "require-dev": {
-        "mikehaertl/php-shellcommand": "^1.1.0",
-        "phpstan/phpstan": "^0.12.82",
-        "phpunit/phpunit": "^8.5 || ^9.2",
-        "scrutinizer/ocular": "^1.6",
-        "unleashedtech/php-coding-standard": "^2.7",
-        "vimeo/psalm": "^4.6"
+        "mikehaertl/php-shellcommand": "~1.1.0",
+        "phpunit/phpunit": "^4.8|^5.7",
+        "scrutinizer/ocular": "~1.1"
       },
       "bin": ["bin/html-to-markdown"],
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-master": "5.1-dev"
+          "dev-master": "4.10-dev"
         }
       },
       "autoload": {
@@ -900,7 +897,7 @@
       "keywords": ["html", "markdown"],
       "support": {
         "issues": "https://github.com/thephpleague/html-to-markdown/issues",
-        "source": "https://github.com/thephpleague/html-to-markdown/tree/5.0.0"
+        "source": "https://github.com/thephpleague/html-to-markdown/tree/4.10.0"
       },
       "funding": [
         {
@@ -920,7 +917,7 @@
           "type": "patreon"
         }
       ],
-      "time": "2021-03-29T01:29:08+00:00"
+      "time": "2020-07-01T00:34:03+00:00"
     },
     {
       "name": "maxmind-db/reader",
@@ -1080,12 +1077,12 @@
       "source": {
         "type": "git",
         "url": "https://github.com/lonnieezell/myth-auth.git",
-        "reference": "89b013a3d04680e1975bc301c3aac31137e31bc2"
+        "reference": "9bba52bd710a0c35a0b2d8cef64a70706224648a"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/lonnieezell/myth-auth/zipball/89b013a3d04680e1975bc301c3aac31137e31bc2",
-        "reference": "89b013a3d04680e1975bc301c3aac31137e31bc2",
+        "url": "https://api.github.com/repos/lonnieezell/myth-auth/zipball/9bba52bd710a0c35a0b2d8cef64a70706224648a",
+        "reference": "9bba52bd710a0c35a0b2d8cef64a70706224648a",
         "shasum": ""
       },
       "require": {
@@ -1098,13 +1095,10 @@
         "codeigniter4/codeigniter4": "dev-develop",
         "codeigniter4/codeigniter4-standard": "^1.0",
         "fakerphp/faker": "^1.9",
-        "friendsofphp/php-cs-fixer": "^3.0",
         "mockery/mockery": "^1.0",
-        "nexusphp/cs-config": "^3.1",
-        "nexusphp/tachycardia": "^1.0",
-        "php-coveralls/php-coveralls": "^2.4",
         "phpstan/phpstan": "^0.12",
-        "phpunit/phpunit": "^9.2"
+        "phpunit/phpunit": "^9.2",
+        "squizlabs/php_codesniffer": "^3.5"
       },
       "default-branch": true,
       "type": "library",
@@ -1129,23 +1123,19 @@
       "keywords": ["Authentication", "authorization", "codeigniter"],
       "support": {
         "issues": "https://github.com/lonnieezell/myth-auth/issues",
-        "source": "https://github.com/lonnieezell/myth-auth/tree/develop"
+        "source": "https://github.com/lonnieezell/myth-auth/tree/v1.0"
       },
       "funding": [
         {
           "url": "https://github.com/lonnieezell",
           "type": "github"
         },
-        {
-          "url": "https://github.com/mgatner",
-          "type": "github"
-        },
         {
           "url": "https://www.patreon.com/lonnieezell",
           "type": "patreon"
         }
       ],
-      "time": "2021-08-06T11:33:46+00:00"
+      "time": "2021-06-10T04:25:01+00:00"
     },
     {
       "name": "opawg/user-agents-php",
@@ -1247,16 +1237,16 @@
     },
     {
       "name": "phpseclib/phpseclib",
-      "version": "2.0.32",
+      "version": "2.0.31",
       "source": {
         "type": "git",
         "url": "https://github.com/phpseclib/phpseclib.git",
-        "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd"
+        "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f5c4c19880d45d0be3e7d24ae8ac434844a898cd",
-        "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd",
+        "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/233a920cb38636a43b18d428f9a8db1f0a1a08f4",
+        "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4",
         "shasum": ""
       },
       "require": {
@@ -1332,7 +1322,7 @@
       ],
       "support": {
         "issues": "https://github.com/phpseclib/phpseclib/issues",
-        "source": "https://github.com/phpseclib/phpseclib/tree/2.0.32"
+        "source": "https://github.com/phpseclib/phpseclib/tree/2.0.31"
       },
       "funding": [
         {
@@ -1348,7 +1338,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-06-12T12:12:59+00:00"
+      "time": "2021-04-06T13:56:45+00:00"
     },
     {
       "name": "podlibre/ipcat",
@@ -1502,21 +1492,20 @@
     },
     {
       "name": "ramsey/collection",
-      "version": "1.2.1",
+      "version": "1.1.3",
       "source": {
         "type": "git",
         "url": "https://github.com/ramsey/collection.git",
-        "reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa"
+        "reference": "28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/ramsey/collection/zipball/eaca1dc1054ddd10cbd83c1461907bee6fb528fa",
-        "reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa",
+        "url": "https://api.github.com/repos/ramsey/collection/zipball/28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1",
+        "reference": "28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1",
         "shasum": ""
       },
       "require": {
-        "php": "^7.3 || ^8",
-        "symfony/polyfill-php81": "^1.23"
+        "php": "^7.2 || ^8"
       },
       "require-dev": {
         "captainhook/captainhook": "^5.3",
@@ -1526,7 +1515,6 @@
         "hamcrest/hamcrest-php": "^2",
         "jangregor/phpstan-prophecy": "^0.8",
         "mockery/mockery": "^1.3",
-        "phpspec/prophecy-phpunit": "^2.0",
         "phpstan/extension-installer": "^1",
         "phpstan/phpstan": "^0.12.32",
         "phpstan/phpstan-mockery": "^0.12.5",
@@ -1552,11 +1540,11 @@
           "homepage": "https://benramsey.com"
         }
       ],
-      "description": "A PHP library for representing and manipulating collections.",
+      "description": "A PHP 7.2+ library for representing and manipulating collections.",
       "keywords": ["array", "collection", "hash", "map", "queue", "set"],
       "support": {
         "issues": "https://github.com/ramsey/collection/issues",
-        "source": "https://github.com/ramsey/collection/tree/1.2.1"
+        "source": "https://github.com/ramsey/collection/tree/1.1.3"
       },
       "funding": [
         {
@@ -1568,20 +1556,20 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-08-06T03:41:06+00:00"
+      "time": "2021-01-21T17:40:04+00:00"
     },
     {
       "name": "ramsey/uuid",
-      "version": "4.2.1",
+      "version": "4.1.1",
       "source": {
         "type": "git",
         "url": "https://github.com/ramsey/uuid.git",
-        "reference": "fe665a03df4f056aa65af552a96e1976df8c8dae"
+        "reference": "cd4032040a750077205918c86049aa0f43d22947"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/ramsey/uuid/zipball/fe665a03df4f056aa65af552a96e1976df8c8dae",
-        "reference": "fe665a03df4f056aa65af552a96e1976df8c8dae",
+        "url": "https://api.github.com/repos/ramsey/uuid/zipball/cd4032040a750077205918c86049aa0f43d22947",
+        "reference": "cd4032040a750077205918c86049aa0f43d22947",
         "shasum": ""
       },
       "require": {
@@ -1595,26 +1583,26 @@
         "rhumsaa/uuid": "self.version"
       },
       "require-dev": {
-        "captainhook/captainhook": "^5.10",
-        "captainhook/plugin-composer": "^5.3",
-        "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+        "codeception/aspect-mock": "^3",
+        "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0",
         "doctrine/annotations": "^1.8",
-        "ergebnis/composer-normalize": "^2.15",
+        "goaop/framework": "^2",
         "mockery/mockery": "^1.3",
         "moontoast/math": "^1.1",
         "paragonie/random-lib": "^2",
-        "php-mock/php-mock": "^2.2",
         "php-mock/php-mock-mockery": "^1.3",
+        "php-mock/php-mock-phpunit": "^2.5",
         "php-parallel-lint/php-parallel-lint": "^1.1",
-        "phpbench/phpbench": "^1.0",
+        "phpbench/phpbench": "^0.17.1",
         "phpstan/extension-installer": "^1.0",
         "phpstan/phpstan": "^0.12",
         "phpstan/phpstan-mockery": "^0.12",
         "phpstan/phpstan-phpunit": "^0.12",
-        "phpunit/phpunit": "^8.5 || ^9",
-        "slevomat/coding-standard": "^7.0",
+        "phpunit/phpunit": "^8.5",
+        "psy/psysh": "^0.10.0",
+        "slevomat/coding-standard": "^6.0",
         "squizlabs/php_codesniffer": "^3.5",
-        "vimeo/psalm": "^4.9"
+        "vimeo/psalm": "3.9.4"
       },
       "suggest": {
         "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
@@ -1627,10 +1615,7 @@
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "4.x-dev"
-        },
-        "captainhook": {
-          "force-install": true
+          "dev-master": "4.x-dev"
         }
       },
       "autoload": {
@@ -1642,22 +1627,20 @@
       "notification-url": "https://packagist.org/downloads/",
       "license": ["MIT"],
       "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+      "homepage": "https://github.com/ramsey/uuid",
       "keywords": ["guid", "identifier", "uuid"],
       "support": {
         "issues": "https://github.com/ramsey/uuid/issues",
-        "source": "https://github.com/ramsey/uuid/tree/4.2.1"
+        "rss": "https://github.com/ramsey/uuid/releases.atom",
+        "source": "https://github.com/ramsey/uuid"
       },
       "funding": [
         {
           "url": "https://github.com/ramsey",
           "type": "github"
-        },
-        {
-          "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
-          "type": "tidelift"
         }
       ],
-      "time": "2021-08-11T01:06:55+00:00"
+      "time": "2020-08-18T17:17:46+00:00"
     },
     {
       "name": "symfony/polyfill-ctype",
@@ -1731,16 +1714,16 @@
     },
     {
       "name": "symfony/polyfill-mbstring",
-      "version": "v1.23.1",
+      "version": "v1.23.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/polyfill-mbstring.git",
-        "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
+        "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
-        "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
+        "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
+        "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
         "shasum": ""
       },
       "require": {
@@ -1781,7 +1764,7 @@
       "homepage": "https://symfony.com",
       "keywords": ["compatibility", "mbstring", "polyfill", "portable", "shim"],
       "support": {
-        "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
+        "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
       },
       "funding": [
         {
@@ -1797,20 +1780,20 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-05-27T12:26:48+00:00"
+      "time": "2021-05-27T09:27:20+00:00"
     },
     {
       "name": "symfony/polyfill-php80",
-      "version": "v1.23.1",
+      "version": "v1.23.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/polyfill-php80.git",
-        "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
+        "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
-        "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
+        "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
+        "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
         "shasum": ""
       },
       "require": {
@@ -1853,7 +1836,7 @@
       "homepage": "https://symfony.com",
       "keywords": ["compatibility", "polyfill", "portable", "shim"],
       "support": {
-        "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
+        "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
       },
       "funding": [
         {
@@ -1869,75 +1852,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-28T13:41:28+00:00"
-    },
-    {
-      "name": "symfony/polyfill-php81",
-      "version": "v1.23.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/symfony/polyfill-php81.git",
-        "reference": "e66119f3de95efc359483f810c4c3e6436279436"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436",
-        "reference": "e66119f3de95efc359483f810c4c3e6436279436",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=7.1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-main": "1.23-dev"
-        },
-        "thanks": {
-          "name": "symfony/polyfill",
-          "url": "https://github.com/symfony/polyfill"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Symfony\\Polyfill\\Php81\\": ""
-        },
-        "files": ["bootstrap.php"],
-        "classmap": ["Resources/stubs"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Nicolas Grekas",
-          "email": "p@tchwork.com"
-        },
-        {
-          "name": "Symfony Community",
-          "homepage": "https://symfony.com/contributors"
-        }
-      ],
-      "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
-      "homepage": "https://symfony.com",
-      "keywords": ["compatibility", "polyfill", "portable", "shim"],
-      "support": {
-        "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0"
-      },
-      "funding": [
-        {
-          "url": "https://symfony.com/sponsor",
-          "type": "custom"
-        },
-        {
-          "url": "https://github.com/fabpot",
-          "type": "github"
-        },
-        {
-          "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-          "type": "tidelift"
-        }
-      ],
-      "time": "2021-05-21T13:25:03+00:00"
+      "time": "2021-02-19T12:13:01+00:00"
     },
     {
       "name": "vlucas/phpdotenv",
@@ -2224,21 +2139,21 @@
     },
     {
       "name": "composer/xdebug-handler",
-      "version": "2.0.2",
+      "version": "2.0.1",
       "source": {
         "type": "git",
         "url": "https://github.com/composer/xdebug-handler.git",
-        "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
+        "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
-        "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
+        "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/964adcdd3a28bf9ed5d9ac6450064e0d71ed7496",
+        "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496",
         "shasum": ""
       },
       "require": {
         "php": "^5.3.2 || ^7.0 || ^8.0",
-        "psr/log": "^1 || ^2 || ^3"
+        "psr/log": "^1.0"
       },
       "require-dev": {
         "phpstan/phpstan": "^0.12.55",
@@ -2263,7 +2178,7 @@
       "support": {
         "irc": "irc://irc.freenode.org/composer",
         "issues": "https://github.com/composer/xdebug-handler/issues",
-        "source": "https://github.com/composer/xdebug-handler/tree/2.0.2"
+        "source": "https://github.com/composer/xdebug-handler/tree/2.0.1"
       },
       "funding": [
         {
@@ -2279,7 +2194,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-31T17:03:58+00:00"
+      "time": "2021-05-05T19:37:51+00:00"
     },
     {
       "name": "danielstjules/stringy",
@@ -2339,16 +2254,16 @@
     },
     {
       "name": "doctrine/annotations",
-      "version": "1.13.2",
+      "version": "1.13.1",
       "source": {
         "type": "git",
         "url": "https://github.com/doctrine/annotations.git",
-        "reference": "5b668aef16090008790395c02c893b1ba13f7e08"
+        "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
-        "reference": "5b668aef16090008790395c02c893b1ba13f7e08",
+        "url": "https://api.github.com/repos/doctrine/annotations/zipball/e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f",
+        "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f",
         "shasum": ""
       },
       "require": {
@@ -2399,9 +2314,9 @@
       "keywords": ["annotations", "docblock", "parser"],
       "support": {
         "issues": "https://github.com/doctrine/annotations/issues",
-        "source": "https://github.com/doctrine/annotations/tree/1.13.2"
+        "source": "https://github.com/doctrine/annotations/tree/1.13.1"
       },
-      "time": "2021-08-05T19:00:23+00:00"
+      "time": "2021-05-16T18:07:53+00:00"
     },
     {
       "name": "doctrine/instantiator",
@@ -2541,16 +2456,16 @@
     },
     {
       "name": "friendsofphp/php-cs-fixer",
-      "version": "v3.0.2",
+      "version": "v3.0.0",
       "source": {
         "type": "git",
         "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
-        "reference": "990b979379502feb7f393d6c9aa36cc9b9765f24"
+        "reference": "c15377bdfa8d1ecf186f1deadec39c89984e1167"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/990b979379502feb7f393d6c9aa36cc9b9765f24",
-        "reference": "990b979379502feb7f393d6c9aa36cc9b9765f24",
+        "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c15377bdfa8d1ecf186f1deadec39c89984e1167",
+        "reference": "c15377bdfa8d1ecf186f1deadec39c89984e1167",
         "shasum": ""
       },
       "require": {
@@ -2613,7 +2528,7 @@
       "description": "A tool to automatically fix PHP code style",
       "support": {
         "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
-        "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.0.2"
+        "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.0.0"
       },
       "funding": [
         {
@@ -2621,20 +2536,20 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-04T19:28:19+00:00"
+      "time": "2021-05-03T21:51:58+00:00"
     },
     {
       "name": "mikey179/vfsstream",
-      "version": "v1.6.9",
+      "version": "v1.6.8",
       "source": {
         "type": "git",
         "url": "https://github.com/bovigo/vfsStream.git",
-        "reference": "2257e326dc3d0f50e55d0a90f71e37899f029718"
+        "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/2257e326dc3d0f50e55d0a90f71e37899f029718",
-        "reference": "2257e326dc3d0f50e55d0a90f71e37899f029718",
+        "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/231c73783ebb7dd9ec77916c10037eff5a2b6efe",
+        "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe",
         "shasum": ""
       },
       "require": {
@@ -2670,7 +2585,7 @@
         "source": "https://github.com/bovigo/vfsStream/tree/master",
         "wiki": "https://github.com/bovigo/vfsStream/wiki"
       },
-      "time": "2021-07-16T08:08:02+00:00"
+      "time": "2019-10-30T15:31:00+00:00"
     },
     {
       "name": "myclabs/deep-copy",
@@ -2854,16 +2769,16 @@
     },
     {
       "name": "nikic/php-parser",
-      "version": "v4.12.0",
+      "version": "v4.10.5",
       "source": {
         "type": "git",
         "url": "https://github.com/nikic/PHP-Parser.git",
-        "reference": "6608f01670c3cc5079e18c1dab1104e002579143"
+        "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6608f01670c3cc5079e18c1dab1104e002579143",
-        "reference": "6608f01670c3cc5079e18c1dab1104e002579143",
+        "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f",
+        "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f",
         "shasum": ""
       },
       "require": {
@@ -2897,22 +2812,22 @@
       "keywords": ["parser", "php"],
       "support": {
         "issues": "https://github.com/nikic/PHP-Parser/issues",
-        "source": "https://github.com/nikic/PHP-Parser/tree/v4.12.0"
+        "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5"
       },
-      "time": "2021-07-21T10:44:31+00:00"
+      "time": "2021-05-03T19:11:20+00:00"
     },
     {
       "name": "phar-io/manifest",
-      "version": "2.0.3",
+      "version": "2.0.1",
       "source": {
         "type": "git",
         "url": "https://github.com/phar-io/manifest.git",
-        "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
+        "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
-        "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
+        "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
+        "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
         "shasum": ""
       },
       "require": {
@@ -2953,9 +2868,9 @@
       "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
       "support": {
         "issues": "https://github.com/phar-io/manifest/issues",
-        "source": "https://github.com/phar-io/manifest/tree/2.0.3"
+        "source": "https://github.com/phar-io/manifest/tree/master"
       },
-      "time": "2021-07-20T11:28:43+00:00"
+      "time": "2020-06-27T14:33:11+00:00"
     },
     {
       "name": "phar-io/version",
@@ -3305,27 +3220,28 @@
     },
     {
       "name": "phpstan/phpdoc-parser",
-      "version": "0.5.5",
+      "version": "0.5.4",
       "source": {
         "type": "git",
         "url": "https://github.com/phpstan/phpdoc-parser.git",
-        "reference": "ea0b17460ec38e20d7eb64e7ec49b5d44af5d28c"
+        "reference": "e352d065af1ae9b41c12d1dfd309e90f7b1f55c9"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/ea0b17460ec38e20d7eb64e7ec49b5d44af5d28c",
-        "reference": "ea0b17460ec38e20d7eb64e7ec49b5d44af5d28c",
+        "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/e352d065af1ae9b41c12d1dfd309e90f7b1f55c9",
+        "reference": "e352d065af1ae9b41c12d1dfd309e90f7b1f55c9",
         "shasum": ""
       },
       "require": {
         "php": "^7.1 || ^8.0"
       },
       "require-dev": {
+        "phing/phing": "^2.16.3",
         "php-parallel-lint/php-parallel-lint": "^1.2",
         "phpstan/extension-installer": "^1.0",
-        "phpstan/phpstan": "^0.12.87",
+        "phpstan/phpstan": "^0.12.60",
         "phpstan/phpstan-strict-rules": "^0.12.5",
-        "phpunit/phpunit": "^9.5",
+        "phpunit/phpunit": "^7.5.20",
         "symfony/process": "^5.2"
       },
       "type": "library",
@@ -3344,22 +3260,22 @@
       "description": "PHPDoc parser with support for nullable, intersection and generic types",
       "support": {
         "issues": "https://github.com/phpstan/phpdoc-parser/issues",
-        "source": "https://github.com/phpstan/phpdoc-parser/tree/0.5.5"
+        "source": "https://github.com/phpstan/phpdoc-parser/tree/0.5.4"
       },
-      "time": "2021-06-11T13:24:46+00:00"
+      "time": "2021-04-03T14:46:19+00:00"
     },
     {
       "name": "phpstan/phpstan",
-      "version": "0.12.94",
+      "version": "0.12.88",
       "source": {
         "type": "git",
         "url": "https://github.com/phpstan/phpstan.git",
-        "reference": "3d0ba4c198a24e3c3fc489f3ec6ac9612c4be5d6"
+        "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3d0ba4c198a24e3c3fc489f3ec6ac9612c4be5d6",
-        "reference": "3d0ba4c198a24e3c3fc489f3ec6ac9612c4be5d6",
+        "url": "https://api.github.com/repos/phpstan/phpstan/zipball/464d1a81af49409c41074aa6640ed0c4cbd9bb68",
+        "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68",
         "shasum": ""
       },
       "require": {
@@ -3383,17 +3299,13 @@
       "description": "PHPStan - PHP Static Analysis Tool",
       "support": {
         "issues": "https://github.com/phpstan/phpstan/issues",
-        "source": "https://github.com/phpstan/phpstan/tree/0.12.94"
+        "source": "https://github.com/phpstan/phpstan/tree/0.12.88"
       },
       "funding": [
         {
           "url": "https://github.com/ondrejmirtes",
           "type": "github"
         },
-        {
-          "url": "https://github.com/phpstan",
-          "type": "github"
-        },
         {
           "url": "https://www.patreon.com/phpstan",
           "type": "patreon"
@@ -3403,7 +3315,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-30T09:05:27+00:00"
+      "time": "2021-05-17T12:24:49+00:00"
     },
     {
       "name": "phpunit/php-code-coverage",
@@ -3692,16 +3604,16 @@
     },
     {
       "name": "phpunit/phpunit",
-      "version": "9.5.8",
+      "version": "9.5.5",
       "source": {
         "type": "git",
         "url": "https://github.com/sebastianbergmann/phpunit.git",
-        "reference": "191768ccd5c85513b4068bdbe99bb6390c7d54fb"
+        "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/191768ccd5c85513b4068bdbe99bb6390c7d54fb",
-        "reference": "191768ccd5c85513b4068bdbe99bb6390c7d54fb",
+        "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276",
+        "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276",
         "shasum": ""
       },
       "require": {
@@ -3713,7 +3625,7 @@
         "ext-xml": "*",
         "ext-xmlwriter": "*",
         "myclabs/deep-copy": "^1.10.1",
-        "phar-io/manifest": "^2.0.3",
+        "phar-io/manifest": "^2.0.1",
         "phar-io/version": "^3.0.2",
         "php": ">=7.3",
         "phpspec/prophecy": "^1.12.1",
@@ -3731,7 +3643,7 @@
         "sebastian/global-state": "^5.0.1",
         "sebastian/object-enumerator": "^4.0.3",
         "sebastian/resource-operations": "^3.0.3",
-        "sebastian/type": "^2.3.4",
+        "sebastian/type": "^2.3.2",
         "sebastian/version": "^3.0.2"
       },
       "require-dev": {
@@ -3767,7 +3679,7 @@
       "keywords": ["phpunit", "testing", "xunit"],
       "support": {
         "issues": "https://github.com/sebastianbergmann/phpunit/issues",
-        "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.8"
+        "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5"
       },
       "funding": [
         {
@@ -3779,7 +3691,7 @@
           "type": "github"
         }
       ],
-      "time": "2021-07-31T15:17:34+00:00"
+      "time": "2021-06-05T04:49:07+00:00"
     },
     {
       "name": "psr/container",
@@ -3871,70 +3783,23 @@
       },
       "time": "2019-01-08T18:20:26+00:00"
     },
-    {
-      "name": "rector/phpstan-rules",
-      "version": "0.3.4",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/rectorphp/phpstan-rules.git",
-        "reference": "31cfc0abb1f464b910b6dad798b2b04c8f659dc9"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/rectorphp/phpstan-rules/zipball/31cfc0abb1f464b910b6dad798b2b04c8f659dc9",
-        "reference": "31cfc0abb1f464b910b6dad798b2b04c8f659dc9",
-        "shasum": ""
-      },
-      "require": {
-        "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "phpstan/phpstan": "^0.12.86",
-        "symplify/phpstan-rules": "^9.3.22"
-      },
-      "require-dev": {
-        "phpstan/extension-installer": "^1.1",
-        "phpunit/phpunit": "^9.5",
-        "rector/rector-src": "^0.11.7",
-        "symplify/easy-coding-standard": "^9.3.22",
-        "symplify/phpstan-extensions": "^9.3.22"
-      },
-      "type": "phpstan-extension",
-      "extra": {
-        "phpstan": {
-          "includes": ["config/config.neon"]
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Rector\\PHPStanRules\\": "src"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "description": "PHPStan rules for Rector projects - with focus on static reflection, constant re-use and Rector design patterns",
-      "support": {
-        "issues": "https://github.com/rectorphp/phpstan-rules/issues",
-        "source": "https://github.com/rectorphp/phpstan-rules/tree/0.3.4"
-      },
-      "time": "2021-06-27T13:29:24+00:00"
-    },
     {
       "name": "rector/rector",
-      "version": "0.11.46",
+      "version": "0.11.16",
       "source": {
         "type": "git",
         "url": "https://github.com/rectorphp/rector.git",
-        "reference": "9802271920e82f8004882094a254b598d3279708"
+        "reference": "5c030ad7cefa59075e0fe14604cd4982ceaa2bd0"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/rectorphp/rector/zipball/9802271920e82f8004882094a254b598d3279708",
-        "reference": "9802271920e82f8004882094a254b598d3279708",
+        "url": "https://api.github.com/repos/rectorphp/rector/zipball/5c030ad7cefa59075e0fe14604cd4982ceaa2bd0",
+        "reference": "5c030ad7cefa59075e0fe14604cd4982ceaa2bd0",
         "shasum": ""
       },
       "require": {
         "php": "^7.1|^8.0",
-        "phpstan/phpstan": "0.12.94"
+        "phpstan/phpstan": ">=0.12.86 <=0.12.88"
       },
       "conflict": {
         "phpstan/phpdoc-parser": "<=0.5.3",
@@ -3942,6 +3807,7 @@
         "rector/rector-cakephp": "*",
         "rector/rector-doctrine": "*",
         "rector/rector-nette": "*",
+        "rector/rector-nette-to-symfony": "*",
         "rector/rector-phpunit": "*",
         "rector/rector-prefixed": "*",
         "rector/rector-symfony": "*"
@@ -3961,7 +3827,7 @@
       "description": "Prefixed and PHP 7.1 downgraded version of rector/rector",
       "support": {
         "issues": "https://github.com/rectorphp/rector/issues",
-        "source": "https://github.com/rectorphp/rector/tree/0.11.46"
+        "source": "https://github.com/rectorphp/rector/tree/0.11.16"
       },
       "funding": [
         {
@@ -3969,7 +3835,53 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-09T13:46:17+00:00"
+      "time": "2021-06-08T08:41:04+00:00"
+    },
+    {
+      "name": "rector/rector-phpstan-rules",
+      "version": "0.2.12",
+      "source": {
+        "type": "git",
+        "url": "https://github.com/rectorphp/phpstan-rules.git",
+        "reference": "84b2034aab951be7e86dc6cc7e141ee92a3d115b"
+      },
+      "dist": {
+        "type": "zip",
+        "url": "https://api.github.com/repos/rectorphp/phpstan-rules/zipball/84b2034aab951be7e86dc6cc7e141ee92a3d115b",
+        "reference": "84b2034aab951be7e86dc6cc7e141ee92a3d115b",
+        "shasum": ""
+      },
+      "require": {
+        "nette/utils": "^3.2",
+        "php": ">=7.3",
+        "phpstan/phpstan": "^0.12.86",
+        "symplify/phpstan-rules": "^9.3.5"
+      },
+      "require-dev": {
+        "phpstan/extension-installer": "^1.1",
+        "phpunit/phpunit": "^9.5",
+        "symplify/easy-coding-standard": "^9.3",
+        "symplify/phpstan-extensions": "^9.3"
+      },
+      "type": "phpstan-extension",
+      "extra": {
+        "phpstan": {
+          "includes": ["config/config.neon"]
+        }
+      },
+      "autoload": {
+        "psr-4": {
+          "Rector\\PHPStanRules\\": "src"
+        }
+      },
+      "notification-url": "https://packagist.org/downloads/",
+      "license": ["MIT"],
+      "description": "PHPStan rules for Rector projects - with focus on static reflection, constant re-use and Rector design patterns",
+      "support": {
+        "issues": "https://github.com/rectorphp/phpstan-rules/issues",
+        "source": "https://github.com/rectorphp/phpstan-rules/tree/0.2.12"
+      },
+      "time": "2021-05-20T22:31:19+00:00"
     },
     {
       "name": "sebastian/cli-parser",
@@ -4429,16 +4341,16 @@
     },
     {
       "name": "sebastian/global-state",
-      "version": "5.0.3",
+      "version": "5.0.2",
       "source": {
         "type": "git",
         "url": "https://github.com/sebastianbergmann/global-state.git",
-        "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49"
+        "reference": "a90ccbddffa067b51f574dea6eb25d5680839455"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49",
-        "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49",
+        "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455",
+        "reference": "a90ccbddffa067b51f574dea6eb25d5680839455",
         "shasum": ""
       },
       "require": {
@@ -4475,7 +4387,7 @@
       "keywords": ["global state"],
       "support": {
         "issues": "https://github.com/sebastianbergmann/global-state/issues",
-        "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3"
+        "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2"
       },
       "funding": [
         {
@@ -4483,7 +4395,7 @@
           "type": "github"
         }
       ],
-      "time": "2021-06-11T13:31:12+00:00"
+      "time": "2020-10-26T15:55:19+00:00"
     },
     {
       "name": "sebastian/lines-of-code",
@@ -4754,16 +4666,16 @@
     },
     {
       "name": "sebastian/type",
-      "version": "2.3.4",
+      "version": "2.3.2",
       "source": {
         "type": "git",
         "url": "https://github.com/sebastianbergmann/type.git",
-        "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
+        "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
-        "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
+        "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0d1c587401514d17e8f9258a27e23527cb1b06c1",
+        "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1",
         "shasum": ""
       },
       "require": {
@@ -4794,7 +4706,7 @@
       "homepage": "https://github.com/sebastianbergmann/type",
       "support": {
         "issues": "https://github.com/sebastianbergmann/type/issues",
-        "source": "https://github.com/sebastianbergmann/type/tree/2.3.4"
+        "source": "https://github.com/sebastianbergmann/type/tree/2.3.2"
       },
       "funding": [
         {
@@ -4802,7 +4714,7 @@
           "type": "github"
         }
       ],
-      "time": "2021-06-15T12:49:02+00:00"
+      "time": "2021-06-04T13:02:07+00:00"
     },
     {
       "name": "sebastian/version",
@@ -4960,16 +4872,16 @@
     },
     {
       "name": "sebastianfeldmann/git",
-      "version": "3.7.2",
+      "version": "3.7.1",
       "source": {
         "type": "git",
         "url": "https://github.com/sebastianfeldmann/git.git",
-        "reference": "ccaa6211cc613c1c631120e70b20f29be30c5fd4"
+        "reference": "406b98e09c37249ce586be8ed5766bf0ca389490"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/sebastianfeldmann/git/zipball/ccaa6211cc613c1c631120e70b20f29be30c5fd4",
-        "reference": "ccaa6211cc613c1c631120e70b20f29be30c5fd4",
+        "url": "https://api.github.com/repos/sebastianfeldmann/git/zipball/406b98e09c37249ce586be8ed5766bf0ca389490",
+        "reference": "406b98e09c37249ce586be8ed5766bf0ca389490",
         "shasum": ""
       },
       "require": {
@@ -5002,7 +4914,7 @@
       "keywords": ["git"],
       "support": {
         "issues": "https://github.com/sebastianfeldmann/git/issues",
-        "source": "https://github.com/sebastianfeldmann/git/tree/3.7.2"
+        "source": "https://github.com/sebastianfeldmann/git/tree/3.7.1"
       },
       "funding": [
         {
@@ -5010,20 +4922,20 @@
           "type": "github"
         }
       ],
-      "time": "2021-07-29T16:13:52+00:00"
+      "time": "2021-05-29T12:47:08+00:00"
     },
     {
       "name": "symfony/config",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/config.git",
-        "reference": "4268f3059c904c61636275182707f81645517a37"
+        "reference": "9f4a448c2d7fd2c90882dfff930b627ddbe16810"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/config/zipball/4268f3059c904c61636275182707f81645517a37",
-        "reference": "4268f3059c904c61636275182707f81645517a37",
+        "url": "https://api.github.com/repos/symfony/config/zipball/9f4a448c2d7fd2c90882dfff930b627ddbe16810",
+        "reference": "9f4a448c2d7fd2c90882dfff930b627ddbe16810",
         "shasum": ""
       },
       "require": {
@@ -5031,7 +4943,7 @@
         "symfony/deprecation-contracts": "^2.1",
         "symfony/filesystem": "^4.4|^5.0",
         "symfony/polyfill-ctype": "~1.8",
-        "symfony/polyfill-php80": "^1.16",
+        "symfony/polyfill-php80": "^1.15",
         "symfony/polyfill-php81": "^1.22"
       },
       "conflict": {
@@ -5069,7 +4981,7 @@
       "description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/config/tree/v5.3.4"
+        "source": "https://github.com/symfony/config/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5085,20 +4997,20 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-21T12:40:44+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/console",
-      "version": "v5.3.6",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/console.git",
-        "reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2"
+        "reference": "058553870f7809087fa80fa734704a21b9bcaeb2"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/console/zipball/51b71afd6d2dc8f5063199357b9880cea8d8bfe2",
-        "reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2",
+        "url": "https://api.github.com/repos/symfony/console/zipball/058553870f7809087fa80fa734704a21b9bcaeb2",
+        "reference": "058553870f7809087fa80fa734704a21b9bcaeb2",
         "shasum": ""
       },
       "require": {
@@ -5106,12 +5018,11 @@
         "symfony/deprecation-contracts": "^2.1",
         "symfony/polyfill-mbstring": "~1.0",
         "symfony/polyfill-php73": "^1.8",
-        "symfony/polyfill-php80": "^1.16",
+        "symfony/polyfill-php80": "^1.15",
         "symfony/service-contracts": "^1.1|^2",
         "symfony/string": "^5.1"
       },
       "conflict": {
-        "psr/log": ">=3",
         "symfony/dependency-injection": "<4.4",
         "symfony/dotenv": "<5.1",
         "symfony/event-dispatcher": "<4.4",
@@ -5119,10 +5030,10 @@
         "symfony/process": "<4.4"
       },
       "provide": {
-        "psr/log-implementation": "1.0|2.0"
+        "psr/log-implementation": "1.0"
       },
       "require-dev": {
-        "psr/log": "^1|^2",
+        "psr/log": "~1.0",
         "symfony/config": "^4.4|^5.0",
         "symfony/dependency-injection": "^4.4|^5.0",
         "symfony/event-dispatcher": "^4.4|^5.0",
@@ -5159,7 +5070,7 @@
       "homepage": "https://symfony.com",
       "keywords": ["cli", "command line", "console", "terminal"],
       "support": {
-        "source": "https://github.com/symfony/console/tree/v5.3.6"
+        "source": "https://github.com/symfony/console/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5175,27 +5086,27 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-27T19:10:22+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/dependency-injection",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/dependency-injection.git",
-        "reference": "5a825e4b386066167a8b55487091cb62beec74c2"
+        "reference": "94d973cb742d8c5c5dcf9534220e6b73b09af1d4"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5a825e4b386066167a8b55487091cb62beec74c2",
-        "reference": "5a825e4b386066167a8b55487091cb62beec74c2",
+        "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/94d973cb742d8c5c5dcf9534220e6b73b09af1d4",
+        "reference": "94d973cb742d8c5c5dcf9534220e6b73b09af1d4",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
         "psr/container": "^1.1.1",
         "symfony/deprecation-contracts": "^2.1",
-        "symfony/polyfill-php80": "^1.16",
+        "symfony/polyfill-php80": "^1.15",
         "symfony/service-contracts": "^1.1.6|^2"
       },
       "conflict": {
@@ -5243,7 +5154,7 @@
       "description": "Allows you to standardize and centralize the way objects are constructed in your application",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/dependency-injection/tree/v5.3.4"
+        "source": "https://github.com/symfony/dependency-injection/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5259,7 +5170,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-23T15:55:36+00:00"
+      "time": "2021-05-26T17:57:12+00:00"
     },
     {
       "name": "symfony/deprecation-contracts",
@@ -5326,21 +5237,22 @@
     },
     {
       "name": "symfony/error-handler",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/error-handler.git",
-        "reference": "281f6c4660bcf5844bb0346fe3a4664722fe4c73"
+        "reference": "0e6768b8c0dcef26df087df2bbbaa143867a59b2"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/error-handler/zipball/281f6c4660bcf5844bb0346fe3a4664722fe4c73",
-        "reference": "281f6c4660bcf5844bb0346fe3a4664722fe4c73",
+        "url": "https://api.github.com/repos/symfony/error-handler/zipball/0e6768b8c0dcef26df087df2bbbaa143867a59b2",
+        "reference": "0e6768b8c0dcef26df087df2bbbaa143867a59b2",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
-        "psr/log": "^1|^2|^3",
+        "psr/log": "^1.0",
+        "symfony/polyfill-php80": "^1.15",
         "symfony/var-dumper": "^4.4|^5.0"
       },
       "require-dev": {
@@ -5370,7 +5282,7 @@
       "description": "Provides tools to manage errors and ease debugging PHP code",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/error-handler/tree/v5.3.4"
+        "source": "https://github.com/symfony/error-handler/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5386,27 +5298,27 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-23T15:55:36+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/event-dispatcher",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/event-dispatcher.git",
-        "reference": "f2fd2208157553874560f3645d4594303058c4bd"
+        "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f2fd2208157553874560f3645d4594303058c4bd",
-        "reference": "f2fd2208157553874560f3645d4594303058c4bd",
+        "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67a5f354afa8e2f231081b3fa11a5912f933c3ce",
+        "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
         "symfony/deprecation-contracts": "^2.1",
         "symfony/event-dispatcher-contracts": "^2",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-php80": "^1.15"
       },
       "conflict": {
         "symfony/dependency-injection": "<4.4"
@@ -5416,7 +5328,7 @@
         "symfony/event-dispatcher-implementation": "2.0"
       },
       "require-dev": {
-        "psr/log": "^1|^2|^3",
+        "psr/log": "~1.0",
         "symfony/config": "^4.4|^5.0",
         "symfony/dependency-injection": "^4.4|^5.0",
         "symfony/error-handler": "^4.4|^5.0",
@@ -5451,7 +5363,7 @@
       "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.4"
+        "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5467,7 +5379,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-23T15:55:36+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/event-dispatcher-contracts",
@@ -5548,22 +5460,21 @@
     },
     {
       "name": "symfony/filesystem",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/filesystem.git",
-        "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32"
+        "reference": "348116319d7fb7d1faa781d26a48922428013eb2"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32",
-        "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32",
+        "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2",
+        "reference": "348116319d7fb7d1faa781d26a48922428013eb2",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
-        "symfony/polyfill-ctype": "~1.8",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-ctype": "~1.8"
       },
       "type": "library",
       "autoload": {
@@ -5587,7 +5498,7 @@
       "description": "Provides basic utilities for the filesystem",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/filesystem/tree/v5.3.4"
+        "source": "https://github.com/symfony/filesystem/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5603,25 +5514,24 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-21T12:40:44+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/finder",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/finder.git",
-        "reference": "17f50e06018baec41551a71a15731287dbaab186"
+        "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/finder/zipball/17f50e06018baec41551a71a15731287dbaab186",
-        "reference": "17f50e06018baec41551a71a15731287dbaab186",
+        "url": "https://api.github.com/repos/symfony/finder/zipball/0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6",
+        "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6",
         "shasum": ""
       },
       "require": {
-        "php": ">=7.2.5",
-        "symfony/polyfill-php80": "^1.16"
+        "php": ">=7.2.5"
       },
       "type": "library",
       "autoload": {
@@ -5645,7 +5555,7 @@
       "description": "Finds files and directories via an intuitive fluent interface",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/finder/tree/v5.3.4"
+        "source": "https://github.com/symfony/finder/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5661,7 +5571,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-23T15:54:19+00:00"
+      "time": "2021-05-26T12:52:38+00:00"
     },
     {
       "name": "symfony/http-client-contracts",
@@ -5741,23 +5651,23 @@
     },
     {
       "name": "symfony/http-foundation",
-      "version": "v5.3.6",
+      "version": "v5.3.1",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/http-foundation.git",
-        "reference": "a8388f7b7054a7401997008ce9cd8c6b0ab7ac75"
+        "reference": "8827b90cf8806e467124ad476acd15216c2fceb6"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a8388f7b7054a7401997008ce9cd8c6b0ab7ac75",
-        "reference": "a8388f7b7054a7401997008ce9cd8c6b0ab7ac75",
+        "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8827b90cf8806e467124ad476acd15216c2fceb6",
+        "reference": "8827b90cf8806e467124ad476acd15216c2fceb6",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
         "symfony/deprecation-contracts": "^2.1",
         "symfony/polyfill-mbstring": "~1.1",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-php80": "^1.15"
       },
       "require-dev": {
         "predis/predis": "~1.0",
@@ -5790,7 +5700,7 @@
       "description": "Defines an object-oriented layer for the HTTP specification",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/http-foundation/tree/v5.3.6"
+        "source": "https://github.com/symfony/http-foundation/tree/v5.3.1"
       },
       "funding": [
         {
@@ -5806,25 +5716,25 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-27T17:08:17+00:00"
+      "time": "2021-06-02T09:32:00+00:00"
     },
     {
       "name": "symfony/http-kernel",
-      "version": "v5.3.6",
+      "version": "v5.3.1",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/http-kernel.git",
-        "reference": "60030f209018356b3b553b9dbd84ad2071c1b7e0"
+        "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/http-kernel/zipball/60030f209018356b3b553b9dbd84ad2071c1b7e0",
-        "reference": "60030f209018356b3b553b9dbd84ad2071c1b7e0",
+        "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74eb022e3bac36b3d3a897951a98759f2b32b864",
+        "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
-        "psr/log": "^1|^2",
+        "psr/log": "~1.0",
         "symfony/deprecation-contracts": "^2.1",
         "symfony/error-handler": "^4.4|^5.0",
         "symfony/event-dispatcher": "^5.0",
@@ -5832,7 +5742,7 @@
         "symfony/http-foundation": "^5.3",
         "symfony/polyfill-ctype": "^1.8",
         "symfony/polyfill-php73": "^1.9",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-php80": "^1.15"
       },
       "conflict": {
         "symfony/browser-kit": "<4.4",
@@ -5851,7 +5761,7 @@
         "twig/twig": "<2.13"
       },
       "provide": {
-        "psr/log-implementation": "1.0|2.0"
+        "psr/log-implementation": "1.0"
       },
       "require-dev": {
         "psr/cache": "^1.0|^2.0|^3.0",
@@ -5898,7 +5808,7 @@
       "description": "Provides a structured process for converting a Request into a Response",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/http-kernel/tree/v5.3.6"
+        "source": "https://github.com/symfony/http-kernel/tree/v5.3.1"
       },
       "funding": [
         {
@@ -5914,27 +5824,27 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-29T07:06:27+00:00"
+      "time": "2021-06-02T10:07:12+00:00"
     },
     {
       "name": "symfony/options-resolver",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/options-resolver.git",
-        "reference": "a603e5701bd6e305cfc777a8b50bf081ef73105e"
+        "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a603e5701bd6e305cfc777a8b50bf081ef73105e",
-        "reference": "a603e5701bd6e305cfc777a8b50bf081ef73105e",
+        "url": "https://api.github.com/repos/symfony/options-resolver/zipball/162e886ca035869866d233a2bfef70cc28f9bbe5",
+        "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
         "symfony/deprecation-contracts": "^2.1",
         "symfony/polyfill-php73": "~1.0",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-php80": "^1.15"
       },
       "type": "library",
       "autoload": {
@@ -5959,7 +5869,7 @@
       "homepage": "https://symfony.com",
       "keywords": ["config", "configuration", "options"],
       "support": {
-        "source": "https://github.com/symfony/options-resolver/tree/v5.3.4"
+        "source": "https://github.com/symfony/options-resolver/tree/v5.3.0"
       },
       "funding": [
         {
@@ -5975,20 +5885,20 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-23T15:55:36+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/polyfill-intl-grapheme",
-      "version": "v1.23.1",
+      "version": "v1.23.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
-        "reference": "16880ba9c5ebe3642d1995ab866db29270b36535"
+        "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535",
-        "reference": "16880ba9c5ebe3642d1995ab866db29270b36535",
+        "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab",
+        "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab",
         "shasum": ""
       },
       "require": {
@@ -6036,7 +5946,7 @@
         "shim"
       ],
       "support": {
-        "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1"
+        "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0"
       },
       "funding": [
         {
@@ -6052,7 +5962,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-05-27T12:26:48+00:00"
+      "time": "2021-05-27T09:17:38+00:00"
     },
     {
       "name": "symfony/polyfill-intl-normalizer",
@@ -6267,23 +6177,91 @@
       ],
       "time": "2021-02-19T12:13:01+00:00"
     },
+    {
+      "name": "symfony/polyfill-php81",
+      "version": "v1.23.0",
+      "source": {
+        "type": "git",
+        "url": "https://github.com/symfony/polyfill-php81.git",
+        "reference": "e66119f3de95efc359483f810c4c3e6436279436"
+      },
+      "dist": {
+        "type": "zip",
+        "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436",
+        "reference": "e66119f3de95efc359483f810c4c3e6436279436",
+        "shasum": ""
+      },
+      "require": {
+        "php": ">=7.1"
+      },
+      "type": "library",
+      "extra": {
+        "branch-alias": {
+          "dev-main": "1.23-dev"
+        },
+        "thanks": {
+          "name": "symfony/polyfill",
+          "url": "https://github.com/symfony/polyfill"
+        }
+      },
+      "autoload": {
+        "psr-4": {
+          "Symfony\\Polyfill\\Php81\\": ""
+        },
+        "files": ["bootstrap.php"],
+        "classmap": ["Resources/stubs"]
+      },
+      "notification-url": "https://packagist.org/downloads/",
+      "license": ["MIT"],
+      "authors": [
+        {
+          "name": "Nicolas Grekas",
+          "email": "p@tchwork.com"
+        },
+        {
+          "name": "Symfony Community",
+          "homepage": "https://symfony.com/contributors"
+        }
+      ],
+      "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+      "homepage": "https://symfony.com",
+      "keywords": ["compatibility", "polyfill", "portable", "shim"],
+      "support": {
+        "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0"
+      },
+      "funding": [
+        {
+          "url": "https://symfony.com/sponsor",
+          "type": "custom"
+        },
+        {
+          "url": "https://github.com/fabpot",
+          "type": "github"
+        },
+        {
+          "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+          "type": "tidelift"
+        }
+      ],
+      "time": "2021-05-21T13:25:03+00:00"
+    },
     {
       "name": "symfony/process",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/process.git",
-        "reference": "d16634ee55b895bd85ec714dadc58e4428ecf030"
+        "reference": "53e36cb1c160505cdaf1ef201501669c4c317191"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/process/zipball/d16634ee55b895bd85ec714dadc58e4428ecf030",
-        "reference": "d16634ee55b895bd85ec714dadc58e4428ecf030",
+        "url": "https://api.github.com/repos/symfony/process/zipball/53e36cb1c160505cdaf1ef201501669c4c317191",
+        "reference": "53e36cb1c160505cdaf1ef201501669c4c317191",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-php80": "^1.15"
       },
       "type": "library",
       "autoload": {
@@ -6307,7 +6285,7 @@
       "description": "Executes commands in sub-processes",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/process/tree/v5.3.4"
+        "source": "https://github.com/symfony/process/tree/v5.3.0"
       },
       "funding": [
         {
@@ -6323,7 +6301,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-23T15:54:19+00:00"
+      "time": "2021-05-26T12:52:38+00:00"
     },
     {
       "name": "symfony/service-contracts",
@@ -6404,16 +6382,16 @@
     },
     {
       "name": "symfony/stopwatch",
-      "version": "v5.3.4",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/stopwatch.git",
-        "reference": "b24c6a92c6db316fee69e38c80591e080e41536c"
+        "reference": "313d02f59d6543311865007e5ff4ace05b35ee65"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b24c6a92c6db316fee69e38c80591e080e41536c",
-        "reference": "b24c6a92c6db316fee69e38c80591e080e41536c",
+        "url": "https://api.github.com/repos/symfony/stopwatch/zipball/313d02f59d6543311865007e5ff4ace05b35ee65",
+        "reference": "313d02f59d6543311865007e5ff4ace05b35ee65",
         "shasum": ""
       },
       "require": {
@@ -6442,7 +6420,7 @@
       "description": "Provides a way to profile code",
       "homepage": "https://symfony.com",
       "support": {
-        "source": "https://github.com/symfony/stopwatch/tree/v5.3.4"
+        "source": "https://github.com/symfony/stopwatch/tree/v5.3.0"
       },
       "funding": [
         {
@@ -6458,20 +6436,20 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-10T08:58:57+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/string",
-      "version": "v5.3.3",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/string.git",
-        "reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1"
+        "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/string/zipball/bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
-        "reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
+        "url": "https://api.github.com/repos/symfony/string/zipball/a9a0f8b6aafc5d2d1c116dcccd1573a95153515b",
+        "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b",
         "shasum": ""
       },
       "require": {
@@ -6512,7 +6490,7 @@
       "homepage": "https://symfony.com",
       "keywords": ["grapheme", "i18n", "string", "unicode", "utf-8", "utf8"],
       "support": {
-        "source": "https://github.com/symfony/string/tree/v5.3.3"
+        "source": "https://github.com/symfony/string/tree/v5.3.0"
       },
       "funding": [
         {
@@ -6528,26 +6506,26 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-06-27T11:44:38+00:00"
+      "time": "2021-05-26T17:43:10+00:00"
     },
     {
       "name": "symfony/var-dumper",
-      "version": "v5.3.6",
+      "version": "v5.3.0",
       "source": {
         "type": "git",
         "url": "https://github.com/symfony/var-dumper.git",
-        "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
+        "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
-        "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+        "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1d3953e627fe4b5f6df503f356b6545ada6351f3",
+        "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3",
         "shasum": ""
       },
       "require": {
         "php": ">=7.2.5",
         "symfony/polyfill-mbstring": "~1.0",
-        "symfony/polyfill-php80": "^1.16"
+        "symfony/polyfill-php80": "^1.15"
       },
       "conflict": {
         "phpunit/phpunit": "<5.4.3",
@@ -6589,7 +6567,7 @@
       "homepage": "https://symfony.com",
       "keywords": ["debug", "dump"],
       "support": {
-        "source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
+        "source": "https://github.com/symfony/var-dumper/tree/v5.3.0"
       },
       "funding": [
         {
@@ -6605,68 +6583,39 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-07-27T01:56:02+00:00"
+      "time": "2021-05-27T12:28:50+00:00"
     },
     {
       "name": "symplify/astral",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/astral.git",
-        "reference": "4e4725517557b19dbf7edb49206b4f61d0110839"
+        "reference": "2d205265eacad08eb5b620ddfa71b334ce992233"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/astral/zipball/4e4725517557b19dbf7edb49206b4f61d0110839",
-        "reference": "4e4725517557b19dbf7edb49206b4f61d0110839",
+        "url": "https://api.github.com/repos/symplify/astral/zipball/2d205265eacad08eb5b620ddfa71b334ce992233",
+        "reference": "2d205265eacad08eb5b620ddfa71b334ce992233",
         "shasum": ""
       },
       "require": {
         "nette/utils": "^3.2",
-        "nikic/php-parser": "^4.11",
-        "php": ">=8.0",
-        "symfony/dependency-injection": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/autowire-array-parameter": "^9.4.27",
-        "symplify/package-builder": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "nikic/php-parser": "4.10.5",
+        "php": ">=7.3",
+        "symfony/dependency-injection": "^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/autowire-array-parameter": "^9.3.22",
+        "symplify/package-builder": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5",
-        "symplify/easy-testing": "^9.4.27"
+        "symplify/easy-testing": "^9.3.22"
       },
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -6678,7 +6627,7 @@
       "license": ["MIT"],
       "description": "Toolking for smart daily work with AST",
       "support": {
-        "source": "https://github.com/symplify/astral/tree/9.4.27"
+        "source": "https://github.com/symplify/astral/tree/v9.3.22"
       },
       "funding": [
         {
@@ -6690,57 +6639,27 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:26:14+00:00"
+      "time": "2021-06-10T09:28:23+00:00"
     },
     {
       "name": "symplify/autowire-array-parameter",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/autowire-array-parameter.git",
-        "reference": "618fcbfc2f7d45401abc254c509258a883e7cdad"
+        "reference": "7794f4d1eafa7e32905e8b38d37eae7b597ed1a8"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/618fcbfc2f7d45401abc254c509258a883e7cdad",
-        "reference": "618fcbfc2f7d45401abc254c509258a883e7cdad",
+        "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/7794f4d1eafa7e32905e8b38d37eae7b597ed1a8",
+        "reference": "7794f4d1eafa7e32905e8b38d37eae7b597ed1a8",
         "shasum": ""
       },
       "require": {
         "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "symfony/dependency-injection": "^5.3",
-        "symplify/package-builder": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/dependency-injection": "^5.2",
+        "symplify/package-builder": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5"
@@ -6748,7 +6667,7 @@
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -6760,7 +6679,7 @@
       "license": ["MIT"],
       "description": "Autowire array parameters for your Symfony applications",
       "support": {
-        "source": "https://github.com/symplify/autowire-array-parameter/tree/9.4.27"
+        "source": "https://github.com/symplify/autowire-array-parameter/tree/v9.3.22"
       },
       "funding": [
         {
@@ -6772,73 +6691,46 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:26:19+00:00"
+      "time": "2021-06-10T09:28:28+00:00"
     },
     {
       "name": "symplify/coding-standard",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/coding-standard.git",
-        "reference": "6b0bedd882dc262666b6b0a4dfc56fb643775939"
+        "reference": "3ce70069790d35e6d6377675778157b573f3a2dd"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/coding-standard/zipball/6b0bedd882dc262666b6b0a4dfc56fb643775939",
-        "reference": "6b0bedd882dc262666b6b0a4dfc56fb643775939",
+        "url": "https://api.github.com/repos/symplify/coding-standard/zipball/3ce70069790d35e6d6377675778157b573f3a2dd",
+        "reference": "3ce70069790d35e6d6377675778157b573f3a2dd",
         "shasum": ""
       },
       "require": {
-        "friendsofphp/php-cs-fixer": "^3.0.2",
+        "friendsofphp/php-cs-fixer": "^3.0",
         "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "symplify/autowire-array-parameter": "^9.4.27",
-        "symplify/package-builder": "^9.4.27",
-        "symplify/rule-doc-generator-contracts": "^9.4.27",
-        "symplify/symplify-kernel": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symplify/autowire-array-parameter": "^9.3.22",
+        "symplify/package-builder": "^9.3.22",
+        "symplify/rule-doc-generator-contracts": "^9.3.22",
+        "symplify/symplify-kernel": "^9.3.22"
       },
       "require-dev": {
-        "doctrine/orm": "^2.9",
+        "doctrine/orm": "^2.7",
         "nette/application": "^3.1",
         "nette/bootstrap": "^3.1",
         "phpunit/phpunit": "^9.5",
-        "symfony/framework-bundle": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/easy-coding-standard": "^9.4.27",
-        "symplify/rule-doc-generator": "^9.4.27",
-        "symplify/smart-file-system": "^9.4.27"
+        "symfony/framework-bundle": "^4.4|^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/easy-coding-standard": "^9.3.22",
+        "symplify/rule-doc-generator": "^9.3.22",
+        "symplify/smart-file-system": "^9.3.22"
       },
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -6850,7 +6742,7 @@
       "license": ["MIT"],
       "description": "Set of Symplify rules for PHP_CodeSniffer and PHP CS Fixer.",
       "support": {
-        "source": "https://github.com/symplify/coding-standard/tree/9.4.27"
+        "source": "https://github.com/symplify/coding-standard/tree/v9.3.22"
       },
       "funding": [
         {
@@ -6862,60 +6754,31 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:26:19+00:00"
+      "time": "2021-06-10T09:28:27+00:00"
     },
     {
       "name": "symplify/composer-json-manipulator",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/composer-json-manipulator.git",
-        "reference": "e58bd52830f83689ee641feee3a42e03a1a3b07c"
+        "reference": "a3d711ec0928cf8ddf3e4c16dad335318d588679"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/composer-json-manipulator/zipball/e58bd52830f83689ee641feee3a42e03a1a3b07c",
-        "reference": "e58bd52830f83689ee641feee3a42e03a1a3b07c",
+        "url": "https://api.github.com/repos/symplify/composer-json-manipulator/zipball/a3d711ec0928cf8ddf3e4c16dad335318d588679",
+        "reference": "a3d711ec0928cf8ddf3e4c16dad335318d588679",
         "shasum": ""
       },
       "require": {
         "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "symfony/config": "^5.3",
-        "symfony/dependency-injection": "^5.3",
-        "symfony/filesystem": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/package-builder": "^9.4.27",
-        "symplify/smart-file-system": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/config": "^4.4|^5.2",
+        "symfony/dependency-injection": "^5.2",
+        "symfony/filesystem": "^4.4|^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/package-builder": "^9.3.22",
+        "symplify/smart-file-system": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5"
@@ -6923,7 +6786,7 @@
       "type": "symfony-bundle",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -6935,7 +6798,7 @@
       "license": ["MIT"],
       "description": "Package to load, merge and save composer.json file(s)",
       "support": {
-        "source": "https://github.com/symplify/composer-json-manipulator/tree/9.4.27"
+        "source": "https://github.com/symplify/composer-json-manipulator/tree/v9.3.22"
       },
       "funding": [
         {
@@ -6947,67 +6810,37 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:26:22+00:00"
+      "time": "2021-06-10T09:28:23+00:00"
     },
     {
       "name": "symplify/console-package-builder",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/console-package-builder.git",
-        "reference": "90a58661c375d97c3deb8cb4b34b322c8151c205"
+        "reference": "14a0eeaed45b850e579ddd16913a5d74ec856f16"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/console-package-builder/zipball/90a58661c375d97c3deb8cb4b34b322c8151c205",
-        "reference": "90a58661c375d97c3deb8cb4b34b322c8151c205",
+        "url": "https://api.github.com/repos/symplify/console-package-builder/zipball/14a0eeaed45b850e579ddd16913a5d74ec856f16",
+        "reference": "14a0eeaed45b850e579ddd16913a5d74ec856f16",
         "shasum": ""
       },
       "require": {
-        "php": ">=8.0",
-        "symfony/console": "^5.3",
-        "symfony/dependency-injection": "^5.3",
-        "symplify/symplify-kernel": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/package-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/console": "^4.4|^5.2",
+        "symfony/dependency-injection": "^5.2",
+        "symplify/symplify-kernel": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5",
-        "symfony/http-kernel": "^5.3",
-        "symplify/package-builder": "^9.4.27"
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/package-builder": "^9.3.22"
       },
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7019,22 +6852,22 @@
       "license": ["MIT"],
       "description": "Package to speed up building command line applications",
       "support": {
-        "source": "https://github.com/symplify/console-package-builder/tree/9.4.27"
+        "source": "https://github.com/symplify/console-package-builder/tree/v9.3.22"
       },
-      "time": "2021-08-11T09:26:34+00:00"
+      "time": "2021-06-10T09:28:40+00:00"
     },
     {
       "name": "symplify/easy-coding-standard",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/easy-coding-standard.git",
-        "reference": "9a386709e9b01d404d7287d6d049a829b1a2fb94"
+        "reference": "7ada08f221241f513531588585e55f423100705d"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/9a386709e9b01d404d7287d6d049a829b1a2fb94",
-        "reference": "9a386709e9b01d404d7287d6d049a829b1a2fb94",
+        "url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/7ada08f221241f513531588585e55f423100705d",
+        "reference": "7ada08f221241f513531588585e55f423100705d",
         "shasum": ""
       },
       "require": {
@@ -7053,7 +6886,7 @@
       "license": ["MIT"],
       "description": "Prefixed scoped version of ECS package",
       "support": {
-        "source": "https://github.com/symplify/easy-coding-standard/tree/9.4.27"
+        "source": "https://github.com/symplify/easy-coding-standard/tree/v9.3.22"
       },
       "funding": [
         {
@@ -7065,60 +6898,33 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:30:16+00:00"
+      "time": "2021-06-10T09:29:11+00:00"
     },
     {
       "name": "symplify/easy-testing",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/easy-testing.git",
-        "reference": "7c0b0f73296129d900c88c1379865fadc18fc653"
+        "reference": "6d5543190c9d578b61d9181d77d7255340743929"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/easy-testing/zipball/7c0b0f73296129d900c88c1379865fadc18fc653",
-        "reference": "7c0b0f73296129d900c88c1379865fadc18fc653",
+        "url": "https://api.github.com/repos/symplify/easy-testing/zipball/6d5543190c9d578b61d9181d77d7255340743929",
+        "reference": "6d5543190c9d578b61d9181d77d7255340743929",
         "shasum": ""
       },
       "require": {
         "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "symfony/console": "^5.3",
-        "symfony/dependency-injection": "^5.3",
-        "symfony/finder": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/console-package-builder": "^9.4.27",
-        "symplify/package-builder": "^9.4.27",
-        "symplify/smart-file-system": "^9.4.27",
-        "symplify/symplify-kernel": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/console": "^4.4|^5.2",
+        "symfony/dependency-injection": "^5.2",
+        "symfony/finder": "^4.4|^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/console-package-builder": "^9.3.22",
+        "symplify/package-builder": "^9.3.22",
+        "symplify/smart-file-system": "^9.3.22",
+        "symplify/symplify-kernel": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5"
@@ -7127,7 +6933,7 @@
       "type": "symfony-bundle",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7139,7 +6945,7 @@
       "license": ["MIT"],
       "description": "Testing made easy",
       "support": {
-        "source": "https://github.com/symplify/easy-testing/tree/9.4.27"
+        "source": "https://github.com/symplify/easy-testing/tree/v9.3.22"
       },
       "funding": [
         {
@@ -7151,70 +6957,42 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:26:46+00:00"
+      "time": "2021-06-10T09:28:48+00:00"
     },
     {
       "name": "symplify/package-builder",
-      "version": "9.4.27",
+      "version": "dev-main",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/package-builder.git",
-        "reference": "7741c38ef6b4665c2692452b1668e14e19e331c6"
+        "reference": "a86c7bd0307ba0b368510851e86082f773e64138"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/package-builder/zipball/7741c38ef6b4665c2692452b1668e14e19e331c6",
-        "reference": "7741c38ef6b4665c2692452b1668e14e19e331c6",
+        "url": "https://api.github.com/repos/symplify/package-builder/zipball/a86c7bd0307ba0b368510851e86082f773e64138",
+        "reference": "a86c7bd0307ba0b368510851e86082f773e64138",
         "shasum": ""
       },
       "require": {
         "nette/neon": "^3.2",
         "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "symfony/config": "^5.3",
-        "symfony/console": "^5.3",
-        "symfony/dependency-injection": "^5.3",
-        "symfony/finder": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/easy-testing": "^9.4.27",
-        "symplify/symplify-kernel": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/config": "^4.4|^5.2",
+        "symfony/console": "^4.4|^5.2",
+        "symfony/dependency-injection": "^5.2",
+        "symfony/finder": "^4.4|^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/easy-testing": "^9.3.22",
+        "symplify/symplify-kernel": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5"
       },
+      "default-branch": true,
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7226,7 +7004,7 @@
       "license": ["MIT"],
       "description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.",
       "support": {
-        "source": "https://github.com/symplify/package-builder/tree/9.4.27"
+        "source": "https://github.com/symplify/package-builder/tree/main"
       },
       "funding": [
         {
@@ -7238,56 +7016,28 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:26:56+00:00"
+      "time": "2021-06-10T09:30:06+00:00"
     },
     {
       "name": "symplify/phpstan-extensions",
-      "version": "9.4.27",
+      "version": "v9.3.21",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/phpstan-extensions.git",
-        "reference": "5f7a302039a4c2d3bf03b602d39b8dcc56dc6b7e"
+        "reference": "e9c83ac50fe205f28bece8013d92f5a9130dc3d6"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/phpstan-extensions/zipball/5f7a302039a4c2d3bf03b602d39b8dcc56dc6b7e",
-        "reference": "5f7a302039a4c2d3bf03b602d39b8dcc56dc6b7e",
+        "url": "https://api.github.com/repos/symplify/phpstan-extensions/zipball/e9c83ac50fe205f28bece8013d92f5a9130dc3d6",
+        "reference": "e9c83ac50fe205f28bece8013d92f5a9130dc3d6",
         "shasum": ""
       },
       "require": {
-        "php": ">=8.0",
-        "phpstan/phpstan": "^0.12.91",
-        "symplify/astral": "^9.4.27",
-        "symplify/package-builder": "^9.4.27",
-        "symplify/smart-file-system": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "phpstan/phpstan": "^0.12.88",
+        "symplify/astral": "^9.3.21",
+        "symplify/package-builder": "^9.3.21",
+        "symplify/smart-file-system": "^9.3.21"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5"
@@ -7295,7 +7045,7 @@
       "type": "phpstan-extension",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         },
         "phpstan": {
           "includes": ["config/config.neon"]
@@ -7310,7 +7060,7 @@
       "license": ["MIT"],
       "description": "Pre-escaped error messages in 'symplify' error format, container aware test case and other useful extensions for PHPStan",
       "support": {
-        "source": "https://github.com/symplify/phpstan-extensions/tree/9.4.27"
+        "source": "https://github.com/symplify/phpstan-extensions/tree/v9.3.21"
       },
       "funding": [
         {
@@ -7322,74 +7072,49 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:27:21+00:00"
+      "time": "2021-06-10T08:50:09+00:00"
     },
     {
       "name": "symplify/phpstan-rules",
-      "version": "9.4.27",
+      "version": "v9.3.21",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/phpstan-rules.git",
-        "reference": "4e6cd3f802f09b60856b9d4a7765a6097f5e64d1"
+        "reference": "1fac85aa8621e29af083b49c71d8ce793ca4dd46"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/phpstan-rules/zipball/4e6cd3f802f09b60856b9d4a7765a6097f5e64d1",
-        "reference": "4e6cd3f802f09b60856b9d4a7765a6097f5e64d1",
+        "url": "https://api.github.com/repos/symplify/phpstan-rules/zipball/1fac85aa8621e29af083b49c71d8ce793ca4dd46",
+        "reference": "1fac85aa8621e29af083b49c71d8ce793ca4dd46",
         "shasum": ""
       },
       "require": {
         "nette/utils": "^3.2",
-        "nikic/php-parser": "^4.11",
-        "php": ">=8.0",
+        "nikic/php-parser": "4.10.5",
+        "php": ">=7.3",
         "phpstan/phpdoc-parser": "^0.5",
-        "phpstan/phpstan": "^0.12.91",
-        "symplify/astral": "^9.4.27",
-        "symplify/composer-json-manipulator": "^9.4.27",
-        "symplify/package-builder": "^9.4.27",
-        "symplify/rule-doc-generator-contracts": "^9.4.27",
-        "symplify/simple-php-doc-parser": "^9.4.27",
-        "symplify/smart-file-system": "^9.4.27",
-        "webmozart/assert": "^1.10"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "phpstan/phpstan": "^0.12.88",
+        "symplify/astral": "^9.3.21",
+        "symplify/composer-json-manipulator": "^9.3.21",
+        "symplify/package-builder": "^9.3.21",
+        "symplify/rule-doc-generator-contracts": "^9.3.21",
+        "symplify/simple-php-doc-parser": "^9.3.21",
+        "symplify/smart-file-system": "^9.3.21",
+        "webmozart/assert": "^1.9"
       },
       "require-dev": {
         "nette/application": "^3.1",
         "nette/forms": "^3.1",
         "phpunit/phpunit": "^9.5",
-        "symfony/framework-bundle": "^5.3",
-        "symplify/easy-testing": "^9.4.27",
-        "symplify/phpstan-extensions": "^9.4.27",
-        "symplify/rule-doc-generator": "^9.4.27"
+        "symfony/framework-bundle": "^4.4|^5.2",
+        "symplify/easy-testing": "^9.3.21",
+        "symplify/phpstan-extensions": "^9.3.21",
+        "symplify/rule-doc-generator": "^9.3.21"
       },
       "type": "phpstan-extension",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         },
         "phpstan": {
           "includes": [
@@ -7410,7 +7135,7 @@
       "license": ["MIT"],
       "description": "Set of Symplify rules for PHPStan",
       "support": {
-        "source": "https://github.com/symplify/phpstan-rules/tree/9.4.27"
+        "source": "https://github.com/symplify/phpstan-rules/tree/v9.3.21"
       },
       "funding": [
         {
@@ -7422,62 +7147,31 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:27:20+00:00"
+      "time": "2021-06-10T08:50:10+00:00"
     },
     {
       "name": "symplify/rule-doc-generator-contracts",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/rule-doc-generator-contracts.git",
-        "reference": "ce95243b6907ab5bf5d7190b426c4e47e8397254"
+        "reference": "a6f944a49198ed3260bc941533629e917137e476"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/rule-doc-generator-contracts/zipball/ce95243b6907ab5bf5d7190b426c4e47e8397254",
-        "reference": "ce95243b6907ab5bf5d7190b426c4e47e8397254",
+        "url": "https://api.github.com/repos/symplify/rule-doc-generator-contracts/zipball/a6f944a49198ed3260bc941533629e917137e476",
+        "reference": "a6f944a49198ed3260bc941533629e917137e476",
         "shasum": ""
       },
       "require": {
         "danielstjules/stringy": "^3.1",
         "nette/utils": "^3.2",
-        "php": ">=8.0"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/package-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3"
       },
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7489,7 +7183,7 @@
       "license": ["MIT"],
       "description": "Contracts for production code of RuleDocGenerator",
       "support": {
-        "source": "https://github.com/symplify/rule-doc-generator-contracts/tree/9.4.27"
+        "source": "https://github.com/symplify/rule-doc-generator-contracts/tree/v9.3.22"
       },
       "funding": [
         {
@@ -7501,68 +7195,38 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:27:35+00:00"
+      "time": "2021-06-06T16:17:29+00:00"
     },
     {
       "name": "symplify/simple-php-doc-parser",
-      "version": "9.4.27",
+      "version": "v9.3.21",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/simple-php-doc-parser.git",
-        "reference": "823e8653f4fe39b310d1e5b267ab66c707ef5c8c"
+        "reference": "5668608067a6ee4f0513348bdb46319617288ce1"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/simple-php-doc-parser/zipball/823e8653f4fe39b310d1e5b267ab66c707ef5c8c",
-        "reference": "823e8653f4fe39b310d1e5b267ab66c707ef5c8c",
+        "url": "https://api.github.com/repos/symplify/simple-php-doc-parser/zipball/5668608067a6ee4f0513348bdb46319617288ce1",
+        "reference": "5668608067a6ee4f0513348bdb46319617288ce1",
         "shasum": ""
       },
       "require": {
-        "php": ">=8.0",
+        "php": ">=7.3",
         "phpstan/phpdoc-parser": "^0.5",
-        "symfony/config": "^5.3",
-        "symfony/dependency-injection": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/package-builder": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/smart-file-system": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "symfony/config": "^4.4|^5.2",
+        "symfony/dependency-injection": "^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/package-builder": "^9.3.21"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5",
-        "symplify/easy-testing": "^9.4.27"
+        "symplify/easy-testing": "^9.3.21"
       },
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7574,7 +7238,7 @@
       "license": ["MIT"],
       "description": "Service integration of phpstan/phpdoc-parser, with few extra goodies for practical simple use",
       "support": {
-        "source": "https://github.com/symplify/simple-php-doc-parser/tree/9.4.27"
+        "source": "https://github.com/symplify/simple-php-doc-parser/tree/v9.3.21"
       },
       "funding": [
         {
@@ -7586,58 +7250,27 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:27:31+00:00"
+      "time": "2021-06-10T08:50:34+00:00"
     },
     {
       "name": "symplify/smart-file-system",
-      "version": "9.4.27",
+      "version": "v9.3.22",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/smart-file-system.git",
-        "reference": "916987b19230dd416075183f56bc4dde473b2038"
+        "reference": "a2a8d39fe46b01ead8d2af7368b0b36b68fac979"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/916987b19230dd416075183f56bc4dde473b2038",
-        "reference": "916987b19230dd416075183f56bc4dde473b2038",
+        "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/a2a8d39fe46b01ead8d2af7368b0b36b68fac979",
+        "reference": "a2a8d39fe46b01ead8d2af7368b0b36b68fac979",
         "shasum": ""
       },
       "require": {
         "nette/utils": "^3.2",
-        "php": ">=8.0",
-        "symfony/filesystem": "^5.3",
-        "symfony/finder": "^5.3"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/autowire-array-parameter": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/composer-json-manipulator": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/package-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/symplify-kernel": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/filesystem": "^4.4|^5.2",
+        "symfony/finder": "^4.4|^5.2"
       },
       "require-dev": {
         "nette/finder": "^2.5",
@@ -7646,7 +7279,7 @@
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7658,7 +7291,7 @@
       "license": ["MIT"],
       "description": "Sanitized FileInfo with safe getRealPath() and other handy methods",
       "support": {
-        "source": "https://github.com/symplify/smart-file-system/tree/9.4.27"
+        "source": "https://github.com/symplify/smart-file-system/tree/v9.3.22"
       },
       "funding": [
         {
@@ -7670,66 +7303,40 @@
           "type": "github"
         }
       ],
-      "time": "2021-08-11T09:27:38+00:00"
+      "time": "2021-05-20T20:16:49+00:00"
     },
     {
       "name": "symplify/symplify-kernel",
-      "version": "9.4.27",
+      "version": "dev-main",
       "source": {
         "type": "git",
         "url": "https://github.com/symplify/symplify-kernel.git",
-        "reference": "199dfc5ca3a1c4e2237a619e03aa4a970fff81d9"
+        "reference": "966602555962ef929214be2459bfeef3d0ceb114"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/symplify/symplify-kernel/zipball/199dfc5ca3a1c4e2237a619e03aa4a970fff81d9",
-        "reference": "199dfc5ca3a1c4e2237a619e03aa4a970fff81d9",
+        "url": "https://api.github.com/repos/symplify/symplify-kernel/zipball/966602555962ef929214be2459bfeef3d0ceb114",
+        "reference": "966602555962ef929214be2459bfeef3d0ceb114",
         "shasum": ""
       },
       "require": {
-        "php": ">=8.0",
-        "symfony/console": "^5.3",
-        "symfony/dependency-injection": "^5.3",
-        "symfony/http-kernel": "^5.3",
-        "symplify/autowire-array-parameter": "^9.4.27",
-        "symplify/composer-json-manipulator": "^9.4.27",
-        "symplify/package-builder": "^9.4.27",
-        "symplify/smart-file-system": "^9.4.27"
-      },
-      "conflict": {
-        "symplify/amnesia": "<9.4.27",
-        "symplify/astral": "<9.4.27",
-        "symplify/coding-standard": "<9.4.27",
-        "symplify/config-transformer": "<9.4.27",
-        "symplify/console-color-diff": "<9.4.27",
-        "symplify/console-package-builder": "<9.4.27",
-        "symplify/easy-ci": "<9.4.27",
-        "symplify/easy-coding-standard": "<9.4.27",
-        "symplify/easy-hydrator": "<9.4.27",
-        "symplify/easy-testing": "<9.4.27",
-        "symplify/git-wrapper": "<9.4.27",
-        "symplify/markdown-diff": "<9.4.27",
-        "symplify/monorepo-builder": "<9.4.27",
-        "symplify/php-config-printer": "<9.4.27",
-        "symplify/phpstan-extensions": "<9.4.27",
-        "symplify/phpstan-rules": "<9.4.27",
-        "symplify/phpunit-upgrader": "<9.4.27",
-        "symplify/psr4-switcher": "<9.4.27",
-        "symplify/rule-doc-generator": "<9.4.27",
-        "symplify/rule-doc-generator-contracts": "<9.4.27",
-        "symplify/simple-php-doc-parser": "<9.4.27",
-        "symplify/skipper": "<9.4.27",
-        "symplify/symfony-php-config": "<9.4.27",
-        "symplify/symfony-static-dumper": "<9.4.27",
-        "symplify/vendor-patches": "<9.4.27"
+        "php": ">=7.3",
+        "symfony/console": "^4.4|^5.2",
+        "symfony/dependency-injection": "^5.2",
+        "symfony/http-kernel": "^4.4|^5.2",
+        "symplify/autowire-array-parameter": "^9.3.22",
+        "symplify/composer-json-manipulator": "^9.3.22",
+        "symplify/package-builder": "^9.3.22",
+        "symplify/smart-file-system": "^9.3.22"
       },
       "require-dev": {
         "phpunit/phpunit": "^9.5"
       },
+      "default-branch": true,
       "type": "library",
       "extra": {
         "branch-alias": {
-          "dev-main": "9.5-dev"
+          "dev-main": "9.4-dev"
         }
       },
       "autoload": {
@@ -7741,22 +7348,22 @@
       "license": ["MIT"],
       "description": "Internal Kernel for Symplify packages",
       "support": {
-        "source": "https://github.com/symplify/symplify-kernel/tree/9.4.27"
+        "source": "https://github.com/symplify/symplify-kernel/tree/main"
       },
-      "time": "2021-08-11T09:27:56+00:00"
+      "time": "2021-06-10T09:29:50+00:00"
     },
     {
       "name": "theseer/tokenizer",
-      "version": "1.2.1",
+      "version": "1.2.0",
       "source": {
         "type": "git",
         "url": "https://github.com/theseer/tokenizer.git",
-        "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
+        "reference": "75a63c33a8577608444246075ea0af0d052e452a"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
-        "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
+        "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a",
+        "reference": "75a63c33a8577608444246075ea0af0d052e452a",
         "shasum": ""
       },
       "require": {
@@ -7781,7 +7388,7 @@
       "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
       "support": {
         "issues": "https://github.com/theseer/tokenizer/issues",
-        "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
+        "source": "https://github.com/theseer/tokenizer/tree/master"
       },
       "funding": [
         {
@@ -7789,7 +7396,7 @@
           "type": "github"
         }
       ],
-      "time": "2021-07-28T10:34:58+00:00"
+      "time": "2020-07-12T23:59:07+00:00"
     },
     {
       "name": "webmozart/assert",
@@ -7858,5 +7465,5 @@
     "php": "^8.0"
   },
   "platform-dev": [],
-  "plugin-api-version": "2.1.0"
+  "plugin-api-version": "2.0.0"
 }
diff --git a/ecs.php b/ecs.php
index 8d32e4f9a8..c60598aa19 100644
--- a/ecs.php
+++ b/ecs.php
@@ -22,10 +22,11 @@ return static function (ContainerConfigurator $containerConfigurator): void {
         __DIR__ . '/modules/**/Views/*',
 
         // skip specific generated files
-        __DIR__ . '/app/Language/*/PersonsTaxonomy.php',
+        __DIR__ . '/modules/Admin/Language/*/PersonsTaxonomy.php',
 
         StandardizeHereNowDocKeywordFixer::class => [
-            __DIR__ . '/app/Views/Components',
+            __DIR__ . '/app/View/Components',
+            __DIR__ . '/modules/**/View/Components',
         ]
     ]);
 
diff --git a/modules/Admin/Controllers/EpisodeController.php b/modules/Admin/Controllers/EpisodeController.php
index 47846cc999..5791a7c330 100644
--- a/modules/Admin/Controllers/EpisodeController.php
+++ b/modules/Admin/Controllers/EpisodeController.php
@@ -824,9 +824,6 @@ class EpisodeController extends BaseController
 
     public function attemptCommentReply(string $commentId): RedirectResponse
     {
-        // var_dump($commentId);
-        // die();
-
         $rules = [
             'message' => 'required|max_length[500]',
         ];
diff --git a/modules/Admin/Controllers/PodcastPlatformController.php b/modules/Admin/Controllers/PodcastPlatformController.php
index 568fc3810f..379a11abfe 100644
--- a/modules/Admin/Controllers/PodcastPlatformController.php
+++ b/modules/Admin/Controllers/PodcastPlatformController.php
@@ -55,7 +55,10 @@ class PodcastPlatformController extends BaseController
         replace_breadcrumb_params([
             0 => $this->podcast->title,
         ]);
-        return view('Modules\Admin\Views\podcast\platforms', $data);
+
+        $view = view('Modules\Admin\Views\podcast\platforms', $data);
+
+        return $view;
     }
 
     public function attemptPlatformsUpdate(string $platformType): RedirectResponse
diff --git a/app/Language/en/AdminNavigation.php b/modules/Admin/Language/en/AdminNavigation.php
similarity index 100%
rename from app/Language/en/AdminNavigation.php
rename to modules/Admin/Language/en/AdminNavigation.php
diff --git a/app/Language/fr/AdminNavigation.php b/modules/Admin/Language/fr/AdminNavigation.php
similarity index 100%
rename from app/Language/fr/AdminNavigation.php
rename to modules/Admin/Language/fr/AdminNavigation.php
diff --git a/modules/Admin/Views/contributor/add.php b/modules/Admin/Views/contributor/add.php
index cfaacfa4cf..4fbbf7c2f7 100644
--- a/modules/Admin/Views/contributor/add.php
+++ b/modules/Admin/Views/contributor/add.php
@@ -15,8 +15,8 @@
     'class' => 'flex flex-col max-w-sm',
 ]) ?>
 <?= csrf_field() ?>
-    
-<?= component('Forms/Label', ['text' => lang('Contributor.form.user')], ['for' => 'user']) ?>
+
+<Forms.Label for="user"><?= lang('Contributor.form.user') ?></Forms.Label>
 <?= form_dropdown('user', $userOptions, [old('user', '')], [
     'id' => 'user',
     'class' => 'form-select mb-4',
@@ -24,7 +24,7 @@
     'placeholder' => lang('Contributor.form.user_placeholder')
 ]) ?>
 
-<?= component('Forms/Label', ['text' => lang('Contributor.form.role')], ['for' => 'role']) ?>
+<Forms.Label for="role"><?= lang('Contributor.form.role') ?></Forms.Label>
 <?= form_dropdown('role', $roleOptions, [old('role', '')], [
     'id' => 'role',
     'class' => 'form-select mb-4',
diff --git a/modules/Admin/Views/contributor/edit.php b/modules/Admin/Views/contributor/edit.php
index 70c6602b62..b49818e079 100644
--- a/modules/Admin/Views/contributor/edit.php
+++ b/modules/Admin/Views/contributor/edit.php
@@ -16,7 +16,7 @@
 ]) ?>
 <?= csrf_field() ?>
 
-<?= component('Forms/Label', ['text' => lang('Contributor.form.role')], ['for' => 'role']) ?>
+<Forms.Label for="role"><?= lang('Contributor.form.role') ?></Forms.Label>
 <?= form_dropdown('role', $roleOptions, [old('role', $contributorGroupId)], [
     'id' => 'role',
     'class' => 'form-select mb-4',
diff --git a/modules/Admin/Views/episode/create.php b/modules/Admin/Views/episode/create.php
index 6fde6539ba..b6bae04860 100644
--- a/modules/Admin/Views/episode/create.php
+++ b/modules/Admin/Views/episode/create.php
@@ -28,11 +28,7 @@
     lang('Episode.form.info_section_subtitle'),
 ) ?>
 
-<?= component(
-    'Forms/Label',
-    ['text' => lang('Episode.form.audio_file'), 'hint' => lang('Episode.form.audio_file_hint')],
-    ['for' => 'audio_file'],
-) ?>
+<Forms.Label for="audio_file" hint="<?= lang('Episode.form.audio_file_hint') ?>"><?= lang('Episode.form.audio_file') ?></Forms.Label>
 <?= form_input([
     'id' => 'audio_file',
     'name' => 'audio_file',
@@ -42,15 +38,7 @@
     'accept' => '.mp3,.m4a',
 ]) ?>
 
-<?= component(
-    'Forms/Label',
-    [   
-        'text' => lang('Episode.form.image'),
-        'hint' => lang('Episode.form.image_hint'),
-        'isOptional' => true
-    ],
-    ['for' => 'image'],
-) ?>
+<Forms.Label for="image" hint="<?= lang('Episode.form.image_hint') ?>" isOptional="true"><?= lang('Episode.form.image') ?></Forms.Label>
 <?= form_input([
     'id' => 'image',
     'name' => 'image',
@@ -62,12 +50,7 @@
     'Common.forms.image_size_hint',
 ) ?></small>
 
-<?= component(
-    'Forms/Label',
-    ['text' => lang('Episode.form.title'),
-     'hint' => lang('Episode.form.title_hint')],
-    ['for' => 'title'],
-) ?>
+<Forms.Label for="title" hint="<?= lang('Episode.form.title_hint') ?>"><?= lang('Episode.form.title') ?></Forms.Label>
 <?= form_input([
     'id' => 'title',
     'name' => 'title',
@@ -77,11 +60,7 @@
     'data-slugify' => 'title',
 ]) ?>
 
-<?= component(
-    'Forms/Label',
-    ['text' => lang('Episode.form.permalink')],
-    ['for' => 'slug']
-) ?>
+<Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></Forms.Label>
 <permalink-edit class="inline-flex items-center mb-4 text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>">
     <span slot="domain"><?= base_url('/@'. $podcast->handle . '/episodes' ) . '/' ?></span>
     <?= form_input([
@@ -97,7 +76,7 @@
 
 <div class="flex flex-col mb-4 gap-x-2 gap-y-4 md:flex-row">
     <div class="flex flex-col flex-1">
-        <?= component('Forms/Label', ['text' => lang('Episode.form.season_number')], ['for' => 'season_number']) ?>
+        <Forms.Label for="season_number"><?= lang('Episode.form.season_number') ?></Forms.Label>
         <?= form_input([
             'id' => 'season_number',
             'name' => 'season_number',
@@ -107,7 +86,7 @@
         ]) ?>
     </div>
     <div class="flex flex-col flex-1">
-        <?= component('Forms/Label', ['text' => lang('Episode.form.episode_number')], ['for' => 'episode_number']) ?>
+        <Forms.Label for="episode_number"><?= lang('Episode.form.episode_number') ?></Forms.Label>
         <?= form_input([
             'id' => 'episode_number',
             'name' => 'episode_number',
@@ -204,46 +183,13 @@
 ) ?>
 
 <div class="mb-4">
-    <?= component('Forms/Label', ['text' => lang('Episode.form.description')], ['for' => 'description']) ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old('description', '', false),
-        ],
-        [
-            'id' => 'description',
-            'name' => 'description',
-            'required' => 'required',
-        ],
-    ) ?>
+    <Forms.Label for="description"><?= lang('Episode.form.description') ?></Forms.Label>
+    <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', '', false) ?></Forms.MarkdownEditor>
 </div>
 
 <div class="mb-4">
-    <?= component( 'Forms/Label',
-    [
-        'text' => lang('Episode.form.description_footer'),
-        'hint' =>  lang('Episode.form.description_footer_hint'),
-        'isOptional' => true
-    ],
-    [
-        'for' => 'description_footer'
-    ],
-    ) ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old(
-                'description_footer',
-                $podcast->episode_description_footer_markdown ?? '',
-                false,
-            ),
-        ],
-        [
-            'id' => 'description_footer',
-            'name' => 'description_footer',
-            'rows' => 6
-        ],
-    ) ?>
+    <Forms.Label for="description_footer" hint="<?= lang('Episode.form.description_footer_hint') ?>" isOptional="true"><?= lang('Episode.form.description_footer') ?></Forms.Label>
+    <Forms.MarkdownEditor id="description_footer" name="description_footer" rows="6"><?= old('description_footer', $podcast->episode_description_footer_markdown ?? '', false) ?></Forms.MarkdownEditor>
 </div>
 
 <?= form_section_close() ?>
@@ -253,14 +199,7 @@
     lang('Episode.form.location_section_subtitle'),
 ) ?>
 
-<?= component( 'Forms/Label',
-    [
-        'text' => lang('Episode.form.location_name'),
-        'hint' => lang('Episode.form.location_name_hint'),
-        'isOptional' => true
-    ],
-    ['for' => 'location_name'],
-) ?>
+<Forms.Label for="location_name" hint="<?= lang('Episode.form.location_name_hint') ?>" isOptional="true"><?= lang('Episode.form.location_name') ?></Forms.Label>
 <?= form_input([
     'id' => 'location_name',
     'name' => 'location_name',
@@ -301,13 +240,7 @@
 
         <div class="py-2 tab-panels">
             <section id="transcript-file-upload" class="flex items-center tab-panel">
-            <?= component( 'Forms/Label',
-                [
-                    'text' => lang('Episode.form.transcript_file'),
-                    'isOptional' => true    
-                ],
-                ['for' => 'transcript_file', 'class' => 'sr-only'],
-            ) ?>
+            <Forms.Label class="sr-only" for="transcript_file" isOptional="true"><?= lang('Episode.form.transcript_file') ?></Forms.Label>
             <?= form_input([
                 'id' => 'transcript_file',
                 'name' => 'transcript_file',
@@ -317,13 +250,7 @@
             ]) ?>
             </section>
             <section id="transcript-file-remote-url" class="tab-panel">
-            <?= component( 'Forms/Label',
-                [
-                    'text' => lang('Episode.form.transcript_file_remote_url'),
-                    'isOptional' => true
-                ],
-                ['for' => 'transcript_file_remote_url', 'class' => 'sr-only'],
-            ) ?>
+            <Forms.Label class="sr-only" for="transcript_file_remote_url" isOptional="true"><?= lang('Episode.form.transcript_file_remote_url') ?></Forms.Label>
             <?= form_input([
                 'id' => 'transcript_file_remote_url',
                 'name' => 'transcript_file_remote_url',
@@ -364,13 +291,7 @@
 
         <div class="py-2 tab-panels">
             <section id="chapters-file-upload" class="flex items-center tab-panel">
-            <?= component( 'Forms/Label',
-                [
-                    'text' => lang('Episode.form.chapters_file'),
-                    'isOptional' => true
-                ],
-                ['for' => 'chapters_file', 'class' => 'sr-only'],
-            ) ?>
+            <Forms.Label class="sr-only" for="chapters_file" isOptional="true"><?= lang('Episode.form.chapters_file') ?></Forms.Label>
             <?= form_input([
                 'id' => 'chapters_file',
                 'name' => 'chapters_file',
@@ -380,16 +301,7 @@
             ]) ?>
             </section>
             <section id="chapters-file-remote-url" class="tab-panel">
-            <?= component( 'Forms/Label',
-                [
-                    'text' =>  lang('Episode.form.chapters_file_remote_url'),
-                    'isOptional' => true
-                ],
-                [
-                    'for' => 'chapters_file_remote_url',
-                    'class' => 'sr-only'
-                ],
-            ) ?>
+            <Forms.Label class="sr-only" for="chapters_file_remote_url" isOptional="true"><?= lang('Episode.form.chapters_file_remote_url') ?></Forms.Label>
             <?= form_input([
                 'id' => 'chapters_file_remote_url',
                 'name' => 'chapters_file_remote_url',
@@ -409,38 +321,12 @@
     lang('Episode.form.advanced_section_title'),
     lang('Episode.form.advanced_section_subtitle'),
 ) ?>
-<?= component( 'Forms/Label',
-    [
-        'text' => lang('Episode.form.custom_rss'),
-    'hint' => lang('Episode.form.custom_rss_hint'),
-    'isOptional' => true
-    ],
-    ['for' => 'custom_rss']
-) ?>
-<?= component('Forms/XMLEditor',
-    [
-        'content' => old('custom_rss', '')
-    ],
-    [
-        'id' => 'custom_rss',
-        'name' => 'custom_rss',
-    ]
-) ?>
+<Forms.Label for="custom_rss" hint="<?= lang('Episode.form.custom_rss_hint') ?>" isOptional="true"><?= lang('Episode.form.custom_rss') ?></Forms.Label>
+<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', '', false) ?></Forms.XMLEditor>
+
 <?= form_section_close() ?>
 
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Episode.form.block'),
-        'hint' => lang('Episode.form.block_hint')
-    ],
-    [
-        'id' => 'block',
-        'name' => 'block',
-        'value' => 'yes',
-        'checked' => old('block', false),
-    ]
-) ?>
+<Forms.Toggler id="block" name="block" value="yes" checked="<?= old('block', false) ?>" hint="<?= lang('Episode.form.block_hint') ?>"><?= lang('Episode.form.block') ?></Forms.Toggler>
 
 <?= button(
     lang('Episode.form.submit_create'),
diff --git a/modules/Admin/Views/episode/edit.php b/modules/Admin/Views/episode/edit.php
index aba8c96bd0..051968d224 100644
--- a/modules/Admin/Views/episode/edit.php
+++ b/modules/Admin/Views/episode/edit.php
@@ -35,12 +35,7 @@
 />',
 ) ?>
 
-<?= component(
-    'Forms/Label',
-    ['text' =>
-    lang('Episode.form.audio_file'), 'hint' => lang('Episode.form.audio_file_hint'),],
-    ['for' => 'audio_file'],
-) ?>
+<Forms.Label for="audio_file" hint="<?= lang('Episode.form.audio_file_hint') ?>"><?= lang('Episode.form.audio_file') ?></Forms.Label>
 <?= form_input([
     'id' => 'audio_file',
     'name' => 'audio_file',
@@ -49,14 +44,7 @@
     'accept' => '.mp3,.m4a',
 ]) ?>
 
-<?= component(
-    'Forms/Label',
-    ['text' =>
-    lang('Episode.form.image'), 'hint' => lang('Episode.form.image_hint'), 'isOptional' =>     true,],
-    ['for' =>
-    'image',]
-) ?>
-
+<Forms.Label for="image" hint="<?= lang('Episode.form.image_hint') ?>" isOptional="true"><?= lang('Episode.form.image') ?></Forms.Label>
 <?= form_input([
     'id' => 'image',
     'name' => 'image',
@@ -68,13 +56,7 @@
     'Common.forms.image_size_hint',
 ) ?></small>
 
-<?= component(
-    'Forms/Label',
-    ['text' =>
-    lang('Episode.form.title'), 'hint' => lang('Episode.form.title_hint'),],
-    ['for' =>
-    'title',]
-) ?>
+<Forms.Label for="title" hint="<?= lang('Episode.form.title_hint') ?>"><?= lang('Episode.form.title') ?></Forms.Label>
 <?= form_input([
     'id' => 'title',
     'name' => 'title',
@@ -84,13 +66,7 @@
     'data-slugify' => 'title',
 ]) ?>
 
-<?= component(
-    'Forms/Label',
-    [
-        'text' => lang('Episode.form.permalink')
-    ],
-    ['for' => 'slug',]
-) ?>
+<Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></Forms.Label>
 <permalink-edit class="inline-flex items-center mb-4 text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>">
     <span slot="domain"><?= base_url('/@' . $podcast->handle . '/episodes') . '/' ?></span>
     <?= form_input([
@@ -106,7 +82,7 @@
 
 <div class="flex flex-col mb-4 gap-x-2 gap-y-4 md:flex-row">
     <div class="flex flex-col flex-1">
-        <?= component('Forms/Label', ['text' => lang('Episode.form.season_number')], ['for' => 'season_number']) ?>
+        <Forms.Label for="season_number"><?= lang('Episode.form.season_number') ?></Forms.Label>
         <?= form_input([
             'id' => 'season_number',
             'name' => 'season_number',
@@ -116,7 +92,7 @@
         ]) ?>
     </div>
     <div class="flex flex-col flex-1">
-        <?= component('Forms/Label', ['text' => lang('Episode.form.episode_number')], ['for' => 'episode_number']) ?>
+        <Forms.Label for="episode_number"><?= lang('Episode.form.episode_number') ?></Forms.Label>
         <?= form_input([
             'id' => 'episode_number',
             'name' => 'episode_number',
@@ -216,44 +192,13 @@
 ) ?>
 
 <div class="mb-4">
-    <?= component('Forms/Label', ['text' => lang('Episode.form.description')], ['for' => 'description']) ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old('description', $episode->description_markdown, false),
-        ],
-        [
-            'id' => 'description',
-            'name' => 'description',
-            'required' => 'required',
-        ],
-    ) ?>
+    <Forms.Label for="description"><?= lang('Episode.form.description') ?></Forms.Label>
+    <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', $episode->description_markdown, false) ?></Forms.MarkdownEditor>
 </div>
 
 <div class="mb-4">
-    <?= component('Forms/Label', 
-        [
-            'text' => lang('Episode.form.description_footer'),
-            'hint' => lang('Episode.form.description_footer_hint'),
-            'isOptional' => true
-        ],
-        ['for' => 'description_footer'],
-    ) ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old(
-                'description_footer',
-                $podcast->episode_description_footer_markdown ?? '',
-                false,
-            ),
-        ],
-        [
-            'id' => 'description_footer',
-            'name' => 'description_footer',
-            'rows' => 6
-        ],
-    ) ?>
+    <Forms.Label for="description_footer" hint="<?= lang('Episode.form.description_footer_hint') ?>" isOptional="true"><?= lang('Episode.form.description_footer') ?></Forms.Label>
+    <Forms.MarkdownEditor id="description_footer" name="description_footer" rows="6"><?= old('description_footer', $podcast->episode_description_footer_markdown ?? '', false) ?></Forms.MarkdownEditor>
 </div>
 
 <?= form_section_close() ?>
@@ -263,14 +208,7 @@
     lang('Episode.form.location_section_subtitle'),
 ) ?>
 
-<?= component('Forms/Label',
-    [
-        'text' => lang('Episode.form.location_name'),
-        'hint' => lang('Episode.form.location_name_hint'),
-        'isOptional' => true
-    ],
-    ['for' => 'location_name']
-) ?>
+<Forms.Label for="location_name" hint="<?= lang('Episode.form.location_name_hint') ?>" isOptional="true"><?= lang('Episode.form.location_name') ?></Forms.Label>
 <?= form_input([
     'id' => 'location_name',
     'name' => 'location_name',
@@ -342,13 +280,7 @@
                         ) ?>
                 </div>
             <?php endif; ?>
-            <?= component( 'Forms/Label',
-                [
-                    'text' => lang('Episode.form.transcript_file'),
-                    'isOptional' => true    
-                ],
-                ['for' => 'transcript_file', 'class' => 'sr-only'],
-            ) ?>
+            <Forms.Label class="sr-only" for="transcript_file" isOptional="true"><?= lang('Episode.form.transcript_file') ?></Forms.Label>
             <?= form_input([
                 'id' => 'transcript_file',
                 'name' => 'transcript_file',
@@ -358,13 +290,7 @@
             ]) ?>
         </section>
         <section id="transcript-file-remote-url" class="tab-panel">
-            <?= component( 'Forms/Label',
-                [
-                    'text' => lang('Episode.form.transcript_file_remote_url'),
-                    'isOptional' => true
-                ],
-                ['for' => 'transcript_file_remote_url', 'class' => 'sr-only'],
-            ) ?>
+            <Forms.Label class="sr-only" for="transcript_file_remote_url" isOptional="true"><?= lang('Episode.form.transcript_file_remote_url') ?></Forms.Label>
             <?= form_input([
                 'id' => 'transcript_file_remote_url',
                 'name' => 'transcript_file_remote_url',
@@ -434,13 +360,7 @@
                         ) ?>
                 </div>
             <?php endif; ?>
-            <?= component( 'Forms/Label',
-                [
-                    'text' => lang('Episode.form.chapters_file'),
-                    'isOptional' => true
-                ],
-                ['for' => 'chapters_file', 'class' => 'sr-only'],
-            ) ?>
+            <Forms.Label class="sr-only" for="chapters_file" isOptional="true"><?= lang('Episode.form.chapters_file') ?></Forms.Label>
             <?= form_input([
                 'id' => 'chapters_file',
                 'name' => 'chapters_file',
@@ -450,16 +370,7 @@
             ]) ?>
         </section>
         <section id="chapters-file-remote-url" class="tab-panel">
-        <?= component( 'Forms/Label',
-                [
-                    'text' =>  lang('Episode.form.chapters_file_remote_url'),
-                    'isOptional' => true
-                ],
-                [
-                    'for' => 'chapters_file_remote_url',
-                    'class' => 'sr-only'
-                ],
-            ) ?>
+            <Forms.Label class="sr-only" for="chapters_file_remote_url" isOptional="true"><?= lang('Episode.form.chapters_file_remote_url') ?></Forms.Label>
             <?= form_input([
                 'id' => 'chapters_file_remote_url',
                 'name' => 'chapters_file_remote_url',
@@ -482,40 +393,12 @@
     lang('Episode.form.advanced_section_title'),
     lang('Episode.form.advanced_section_subtitle'),
 ) ?>
-<?= component('Forms/Label', 
-    [
-        'text' => lang('Episode.form.custom_rss'),
-        'hint' => lang('Episode.form.custom_rss_hint'),
-        'isOptional' => true,
-    ],
-    [
-        'for' => 'custom_rss',
-    ]
-) ?>
-<?= component('Forms/XMLEditor',
-    [
-        'content' => old('custom_rss', $episode->custom_rss_string)
-    ],
-    [
-        'id' => 'custom_rss',
-        'name' => 'custom_rss',
-    ]
-) ?>
+<Forms.Label for="custom_rss" hint="<?= lang('Episode.form.custom_rss_hint') ?>" isOptional="true"><?= lang('Episode.form.custom_rss') ?></Forms.Label>
+<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', $episode->custom_rss_string, false) ?></Forms.XMLEditor>
+
 <?= form_section_close() ?>
 
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Episode.form.block'),
-        'hint' => lang('Episode.form.block_hint')
-    ],
-    [
-        'id' => 'block',
-        'name' => 'block',
-        'value' => 'yes',
-        'checked' => old('block', $episode->is_blocked),
-    ]
-) ?>
+<Forms.Toggler id="block" name="block" value="yes" checked="<?= old('block', $episode->is_blocked) ?>" hint="<?= lang('Episode.form.block_hint') ?>"><?= lang('Episode.form.block') ?></Forms.Toggler>
 
 <?= button(
     lang('Episode.form.submit_edit'),
diff --git a/modules/Admin/Views/episode/persons.php b/modules/Admin/Views/episode/persons.php
index fbf0c02201..aca39770c0 100644
--- a/modules/Admin/Views/episode/persons.php
+++ b/modules/Admin/Views/episode/persons.php
@@ -95,28 +95,11 @@
     lang('Person.episode_form.add_section_subtitle'),
 ) ?>
 
-<?= component(
-    'Forms/Label',
-    ['text' => lang('Person.episode_form.persons'), 'hint' =>     lang('Person.episode_form.persons_hint')],
-    ['for' => 'persons'],
-) ?>
-<?= component('Forms/MultiSelect', ['options' => $personOptions, 'selected' => old('persons', [])], [
-    'id' => 'persons',
-    'name' => 'persons[]',
-    'class' => 'mb-4',
-    'required' => 'required',
-]) ?>
+<Forms.Label for="persons" hint="<?= lang('Person.episode_form.persons_hint') ?>"><?= lang('Person.episode_form.persons') ?></Forms.Label>
+<Forms.MultiSelect id="persons" name="persons[]" class="mb-4" required="required" options="<?= htmlspecialchars(json_encode($personOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('persons', []))) ?>"/>
 
-<?= component(
-    'Forms/Label',
-    ['text' => lang('Person.episode_form.roles'), 'hint' =>     lang('Person.episode_form.roles_hint'), 'isOptional' => true],
-    ['for' => 'roles'],
-) ?>
-<?= component('Forms/MultiSelect', ['options' => $taxonomyOptions, 'selected' => old('roles', [])], [
-    'id' => 'roles',
-    'name' => 'roles[]',
-    'class' => 'mb-4',
-]) ?>
+<Forms.Label for="roles" hint="<?= lang('Person.episode_form.roles_hint') ?>" isOptional="true"><?= lang('Person.episode_form.roles') ?></Forms.Label>
+<Forms.MultiSelect id="roles" name="roles[]" class="mb-4" options="<?= htmlspecialchars(json_encode($taxonomyOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('roles', []))) ?>"/>
 
 <?= form_section_close() ?>
 <?= button(
diff --git a/modules/Admin/Views/episode/publish_edit.php b/modules/Admin/Views/episode/publish_edit.php
index d093ac9099..08cdb94dd9 100644
--- a/modules/Admin/Views/episode/publish_edit.php
+++ b/modules/Admin/Views/episode/publish_edit.php
@@ -189,4 +189,4 @@
 
 <?= form_close() ?>
 
-<?= $this->endSection() ?>
\ No newline at end of file
+<?= $this->endSection() ?>
diff --git a/modules/Admin/Views/page/create.php b/modules/Admin/Views/page/create.php
index 58769124fd..0fccd6b44b 100644
--- a/modules/Admin/Views/page/create.php
+++ b/modules/Admin/Views/page/create.php
@@ -46,18 +46,7 @@
 
 <div class="mb-4">
     <?= form_label(lang('Page.form.content'), 'content') ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old('content', '', false)
-        ],
-        [
-            'id' => 'content',
-            'name' => 'content',
-            'required' => 'required',
-            'rows' => 20
-        ],
-    ) ?>
+    <Forms.MarkdownEditor id="content" name="content" required="required" rows="20"><?= old('content', '', false) ?></Forms.MarkdownEditor>
 </div>
 
 
diff --git a/modules/Admin/Views/page/edit.php b/modules/Admin/Views/page/edit.php
index 5f2353fde3..d5ae383ae5 100644
--- a/modules/Admin/Views/page/edit.php
+++ b/modules/Admin/Views/page/edit.php
@@ -46,17 +46,7 @@
 
 <div class="mb-4">
     <?= form_label(lang('Page.form.content'), 'content') ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old('content', $page->content_markdown, false),
-        ],
-        [
-            'id' => 'content',
-            'name' => 'content',
-            'required' => 'required',
-        ],
-    ) ?>
+    <Forms.MarkdownEditor id="content" name="content" required="required"><?= old('content', $page->content_markdown, false) ?></Forms.MarkdownEditor>
 </div>
 
 <?= button(
diff --git a/modules/Admin/Views/podcast/create.php b/modules/Admin/Views/podcast/create.php
index c104803b65..ca5ec8f862 100644
--- a/modules/Admin/Views/podcast/create.php
+++ b/modules/Admin/Views/podcast/create.php
@@ -1,3 +1,6 @@
+<?php 
+?>
+
 <?= $this->extend('Modules\Admin\Views\_layout') ?>
 
 <?= $this->section('title') ?>
@@ -81,18 +84,8 @@
 <?= form_fieldset_close() ?>
 
 <div class="mb-4">
-    <?= form_label(lang('Podcast.form.description'), 'description') ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old('description', '', false),
-        ],
-        [
-            'id' => 'description',
-            'name' => 'description',
-            'required' => 'required',
-        ],
-    ) ?>
+    <Forms.Label for="description"><?= lang('Podcast.form.description') ?></Forms.Label>
+    <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', '', false) ?></Forms.MarkdownEditor>
 </div>
 
 <?= form_section_close() ?>
@@ -125,12 +118,13 @@
     '',
     true,
 ) ?>
-<?= component('Forms/MultiSelect', ['options' => $categoryOptions, 'selected' => old('other_categories', [])], [
-    'id' => 'other_categories',
-    'name' => 'other_categories[]',
-    'class' => 'mb-4',
-    'data-max-item-count' => '2',
-]) ?>
+<Forms.MultiSelect
+    id="other_categories"
+    name="other_categories[]"
+    class="mb-4"
+    data-max-item-count="2"
+    selected="<?= htmlspecialchars(json_encode(old('other_categories', []))) ?>"
+    options="<?= htmlspecialchars(json_encode($categoryOptions)) ?>" />
 
 <?= form_fieldset('', ['class' => 'mb-4']) ?>
     <legend>
@@ -339,15 +333,8 @@
     lang('Podcast.form.custom_rss_hint'),
     true,
 ) ?>
-<?= component('Forms/XMLEditor', 
-    [
-        'content' => old('custom_rss', '')
-    ],
-    [
-        'id' => 'custom_rss',
-        'name' => 'custom_rss',
-    ]
-) ?>
+<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', '', false) ?></Forms.XMLEditor>
+
 <?= form_section_close() ?>
 
 <?= form_section(
@@ -355,47 +342,15 @@
     lang('Podcast.form.status_section_subtitle'),
 ) ?>
 
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Podcast.form.lock'),
-        'hint' => lang('Podcast.form.lock_hint'),
-    ],
-    [
-        'id' => 'lock',
-        'name' => 'lock',
-        'value' => 'yes',
-        'checked' => old('complete', true),
-        'class' => 'mb-2'
-    ]
-) ?>
-
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Podcast.form.block'),
-    ],
-    [
-        'id' => 'block',
-        'name' => 'block',
-        'value' => 'yes',
-        'checked' => old('block', false),
-        'class' => 'mb-2'
-    ]
-) ?>
-
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Podcast.form.complete'),
-    ],
-    [
-        'id' => 'complete',
-        'name' => 'complete',
-        'value' => 'yes',
-        'checked' => old('complete', false),
-    ]
-) ?>
+<Forms.Toggler class="mb-2" id="lock" name="lock" value="yes" checked="<?= old('complete', true) ?>" hint="<?= lang('Podcast.form.lock_hint') ?>">
+    <?= lang('Podcast.form.lock') ?>
+</Forms.Toggler>
+<Forms.Toggler class="mb-2" id="block" name="block" value="yes" checked="<?= old('complete', false) ?>">
+    <?= lang('Podcast.form.block') ?>
+</Forms.Toggler>
+<Forms.Toggler id="complete" name="complete" value="yes" checked="<?= old('complete', false) ?>">
+    <?= lang('Podcast.form.complete') ?>
+</Forms.Toggler>
 
 <?= form_section_close() ?>
 
@@ -406,7 +361,6 @@
     ['type' => 'submit', 'class' => 'self-end'],
 ) ?>
 
-
 <?= form_close() ?>
 
 
diff --git a/modules/Admin/Views/podcast/edit.php b/modules/Admin/Views/podcast/edit.php
index 13e8ece09d..bf21b9352b 100644
--- a/modules/Admin/Views/podcast/edit.php
+++ b/modules/Admin/Views/podcast/edit.php
@@ -1,3 +1,6 @@
+<?php 
+?>
+
 <?= $this->extend('Modules\Admin\Views\_layout') ?>
 
 <?= $this->section('title') ?>
@@ -11,7 +14,7 @@
 
 <?= $this->section('content') ?>
 
-<?= form_open_multipart(route_to('podcast-edit', $podcast->id), [
+<?= form_open_multipart((string) route_to('podcast-edit', $podcast->id), [
     'method' => 'post',
     'class' => 'flex flex-col',
 ]) ?>
@@ -24,7 +27,6 @@
 ) ?>
 
 <?= form_label(lang('Podcast.form.image'), 'image') ?>
-
 <img src="<?= $podcast->image->thumbnail_url ?>" alt="<?= $podcast->title ?>" class="object-cover w-32 h-32" />
 <?= form_input([
     'id' => 'image',
@@ -71,18 +73,8 @@
 <?= form_fieldset_close() ?>
 
 <div class="mb-4">
-    <?= form_label(lang('Podcast.form.description'), 'description') ?>
-    <?= component(
-        'Forms/MarkdownEditor',
-        [
-            'content' => old('description', $podcast->description_markdown, false)
-        ],
-        [
-            'id' => 'description',
-            'name' => 'description',
-            'required' => 'required',
-        ],
-    ) ?>
+    <Forms.Label for="description"><?= lang('Podcast.form.description') ?></Forms.Label>
+    <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', $podcast->description_markdown, false) ?></Forms.MarkdownEditor>
 </div>
 
 <?= form_section_close() ?>
@@ -125,12 +117,13 @@ lang('Podcast.form.classification_section_subtitle'),
     true,
 ) ?>
 
-<?= component('Forms/MultiSelect', ['options' => $categoryOptions, 'selected' => old('other_categories', $podcast->other_categories_ids)], [
-    'id' => 'other_categories',
-    'name' => 'other_categories[]',
-    'class' => 'mb-4',
-    'data-max-item-count' => '2',
-]) ?>
+<Forms.MultiSelect
+    id="other_categories"
+    name="other_categories[]"
+    class="mb-4"
+    data-max-item-count="2"
+    selected="<?= json_encode(old('other_categories', $podcast->other_categories_ids)) ?>"
+    options="<?= htmlspecialchars(json_encode($categoryOptions)) ?>" />
 
 <?= form_fieldset('', ['class' => 'mb-4']) ?>
 <legend><?= lang('Podcast.form.parental_advisory.label') .
@@ -349,16 +342,7 @@ lang('Podcast.form.classification_section_subtitle'),
     lang('Podcast.form.custom_rss_hint'),
     true,
 ) ?>
-
-<?= component('Forms/XMLEditor', 
-    [
-        'content' => old('custom_rss', $podcast->custom_rss_string)
-    ],
-    [
-        'id' => 'custom_rss',
-        'name' => 'custom_rss',
-    ]
-) ?>
+<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', $podcast->custom_rss_string, false) ?></Forms.XMLEditor>
 
 <?= form_section_close() ?>
 
@@ -367,61 +351,21 @@ lang('Podcast.form.classification_section_subtitle'),
     lang('Podcast.form.status_section_subtitle'),
 ) ?>
 
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Podcast.form.lock'),
-        'hint' => lang('Podcast.form.lock_hint'),
-    ],
-    [
-        'id' => 'lock',
-        'name' => 'lock',
-        'value' => 'yes',
-        'checked' => old('complete', $podcast->is_locked),
-        'class' => 'mb-2'
-    ]
-) ?>
-
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Podcast.form.block'),
-    ],
-    [
-        'id' => 'block',
-        'name' => 'block',
-        'value' => 'yes',
-        'checked' => old('block', $podcast->is_blocked),
-        'class' => 'mb-2'
-    ]
-) ?>
-
-<?= component(
-    'Forms/Toggler',
-    [
-        'label' => lang('Podcast.form.complete'),
-    ],
-    [
-        'id' => 'complete',
-        'name' => 'complete',
-        'value' => 'yes',
-        'checked' => old('complete', $podcast->is_completed),
-    ]
-) ?>
+<Forms.Toggler class="mb-2" id="lock" name="lock" value="yes" checked="<?= old('complete', $podcast->is_locked) ?>" hint="<?= lang('Podcast.form.lock_hint') ?>">
+    <?= lang('Podcast.form.lock') ?>
+</Forms.Toggler>
+<Forms.Toggler class="mb-2" id="block" name="block" value="yes" checked="<?= old('complete', $podcast->is_blocked) ?>">
+    <?= lang('Podcast.form.block') ?>
+</Forms.Toggler>
+<Forms.Toggler id="complete" name="complete" value="yes" checked="<?= old('complete', $podcast->is_completed) ?>">
+    <?= lang('Podcast.form.complete') ?>
+</Forms.Toggler>
 
 <?= form_section_close() ?>
 
-<?= component(
-    'Button',
-    [
-        'label' => lang('Podcast.form.submit_edit'),
-        'variant' => 'primary',
-    ],
-    [
-        'type' => 'submit',
-        'class' => 'self-end'
-    ]
-) ?>
+<Button variant="primary" type="submit" class="self-end" iconLeft="heart">
+<?= lang('Podcast.form.submit_edit') ?>
+</Button>
 
 <?= form_close() ?>
 
diff --git a/modules/Admin/Views/podcast/persons.php b/modules/Admin/Views/podcast/persons.php
index 2e51cacb15..1f79dfdd3c 100644
--- a/modules/Admin/Views/podcast/persons.php
+++ b/modules/Admin/Views/podcast/persons.php
@@ -99,13 +99,7 @@
     [],
     lang('Person.podcast_form.persons_hint'),
 ) ?>
-<?= component('Forms/MultiSelect', ['options' => $personOptions, 'selected' => old('persons', [])], [
-    'id' => 'persons',
-    'name' => 'persons[]',
-    'class' => 'mb-4',
-    'required' => 'required',
-    'data-max-item-count' => '2',
-]) ?>
+<Forms.MultiSelect id="persons" name="persons[]" class="mb-4" required="required" options="<?= htmlspecialchars(json_encode($personOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('persons', []))) ?>"/>
 
 <?= form_label(
     lang('Person.podcast_form.roles'),
@@ -114,11 +108,7 @@
     lang('Person.podcast_form.roles_hint'),
     true,
 ) ?>
-<?= component('Forms/MultiSelect', ['options' => $taxonomyOptions, 'selected' => old('roles', [])], [
-    'id' => 'roles',
-    'name' => 'roles[]',
-    'class' => 'mb-4',
-]) ?>
+<Forms.MultiSelect id="roles" name="roles[]" class="mb-4" options="<?= htmlspecialchars(json_encode($taxonomyOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('roles', []))) ?>"/>
 
 <?= form_section_close() ?>
 <?= button(
diff --git a/modules/Admin/Views/podcast/platforms.php b/modules/Admin/Views/podcast/platforms.php
index 95d72e03a1..8d1ecf35c1 100644
--- a/modules/Admin/Views/podcast/platforms.php
+++ b/modules/Admin/Views/podcast/platforms.php
@@ -103,40 +103,8 @@
             'type' => 'text',
             'placeholder' => lang("Platforms.description.{$platform->type}"),
         ]) ?>
-        <?= component(
-            'Forms/Toggler',
-            [
-                'label' => lang('Platforms.visible'),
-            ],
-            [
-                'id' => $platform->slug . '_visible',
-                'name' => 'platforms[' . $platform->slug . '][visible]',
-                'value' => 'yes',
-                'checked' => old(
-                    $platform->slug . '_visible',
-                    $platform->is_visible ? $platform->is_visible : false,
-                ),
-                'class' => 'text-sm mb-1'
-            ]
-        ) ?>
-        <?= component(
-            'Forms/Toggler',
-            [
-                'label' => lang('Platforms.on_embeddable_player'),
-            ],
-            [
-                'id' => $platform->slug . '_on_embeddable_player',
-                'name' => 'platforms[' . $platform->slug . '][on_embeddable_player]',
-                'value' => 'yes',
-                'checked' => old(
-                    $platform->slug . '_on_embeddable_player',
-                    $platform->is_on_embeddable_player
-                        ? $platform->is_on_embeddable_player
-                        : false,
-                ),
-                'class' => 'text-sm'
-            ]
-        ) ?>
+        <Forms.Toggler class="mb-1 text-sm" id="<?= $platform->slug . '_visible' ?>" name="<?= 'platforms[' . $platform->slug . '][visible]'?>" value="yes" checked="<?= old($platform->slug . '_visible', $platform->is_visible ? $platform->is_visible : false ) ?>"><?= lang('Platforms.visible') ?></Forms.Toggler>
+        <Forms.Toggler class="text-sm" id="<?= $platform->slug . '_on_embeddable_player' ?>" name="<?= 'platforms[' . $platform->slug . '][on_embeddable_player]'?>" value="yes" checked="<?= old($platform->slug . '_on_embeddable_player', $platform->is_on_embeddable_player ? $platform->is_on_embeddable_player : false ) ?>"><?= lang('Platforms.on_embeddable_player') ?></Forms.Toggler>
     </div>
 </div>
 
diff --git a/modules/Admin/Views/user/edit.php b/modules/Admin/Views/user/edit.php
index be89f21c51..77a5d6a2f6 100644
--- a/modules/Admin/Views/user/edit.php
+++ b/modules/Admin/Views/user/edit.php
@@ -17,11 +17,7 @@
 <?= csrf_field() ?>
 
 <?= form_label(lang('User.form.roles'), 'roles') ?>
-<?= component('Forms/MultiSelect', ['options' => $roleOptions, 'selected' => $user->roles], [
-    'id' => 'roles',
-    'name' => 'roles[]',
-    'class' => 'mb-4',
-]) ?>
+<Forms.MultiSelect id="roles" name="roles[]" class="mb-4" required="required" options="<?= htmlspecialchars(json_encode($roleOptions)) ?>" selected="<?= htmlspecialchars(json_encode($user->roles)) ?>"/>
 
 <?= button(
     lang('User.form.submit_edit'),
diff --git a/modules/Analytics/Config/Analytics.php b/modules/Analytics/Config/Analytics.php
index 7e3957d66d..b4ffd7952e 100644
--- a/modules/Analytics/Config/Analytics.php
+++ b/modules/Analytics/Config/Analytics.php
@@ -30,7 +30,7 @@ class Analytics extends BaseConfig
      *
      * @param string|string[] $audioFilePath
      */
-    public function getAudioFileUrl(string|array $audioFilePath): string
+    public function getAudioFileUrl(string | array $audioFilePath): string
     {
         helper('media');
 
diff --git a/modules/Auth/Database/Seeds/AuthSeeder.php b/modules/Auth/Database/Seeds/AuthSeeder.php
index 2c2dc153b7..2deabcd0f7 100644
--- a/modules/Auth/Database/Seeds/AuthSeeder.php
+++ b/modules/Auth/Database/Seeds/AuthSeeder.php
@@ -238,13 +238,13 @@ class AuthSeeder extends Seeder
             [
                 'name' => 'block_actors',
                 'description' =>
-                    'Block an activitypub actors from interacting with the instance.',
+                    'Block fediverse actors from interacting with the instance.',
                 'has_permission' => ['superadmin'],
             ],
             [
                 'name' => 'block_domains',
                 'description' =>
-                    'Block an activitypub domains from interacting with the instance.',
+                    'Block fediverse domains from interacting with the instance.',
                 'has_permission' => ['superadmin'],
             ],
         ],
diff --git a/modules/Fediverse/Config/Fediverse.php b/modules/Fediverse/Config/Fediverse.php
index fd7cb2e9b8..19dfebb9ec 100644
--- a/modules/Fediverse/Config/Fediverse.php
+++ b/modules/Fediverse/Config/Fediverse.php
@@ -18,7 +18,7 @@ class Fediverse extends BaseConfig
 {
     /**
      * --------------------------------------------------------------------
-     * ActivityPub Objects
+     * Fediverse Objects
      * --------------------------------------------------------------------
      */
     public string $actorObject = ActorObject::class;
@@ -38,6 +38,8 @@ class Fediverse extends BaseConfig
 
     public string $defaultCoverImageMimetype = 'image/jpeg';
 
+    public string $tablesPrefix = 'fediverse_';
+
     /**
      * --------------------------------------------------------------------
      * Cache options
diff --git a/modules/Fediverse/Config/Routes.php b/modules/Fediverse/Config/Routes.php
index 62ac3d2dcc..5df9c97d8d 100644
--- a/modules/Fediverse/Config/Routes.php
+++ b/modules/Fediverse/Config/Routes.php
@@ -18,7 +18,7 @@ $routes->addPlaceholder(
 $routes->addPlaceholder('postAction', '\bfavourite|\breblog|\breply');
 
 /**
- * ActivityPub routes file
+ * Fediverse routes file
  */
 
 $routes->group('', [
diff --git a/modules/Fediverse/Controllers/ActorController.php b/modules/Fediverse/Controllers/ActorController.php
index d208709df4..d28e64f039 100644
--- a/modules/Fediverse/Controllers/ActorController.php
+++ b/modules/Fediverse/Controllers/ActorController.php
@@ -26,11 +26,11 @@ class ActorController extends Controller
     /**
      * @var string[]
      */
-    protected $helpers = ['activitypub'];
+    protected $helpers = ['fediverse'];
 
     protected Actor $actor;
 
-    protected ActivityPub $config;
+    protected Fediverse $config;
 
     public function __construct()
     {
@@ -298,11 +298,14 @@ class ActorController extends Controller
      */
     public function followers(): ResponseInterface
     {
+        $tablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         // get followers for a specific actor
         $followers = model('ActorModel')
-            ->join('activitypub_follows', 'activitypub_follows.actor_id = id', 'inner')
-            ->where('activitypub_follows.target_actor_id', $this->actor->id)
-            ->orderBy('activitypub_follows.created_at', 'DESC');
+            ->join($tablesPrefix . 'follows', $tablesPrefix . 'follows.actor_id = id', 'inner')
+            ->where($tablesPrefix . 'follows.target_actor_id', $this->actor->id)
+            ->orderBy($tablesPrefix . 'follows.created_at', 'DESC');
 
         $pageNumber = (int) $this->request->getGet('page');
 
@@ -343,7 +346,7 @@ class ActorController extends Controller
         helper('text');
 
         // get webfinger data from actor
-        // parse activityPub id to get actor and domain
+        // parse actor id to get actor and domain
         // check if actor and domain exist
 
         if (
@@ -353,7 +356,7 @@ class ActorController extends Controller
             return redirect()
                 ->back()
                 ->withInput()
-                ->with('error', lang('ActivityPub.follow.accountNotFound'));
+                ->with('error', lang('Fediverse.follow.accountNotFound'));
         }
 
         $ostatusKey = array_search(
diff --git a/modules/Fediverse/Controllers/BlockController.php b/modules/Fediverse/Controllers/BlockController.php
index 76fad3f050..162cc56344 100644
--- a/modules/Fediverse/Controllers/BlockController.php
+++ b/modules/Fediverse/Controllers/BlockController.php
@@ -18,7 +18,7 @@ class BlockController extends Controller
     /**
      * @var string[]
      */
-    protected $helpers = ['activitypub'];
+    protected $helpers = ['fediverse'];
 
     public function attemptBlockActor(): RedirectResponse
     {
diff --git a/modules/Fediverse/Controllers/PostController.php b/modules/Fediverse/Controllers/PostController.php
index 0db0ea67f4..4240e9f7bf 100644
--- a/modules/Fediverse/Controllers/PostController.php
+++ b/modules/Fediverse/Controllers/PostController.php
@@ -16,6 +16,7 @@ use CodeIgniter\HTTP\RedirectResponse;
 use CodeIgniter\HTTP\Response;
 use CodeIgniter\HTTP\ResponseInterface;
 use CodeIgniter\I18n\Time;
+use Modules\Fediverse\Config\Fediverse;
 use Modules\Fediverse\Entities\Post;
 use Modules\Fediverse\Objects\OrderedCollectionObject;
 use Modules\Fediverse\Objects\OrderedCollectionPage;
@@ -25,11 +26,11 @@ class PostController extends Controller
     /**
      * @var string[]
      */
-    protected $helpers = ['activitypub'];
+    protected $helpers = ['fediverse'];
 
     protected Post $post;
 
-    protected ActivityPub $config;
+    protected Fediverse $config;
 
     public function __construct()
     {
@@ -229,7 +230,7 @@ class PostController extends Controller
         helper('text');
 
         // get webfinger data from actor
-        // parse activityPub id to get actor and domain
+        // parse actor id to get actor and domain
         // check if actor and domain exist
         if (
             ! ($parts = split_handle($this->request->getPost('handle'))) ||
@@ -238,7 +239,7 @@ class PostController extends Controller
             return redirect()
                 ->back()
                 ->withInput()
-                ->with('error', lang('ActivityPub.follow.accountNotFound'));
+                ->with('error', lang('Fediverse.follow.accountNotFound'));
         }
 
         $ostatusKey = array_search(
diff --git a/modules/Fediverse/Controllers/SchedulerController.php b/modules/Fediverse/Controllers/SchedulerController.php
index 43383a331a..9331d77b8f 100644
--- a/modules/Fediverse/Controllers/SchedulerController.php
+++ b/modules/Fediverse/Controllers/SchedulerController.php
@@ -17,7 +17,7 @@ class SchedulerController extends Controller
     /**
      * @var string[]
      */
-    protected $helpers = ['activitypub'];
+    protected $helpers = ['fediverse'];
 
     public function activity(): void
     {
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php b/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php
index 95ad02d39d..ee629647e0 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddActors Creates activitypub_actors table in database
+ * Class AddActors Creates actors table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -113,11 +113,11 @@ class AddActors extends Migration
         $this->forge->addPrimaryKey('id');
         $this->forge->addUniqueKey('uri');
         $this->forge->addUniqueKey(['username', 'domain']);
-        $this->forge->createTable('activitypub_actors');
+        $this->forge->createTable(config('Fediverse')->tablesPrefix . 'actors');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_actors');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'actors');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php b/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php
index b3ffa0f070..a514c2e6fd 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddPosts Creates activitypub_posts table in database
+ * Class AddPosts Creates posts table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -74,18 +74,22 @@ class AddPosts extends Migration
                 'type' => 'DATETIME',
             ],
         ]);
+
+        $tablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addPrimaryKey('id');
         $this->forge->addUniqueKey('uri');
         // FIXME: an actor must reblog a post only once
         // $this->forge->addUniqueKey(['actor_id', 'reblog_of_id']);
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('in_reply_to_id', 'activitypub_posts', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('reblog_of_id', 'activitypub_posts', 'id', '', 'CASCADE');
-        $this->forge->createTable('activitypub_posts');
+        $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('in_reply_to_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('reblog_of_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
+        $this->forge->createTable($tablesPrefix . 'posts');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_posts');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'posts');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php
index 97405b71ea..f9bec2bf59 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddActivities Creates activitypub_activities table in database
+ * Class AddActivities Creates activities table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -59,15 +59,19 @@ class AddActivities extends Migration
                 'type' => 'DATETIME',
             ],
         ]);
+
+        $tablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addPrimaryKey('id');
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('target_actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('post_id', 'activitypub_posts', 'id', '', 'CASCADE');
-        $this->forge->createTable('activitypub_activities');
+        $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
+        $this->forge->createTable($tablesPrefix . 'activities');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_activities');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'activities');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php
index f1e4a190a9..d89ad195ff 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddFavourites Creates activitypub_favourites table in database
+ * Class AddFavourites Creates favourites table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -28,15 +28,19 @@ class AddFavourites extends Migration
                 'constraint' => 16,
             ],
         ]);
+
+        $tablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
         $this->forge->addPrimaryKey(['actor_id', 'post_id']);
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('post_id', 'activitypub_posts', 'id', '', 'CASCADE');
-        $this->forge->createTable('activitypub_favourites');
+        $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
+        $this->forge->createTable($tablesPrefix . 'favourites');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_favourites');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'favourites');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php
index 15992da5fa..46e3a4bb4b 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddFollowers Creates activitypub_followers table in database
+ * Class AddFollowers Creates followers table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -30,15 +30,19 @@ class AddFollowers extends Migration
                 'comment' => 'Actor that is followed',
             ],
         ]);
+
+        $tablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
         $this->forge->addPrimaryKey(['actor_id', 'target_actor_id']);
-        $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('target_actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
-        $this->forge->createTable('activitypub_follows');
+        $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
+        $this->forge->createTable($tablesPrefix . 'follows');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_follows');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'follows');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php
index 291a8974b8..29b7d9dd0d 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddPreviewCards Creates activitypub_preview_cards table in database
+ * Class AddPreviewCards Creates preview_cards table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -75,11 +75,11 @@ class AddPreviewCards extends Migration
 
         $this->forge->addPrimaryKey('id');
         $this->forge->addUniqueKey('url');
-        $this->forge->createTable('activitypub_preview_cards');
+        $this->forge->createTable(config('Fediverse')->tablesPrefix . 'preview_cards');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_preview_cards');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'preview_cards');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php b/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php
index 8e58ceb3b9..bbd4b1afe2 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddPostsPreviewCards Creates activitypub_posts_preview_cards table in database
+ * Class AddPostsPreviewCards Creates posts_preview_cards table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -29,14 +29,17 @@ class AddPostsPreviewCards extends Migration
             ],
         ]);
 
+        $tablesPrefix = config('Fediverse')
+            ->tablesPrefix;
+
         $this->forge->addPrimaryKey(['post_id', 'preview_card_id']);
-        $this->forge->addForeignKey('post_id', 'activitypub_posts', 'id', '', 'CASCADE');
-        $this->forge->addForeignKey('preview_card_id', 'activitypub_preview_cards', 'id', '', 'CASCADE');
-        $this->forge->createTable('activitypub_posts_preview_cards');
+        $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
+        $this->forge->addForeignKey('preview_card_id', $tablesPrefix . 'preview_cards', 'id', '', 'CASCADE');
+        $this->forge->createTable($tablesPrefix . 'posts_preview_cards');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_posts_preview_cards');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'posts_preview_cards');
     }
 }
diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php b/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php
index 9d08859050..8243aa85df 100644
--- a/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php
+++ b/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 /**
- * Class AddBlockedDomains Creates activitypub_blocked_domains table in database
+ * Class AddBlockedDomains Creates blocked_domains table in database
  *
  * @copyright  2021 Podlibre
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@@ -28,11 +28,11 @@ class AddBlockedDomains extends Migration
             ],
         ]);
         $this->forge->addPrimaryKey('name');
-        $this->forge->createTable('activitypub_blocked_domains');
+        $this->forge->createTable(config('Fediverse')->tablesPrefix . 'blocked_domains');
     }
 
     public function down(): void
     {
-        $this->forge->dropTable('activitypub_blocked_domains');
+        $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'blocked_domains');
     }
 }
diff --git a/modules/Fediverse/Entities/Post.php b/modules/Fediverse/Entities/Post.php
index 145a01dd00..c663964607 100644
--- a/modules/Fediverse/Entities/Post.php
+++ b/modules/Fediverse/Entities/Post.php
@@ -193,7 +193,7 @@ class Post extends UuidEntity
 
     public function setMessage(string $message): static
     {
-        helper('activitypub');
+        helper('fediverse');
 
         $messageWithoutTags = strip_tags($message);
 
diff --git a/modules/Fediverse/Filters/ActivityPubFilter.php b/modules/Fediverse/Filters/FediverseFilter.php
similarity index 98%
rename from modules/Fediverse/Filters/ActivityPubFilter.php
rename to modules/Fediverse/Filters/FediverseFilter.php
index 56c0c3327f..5a4e607d58 100644
--- a/modules/Fediverse/Filters/ActivityPubFilter.php
+++ b/modules/Fediverse/Filters/FediverseFilter.php
@@ -13,7 +13,7 @@ use Config\Services;
 use Exception;
 use Modules\Fediverse\HttpSignature;
 
-class ActivityPubFilter implements FilterInterface
+class FediverseFilter implements FilterInterface
 {
     /**
      * Do whatever processing this filter needs to do. By default it should not return anything during normal execution.
diff --git a/modules/Fediverse/Helpers/activitypub_helper.php b/modules/Fediverse/Helpers/fediverse_helper.php
similarity index 100%
rename from modules/Fediverse/Helpers/activitypub_helper.php
rename to modules/Fediverse/Helpers/fediverse_helper.php
diff --git a/modules/Fediverse/Models/ActivityModel.php b/modules/Fediverse/Models/ActivityModel.php
index 0286bd7853..09428848cd 100644
--- a/modules/Fediverse/Models/ActivityModel.php
+++ b/modules/Fediverse/Models/ActivityModel.php
@@ -13,15 +13,14 @@ namespace Modules\Fediverse\Models;
 use CodeIgniter\Database\BaseResult;
 use CodeIgniter\I18n\Time;
 use DateTimeInterface;
-use Michalsn\Uuid\UuidModel;
 use Modules\Fediverse\Entities\Activity;
 
-class ActivityModel extends UuidModel
+class ActivityModel extends BaseUuidModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_activities';
+    protected $table = 'activities';
 
     /**
      * @var string
diff --git a/modules/Fediverse/Models/ActorModel.php b/modules/Fediverse/Models/ActorModel.php
index 9bab67cb71..3f0592ed23 100644
--- a/modules/Fediverse/Models/ActorModel.php
+++ b/modules/Fediverse/Models/ActorModel.php
@@ -11,15 +11,14 @@ declare(strict_types=1);
 namespace Modules\Fediverse\Models;
 
 use CodeIgniter\Events\Events;
-use CodeIgniter\Model;
 use Modules\Fediverse\Entities\Actor;
 
-class ActorModel extends Model
+class ActorModel extends BaseModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_actors';
+    protected $table = 'actors';
 
     /**
      * @var string[]
@@ -80,7 +79,7 @@ class ActorModel extends Model
     public function getActorByUsername(string $username, ?string $domain = null): ?Actor
     {
         // TODO: is there a better way?
-        helper('activitypub');
+        helper('fediverse');
 
         if (! $domain) {
             $domain = get_current_domain();
@@ -129,8 +128,10 @@ class ActorModel extends Model
             config('Fediverse')
                 ->cachePrefix . "actor#{$actorId}_followers";
         if (! ($found = cache($cacheName))) {
-            $found = $this->join('activitypub_follows', 'activitypub_follows.actor_id = id', 'inner')
-                ->where('activitypub_follows.target_actor_id', $actorId)
+            $tablesPrefix = config('Fediverse')
+                ->tablesPrefix;
+            $found = $this->join($tablesPrefix . 'follows', $tablesPrefix . 'follows.actor_id = id', 'inner')
+                ->where($tablesPrefix . 'follows.target_actor_id', $actorId)
                 ->findAll();
 
             cache()
diff --git a/modules/Fediverse/Models/BaseModel.php b/modules/Fediverse/Models/BaseModel.php
new file mode 100644
index 0000000000..685f1776ec
--- /dev/null
+++ b/modules/Fediverse/Models/BaseModel.php
@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Modules\Fediverse\Models;
+
+use CodeIgniter\Database\ConnectionInterface;
+use CodeIgniter\Model;
+use CodeIgniter\Validation\ValidationInterface;
+
+class BaseModel extends Model
+{
+    /**
+     * Model constructor.
+     *
+     * @param ConnectionInterface|null $db         DB Connection
+     * @param ValidationInterface|null $validation Validation
+     */
+    public function __construct(ConnectionInterface &$db = null, ValidationInterface $validation = null)
+    {
+        parent::__construct($db, $validation);
+
+        $this->table = config('Fediverse')
+            ->tablesPrefix . $this->table;
+    }
+}
diff --git a/modules/Fediverse/Models/BaseUuidModel.php b/modules/Fediverse/Models/BaseUuidModel.php
new file mode 100644
index 0000000000..e2f80ea90d
--- /dev/null
+++ b/modules/Fediverse/Models/BaseUuidModel.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Modules\Fediverse\Models;
+
+use CodeIgniter\Database\ConnectionInterface;
+use CodeIgniter\Validation\ValidationInterface;
+use Michalsn\Uuid\UuidModel;
+
+class BaseUuidModel extends UuidModel
+{
+    public function __construct(ConnectionInterface &$db = null, ValidationInterface $validation = null)
+    {
+        parent::__construct($db, $validation);
+
+        $this->table = config('Fediverse')
+            ->tablesPrefix . $this->table;
+    }
+}
diff --git a/modules/Fediverse/Models/BlockedDomainModel.php b/modules/Fediverse/Models/BlockedDomainModel.php
index 8ffd8f3731..9f2881eb63 100644
--- a/modules/Fediverse/Models/BlockedDomainModel.php
+++ b/modules/Fediverse/Models/BlockedDomainModel.php
@@ -15,12 +15,12 @@ use CodeIgniter\Events\Events;
 use CodeIgniter\Model;
 use Modules\Fediverse\Entities\BlockedDomain;
 
-class BlockedDomainModel extends Model
+class BlockedDomainModel extends BaseModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_blocked_domains';
+    protected $table = 'blocked_domains';
 
     /**
      * @var string
diff --git a/modules/Fediverse/Models/FavouriteModel.php b/modules/Fediverse/Models/FavouriteModel.php
index 1ddca50efb..93cd56679d 100644
--- a/modules/Fediverse/Models/FavouriteModel.php
+++ b/modules/Fediverse/Models/FavouriteModel.php
@@ -11,19 +11,18 @@ declare(strict_types=1);
 namespace Modules\Fediverse\Models;
 
 use CodeIgniter\Events\Events;
-use Michalsn\Uuid\UuidModel;
 use Modules\Fediverse\Activities\LikeActivity;
 use Modules\Fediverse\Activities\UndoActivity;
 use Modules\Fediverse\Entities\Actor;
 use Modules\Fediverse\Entities\Favourite;
 use Modules\Fediverse\Entities\Post;
 
-class FavouriteModel extends UuidModel
+class FavouriteModel extends BaseUuidModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_favourites';
+    protected $table = 'favourites';
 
     /**
      * @var string[]
diff --git a/modules/Fediverse/Models/FollowModel.php b/modules/Fediverse/Models/FollowModel.php
index b0d7c2e70b..0917fe96a7 100644
--- a/modules/Fediverse/Models/FollowModel.php
+++ b/modules/Fediverse/Models/FollowModel.php
@@ -21,12 +21,12 @@ use Modules\Fediverse\Activities\UndoActivity;
 use Modules\Fediverse\Entities\Actor;
 use Modules\Fediverse\Entities\Follow;
 
-class FollowModel extends Model
+class FollowModel extends BaseModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_follows';
+    protected $table = 'follows';
 
     /**
      * @var string[]
diff --git a/modules/Fediverse/Models/PostModel.php b/modules/Fediverse/Models/PostModel.php
index dcb2de6f34..2d390eb3dc 100644
--- a/modules/Fediverse/Models/PostModel.php
+++ b/modules/Fediverse/Models/PostModel.php
@@ -16,7 +16,6 @@ use CodeIgniter\Events\Events;
 use CodeIgniter\HTTP\URI;
 use CodeIgniter\I18n\Time;
 use Exception;
-use Michalsn\Uuid\UuidModel;
 use Modules\Fediverse\Activities\AnnounceActivity;
 use Modules\Fediverse\Activities\CreateActivity;
 use Modules\Fediverse\Activities\DeleteActivity;
@@ -25,12 +24,12 @@ use Modules\Fediverse\Entities\Actor;
 use Modules\Fediverse\Entities\Post;
 use Modules\Fediverse\Objects\TombstoneObject;
 
-class PostModel extends UuidModel
+class PostModel extends BaseUuidModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_posts';
+    protected $table = 'posts';
 
     /**
      * @var string
@@ -183,10 +182,16 @@ class PostModel extends UuidModel
             ($withBlocked ? '_withBlocked' : '');
 
         if (! ($found = cache($cacheName))) {
+            $tablesPrefix = config('Fediverse')
+                ->tablesPrefix;
             if (! $withBlocked) {
-                $this->select('activitypub_posts.*')
-                    ->join('activitypub_actors', 'activitypub_actors.id = activitypub_posts.actor_id', 'inner')
-                    ->where('activitypub_actors.is_blocked', 0);
+                $this->select($tablesPrefix . 'posts.*')
+                    ->join(
+                        $tablesPrefix . 'actors',
+                        $tablesPrefix . 'actors.id = ' . $tablesPrefix . 'posts.actor_id',
+                        'inner'
+                    )
+                    ->where($tablesPrefix . 'actors.is_blocked', 0);
             }
 
             $this->where('in_reply_to_id', $this->uuid->fromString($postId) ->getBytes())
@@ -227,7 +232,7 @@ class PostModel extends UuidModel
 
     public function addPreviewCard(string $postId, int $previewCardId): Query | bool
     {
-        return $this->db->table('activitypub_posts_preview_cards')
+        return $this->db->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards')
             ->insert([
                 'post_id' => $this->uuid->fromString($postId)
                     ->getBytes(),
@@ -245,7 +250,7 @@ class PostModel extends UuidModel
         bool $createPreviewCard = true,
         bool $registerActivity = true
     ): string | false {
-        helper('activitypub');
+        helper('fediverse');
 
         $this->db->transStart();
 
@@ -385,7 +390,7 @@ class PostModel extends UuidModel
         if (
             $post->preview_card &&
             $this->db
-                ->table('activitypub_posts_preview_cards')
+                ->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards')
                 ->where('preview_card_id', $post->preview_card->id)
                 ->countAll() <= 1
         ) {
diff --git a/modules/Fediverse/Models/PreviewCardModel.php b/modules/Fediverse/Models/PreviewCardModel.php
index bfbd00f7c8..55f017f1e0 100644
--- a/modules/Fediverse/Models/PreviewCardModel.php
+++ b/modules/Fediverse/Models/PreviewCardModel.php
@@ -11,15 +11,14 @@ declare(strict_types=1);
 namespace Modules\Fediverse\Models;
 
 use CodeIgniter\Database\BaseResult;
-use CodeIgniter\Model;
 use Modules\Fediverse\Entities\PreviewCard;
 
-class PreviewCardModel extends Model
+class PreviewCardModel extends BaseModel
 {
     /**
      * @var string
      */
-    protected $table = 'activitypub_preview_cards';
+    protected $table = 'preview_cards';
 
     /**
      * @var string[]
@@ -76,9 +75,11 @@ class PreviewCardModel extends Model
             config('Fediverse')
                 ->cachePrefix . "post#{$postId}_preview_card";
         if (! ($found = cache($cacheName))) {
+            $tablesPrefix = config('Fediverse')
+                ->tablesPrefix;
             $found = $this->join(
-                'activitypub_posts_preview_cards',
-                'activitypub_posts_preview_cards.preview_card_id = id',
+                $tablesPrefix . 'posts_preview_cards',
+                $tablesPrefix . 'posts_preview_cards.preview_card_id = id',
                 'inner',
             )
                 ->where('post_id', service('uuid') ->fromString($postId) ->getBytes())
diff --git a/phpstan.neon b/phpstan.neon
index 83d920db3c..43e45fc773 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -15,6 +15,7 @@ parameters:
     excludes_analyse:
         - app/Libraries/Router.php
         - app/Views/*
+        - modules/*/Views/*
     ignoreErrors:
         - '#This property type might be inlined to PHP. Do you have confidence it is correct\? Put it here#'
         - '#^Cognitive complexity for#'
@@ -30,4 +31,3 @@ parameters:
             message: '#Function "function_exists\(\)" cannot be used/left in the code#'
             paths:
                 - app/Helpers
-                - app/Libraries/ViewComponents/Helpers
diff --git a/rector.php b/rector.php
index f3057c6679..c173dbd552 100644
--- a/rector.php
+++ b/rector.php
@@ -4,7 +4,9 @@ declare(strict_types=1);
 
 use Rector\CodingStyle\Rector\ClassMethod\UnSpreadOperatorRector;
 use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
+use Rector\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector;
 use Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector;
+use Rector\CodingStyle\Rector\FuncCall\VersionCompareFuncCallToConstantRector;
 use Rector\CodingStyle\Rector\String_\SplitStringClassConstantToClassConstFetchRector;
 use Rector\Core\Configuration\Option;
 use Rector\Core\ValueObject\PhpVersion;
@@ -13,6 +15,7 @@ use Rector\EarlyReturn\Rector\If_\ChangeOrIfReturnToEarlyReturnRector;
 use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
 use Rector\Php80\Rector\ClassMethod\OptionalParametersAfterRequiredRector;
 use Rector\Set\ValueObject\SetList;
+use Rector\Transform\Rector\FuncCall\FuncCallToConstFetchRector;
 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
 
 return static function (ContainerConfigurator $containerConfigurator): void {
@@ -21,6 +24,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
 
     $parameters->set(Option::PATHS, [
         __DIR__ . '/app',
+        __DIR__ . '/modules',
         __DIR__ . '/tests',
         __DIR__ . '/public',
     ]);
@@ -47,7 +51,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
 
     $parameters->set(Option::SKIP, [
         // skip specific generated files
-        __DIR__ . '/app/Language/*/PersonsTaxonomy.php',
+        __DIR__ . '/modules/Admin/Language/*/PersonsTaxonomy.php',
 
         // skip rules from used sets
         ChangeOrIfReturnToEarlyReturnRector::class,
@@ -59,6 +63,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
         // skip rule in specific directory
         StringClassNameToClassConstantRector::class => [
             __DIR__ . '/app/Language/*',
+            __DIR__ . '/modules/*/Language/*',
         ],
         OptionalParametersAfterRequiredRector::class => [
             __DIR__ . '/app/Validation',
-- 
GitLab