From f77236aa3832a5a0f050e097c60189b9b6a19969 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Tue, 26 Oct 2021 22:04:18 +0100
Subject: [PATCH 1/6] Laravel 7.x Shift (#3011)

* Apply Laravel coding style
* Shift bindings
* Shift core files
* Shift to Throwable
* Add laravel/ui dependency
* Shift Eloquent methods
* Shift config files
* Shift Laravel dependencies
* Shift cleanup
* Shift test config and references
* Applied styleci changes
* Applied fixes post shift to laravel 7

Co-authored-by: Shift <shift@laravelshift.com>
---
 app/Actions/Activity.php                      |    2 +-
 app/Api/ApiToken.php                          |    2 +-
 app/Api/ApiTokenGuard.php                     |    4 +-
 app/Auth/Role.php                             |    6 +-
 app/Auth/SocialAccount.php                    |    2 +-
 app/Auth/User.php                             |    6 +-
 app/Config/mail.php                           |    2 +
 app/Entities/Models/Deletion.php              |    2 +-
 app/Entities/Models/Entity.php                |   10 +-
 app/Entities/Models/Page.php                  |    2 +-
 app/Entities/Tools/SearchOptions.php          |    4 +-
 app/Entities/Tools/SearchRunner.php           |    2 +-
 app/Exceptions/Handler.php                    |    9 +-
 app/Exceptions/NotifyException.php            |    2 +-
 app/Exceptions/PrettyException.php            |    2 +-
 .../StoppedAuthenticationException.php        |    2 +-
 app/Http/Controllers/PageController.php       |    2 +-
 app/Http/Middleware/TrustHosts.php            |   20 +
 app/Uploads/Attachment.php                    |    2 +-
 composer.json                                 |   31 +-
 composer.lock                                 | 2589 ++++++++---------
 ..._08_04_115700_create_bookshelves_table.php |   12 +-
 phpunit.xml                                   |    9 +-
 resources/lang/ar/auth.php                    |    4 +-
 resources/lang/ar/common.php                  |    2 +-
 resources/lang/ar/entities.php                |    2 +-
 resources/lang/ar/passwords.php               |    2 +-
 resources/lang/ar/settings.php                |    6 +-
 resources/lang/bg/auth.php                    |    4 +-
 resources/lang/bg/common.php                  |    2 +-
 resources/lang/bg/entities.php                |    2 +-
 resources/lang/bg/passwords.php               |    2 +-
 resources/lang/bg/settings.php                |    6 +-
 resources/lang/bs/auth.php                    |    4 +-
 resources/lang/bs/common.php                  |    2 +-
 resources/lang/bs/entities.php                |    2 +-
 resources/lang/bs/passwords.php               |    2 +-
 resources/lang/bs/settings.php                |    4 +-
 resources/lang/ca/auth.php                    |    4 +-
 resources/lang/ca/common.php                  |    2 +-
 resources/lang/ca/entities.php                |    2 +-
 resources/lang/ca/settings.php                |    4 +-
 resources/lang/cs/auth.php                    |    4 +-
 resources/lang/cs/common.php                  |    2 +-
 resources/lang/cs/entities.php                |    4 +-
 resources/lang/cs/passwords.php               |    2 +-
 resources/lang/cs/settings.php                |    6 +-
 resources/lang/da/auth.php                    |    4 +-
 resources/lang/da/common.php                  |    2 +-
 resources/lang/da/entities.php                |    2 +-
 resources/lang/da/passwords.php               |    2 +-
 resources/lang/da/settings.php                |    6 +-
 resources/lang/de/auth.php                    |    4 +-
 resources/lang/de/common.php                  |    2 +-
 resources/lang/de/entities.php                |    2 +-
 resources/lang/de/passwords.php               |    2 +-
 resources/lang/de/settings.php                |    6 +-
 resources/lang/de_informal/auth.php           |    4 +-
 resources/lang/de_informal/common.php         |    2 +-
 resources/lang/de_informal/entities.php       |    2 +-
 resources/lang/de_informal/passwords.php      |    2 +-
 resources/lang/de_informal/settings.php       |    6 +-
 resources/lang/en/auth.php                    |    4 +-
 resources/lang/en/common.php                  |    2 +-
 resources/lang/en/entities.php                |    2 +-
 resources/lang/en/settings.php                |    4 +-
 resources/lang/es/auth.php                    |    4 +-
 resources/lang/es/common.php                  |    2 +-
 resources/lang/es/entities.php                |    2 +-
 resources/lang/es/passwords.php               |    2 +-
 resources/lang/es/settings.php                |    6 +-
 resources/lang/es_AR/auth.php                 |    4 +-
 resources/lang/es_AR/common.php               |    2 +-
 resources/lang/es_AR/entities.php             |    2 +-
 resources/lang/es_AR/passwords.php            |    2 +-
 resources/lang/es_AR/settings.php             |    6 +-
 resources/lang/et/auth.php                    |    4 +-
 resources/lang/et/common.php                  |    2 +-
 resources/lang/et/entities.php                |    2 +-
 resources/lang/et/passwords.php               |    2 +-
 resources/lang/et/settings.php                |    6 +-
 resources/lang/fa/auth.php                    |    4 +-
 resources/lang/fa/common.php                  |    2 +-
 resources/lang/fa/entities.php                |    2 +-
 resources/lang/fa/passwords.php               |    2 +-
 resources/lang/fa/settings.php                |    4 +-
 resources/lang/fr/auth.php                    |    4 +-
 resources/lang/fr/common.php                  |    2 +-
 resources/lang/fr/entities.php                |    4 +-
 resources/lang/fr/settings.php                |    4 +-
 resources/lang/he/auth.php                    |    4 +-
 resources/lang/he/common.php                  |    2 +-
 resources/lang/he/entities.php                |    4 +-
 resources/lang/he/passwords.php               |    2 +-
 resources/lang/he/settings.php                |    6 +-
 resources/lang/hr/auth.php                    |    4 +-
 resources/lang/hr/common.php                  |    2 +-
 resources/lang/hr/entities.php                |    2 +-
 resources/lang/hr/settings.php                |    4 +-
 resources/lang/hu/auth.php                    |    4 +-
 resources/lang/hu/common.php                  |    2 +-
 resources/lang/hu/entities.php                |    2 +-
 resources/lang/hu/passwords.php               |    2 +-
 resources/lang/hu/settings.php                |    6 +-
 resources/lang/id/auth.php                    |    4 +-
 resources/lang/id/common.php                  |    2 +-
 resources/lang/id/entities.php                |    2 +-
 resources/lang/id/passwords.php               |    2 +-
 resources/lang/id/settings.php                |    6 +-
 resources/lang/it/auth.php                    |    4 +-
 resources/lang/it/common.php                  |    2 +-
 resources/lang/it/entities.php                |    2 +-
 resources/lang/it/passwords.php               |    2 +-
 resources/lang/it/settings.php                |    6 +-
 resources/lang/ja/auth.php                    |    4 +-
 resources/lang/ja/common.php                  |    2 +-
 resources/lang/ja/entities.php                |    4 +-
 resources/lang/ja/passwords.php               |    2 +-
 resources/lang/ja/settings.php                |    6 +-
 resources/lang/ko/auth.php                    |    4 +-
 resources/lang/ko/common.php                  |    2 +-
 resources/lang/ko/entities.php                |    6 +-
 resources/lang/ko/errors.php                  |    2 +-
 resources/lang/ko/passwords.php               |    2 +-
 resources/lang/ko/settings.php                |    6 +-
 resources/lang/lt/auth.php                    |    4 +-
 resources/lang/lt/common.php                  |    2 +-
 resources/lang/lt/entities.php                |    2 +-
 resources/lang/lt/settings.php                |    4 +-
 resources/lang/lv/auth.php                    |    4 +-
 resources/lang/lv/common.php                  |    2 +-
 resources/lang/lv/entities.php                |    4 +-
 resources/lang/lv/passwords.php               |    2 +-
 resources/lang/lv/settings.php                |    6 +-
 resources/lang/nb/auth.php                    |    4 +-
 resources/lang/nb/common.php                  |    2 +-
 resources/lang/nb/entities.php                |    2 +-
 resources/lang/nb/passwords.php               |    2 +-
 resources/lang/nb/settings.php                |    6 +-
 resources/lang/nl/auth.php                    |    4 +-
 resources/lang/nl/common.php                  |    2 +-
 resources/lang/nl/entities.php                |    2 +-
 resources/lang/nl/passwords.php               |    2 +-
 resources/lang/nl/settings.php                |    6 +-
 resources/lang/pl/auth.php                    |    4 +-
 resources/lang/pl/common.php                  |    2 +-
 resources/lang/pl/entities.php                |    2 +-
 resources/lang/pl/passwords.php               |    2 +-
 resources/lang/pl/settings.php                |    6 +-
 resources/lang/pt/auth.php                    |    4 +-
 resources/lang/pt/common.php                  |    2 +-
 resources/lang/pt/entities.php                |    2 +-
 resources/lang/pt/passwords.php               |    2 +-
 resources/lang/pt/settings.php                |    6 +-
 resources/lang/pt_BR/auth.php                 |    4 +-
 resources/lang/pt_BR/common.php               |    2 +-
 resources/lang/pt_BR/entities.php             |    2 +-
 resources/lang/pt_BR/passwords.php            |    2 +-
 resources/lang/pt_BR/settings.php             |    6 +-
 resources/lang/ru/auth.php                    |    4 +-
 resources/lang/ru/common.php                  |    2 +-
 resources/lang/ru/entities.php                |    4 +-
 resources/lang/ru/errors.php                  |    2 +-
 resources/lang/ru/passwords.php               |    2 +-
 resources/lang/ru/settings.php                |    6 +-
 resources/lang/sk/auth.php                    |    4 +-
 resources/lang/sk/common.php                  |    2 +-
 resources/lang/sk/entities.php                |    2 +-
 resources/lang/sk/passwords.php               |    2 +-
 resources/lang/sk/settings.php                |    6 +-
 resources/lang/sl/auth.php                    |    4 +-
 resources/lang/sl/common.php                  |    2 +-
 resources/lang/sl/entities.php                |    2 +-
 resources/lang/sl/passwords.php               |    2 +-
 resources/lang/sl/settings.php                |    6 +-
 resources/lang/sv/auth.php                    |    4 +-
 resources/lang/sv/common.php                  |    2 +-
 resources/lang/sv/entities.php                |    2 +-
 resources/lang/sv/passwords.php               |    2 +-
 resources/lang/sv/settings.php                |    6 +-
 resources/lang/th/auth.php                    |    6 +-
 resources/lang/th/common.php                  |    2 +-
 resources/lang/th/entities.php                |    4 +-
 resources/lang/th/settings.php                |    4 +-
 resources/lang/tr/auth.php                    |    4 +-
 resources/lang/tr/common.php                  |    2 +-
 resources/lang/tr/entities.php                |    4 +-
 resources/lang/tr/passwords.php               |    2 +-
 resources/lang/tr/settings.php                |    6 +-
 resources/lang/uk/auth.php                    |    4 +-
 resources/lang/uk/common.php                  |    2 +-
 resources/lang/uk/entities.php                |    2 +-
 resources/lang/uk/passwords.php               |    2 +-
 resources/lang/uk/settings.php                |    6 +-
 resources/lang/vi/auth.php                    |    4 +-
 resources/lang/vi/common.php                  |    2 +-
 resources/lang/vi/entities.php                |    2 +-
 resources/lang/vi/passwords.php               |    2 +-
 resources/lang/vi/settings.php                |    6 +-
 resources/lang/zh_CN/auth.php                 |    4 +-
 resources/lang/zh_CN/common.php               |    2 +-
 resources/lang/zh_CN/entities.php             |    2 +-
 resources/lang/zh_CN/passwords.php            |    2 +-
 resources/lang/zh_CN/settings.php             |    6 +-
 resources/lang/zh_TW/auth.php                 |    4 +-
 resources/lang/zh_TW/common.php               |    2 +-
 resources/lang/zh_TW/entities.php             |    4 +-
 resources/lang/zh_TW/passwords.php            |    2 +-
 resources/lang/zh_TW/settings.php             |    6 +-
 tests/Api/AttachmentsApiTest.php              |    2 +-
 tests/Auth/MfaConfigurationTest.php           |    6 +-
 tests/Auth/Saml2Test.php                      |    2 +-
 tests/Entity/BookShelfTest.php                |    2 +-
 tests/Entity/BookTest.php                     |    2 +-
 tests/Entity/CommentTest.php                  |    6 +-
 tests/Entity/ExportTest.php                   |   14 +-
 tests/Entity/PageContentTest.php              |   16 +-
 tests/Permissions/RolesTest.php               |    6 +-
 tests/SecurityHeaderTest.php                  |    2 +-
 tests/Settings/CustomHeadContentTest.php      |    8 +-
 tests/Settings/FooterLinksTest.php            |    8 +-
 tests/SharedTestHelpers.php                   |    4 +-
 tests/TestResponse.php                        |    2 +-
 tests/Uploads/AttachmentTest.php              |    4 +-
 tests/Uploads/DrawioTest.php                  |    6 +-
 225 files changed, 1618 insertions(+), 1804 deletions(-)
 create mode 100644 app/Http/Middleware/TrustHosts.php

diff --git a/app/Actions/Activity.php b/app/Actions/Activity.php
index 6a8a9bcd0..3b1408cb9 100644
--- a/app/Actions/Activity.php
+++ b/app/Actions/Activity.php
@@ -61,7 +61,7 @@ class Activity extends Model
     /**
      * Checks if another Activity matches the general information of another.
      */
-    public function isSimilarTo(Activity $activityB): bool
+    public function isSimilarTo(self $activityB): bool
     {
         return [$this->type, $this->entity_type, $this->entity_id] === [$activityB->type, $activityB->entity_type, $activityB->entity_id];
     }
diff --git a/app/Api/ApiToken.php b/app/Api/ApiToken.php
index f44fde19a..70b289ae1 100644
--- a/app/Api/ApiToken.php
+++ b/app/Api/ApiToken.php
@@ -43,7 +43,7 @@ class ApiToken extends Model implements Loggable
     }
 
     /**
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function logDescriptor(): string
     {
diff --git a/app/Api/ApiTokenGuard.php b/app/Api/ApiTokenGuard.php
index 8b9cbc8e1..1bb672556 100644
--- a/app/Api/ApiTokenGuard.php
+++ b/app/Api/ApiTokenGuard.php
@@ -42,7 +42,7 @@ class ApiTokenGuard implements Guard
     }
 
     /**
-     * @inheritDoc
+     * {@inheritdoc}
      */
     public function user()
     {
@@ -152,7 +152,7 @@ class ApiTokenGuard implements Guard
     }
 
     /**
-     * @inheritDoc
+     * {@inheritdoc}
      */
     public function validate(array $credentials = [])
     {
diff --git a/app/Auth/Role.php b/app/Auth/Role.php
index 46921caeb..fc2e39aa9 100644
--- a/app/Auth/Role.php
+++ b/app/Auth/Role.php
@@ -83,7 +83,7 @@ class Role extends Model implements Loggable
     /**
      * Get the role of the specified display name.
      */
-    public static function getRole(string $displayName): ?Role
+    public static function getRole(string $displayName): ?self
     {
         return static::query()->where('display_name', '=', $displayName)->first();
     }
@@ -91,7 +91,7 @@ class Role extends Model implements Loggable
     /**
      * Get the role object for the specified system role.
      */
-    public static function getSystemRole(string $systemName): ?Role
+    public static function getSystemRole(string $systemName): ?self
     {
         return static::query()->where('system_name', '=', $systemName)->first();
     }
@@ -116,7 +116,7 @@ class Role extends Model implements Loggable
     }
 
     /**
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function logDescriptor(): string
     {
diff --git a/app/Auth/SocialAccount.php b/app/Auth/SocialAccount.php
index f076ecdd4..6cf0224a8 100644
--- a/app/Auth/SocialAccount.php
+++ b/app/Auth/SocialAccount.php
@@ -21,7 +21,7 @@ class SocialAccount extends Model implements Loggable
     }
 
     /**
-     * @inheritDoc
+     * {@inheritdoc}
      */
     public function logDescriptor(): string
     {
diff --git a/app/Auth/User.php b/app/Auth/User.php
index 0a6849fe0..aa8b44e9f 100644
--- a/app/Auth/User.php
+++ b/app/Auth/User.php
@@ -90,7 +90,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
     /**
      * Returns the default public user.
      */
-    public static function getDefault(): User
+    public static function getDefault(): self
     {
         if (!is_null(static::$defaultUser)) {
             return static::$defaultUser;
@@ -336,7 +336,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
     }
 
     /**
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function logDescriptor(): string
     {
@@ -344,7 +344,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
     }
 
     /**
-     * @inheritDoc
+     * {@inheritdoc}
      */
     public function refreshSlug(): string
     {
diff --git a/app/Config/mail.php b/app/Config/mail.php
index 34b28fe2a..b223e382a 100644
--- a/app/Config/mail.php
+++ b/app/Config/mail.php
@@ -11,6 +11,8 @@
 return [
 
     // Mail driver to use.
+    // From Laravel 7+ this is MAIL_MAILER in laravel.
+    // Kept as MAIL_DRIVER in BookStack to prevent breaking change.
     // Options: smtp, sendmail, log, array
     'driver' => env('MAIL_DRIVER', 'smtp'),
 
diff --git a/app/Entities/Models/Deletion.php b/app/Entities/Models/Deletion.php
index 764c4a1e3..dab89ce37 100644
--- a/app/Entities/Models/Deletion.php
+++ b/app/Entities/Models/Deletion.php
@@ -32,7 +32,7 @@ class Deletion extends Model implements Loggable
     /**
      * Create a new deletion record for the provided entity.
      */
-    public static function createForEntity(Entity $entity): Deletion
+    public static function createForEntity(Entity $entity): self
     {
         $record = (new self())->forceFill([
             'deleted_by'     => user()->id,
diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php
index a02926c4d..f5f9d91f0 100644
--- a/app/Entities/Models/Entity.php
+++ b/app/Entities/Models/Entity.php
@@ -106,7 +106,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
      * Compares this entity to another given entity.
      * Matches by comparing class and id.
      */
-    public function matches(Entity $entity): bool
+    public function matches(self $entity): bool
     {
         return [get_class($this), $this->id] === [get_class($entity), $entity->id];
     }
@@ -114,7 +114,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
     /**
      * Checks if the current entity matches or contains the given.
      */
-    public function matchesOrContains(Entity $entity): bool
+    public function matchesOrContains(self $entity): bool
     {
         if ($this->matches($entity)) {
             return true;
@@ -270,7 +270,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
      * This is the "static" parent and does not include dynamic
      * relations such as shelves to books.
      */
-    public function getParent(): ?Entity
+    public function getParent(): ?self
     {
         if ($this instanceof Page) {
             return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book()->withTrashed()->first();
@@ -300,7 +300,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
     }
 
     /**
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function refreshSlug(): string
     {
@@ -310,7 +310,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
     }
 
     /**
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function favourites(): MorphMany
     {
diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php
index 601e9630d..452965667 100644
--- a/app/Entities/Models/Page.php
+++ b/app/Entities/Models/Page.php
@@ -129,7 +129,7 @@ class Page extends BookChild
     /**
      * Get this page for JSON display.
      */
-    public function forJsonDisplay(): Page
+    public function forJsonDisplay(): self
     {
         $refreshed = $this->refresh()->unsetRelations()->load(['tags', 'createdBy', 'updatedBy', 'ownedBy']);
         $refreshed->setHidden(array_diff($refreshed->getHidden(), ['html', 'markdown']));
diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php
index 7913e0969..5ce64cc65 100644
--- a/app/Entities/Tools/SearchOptions.php
+++ b/app/Entities/Tools/SearchOptions.php
@@ -29,7 +29,7 @@ class SearchOptions
     /**
      * Create a new instance from a search string.
      */
-    public static function fromString(string $search): SearchOptions
+    public static function fromString(string $search): self
     {
         $decoded = static::decode($search);
         $instance = new static();
@@ -45,7 +45,7 @@ class SearchOptions
      * Will look for a classic string term and use that
      * Otherwise we'll use the details from an advanced search form.
      */
-    public static function fromRequest(Request $request): SearchOptions
+    public static function fromRequest(Request $request): self
     {
         if (!$request->has('search') && !$request->has('term')) {
             return static::fromString('');
diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php
index ca592755b..df566eb0b 100644
--- a/app/Entities/Tools/SearchRunner.php
+++ b/app/Entities/Tools/SearchRunner.php
@@ -196,7 +196,7 @@ class SearchRunner
             $escapedOperators[] = preg_quote($operator);
         }
 
-        return join('|', $escapedOperators);
+        return implode('|', $escapedOperators);
     }
 
     /**
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 2d40f4476..63b5cfc5a 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -9,6 +9,7 @@ use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Validation\ValidationException;
 use Symfony\Component\HttpKernel\Exception\HttpException;
+use Throwable;
 
 class Handler extends ExceptionHandler
 {
@@ -34,13 +35,13 @@ class Handler extends ExceptionHandler
     /**
      * Report or log an exception.
      *
-     * @param Exception $exception
+     * @param \Throwable $exception
      *
-     * @throws Exception
+     * @throws \Throwable
      *
      * @return void
      */
-    public function report(Exception $exception)
+    public function report(Throwable $exception)
     {
         parent::report($exception);
     }
@@ -53,7 +54,7 @@ class Handler extends ExceptionHandler
      *
      * @return \Illuminate\Http\Response
      */
-    public function render($request, Exception $e)
+    public function render($request, Throwable $e)
     {
         if ($this->isApiRequest($request)) {
             return $this->renderApiException($e);
diff --git a/app/Exceptions/NotifyException.php b/app/Exceptions/NotifyException.php
index ef9a44101..8e748a21d 100644
--- a/app/Exceptions/NotifyException.php
+++ b/app/Exceptions/NotifyException.php
@@ -23,7 +23,7 @@ class NotifyException extends Exception implements Responsable
     /**
      * Send the response for this type of exception.
      *
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function toResponse($request)
     {
diff --git a/app/Exceptions/PrettyException.php b/app/Exceptions/PrettyException.php
index 33c1471f2..f446442d0 100644
--- a/app/Exceptions/PrettyException.php
+++ b/app/Exceptions/PrettyException.php
@@ -20,7 +20,7 @@ class PrettyException extends Exception implements Responsable
     /**
      * Render a response for when this exception occurs.
      *
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function toResponse($request)
     {
diff --git a/app/Exceptions/StoppedAuthenticationException.php b/app/Exceptions/StoppedAuthenticationException.php
index d10a6da5e..b9aadb03f 100644
--- a/app/Exceptions/StoppedAuthenticationException.php
+++ b/app/Exceptions/StoppedAuthenticationException.php
@@ -23,7 +23,7 @@ class StoppedAuthenticationException extends \Exception implements Responsable
     }
 
     /**
-     * @inheritdoc
+     * {@inheritdoc}
      */
     public function toResponse($request)
     {
diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php
index a94a61803..ddb15a7aa 100644
--- a/app/Http/Controllers/PageController.php
+++ b/app/Http/Controllers/PageController.php
@@ -176,7 +176,7 @@ class PageController extends Controller
     {
         $page = $this->pageRepo->getById($pageId);
         $page->setHidden(array_diff($page->getHidden(), ['html', 'markdown']));
-        $page->addHidden(['book']);
+        $page->makeHidden(['book']);
 
         return response()->json($page);
     }
diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php
new file mode 100644
index 000000000..b0550cfc7
--- /dev/null
+++ b/app/Http/Middleware/TrustHosts.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Http\Middleware\TrustHosts as Middleware;
+
+class TrustHosts extends Middleware
+{
+    /**
+     * Get the host patterns that should be trusted.
+     *
+     * @return array
+     */
+    public function hosts()
+    {
+        return [
+            $this->allSubdomainsOfApplicationUrl(),
+        ];
+    }
+}
diff --git a/app/Uploads/Attachment.php b/app/Uploads/Attachment.php
index a470ec534..5e637246a 100644
--- a/app/Uploads/Attachment.php
+++ b/app/Uploads/Attachment.php
@@ -93,7 +93,7 @@ class Attachment extends Model
 
         return $permissionService->filterRelatedEntity(
             Page::class,
-            Attachment::query(),
+            self::query(),
             'attachments',
             'uploaded_to'
         );
diff --git a/composer.json b/composer.json
index fa2c0c2b5..b50cee762 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,10 @@
 {
     "name": "bookstackapp/bookstack",
     "description": "BookStack documentation platform",
-    "keywords": ["BookStack", "Documentation"],
+    "keywords": [
+        "BookStack",
+        "Documentation"
+    ],
     "license": "MIT",
     "type": "project",
     "require": {
@@ -16,17 +19,16 @@
         "bacon/bacon-qr-code": "^2.0",
         "barryvdh/laravel-dompdf": "^0.9.0",
         "barryvdh/laravel-snappy": "^0.4.8",
-        "doctrine/dbal": "^2.12.1",
+        "doctrine/dbal": "^3.1",
         "fideloper/proxy": "^4.4.1",
         "filp/whoops": "^2.14",
-        "intervention/image": "^2.5.1",
-        "laravel/framework": "^6.20.33",
-        "laravel/socialite": "^5.1",
+        "intervention/image": "^2.7",
+        "laravel/framework": "^7.29",
+        "laravel/socialite": "^5.2",
         "league/commonmark": "^1.5",
         "league/flysystem-aws-s3-v3": "^1.0.29",
         "league/html-to-markdown": "^5.0.0",
         "league/oauth2-client": "^2.6",
-        "nunomaduro/collision": "^3.1",
         "onelogin/php-saml": "^4.0",
         "phpseclib/phpseclib": "~3.0",
         "pragmarx/google2fa": "^8.0",
@@ -37,15 +39,18 @@
         "socialiteproviders/okta": "^4.1",
         "socialiteproviders/slack": "^4.1",
         "socialiteproviders/twitch": "^5.3",
-        "ssddanbrown/htmldiff": "^v1.0.1"
+        "ssddanbrown/htmldiff": "^1.0.1",
+        "laravel/ui": "^2.5",
+        "guzzlehttp/guzzle": "^7.4.0",
+        "laravel/tinker": "^2.5"
     },
     "require-dev": {
-        "barryvdh/laravel-debugbar": "^3.5.1",
-        "barryvdh/laravel-ide-helper": "^2.8.2",
+        "barryvdh/laravel-debugbar": "^3.6",
         "fakerphp/faker": "^1.13.0",
         "mockery/mockery": "^1.3.3",
         "phpunit/phpunit": "^9.5.3",
-        "symfony/dom-crawler": "^5.3"
+        "symfony/dom-crawler": "^5.3",
+        "nunomaduro/collision": "^4.3"
     },
     "autoload": {
         "classmap": [
@@ -55,9 +60,9 @@
         "psr-4": {
             "BookStack\\": "app/"
         },
-		"files": [
-			"app/helpers.php"
-		]
+        "files": [
+            "app/helpers.php"
+        ]
     },
     "autoload-dev": {
         "psr-4": {
diff --git a/composer.lock b/composer.lock
index 318544c5a..f07d61062 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "fc6d8f731e3975127a9101802cc4bb3a",
+    "content-hash": "491a3de7d49182613d0c81032a7001e1",
     "packages": [
         {
             "name": "aws/aws-crt-php",
@@ -58,16 +58,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.199.3",
+            "version": "3.199.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "132a1148ebb63d04023837bcf9a36f49b308a0bd"
+                "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/132a1148ebb63d04023837bcf9a36f49b308a0bd",
-                "reference": "132a1148ebb63d04023837bcf9a36f49b308a0bd",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/047f6ce04b1de9320ca00bf393d6f03b9d036fa5",
+                "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5",
                 "shasum": ""
             },
             "require": {
@@ -143,9 +143,9 @@
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.199.3"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.199.4"
             },
-            "time": "2021-10-25T18:17:28+00:00"
+            "time": "2021-10-26T18:14:35+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -331,6 +331,139 @@
             },
             "time": "2020-09-07T12:33:10+00:00"
         },
+        {
+            "name": "brick/math",
+            "version": "0.9.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/brick/math.git",
+                "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
+                "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "^2.2",
+                "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
+                "vimeo/psalm": "4.9.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Brick\\Math\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Arbitrary-precision arithmetic library",
+            "keywords": [
+                "Arbitrary-precision",
+                "BigInteger",
+                "BigRational",
+                "arithmetic",
+                "bigdecimal",
+                "bignum",
+                "brick",
+                "math"
+            ],
+            "support": {
+                "issues": "https://github.com/brick/math/issues",
+                "source": "https://github.com/brick/math/tree/0.9.3"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/BenMorel",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/brick/math",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-08-15T20:50:18+00:00"
+        },
+        {
+            "name": "composer/package-versions-deprecated",
+            "version": "1.11.99.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/composer/package-versions-deprecated.git",
+                "reference": "b174585d1fe49ceed21928a945138948cb394600"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b174585d1fe49ceed21928a945138948cb394600",
+                "reference": "b174585d1fe49ceed21928a945138948cb394600",
+                "shasum": ""
+            },
+            "require": {
+                "composer-plugin-api": "^1.1.0 || ^2.0",
+                "php": "^7 || ^8"
+            },
+            "replace": {
+                "ocramius/package-versions": "1.11.99"
+            },
+            "require-dev": {
+                "composer/composer": "^1.9.3 || ^2.0@dev",
+                "ext-zip": "^1.13",
+                "phpunit/phpunit": "^6.5 || ^7"
+            },
+            "type": "composer-plugin",
+            "extra": {
+                "class": "PackageVersions\\Installer",
+                "branch-alias": {
+                    "dev-master": "1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "PackageVersions\\": "src/PackageVersions"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Marco Pivetta",
+                    "email": "ocramius@gmail.com"
+                },
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be"
+                }
+            ],
+            "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
+            "support": {
+                "issues": "https://github.com/composer/package-versions-deprecated/issues",
+                "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.4"
+            },
+            "funding": [
+                {
+                    "url": "https://packagist.com",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/composer",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-09-13T08:41:34+00:00"
+        },
         {
             "name": "dasprid/enum",
             "version": "1.0.3",
@@ -479,34 +612,35 @@
         },
         {
             "name": "doctrine/dbal",
-            "version": "2.13.4",
+            "version": "3.1.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/dbal.git",
-                "reference": "2411a55a2a628e6d8dd598388ab13474802c7b6e"
+                "reference": "96b0053775a544b4a6ab47654dac0621be8b4cf8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/dbal/zipball/2411a55a2a628e6d8dd598388ab13474802c7b6e",
-                "reference": "2411a55a2a628e6d8dd598388ab13474802c7b6e",
+                "url": "https://api.github.com/repos/doctrine/dbal/zipball/96b0053775a544b4a6ab47654dac0621be8b4cf8",
+                "reference": "96b0053775a544b4a6ab47654dac0621be8b4cf8",
                 "shasum": ""
             },
             "require": {
+                "composer/package-versions-deprecated": "^1.11.99",
                 "doctrine/cache": "^1.0|^2.0",
                 "doctrine/deprecations": "^0.5.3",
                 "doctrine/event-manager": "^1.0",
-                "ext-pdo": "*",
-                "php": "^7.1 || ^8"
+                "php": "^7.3 || ^8.0"
             },
             "require-dev": {
                 "doctrine/coding-standard": "9.0.0",
                 "jetbrains/phpstorm-stubs": "2021.1",
                 "phpstan/phpstan": "0.12.99",
-                "phpunit/phpunit": "^7.5.20|^8.5|9.5.10",
+                "phpstan/phpstan-strict-rules": "^0.12.11",
+                "phpunit/phpunit": "9.5.10",
                 "psalm/plugin-phpunit": "0.16.1",
                 "squizlabs/php_codesniffer": "3.6.0",
-                "symfony/cache": "^4.4",
-                "symfony/console": "^2.0.5|^3.0|^4.0|^5.0",
+                "symfony/cache": "^5.2|^6.0",
+                "symfony/console": "^2.0.5|^3.0|^4.0|^5.0|^6.0",
                 "vimeo/psalm": "4.10.0"
             },
             "suggest": {
@@ -518,7 +652,7 @@
             "type": "library",
             "autoload": {
                 "psr-4": {
-                    "Doctrine\\DBAL\\": "lib/Doctrine/DBAL"
+                    "Doctrine\\DBAL\\": "src"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -561,14 +695,13 @@
                 "queryobject",
                 "sasql",
                 "sql",
-                "sqlanywhere",
                 "sqlite",
                 "sqlserver",
                 "sqlsrv"
             ],
             "support": {
                 "issues": "https://github.com/doctrine/dbal/issues",
-                "source": "https://github.com/doctrine/dbal/tree/2.13.4"
+                "source": "https://github.com/doctrine/dbal/tree/3.1.3"
             },
             "funding": [
                 {
@@ -584,7 +717,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-10-02T15:59:26+00:00"
+            "time": "2021-10-02T16:15:05+00:00"
         },
         {
             "name": "doctrine/deprecations",
@@ -1710,16 +1843,16 @@
         },
         {
             "name": "laravel/framework",
-            "version": "v6.20.36",
+            "version": "v7.30.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "10f6bfaec9efb68aa88d7196b8b1b162d83040ae"
+                "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/10f6bfaec9efb68aa88d7196b8b1b162d83040ae",
-                "reference": "10f6bfaec9efb68aa88d7196b8b1b162d83040ae",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/9dd38140dc2924daa1a020a3d7a45f9ceff03df3",
+                "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3",
                 "shasum": ""
             },
             "require": {
@@ -1731,29 +1864,34 @@
                 "ext-openssl": "*",
                 "league/commonmark": "^1.3",
                 "league/flysystem": "^1.1",
-                "monolog/monolog": "^1.12|^2.0",
+                "monolog/monolog": "^2.0",
                 "nesbot/carbon": "^2.31",
                 "opis/closure": "^3.6",
                 "php": "^7.2.5|^8.0",
                 "psr/container": "^1.0",
                 "psr/simple-cache": "^1.0",
-                "ramsey/uuid": "^3.7",
+                "ramsey/uuid": "^3.7|^4.0",
                 "swiftmailer/swiftmailer": "^6.0",
-                "symfony/console": "^4.3.4",
-                "symfony/debug": "^4.3.4",
-                "symfony/finder": "^4.3.4",
-                "symfony/http-foundation": "^4.3.4",
-                "symfony/http-kernel": "^4.3.4",
+                "symfony/console": "^5.0",
+                "symfony/error-handler": "^5.0",
+                "symfony/finder": "^5.0",
+                "symfony/http-foundation": "^5.0",
+                "symfony/http-kernel": "^5.0",
+                "symfony/mime": "^5.0",
                 "symfony/polyfill-php73": "^1.17",
-                "symfony/process": "^4.3.4",
-                "symfony/routing": "^4.3.4",
-                "symfony/var-dumper": "^4.3.4",
-                "tijsverkoyen/css-to-inline-styles": "^2.2.1",
-                "vlucas/phpdotenv": "^3.3"
+                "symfony/process": "^5.0",
+                "symfony/routing": "^5.0",
+                "symfony/var-dumper": "^5.0",
+                "tijsverkoyen/css-to-inline-styles": "^2.2.2",
+                "vlucas/phpdotenv": "^4.0",
+                "voku/portable-ascii": "^1.4.8"
             },
             "conflict": {
                 "tightenco/collect": "<5.5.33"
             },
+            "provide": {
+                "psr/container-implementation": "1.0"
+            },
             "replace": {
                 "illuminate/auth": "self.version",
                 "illuminate/broadcasting": "self.version",
@@ -1780,6 +1918,7 @@
                 "illuminate/routing": "self.version",
                 "illuminate/session": "self.version",
                 "illuminate/support": "self.version",
+                "illuminate/testing": "self.version",
                 "illuminate/translation": "self.version",
                 "illuminate/validation": "self.version",
                 "illuminate/view": "self.version"
@@ -1792,11 +1931,11 @@
                 "league/flysystem-cached-adapter": "^1.0",
                 "mockery/mockery": "~1.3.3|^1.4.2",
                 "moontoast/math": "^1.1",
-                "orchestra/testbench-core": "^4.8",
+                "orchestra/testbench-core": "^5.8",
                 "pda/pheanstalk": "^4.0",
-                "phpunit/phpunit": "^7.5.15|^8.4|^9.3.3",
+                "phpunit/phpunit": "^8.4|^9.3.3",
                 "predis/predis": "^1.1.1",
-                "symfony/cache": "^4.3.4"
+                "symfony/cache": "^5.0"
             },
             "suggest": {
                 "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).",
@@ -1809,25 +1948,28 @@
                 "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).",
                 "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
                 "filp/whoops": "Required for friendly error pages in development (^2.8).",
-                "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).",
+                "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).",
                 "laravel/tinker": "Required to use the tinker console command (^2.0).",
                 "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).",
                 "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).",
                 "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).",
+                "mockery/mockery": "Required to use mocking (~1.3.3|^1.4.2).",
                 "moontoast/math": "Required to use ordered UUIDs (^1.1).",
                 "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).",
                 "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).",
+                "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.3.3).",
                 "predis/predis": "Required to use the predis connector (^1.1.2).",
                 "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
                 "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).",
-                "symfony/cache": "Required to PSR-6 cache bridge (^4.3.4).",
-                "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^1.2).",
+                "symfony/cache": "Required to PSR-6 cache bridge (^5.0).",
+                "symfony/filesystem": "Required to create relative storage directory symbolic links (^5.0).",
+                "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).",
                 "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)."
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "6.x-dev"
+                    "dev-master": "7.x-dev"
                 }
             },
             "autoload": {
@@ -1859,7 +2001,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2021-10-19T13:59:55+00:00"
+            "time": "2021-01-21T14:10:48+00:00"
         },
         {
             "name": "laravel/socialite",
@@ -1930,6 +2072,129 @@
             },
             "time": "2021-08-31T15:16:26+00:00"
         },
+        {
+            "name": "laravel/tinker",
+            "version": "v2.6.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/laravel/tinker.git",
+                "reference": "c808a7227f97ecfd9219fbf913bad842ea854ddc"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/laravel/tinker/zipball/c808a7227f97ecfd9219fbf913bad842ea854ddc",
+                "reference": "c808a7227f97ecfd9219fbf913bad842ea854ddc",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/console": "^6.0|^7.0|^8.0",
+                "illuminate/contracts": "^6.0|^7.0|^8.0",
+                "illuminate/support": "^6.0|^7.0|^8.0",
+                "php": "^7.2.5|^8.0",
+                "psy/psysh": "^0.10.4",
+                "symfony/var-dumper": "^4.3.4|^5.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "~1.3.3|^1.4.2",
+                "phpunit/phpunit": "^8.5.8|^9.3.3"
+            },
+            "suggest": {
+                "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.x-dev"
+                },
+                "laravel": {
+                    "providers": [
+                        "Laravel\\Tinker\\TinkerServiceProvider"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Laravel\\Tinker\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "Powerful REPL for the Laravel framework.",
+            "keywords": [
+                "REPL",
+                "Tinker",
+                "laravel",
+                "psysh"
+            ],
+            "support": {
+                "issues": "https://github.com/laravel/tinker/issues",
+                "source": "https://github.com/laravel/tinker/tree/v2.6.2"
+            },
+            "time": "2021-09-28T15:47:34+00:00"
+        },
+        {
+            "name": "laravel/ui",
+            "version": "v2.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/laravel/ui.git",
+                "reference": "d01a705763c243b07be795e9d1bb47f89260f73d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/laravel/ui/zipball/d01a705763c243b07be795e9d1bb47f89260f73d",
+                "reference": "d01a705763c243b07be795e9d1bb47f89260f73d",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/console": "^7.0",
+                "illuminate/filesystem": "^7.0",
+                "illuminate/support": "^7.0",
+                "php": "^7.2.5|^8.0"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "Laravel\\Ui\\UiServiceProvider"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Laravel\\Ui\\": "src/",
+                    "Illuminate\\Foundation\\Auth\\": "auth-backend/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "Laravel UI utilities and presets.",
+            "keywords": [
+                "laravel",
+                "ui"
+            ],
+            "support": {
+                "issues": "https://github.com/laravel/ui/issues",
+                "source": "https://github.com/laravel/ui/tree/v2.5.0"
+            },
+            "time": "2020-11-03T19:45:19+00:00"
+        },
         {
             "name": "league/commonmark",
             "version": "1.6.6",
@@ -2722,84 +2987,60 @@
             "time": "2021-09-06T09:29:23+00:00"
         },
         {
-            "name": "nunomaduro/collision",
-            "version": "v3.2.0",
+            "name": "nikic/php-parser",
+            "version": "v4.13.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/nunomaduro/collision.git",
-                "reference": "f7c45764dfe4ba5f2618d265a6f1f9c72732e01d"
+                "url": "https://github.com/nikic/PHP-Parser.git",
+                "reference": "50953a2691a922aa1769461637869a0a2faa3f53"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f7c45764dfe4ba5f2618d265a6f1f9c72732e01d",
-                "reference": "f7c45764dfe4ba5f2618d265a6f1f9c72732e01d",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53",
+                "reference": "50953a2691a922aa1769461637869a0a2faa3f53",
                 "shasum": ""
             },
             "require": {
-                "filp/whoops": "^2.1.4",
-                "php": "^7.2.5 || ^8.0",
-                "php-parallel-lint/php-console-highlighter": "0.5.*",
-                "symfony/console": "~2.8|~3.3|~4.0"
+                "ext-tokenizer": "*",
+                "php": ">=7.0"
             },
             "require-dev": {
-                "laravel/framework": "^6.0",
-                "phpunit/phpunit": "^8.0 || ^9.0"
+                "ircmaxell/php-yacc": "^0.0.7",
+                "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
             },
+            "bin": [
+                "bin/php-parse"
+            ],
             "type": "library",
             "extra": {
-                "laravel": {
-                    "providers": [
-                        "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider"
-                    ]
+                "branch-alias": {
+                    "dev-master": "4.9-dev"
                 }
             },
             "autoload": {
                 "psr-4": {
-                    "NunoMaduro\\Collision\\": "src/"
+                    "PhpParser\\": "lib/PhpParser"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
-                "MIT"
+                "BSD-3-Clause"
             ],
             "authors": [
                 {
-                    "name": "Nuno Maduro",
-                    "email": "enunomaduro@gmail.com"
+                    "name": "Nikita Popov"
                 }
             ],
-            "description": "Cli error handling for console/command-line PHP applications.",
+            "description": "A PHP parser written in PHP",
             "keywords": [
-                "artisan",
-                "cli",
-                "command-line",
-                "console",
-                "error",
-                "handling",
-                "laravel",
-                "laravel-zero",
-                "php",
-                "symfony"
+                "parser",
+                "php"
             ],
             "support": {
-                "issues": "https://github.com/nunomaduro/collision/issues",
-                "source": "https://github.com/nunomaduro/collision"
+                "issues": "https://github.com/nikic/PHP-Parser/issues",
+                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0"
             },
-            "funding": [
-                {
-                    "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/nunomaduro",
-                    "type": "github"
-                },
-                {
-                    "url": "https://www.patreon.com/nunomaduro",
-                    "type": "patreon"
-                }
-            ],
-            "time": "2021-02-11T09:01:42+00:00"
+            "time": "2021-09-20T12:20:58+00:00"
         },
         {
             "name": "onelogin/php-saml",
@@ -3124,108 +3365,6 @@
             },
             "time": "2019-09-11T20:02:13+00:00"
         },
-        {
-            "name": "php-parallel-lint/php-console-color",
-            "version": "v0.3",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-parallel-lint/PHP-Console-Color.git",
-                "reference": "b6af326b2088f1ad3b264696c9fd590ec395b49e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/php-parallel-lint/PHP-Console-Color/zipball/b6af326b2088f1ad3b264696c9fd590ec395b49e",
-                "reference": "b6af326b2088f1ad3b264696c9fd590ec395b49e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.4.0"
-            },
-            "replace": {
-                "jakub-onderka/php-console-color": "*"
-            },
-            "require-dev": {
-                "php-parallel-lint/php-code-style": "1.0",
-                "php-parallel-lint/php-parallel-lint": "1.0",
-                "php-parallel-lint/php-var-dump-check": "0.*",
-                "phpunit/phpunit": "~4.3",
-                "squizlabs/php_codesniffer": "1.*"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "JakubOnderka\\PhpConsoleColor\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-2-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jakub Onderka",
-                    "email": "jakub.onderka@gmail.com"
-                }
-            ],
-            "support": {
-                "issues": "https://github.com/php-parallel-lint/PHP-Console-Color/issues",
-                "source": "https://github.com/php-parallel-lint/PHP-Console-Color/tree/master"
-            },
-            "time": "2020-05-14T05:47:14+00:00"
-        },
-        {
-            "name": "php-parallel-lint/php-console-highlighter",
-            "version": "v0.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-parallel-lint/PHP-Console-Highlighter.git",
-                "reference": "21bf002f077b177f056d8cb455c5ed573adfdbb8"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/php-parallel-lint/PHP-Console-Highlighter/zipball/21bf002f077b177f056d8cb455c5ed573adfdbb8",
-                "reference": "21bf002f077b177f056d8cb455c5ed573adfdbb8",
-                "shasum": ""
-            },
-            "require": {
-                "ext-tokenizer": "*",
-                "php": ">=5.4.0",
-                "php-parallel-lint/php-console-color": "~0.2"
-            },
-            "replace": {
-                "jakub-onderka/php-console-highlighter": "*"
-            },
-            "require-dev": {
-                "php-parallel-lint/php-code-style": "~1.0",
-                "php-parallel-lint/php-parallel-lint": "~1.0",
-                "php-parallel-lint/php-var-dump-check": "~0.1",
-                "phpunit/phpunit": "~4.0",
-                "squizlabs/php_codesniffer": "~1.5"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "JakubOnderka\\PhpConsoleHighlighter\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jakub Onderka",
-                    "email": "acci@acci.cz",
-                    "homepage": "http://www.acci.cz/"
-                }
-            ],
-            "description": "Highlight PHP code in terminal",
-            "support": {
-                "issues": "https://github.com/php-parallel-lint/PHP-Console-Highlighter/issues",
-                "source": "https://github.com/php-parallel-lint/PHP-Console-Highlighter/tree/master"
-            },
-            "time": "2020-05-13T07:37:49+00:00"
-        },
         {
             "name": "phpoption/phpoption",
             "version": "1.8.0",
@@ -3572,6 +3711,56 @@
             },
             "time": "2021-03-05T17:36:06+00:00"
         },
+        {
+            "name": "psr/event-dispatcher",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/event-dispatcher.git",
+                "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+                "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\EventDispatcher\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Standard interfaces for event handling.",
+            "keywords": [
+                "events",
+                "psr",
+                "psr-14"
+            ],
+            "support": {
+                "issues": "https://github.com/php-fig/event-dispatcher/issues",
+                "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+            },
+            "time": "2019-01-08T18:20:26+00:00"
+        },
         {
             "name": "psr/http-client",
             "version": "1.0.1",
@@ -3833,6 +4022,81 @@
             },
             "time": "2017-10-23T01:57:42+00:00"
         },
+        {
+            "name": "psy/psysh",
+            "version": "v0.10.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/bobthecow/psysh.git",
+                "reference": "01281336c4ae557fe4a994544f30d3a1bc204375"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/01281336c4ae557fe4a994544f30d3a1bc204375",
+                "reference": "01281336c4ae557fe4a994544f30d3a1bc204375",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-tokenizer": "*",
+                "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3",
+                "php": "^8.0 || ^7.0 || ^5.5.9",
+                "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10",
+                "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.2",
+                "hoa/console": "3.17.*"
+            },
+            "suggest": {
+                "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)",
+                "ext-pdo-sqlite": "The doc command requires SQLite to work.",
+                "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.",
+                "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.",
+                "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit."
+            },
+            "bin": [
+                "bin/psysh"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "0.10.x-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/functions.php"
+                ],
+                "psr-4": {
+                    "Psy\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Justin Hileman",
+                    "email": "justin@justinhileman.info",
+                    "homepage": "http://justinhileman.com"
+                }
+            ],
+            "description": "An interactive shell for modern PHP.",
+            "homepage": "http://psysh.org",
+            "keywords": [
+                "REPL",
+                "console",
+                "interactive",
+                "shell"
+            ],
+            "support": {
+                "issues": "https://github.com/bobthecow/psysh/issues",
+                "source": "https://github.com/bobthecow/psysh/tree/v0.10.9"
+            },
+            "time": "2021-10-10T13:37:39+00:00"
+        },
         {
             "name": "ralouphie/getallheaders",
             "version": "3.0.3",
@@ -3878,56 +4142,146 @@
             "time": "2019-03-08T08:55:37+00:00"
         },
         {
-            "name": "ramsey/uuid",
-            "version": "3.9.6",
+            "name": "ramsey/collection",
+            "version": "1.2.2",
             "source": {
                 "type": "git",
-                "url": "https://github.com/ramsey/uuid.git",
-                "reference": "ffa80ab953edd85d5b6c004f96181a538aad35a3"
+                "url": "https://github.com/ramsey/collection.git",
+                "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ramsey/uuid/zipball/ffa80ab953edd85d5b6c004f96181a538aad35a3",
-                "reference": "ffa80ab953edd85d5b6c004f96181a538aad35a3",
+                "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a",
+                "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a",
                 "shasum": ""
             },
             "require": {
+                "php": "^7.3 || ^8",
+                "symfony/polyfill-php81": "^1.23"
+            },
+            "require-dev": {
+                "captainhook/captainhook": "^5.3",
+                "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+                "ergebnis/composer-normalize": "^2.6",
+                "fakerphp/faker": "^1.5",
+                "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",
+                "phpstan/phpstan-phpunit": "^0.12.11",
+                "phpunit/phpunit": "^8.5 || ^9",
+                "psy/psysh": "^0.10.4",
+                "slevomat/coding-standard": "^6.3",
+                "squizlabs/php_codesniffer": "^3.5",
+                "vimeo/psalm": "^4.4"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Ramsey\\Collection\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ben Ramsey",
+                    "email": "ben@benramsey.com",
+                    "homepage": "https://benramsey.com"
+                }
+            ],
+            "description": "A PHP 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.2"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/ramsey",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-10-10T03:01:02+00:00"
+        },
+        {
+            "name": "ramsey/uuid",
+            "version": "4.2.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ramsey/uuid.git",
+                "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
+                "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
+                "shasum": ""
+            },
+            "require": {
+                "brick/math": "^0.8 || ^0.9",
                 "ext-json": "*",
-                "paragonie/random_compat": "^1 | ^2 | ^9.99.99",
-                "php": "^5.4 | ^7.0 | ^8.0",
-                "symfony/polyfill-ctype": "^1.8"
+                "php": "^7.2 || ^8.0",
+                "ramsey/collection": "^1.0",
+                "symfony/polyfill-ctype": "^1.8",
+                "symfony/polyfill-php80": "^1.14"
             },
             "replace": {
                 "rhumsaa/uuid": "self.version"
             },
             "require-dev": {
-                "codeception/aspect-mock": "^1 | ^2",
-                "doctrine/annotations": "^1.2",
-                "goaop/framework": "1.0.0-alpha.2 | ^1 | >=2.1.0 <=2.3.2",
-                "mockery/mockery": "^0.9.11 | ^1",
+                "captainhook/captainhook": "^5.10",
+                "captainhook/plugin-composer": "^5.3",
+                "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+                "doctrine/annotations": "^1.8",
+                "ergebnis/composer-normalize": "^2.15",
+                "mockery/mockery": "^1.3",
                 "moontoast/math": "^1.1",
-                "nikic/php-parser": "<=4.5.0",
                 "paragonie/random-lib": "^2",
-                "php-mock/php-mock-phpunit": "^0.3 | ^1.1 | ^2.6",
-                "php-parallel-lint/php-parallel-lint": "^1.3",
-                "phpunit/phpunit": ">=4.8.36 <9.0.0 | >=9.3.0",
+                "php-mock/php-mock": "^2.2",
+                "php-mock/php-mock-mockery": "^1.3",
+                "php-parallel-lint/php-parallel-lint": "^1.1",
+                "phpbench/phpbench": "^1.0",
+                "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",
                 "squizlabs/php_codesniffer": "^3.5",
-                "yoast/phpunit-polyfills": "^1.0"
+                "vimeo/psalm": "^4.9"
             },
             "suggest": {
-                "ext-ctype": "Provides support for PHP Ctype functions",
-                "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator",
-                "ext-openssl": "Provides the OpenSSL extension for use with the OpenSslGenerator",
-                "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator",
-                "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).",
+                "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
+                "ext-ctype": "Enables faster processing of character classification using ctype functions.",
+                "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
+                "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
                 "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
-                "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid",
                 "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.x-dev"
+                    "dev-main": "4.x-dev"
+                },
+                "captainhook": {
+                    "force-install": true
                 }
             },
             "autoload": {
@@ -3942,23 +4296,7 @@
             "license": [
                 "MIT"
             ],
-            "authors": [
-                {
-                    "name": "Ben Ramsey",
-                    "email": "ben@benramsey.com",
-                    "homepage": "https://benramsey.com"
-                },
-                {
-                    "name": "Marijn Huizendveld",
-                    "email": "marijn.huizendveld@gmail.com"
-                },
-                {
-                    "name": "Thibaud Fabre",
-                    "email": "thibaud@aztech.io"
-                }
-            ],
-            "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).",
-            "homepage": "https://github.com/ramsey/uuid",
+            "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
             "keywords": [
                 "guid",
                 "identifier",
@@ -3966,9 +4304,7 @@
             ],
             "support": {
                 "issues": "https://github.com/ramsey/uuid/issues",
-                "rss": "https://github.com/ramsey/uuid/releases.atom",
-                "source": "https://github.com/ramsey/uuid",
-                "wiki": "https://github.com/ramsey/uuid/wiki"
+                "source": "https://github.com/ramsey/uuid/tree/4.2.3"
             },
             "funding": [
                 {
@@ -3980,7 +4316,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-25T23:07:42+00:00"
+            "time": "2021-09-25T23:10:38+00:00"
         },
         {
             "name": "robrichards/xmlseclibs",
@@ -4515,43 +4851,46 @@
         },
         {
             "name": "symfony/console",
-            "version": "v4.4.30",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "a3f7189a0665ee33b50e9e228c46f50f5acbed22"
+                "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/a3f7189a0665ee33b50e9e228c46f50f5acbed22",
-                "reference": "a3f7189a0665ee33b50e9e228c46f50f5acbed22",
+                "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a",
+                "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-mbstring": "~1.0",
                 "symfony/polyfill-php73": "^1.8",
                 "symfony/polyfill-php80": "^1.16",
-                "symfony/service-contracts": "^1.1|^2"
+                "symfony/service-contracts": "^1.1|^2",
+                "symfony/string": "^5.1"
             },
             "conflict": {
                 "psr/log": ">=3",
-                "symfony/dependency-injection": "<3.4",
-                "symfony/event-dispatcher": "<4.3|>=5",
+                "symfony/dependency-injection": "<4.4",
+                "symfony/dotenv": "<5.1",
+                "symfony/event-dispatcher": "<4.4",
                 "symfony/lock": "<4.4",
-                "symfony/process": "<3.3"
+                "symfony/process": "<4.4"
             },
             "provide": {
                 "psr/log-implementation": "1.0|2.0"
             },
             "require-dev": {
                 "psr/log": "^1|^2",
-                "symfony/config": "^3.4|^4.0|^5.0",
-                "symfony/dependency-injection": "^3.4|^4.0|^5.0",
-                "symfony/event-dispatcher": "^4.3",
+                "symfony/config": "^4.4|^5.0",
+                "symfony/dependency-injection": "^4.4|^5.0",
+                "symfony/event-dispatcher": "^4.4|^5.0",
                 "symfony/lock": "^4.4|^5.0",
-                "symfony/process": "^3.4|^4.0|^5.0",
-                "symfony/var-dumper": "^4.3|^5.0"
+                "symfony/process": "^4.4|^5.0",
+                "symfony/var-dumper": "^4.4|^5.0"
             },
             "suggest": {
                 "psr/log": "For using the console logger",
@@ -4584,8 +4923,14 @@
             ],
             "description": "Eases the creation of beautiful and testable command line interfaces",
             "homepage": "https://symfony.com",
+            "keywords": [
+                "cli",
+                "command line",
+                "console",
+                "terminal"
+            ],
             "support": {
-                "source": "https://github.com/symfony/console/tree/v4.4.30"
+                "source": "https://github.com/symfony/console/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -4601,7 +4946,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-25T19:27:26+00:00"
+            "time": "2021-08-25T20:02:16+00:00"
         },
         {
             "name": "symfony/css-selector",
@@ -4669,74 +5014,6 @@
             ],
             "time": "2021-07-21T12:38:00+00:00"
         },
-        {
-            "name": "symfony/debug",
-            "version": "v4.4.31",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/debug.git",
-                "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0",
-                "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.1.3",
-                "psr/log": "^1|^2|^3"
-            },
-            "conflict": {
-                "symfony/http-kernel": "<3.4"
-            },
-            "require-dev": {
-                "symfony/http-kernel": "^3.4|^4.0|^5.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Debug\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Provides tools to ease debugging PHP code",
-            "homepage": "https://symfony.com",
-            "support": {
-                "source": "https://github.com/symfony/debug/tree/v4.4.31"
-            },
-            "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-09-24T13:30:14+00:00"
-        },
         {
             "name": "symfony/deprecation-contracts",
             "version": "v2.4.0",
@@ -4806,25 +5083,25 @@
         },
         {
             "name": "symfony/error-handler",
-            "version": "v4.4.30",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/error-handler.git",
-                "reference": "51f98f7aa99f00f3b1da6bafe934e67ae6ba6dc5"
+                "reference": "3bc60d0fba00ae8d1eaa9eb5ab11a2bbdd1fc321"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/error-handler/zipball/51f98f7aa99f00f3b1da6bafe934e67ae6ba6dc5",
-                "reference": "51f98f7aa99f00f3b1da6bafe934e67ae6ba6dc5",
+                "url": "https://api.github.com/repos/symfony/error-handler/zipball/3bc60d0fba00ae8d1eaa9eb5ab11a2bbdd1fc321",
+                "reference": "3bc60d0fba00ae8d1eaa9eb5ab11a2bbdd1fc321",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
                 "psr/log": "^1|^2|^3",
-                "symfony/debug": "^4.4.5",
                 "symfony/var-dumper": "^4.4|^5.0"
             },
             "require-dev": {
+                "symfony/deprecation-contracts": "^2.1",
                 "symfony/http-kernel": "^4.4|^5.0",
                 "symfony/serializer": "^4.4|^5.0"
             },
@@ -4854,7 +5131,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/v4.4.30"
+                "source": "https://github.com/symfony/error-handler/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -4870,43 +5147,44 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-27T17:42:48+00:00"
+            "time": "2021-08-28T15:07:08+00:00"
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v4.4.30",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "2fe81680070043c4c80e7cedceb797e34f377bac"
+                "reference": "ce7b20d69c66a20939d8952b617506a44d102130"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2fe81680070043c4c80e7cedceb797e34f377bac",
-                "reference": "2fe81680070043c4c80e7cedceb797e34f377bac",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ce7b20d69c66a20939d8952b617506a44d102130",
+                "reference": "ce7b20d69c66a20939d8952b617506a44d102130",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
-                "symfony/event-dispatcher-contracts": "^1.1",
+                "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.1",
+                "symfony/event-dispatcher-contracts": "^2",
                 "symfony/polyfill-php80": "^1.16"
             },
             "conflict": {
-                "symfony/dependency-injection": "<3.4"
+                "symfony/dependency-injection": "<4.4"
             },
             "provide": {
                 "psr/event-dispatcher-implementation": "1.0",
-                "symfony/event-dispatcher-implementation": "1.1"
+                "symfony/event-dispatcher-implementation": "2.0"
             },
             "require-dev": {
                 "psr/log": "^1|^2|^3",
-                "symfony/config": "^3.4|^4.0|^5.0",
-                "symfony/dependency-injection": "^3.4|^4.0|^5.0",
-                "symfony/error-handler": "~3.4|~4.4",
-                "symfony/expression-language": "^3.4|^4.0|^5.0",
-                "symfony/http-foundation": "^3.4|^4.0|^5.0",
+                "symfony/config": "^4.4|^5.0",
+                "symfony/dependency-injection": "^4.4|^5.0",
+                "symfony/error-handler": "^4.4|^5.0",
+                "symfony/expression-language": "^4.4|^5.0",
+                "symfony/http-foundation": "^4.4|^5.0",
                 "symfony/service-contracts": "^1.1|^2",
-                "symfony/stopwatch": "^3.4|^4.0|^5.0"
+                "symfony/stopwatch": "^4.4|^5.0"
             },
             "suggest": {
                 "symfony/dependency-injection": "",
@@ -4938,7 +5216,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/v4.4.30"
+                "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -4954,33 +5232,33 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-04T20:31:23+00:00"
+            "time": "2021-08-04T21:20:46+00:00"
         },
         {
             "name": "symfony/event-dispatcher-contracts",
-            "version": "v1.1.9",
+            "version": "v2.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher-contracts.git",
-                "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7"
+                "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/84e23fdcd2517bf37aecbd16967e83f0caee25a7",
-                "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11",
+                "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3"
+                "php": ">=7.2.5",
+                "psr/event-dispatcher": "^1"
             },
             "suggest": {
-                "psr/event-dispatcher": "",
                 "symfony/event-dispatcher-implementation": ""
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.1-dev"
+                    "dev-main": "2.4-dev"
                 },
                 "thanks": {
                     "name": "symfony/contracts",
@@ -5017,7 +5295,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.9"
+                "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0"
             },
             "funding": [
                 {
@@ -5033,24 +5311,24 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-07-06T13:19:58+00:00"
+            "time": "2021-03-23T23:28:01+00:00"
         },
         {
             "name": "symfony/finder",
-            "version": "v4.4.30",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "70362f1e112280d75b30087c7598b837c1b468b6"
+                "reference": "a10000ada1e600d109a6c7632e9ac42e8bf2fb93"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/70362f1e112280d75b30087c7598b837c1b468b6",
-                "reference": "70362f1e112280d75b30087c7598b837c1b468b6",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/a10000ada1e600d109a6c7632e9ac42e8bf2fb93",
+                "reference": "a10000ada1e600d109a6c7632e9ac42e8bf2fb93",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
                 "symfony/polyfill-php80": "^1.16"
             },
             "type": "library",
@@ -5079,7 +5357,7 @@
             "description": "Finds files and directories via an intuitive fluent interface",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/finder/tree/v4.4.30"
+                "source": "https://github.com/symfony/finder/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -5095,7 +5373,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-04T20:31:23+00:00"
+            "time": "2021-08-04T21:20:46+00:00"
         },
         {
             "name": "symfony/http-client-contracts",
@@ -5177,27 +5455,32 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v4.4.30",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "09b3202651ab23ac8dcf455284a48a3500e56731"
+                "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/09b3202651ab23ac8dcf455284a48a3500e56731",
-                "reference": "09b3202651ab23ac8dcf455284a48a3500e56731",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e36c8e5502b4f3f0190c675f1c1f1248a64f04e5",
+                "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
-                "symfony/mime": "^4.3|^5.0",
+                "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-mbstring": "~1.1",
                 "symfony/polyfill-php80": "^1.16"
             },
             "require-dev": {
                 "predis/predis": "~1.0",
-                "symfony/expression-language": "^3.4|^4.0|^5.0"
+                "symfony/cache": "^4.4|^5.0",
+                "symfony/expression-language": "^4.4|^5.0",
+                "symfony/mime": "^4.4|^5.0"
+            },
+            "suggest": {
+                "symfony/mime": "To use the file extension guesser"
             },
             "type": "library",
             "autoload": {
@@ -5225,7 +5508,7 @@
             "description": "Defines an object-oriented layer for the HTTP specification",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-foundation/tree/v4.4.30"
+                "source": "https://github.com/symfony/http-foundation/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -5241,61 +5524,69 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-26T15:51:23+00:00"
+            "time": "2021-08-27T11:20:35+00:00"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v4.4.32",
+            "version": "v5.3.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-kernel.git",
-                "reference": "f7bda3ea8f05ae90627400e58af5179b25ce0f38"
+                "reference": "ceaf46a992f60e90645e7279825a830f733a17c5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f7bda3ea8f05ae90627400e58af5179b25ce0f38",
-                "reference": "f7bda3ea8f05ae90627400e58af5179b25ce0f38",
+                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ceaf46a992f60e90645e7279825a830f733a17c5",
+                "reference": "ceaf46a992f60e90645e7279825a830f733a17c5",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
                 "psr/log": "^1|^2",
-                "symfony/error-handler": "^4.4",
-                "symfony/event-dispatcher": "^4.4",
+                "symfony/deprecation-contracts": "^2.1",
+                "symfony/error-handler": "^4.4|^5.0",
+                "symfony/event-dispatcher": "^5.0",
                 "symfony/http-client-contracts": "^1.1|^2",
-                "symfony/http-foundation": "^4.4.30|^5.3.7",
+                "symfony/http-foundation": "^5.3.7",
                 "symfony/polyfill-ctype": "^1.8",
                 "symfony/polyfill-php73": "^1.9",
                 "symfony/polyfill-php80": "^1.16"
             },
             "conflict": {
-                "symfony/browser-kit": "<4.3",
-                "symfony/config": "<3.4",
-                "symfony/console": ">=5",
-                "symfony/dependency-injection": "<4.3",
-                "symfony/translation": "<4.2",
-                "twig/twig": "<1.43|<2.13,>=2"
+                "symfony/browser-kit": "<4.4",
+                "symfony/cache": "<5.0",
+                "symfony/config": "<5.0",
+                "symfony/console": "<4.4",
+                "symfony/dependency-injection": "<5.3",
+                "symfony/doctrine-bridge": "<5.0",
+                "symfony/form": "<5.0",
+                "symfony/http-client": "<5.0",
+                "symfony/mailer": "<5.0",
+                "symfony/messenger": "<5.0",
+                "symfony/translation": "<5.0",
+                "symfony/twig-bridge": "<5.0",
+                "symfony/validator": "<5.0",
+                "twig/twig": "<2.13"
             },
             "provide": {
                 "psr/log-implementation": "1.0|2.0"
             },
             "require-dev": {
                 "psr/cache": "^1.0|^2.0|^3.0",
-                "symfony/browser-kit": "^4.3|^5.0",
-                "symfony/config": "^3.4|^4.0|^5.0",
-                "symfony/console": "^3.4|^4.0",
-                "symfony/css-selector": "^3.4|^4.0|^5.0",
-                "symfony/dependency-injection": "^4.3|^5.0",
-                "symfony/dom-crawler": "^3.4|^4.0|^5.0",
-                "symfony/expression-language": "^3.4|^4.0|^5.0",
-                "symfony/finder": "^3.4|^4.0|^5.0",
-                "symfony/process": "^3.4|^4.0|^5.0",
-                "symfony/routing": "^3.4|^4.0|^5.0",
-                "symfony/stopwatch": "^3.4|^4.0|^5.0",
-                "symfony/templating": "^3.4|^4.0|^5.0",
-                "symfony/translation": "^4.2|^5.0",
+                "symfony/browser-kit": "^4.4|^5.0",
+                "symfony/config": "^5.0",
+                "symfony/console": "^4.4|^5.0",
+                "symfony/css-selector": "^4.4|^5.0",
+                "symfony/dependency-injection": "^5.3",
+                "symfony/dom-crawler": "^4.4|^5.0",
+                "symfony/expression-language": "^4.4|^5.0",
+                "symfony/finder": "^4.4|^5.0",
+                "symfony/process": "^4.4|^5.0",
+                "symfony/routing": "^4.4|^5.0",
+                "symfony/stopwatch": "^4.4|^5.0",
+                "symfony/translation": "^4.4|^5.0",
                 "symfony/translation-contracts": "^1.1|^2",
-                "twig/twig": "^1.43|^2.13|^3.0.4"
+                "twig/twig": "^2.13|^3.0.4"
             },
             "suggest": {
                 "symfony/browser-kit": "",
@@ -5329,7 +5620,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/v4.4.32"
+                "source": "https://github.com/symfony/http-kernel/tree/v5.3.9"
             },
             "funding": [
                 {
@@ -5345,7 +5636,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-28T10:20:04+00:00"
+            "time": "2021-09-28T10:25:11+00:00"
         },
         {
             "name": "symfony/mime",
@@ -5589,6 +5880,87 @@
             ],
             "time": "2021-05-27T09:27:20+00:00"
         },
+        {
+            "name": "symfony/polyfill-intl-grapheme",
+            "version": "v1.23.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+                "reference": "16880ba9c5ebe3642d1995ab866db29270b36535"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535",
+                "reference": "16880ba9c5ebe3642d1995ab866db29270b36535",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "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\\Intl\\Grapheme\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "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 for intl's grapheme_* functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "grapheme",
+                "intl",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1"
+            },
+            "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-27T12:26:48+00:00"
+        },
         {
             "name": "symfony/polyfill-intl-idn",
             "version": "v1.23.0",
@@ -6079,21 +6451,100 @@
             "time": "2021-07-28T13:41:28+00:00"
         },
         {
-            "name": "symfony/process",
-            "version": "v4.4.30",
+            "name": "symfony/polyfill-php81",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/process.git",
-                "reference": "13d3161ef63a8ec21eeccaaf9a4d7f784a87a97d"
+                "url": "https://github.com/symfony/polyfill-php81.git",
+                "reference": "e66119f3de95efc359483f810c4c3e6436279436"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/13d3161ef63a8ec21eeccaaf9a4d7f784a87a97d",
-                "reference": "13d3161ef63a8ec21eeccaaf9a4d7f784a87a97d",
+                "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436",
+                "reference": "e66119f3de95efc359483f810c4c3e6436279436",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "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.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/process.git",
+                "reference": "38f26c7d6ed535217ea393e05634cb0b244a1967"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/process/zipball/38f26c7d6ed535217ea393e05634cb0b244a1967",
+                "reference": "38f26c7d6ed535217ea393e05634cb0b244a1967",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2.5",
                 "symfony/polyfill-php80": "^1.16"
             },
             "type": "library",
@@ -6122,7 +6573,7 @@
             "description": "Executes commands in sub-processes",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/process/tree/v4.4.30"
+                "source": "https://github.com/symfony/process/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -6138,42 +6589,43 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-04T20:31:23+00:00"
+            "time": "2021-08-04T21:20:46+00:00"
         },
         {
             "name": "symfony/routing",
-            "version": "v4.4.30",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/routing.git",
-                "reference": "9ddf033927ad9f30ba2bfd167a7b342cafa13e8e"
+                "reference": "be865017746fe869007d94220ad3f5297951811b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/routing/zipball/9ddf033927ad9f30ba2bfd167a7b342cafa13e8e",
-                "reference": "9ddf033927ad9f30ba2bfd167a7b342cafa13e8e",
+                "url": "https://api.github.com/repos/symfony/routing/zipball/be865017746fe869007d94220ad3f5297951811b",
+                "reference": "be865017746fe869007d94220ad3f5297951811b",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-php80": "^1.16"
             },
             "conflict": {
-                "symfony/config": "<4.2",
-                "symfony/dependency-injection": "<3.4",
-                "symfony/yaml": "<3.4"
+                "doctrine/annotations": "<1.12",
+                "symfony/config": "<5.3",
+                "symfony/dependency-injection": "<4.4",
+                "symfony/yaml": "<4.4"
             },
             "require-dev": {
-                "doctrine/annotations": "^1.10.4",
+                "doctrine/annotations": "^1.12",
                 "psr/log": "^1|^2|^3",
-                "symfony/config": "^4.2|^5.0",
-                "symfony/dependency-injection": "^3.4|^4.0|^5.0",
-                "symfony/expression-language": "^3.4|^4.0|^5.0",
-                "symfony/http-foundation": "^3.4|^4.0|^5.0",
-                "symfony/yaml": "^3.4|^4.0|^5.0"
+                "symfony/config": "^5.3",
+                "symfony/dependency-injection": "^4.4|^5.0",
+                "symfony/expression-language": "^4.4|^5.0",
+                "symfony/http-foundation": "^4.4|^5.0",
+                "symfony/yaml": "^4.4|^5.0"
             },
             "suggest": {
-                "doctrine/annotations": "For using the annotation loader",
                 "symfony/config": "For using the all-in-one router or any loader",
                 "symfony/expression-language": "For using expression matching",
                 "symfony/http-foundation": "For using a Symfony Request object",
@@ -6211,7 +6663,7 @@
                 "url"
             ],
             "support": {
-                "source": "https://github.com/symfony/routing/tree/v4.4.30"
+                "source": "https://github.com/symfony/routing/tree/v5.3.7"
             },
             "funding": [
                 {
@@ -6227,7 +6679,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-04T21:41:01+00:00"
+            "time": "2021-08-04T21:42:42+00:00"
         },
         {
             "name": "symfony/service-contracts",
@@ -6309,44 +6761,130 @@
             "time": "2021-04-01T10:43:52+00:00"
         },
         {
-            "name": "symfony/translation",
-            "version": "v4.4.32",
+            "name": "symfony/string",
+            "version": "v5.3.7",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/translation.git",
-                "reference": "db0ba1e85280d8ff11e38d53c70f8814d4d740f5"
+                "url": "https://github.com/symfony/string.git",
+                "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation/zipball/db0ba1e85280d8ff11e38d53c70f8814d4d740f5",
-                "reference": "db0ba1e85280d8ff11e38d53c70f8814d4d740f5",
+                "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5",
+                "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
+                "symfony/polyfill-ctype": "~1.8",
+                "symfony/polyfill-intl-grapheme": "~1.0",
+                "symfony/polyfill-intl-normalizer": "~1.0",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/polyfill-php80": "~1.15"
+            },
+            "require-dev": {
+                "symfony/error-handler": "^4.4|^5.0",
+                "symfony/http-client": "^4.4|^5.0",
+                "symfony/translation-contracts": "^1.1|^2",
+                "symfony/var-exporter": "^4.4|^5.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\String\\": ""
+                },
+                "files": [
+                    "Resources/functions.php"
+                ],
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "grapheme",
+                "i18n",
+                "string",
+                "unicode",
+                "utf-8",
+                "utf8"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/string/tree/v5.3.7"
+            },
+            "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-08-26T08:00:08+00:00"
+        },
+        {
+            "name": "symfony/translation",
+            "version": "v5.3.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/translation.git",
+                "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/6e69f3551c1a3356cf6ea8d019bf039a0f8b6886",
+                "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-mbstring": "~1.0",
                 "symfony/polyfill-php80": "^1.16",
-                "symfony/translation-contracts": "^1.1.6|^2"
+                "symfony/translation-contracts": "^2.3"
             },
             "conflict": {
-                "symfony/config": "<3.4",
-                "symfony/dependency-injection": "<3.4",
-                "symfony/http-kernel": "<4.4",
-                "symfony/yaml": "<3.4"
+                "symfony/config": "<4.4",
+                "symfony/dependency-injection": "<5.0",
+                "symfony/http-kernel": "<5.0",
+                "symfony/twig-bundle": "<5.0",
+                "symfony/yaml": "<4.4"
             },
             "provide": {
-                "symfony/translation-implementation": "1.0|2.0"
+                "symfony/translation-implementation": "2.3"
             },
             "require-dev": {
                 "psr/log": "^1|^2|^3",
-                "symfony/config": "^3.4|^4.0|^5.0",
-                "symfony/console": "^3.4|^4.0|^5.0",
-                "symfony/dependency-injection": "^3.4|^4.0|^5.0",
-                "symfony/finder": "~2.8|~3.0|~4.0|^5.0",
-                "symfony/http-kernel": "^4.4",
-                "symfony/intl": "^3.4|^4.0|^5.0",
+                "symfony/config": "^4.4|^5.0",
+                "symfony/console": "^4.4|^5.0",
+                "symfony/dependency-injection": "^5.0",
+                "symfony/finder": "^4.4|^5.0",
+                "symfony/http-kernel": "^5.0",
+                "symfony/intl": "^4.4|^5.0",
+                "symfony/polyfill-intl-icu": "^1.21",
                 "symfony/service-contracts": "^1.1.2|^2",
-                "symfony/yaml": "^3.4|^4.0|^5.0"
+                "symfony/yaml": "^4.4|^5.0"
             },
             "suggest": {
                 "psr/log-implementation": "To use logging capability in translator",
@@ -6355,6 +6893,9 @@
             },
             "type": "library",
             "autoload": {
+                "files": [
+                    "Resources/functions.php"
+                ],
                 "psr-4": {
                     "Symfony\\Component\\Translation\\": ""
                 },
@@ -6379,7 +6920,7 @@
             "description": "Provides tools to internationalize your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/translation/tree/v4.4.32"
+                "source": "https://github.com/symfony/translation/tree/v5.3.9"
             },
             "funding": [
                 {
@@ -6395,7 +6936,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-26T05:57:13+00:00"
+            "time": "2021-08-26T08:22:53+00:00"
         },
         {
             "name": "symfony/translation-contracts",
@@ -6477,33 +7018,32 @@
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v4.4.31",
+            "version": "v5.3.8",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "1f12cc0c2e880a5f39575c19af81438464717839"
+                "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1f12cc0c2e880a5f39575c19af81438464717839",
-                "reference": "1f12cc0c2e880a5f39575c19af81438464717839",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eaaea4098be1c90c8285543e1356a09c8aa5c8da",
+                "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
+                "php": ">=7.2.5",
                 "symfony/polyfill-mbstring": "~1.0",
-                "symfony/polyfill-php72": "~1.5",
                 "symfony/polyfill-php80": "^1.16"
             },
             "conflict": {
-                "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
-                "symfony/console": "<3.4"
+                "phpunit/phpunit": "<5.4.3",
+                "symfony/console": "<4.4"
             },
             "require-dev": {
                 "ext-iconv": "*",
-                "symfony/console": "^3.4|^4.0|^5.0",
+                "symfony/console": "^4.4|^5.0",
                 "symfony/process": "^4.4|^5.0",
-                "twig/twig": "^1.43|^2.13|^3.0.4"
+                "twig/twig": "^2.13|^3.0.4"
             },
             "suggest": {
                 "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
@@ -6546,7 +7086,7 @@
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v4.4.31"
+                "source": "https://github.com/symfony/var-dumper/tree/v5.3.8"
             },
             "funding": [
                 {
@@ -6562,7 +7102,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-24T15:30:11+00:00"
+            "time": "2021-09-24T15:59:58+00:00"
         },
         {
             "name": "tijsverkoyen/css-to-inline-styles",
@@ -6619,24 +7159,25 @@
         },
         {
             "name": "vlucas/phpdotenv",
-            "version": "v3.6.9",
+            "version": "v4.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/vlucas/phpdotenv.git",
-                "reference": "a1bf4c9853d90ade427b4efe35355fc41b3d6988"
+                "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a1bf4c9853d90ade427b4efe35355fc41b3d6988",
-                "reference": "a1bf4c9853d90ade427b4efe35355fc41b3d6988",
+                "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/d38f4d1edcbe32515a0ad593cbd4c858e337263c",
+                "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.4 || ^7.0 || ^8.0",
-                "phpoption/phpoption": "^1.5.2",
+                "php": "^5.5.9 || ^7.0 || ^8.0",
+                "phpoption/phpoption": "^1.7.3",
                 "symfony/polyfill-ctype": "^1.17"
             },
             "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.4.1",
                 "ext-filter": "*",
                 "ext-pcre": "*",
                 "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.21"
@@ -6648,7 +7189,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.6-dev"
+                    "dev-master": "4.2-dev"
                 }
             },
             "autoload": {
@@ -6678,7 +7219,7 @@
             ],
             "support": {
                 "issues": "https://github.com/vlucas/phpdotenv/issues",
-                "source": "https://github.com/vlucas/phpdotenv/tree/v3.6.9"
+                "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.1"
             },
             "funding": [
                 {
@@ -6690,7 +7231,81 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-10-02T19:07:56+00:00"
+            "time": "2021-10-02T19:17:08+00:00"
+        },
+        {
+            "name": "voku/portable-ascii",
+            "version": "1.5.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/voku/portable-ascii.git",
+                "reference": "80953678b19901e5165c56752d087fc11526017c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c",
+                "reference": "80953678b19901e5165c56752d087fc11526017c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+            },
+            "suggest": {
+                "ext-intl": "Use Intl for transliterator_transliterate() support"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "voku\\": "src/voku/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Lars Moelleken",
+                    "homepage": "http://www.moelleken.org/"
+                }
+            ],
+            "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+            "homepage": "https://github.com/voku/portable-ascii",
+            "keywords": [
+                "ascii",
+                "clean",
+                "php"
+            ],
+            "support": {
+                "issues": "https://github.com/voku/portable-ascii/issues",
+                "source": "https://github.com/voku/portable-ascii/tree/1.5.6"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/moelleken",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/voku",
+                    "type": "github"
+                },
+                {
+                    "url": "https://opencollective.com/portable-ascii",
+                    "type": "open_collective"
+                },
+                {
+                    "url": "https://www.patreon.com/voku",
+                    "type": "patreon"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-11-12T00:07:28+00:00"
         }
     ],
     "packages-dev": [
@@ -6779,611 +7394,6 @@
             ],
             "time": "2021-10-21T10:57:31+00:00"
         },
-        {
-            "name": "barryvdh/laravel-ide-helper",
-            "version": "v2.8.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/barryvdh/laravel-ide-helper.git",
-                "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/5515cabea39b9cf55f98980d0f269dc9d85cfcca",
-                "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca",
-                "shasum": ""
-            },
-            "require": {
-                "barryvdh/reflection-docblock": "^2.0.6",
-                "composer/composer": "^1.6 || ^2",
-                "doctrine/dbal": "~2.3",
-                "ext-json": "*",
-                "illuminate/console": "^6 || ^7 || ^8",
-                "illuminate/filesystem": "^6 || ^7 || ^8",
-                "illuminate/support": "^6 || ^7 || ^8",
-                "php": ">=7.2",
-                "phpdocumentor/type-resolver": "^1.1.0"
-            },
-            "require-dev": {
-                "ext-pdo_sqlite": "*",
-                "friendsofphp/php-cs-fixer": "^2",
-                "illuminate/config": "^6 || ^7 || ^8",
-                "illuminate/view": "^6 || ^7 || ^8",
-                "mockery/mockery": "^1.3.3",
-                "orchestra/testbench": "^4 || ^5 || ^6",
-                "phpunit/phpunit": "^8.5 || ^9",
-                "spatie/phpunit-snapshot-assertions": "^1.4 || ^2.2 || ^3 || ^4",
-                "vimeo/psalm": "^3.12"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.8-dev"
-                },
-                "laravel": {
-                    "providers": [
-                        "Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider"
-                    ]
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Barryvdh\\LaravelIdeHelper\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Barry vd. Heuvel",
-                    "email": "barryvdh@gmail.com"
-                }
-            ],
-            "description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.",
-            "keywords": [
-                "autocomplete",
-                "codeintel",
-                "helper",
-                "ide",
-                "laravel",
-                "netbeans",
-                "phpdoc",
-                "phpstorm",
-                "sublime"
-            ],
-            "support": {
-                "issues": "https://github.com/barryvdh/laravel-ide-helper/issues",
-                "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.8.2"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/barryvdh",
-                    "type": "github"
-                }
-            ],
-            "time": "2020-12-06T08:55:05+00:00"
-        },
-        {
-            "name": "barryvdh/reflection-docblock",
-            "version": "v2.0.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/barryvdh/ReflectionDocBlock.git",
-                "reference": "6b69015d83d3daf9004a71a89f26e27d27ef6a16"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/6b69015d83d3daf9004a71a89f26e27d27ef6a16",
-                "reference": "6b69015d83d3daf9004a71a89f26e27d27ef6a16",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.0,<4.5"
-            },
-            "suggest": {
-                "dflydev/markdown": "~1.0",
-                "erusev/parsedown": "~1.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Barryvdh": [
-                        "src/"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Mike van Riel",
-                    "email": "mike.vanriel@naenius.com"
-                }
-            ],
-            "support": {
-                "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.0.6"
-            },
-            "time": "2018-12-13T10:34:14+00:00"
-        },
-        {
-            "name": "composer/ca-bundle",
-            "version": "1.2.11",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/composer/ca-bundle.git",
-                "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0b072d51c5a9c6f3412f7ea3ab043d6603cb2582",
-                "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582",
-                "shasum": ""
-            },
-            "require": {
-                "ext-openssl": "*",
-                "ext-pcre": "*",
-                "php": "^5.3.2 || ^7.0 || ^8.0"
-            },
-            "require-dev": {
-                "phpstan/phpstan": "^0.12.55",
-                "psr/log": "^1.0",
-                "symfony/phpunit-bridge": "^4.2 || ^5",
-                "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-main": "1.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Composer\\CaBundle\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be"
-                }
-            ],
-            "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
-            "keywords": [
-                "cabundle",
-                "cacert",
-                "certificate",
-                "ssl",
-                "tls"
-            ],
-            "support": {
-                "irc": "irc://irc.freenode.org/composer",
-                "issues": "https://github.com/composer/ca-bundle/issues",
-                "source": "https://github.com/composer/ca-bundle/tree/1.2.11"
-            },
-            "funding": [
-                {
-                    "url": "https://packagist.com",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/composer",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2021-09-25T20:32:43+00:00"
-        },
-        {
-            "name": "composer/composer",
-            "version": "2.1.9",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/composer/composer.git",
-                "reference": "e558c88f28d102d497adec4852802c0dc14c7077"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/composer/composer/zipball/e558c88f28d102d497adec4852802c0dc14c7077",
-                "reference": "e558c88f28d102d497adec4852802c0dc14c7077",
-                "shasum": ""
-            },
-            "require": {
-                "composer/ca-bundle": "^1.0",
-                "composer/metadata-minifier": "^1.0",
-                "composer/semver": "^3.0",
-                "composer/spdx-licenses": "^1.2",
-                "composer/xdebug-handler": "^2.0",
-                "justinrainbow/json-schema": "^5.2.11",
-                "php": "^5.3.2 || ^7.0 || ^8.0",
-                "psr/log": "^1.0",
-                "react/promise": "^1.2 || ^2.7",
-                "seld/jsonlint": "^1.4",
-                "seld/phar-utils": "^1.0",
-                "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
-                "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
-                "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
-                "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0"
-            },
-            "require-dev": {
-                "phpspec/prophecy": "^1.10",
-                "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0"
-            },
-            "suggest": {
-                "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
-                "ext-zip": "Enabling the zip extension allows you to unzip archives",
-                "ext-zlib": "Allow gzip compression of HTTP requests"
-            },
-            "bin": [
-                "bin/composer"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.1-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Composer\\": "src/Composer"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Nils Adermann",
-                    "email": "naderman@naderman.de",
-                    "homepage": "https://www.naderman.de"
-                },
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "https://seld.be"
-                }
-            ],
-            "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.",
-            "homepage": "https://getcomposer.org/",
-            "keywords": [
-                "autoload",
-                "dependency",
-                "package"
-            ],
-            "support": {
-                "irc": "ircs://irc.libera.chat:6697/composer",
-                "issues": "https://github.com/composer/composer/issues",
-                "source": "https://github.com/composer/composer/tree/2.1.9"
-            },
-            "funding": [
-                {
-                    "url": "https://packagist.com",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/composer",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2021-10-05T07:47:38+00:00"
-        },
-        {
-            "name": "composer/metadata-minifier",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/composer/metadata-minifier.git",
-                "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
-                "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.2 || ^7.0 || ^8.0"
-            },
-            "require-dev": {
-                "composer/composer": "^2",
-                "phpstan/phpstan": "^0.12.55",
-                "symfony/phpunit-bridge": "^4.2 || ^5"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-main": "1.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Composer\\MetadataMinifier\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be"
-                }
-            ],
-            "description": "Small utility library that handles metadata minification and expansion.",
-            "keywords": [
-                "composer",
-                "compression"
-            ],
-            "support": {
-                "issues": "https://github.com/composer/metadata-minifier/issues",
-                "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
-            },
-            "funding": [
-                {
-                    "url": "https://packagist.com",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/composer",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2021-04-07T13:37:33+00:00"
-        },
-        {
-            "name": "composer/semver",
-            "version": "3.2.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/composer/semver.git",
-                "reference": "83e511e247de329283478496f7a1e114c9517506"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506",
-                "reference": "83e511e247de329283478496f7a1e114c9517506",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.2 || ^7.0 || ^8.0"
-            },
-            "require-dev": {
-                "phpstan/phpstan": "^0.12.54",
-                "symfony/phpunit-bridge": "^4.2 || ^5"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-main": "3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Composer\\Semver\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Nils Adermann",
-                    "email": "naderman@naderman.de",
-                    "homepage": "http://www.naderman.de"
-                },
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be"
-                },
-                {
-                    "name": "Rob Bast",
-                    "email": "rob.bast@gmail.com",
-                    "homepage": "http://robbast.nl"
-                }
-            ],
-            "description": "Semver library that offers utilities, version constraint parsing and validation.",
-            "keywords": [
-                "semantic",
-                "semver",
-                "validation",
-                "versioning"
-            ],
-            "support": {
-                "irc": "irc://irc.freenode.org/composer",
-                "issues": "https://github.com/composer/semver/issues",
-                "source": "https://github.com/composer/semver/tree/3.2.6"
-            },
-            "funding": [
-                {
-                    "url": "https://packagist.com",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/composer",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2021-10-25T11:34:17+00:00"
-        },
-        {
-            "name": "composer/spdx-licenses",
-            "version": "1.5.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/composer/spdx-licenses.git",
-                "reference": "de30328a7af8680efdc03e396aad24befd513200"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/de30328a7af8680efdc03e396aad24befd513200",
-                "reference": "de30328a7af8680efdc03e396aad24befd513200",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.2 || ^7.0 || ^8.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-main": "1.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Composer\\Spdx\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Nils Adermann",
-                    "email": "naderman@naderman.de",
-                    "homepage": "http://www.naderman.de"
-                },
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be"
-                },
-                {
-                    "name": "Rob Bast",
-                    "email": "rob.bast@gmail.com",
-                    "homepage": "http://robbast.nl"
-                }
-            ],
-            "description": "SPDX licenses list and validation library.",
-            "keywords": [
-                "license",
-                "spdx",
-                "validator"
-            ],
-            "support": {
-                "irc": "irc://irc.freenode.org/composer",
-                "issues": "https://github.com/composer/spdx-licenses/issues",
-                "source": "https://github.com/composer/spdx-licenses/tree/1.5.5"
-            },
-            "funding": [
-                {
-                    "url": "https://packagist.com",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/composer",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2020-12-03T16:04:16+00:00"
-        },
-        {
-            "name": "composer/xdebug-handler",
-            "version": "2.0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/composer/xdebug-handler.git",
-                "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
-                "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.2 || ^7.0 || ^8.0",
-                "psr/log": "^1 || ^2 || ^3"
-            },
-            "require-dev": {
-                "phpstan/phpstan": "^0.12.55",
-                "symfony/phpunit-bridge": "^4.2 || ^5"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Composer\\XdebugHandler\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "John Stevenson",
-                    "email": "john-stevenson@blueyonder.co.uk"
-                }
-            ],
-            "description": "Restarts a process without Xdebug.",
-            "keywords": [
-                "Xdebug",
-                "performance"
-            ],
-            "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"
-            },
-            "funding": [
-                {
-                    "url": "https://packagist.com",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/composer",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2021-07-31T17:03:58+00:00"
-        },
         {
             "name": "doctrine/instantiator",
             "version": "1.4.0",
@@ -7453,6 +7463,59 @@
             ],
             "time": "2020-11-10T18:47:58+00:00"
         },
+        {
+            "name": "facade/ignition-contracts",
+            "version": "1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/facade/ignition-contracts.git",
+                "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
+                "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.3|^8.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^v2.15.8",
+                "phpunit/phpunit": "^9.3.11",
+                "vimeo/psalm": "^3.17.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Facade\\IgnitionContracts\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Freek Van der Herten",
+                    "email": "freek@spatie.be",
+                    "homepage": "https://flareapp.io",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Solution contracts for Ignition",
+            "homepage": "https://github.com/facade/ignition-contracts",
+            "keywords": [
+                "contracts",
+                "flare",
+                "ignition"
+            ],
+            "support": {
+                "issues": "https://github.com/facade/ignition-contracts/issues",
+                "source": "https://github.com/facade/ignition-contracts/tree/1.0.2"
+            },
+            "time": "2020-10-16T08:27:54+00:00"
+        },
         {
             "name": "fakerphp/faker",
             "version": "v1.16.0",
@@ -7569,76 +7632,6 @@
             },
             "time": "2020-07-09T08:09:16+00:00"
         },
-        {
-            "name": "justinrainbow/json-schema",
-            "version": "5.2.11",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/justinrainbow/json-schema.git",
-                "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa",
-                "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1",
-                "json-schema/json-schema-test-suite": "1.2.0",
-                "phpunit/phpunit": "^4.8.35"
-            },
-            "bin": [
-                "bin/validate-json"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "5.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "JsonSchema\\": "src/JsonSchema/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bruno Prieto Reis",
-                    "email": "bruno.p.reis@gmail.com"
-                },
-                {
-                    "name": "Justin Rainbow",
-                    "email": "justin.rainbow@gmail.com"
-                },
-                {
-                    "name": "Igor Wiedler",
-                    "email": "igor@wiedler.ch"
-                },
-                {
-                    "name": "Robert Schönthal",
-                    "email": "seroscho@googlemail.com"
-                }
-            ],
-            "description": "A library to validate a json schema.",
-            "homepage": "https://github.com/justinrainbow/json-schema",
-            "keywords": [
-                "json",
-                "schema"
-            ],
-            "support": {
-                "issues": "https://github.com/justinrainbow/json-schema/issues",
-                "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11"
-            },
-            "time": "2021-07-22T09:24:00+00:00"
-        },
         {
             "name": "maximebf/debugbar",
             "version": "v1.17.2",
@@ -7835,60 +7828,92 @@
             "time": "2020-11-13T09:40:50+00:00"
         },
         {
-            "name": "nikic/php-parser",
-            "version": "v4.13.0",
+            "name": "nunomaduro/collision",
+            "version": "v4.3.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "50953a2691a922aa1769461637869a0a2faa3f53"
+                "url": "https://github.com/nunomaduro/collision.git",
+                "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53",
-                "reference": "50953a2691a922aa1769461637869a0a2faa3f53",
+                "url": "https://api.github.com/repos/nunomaduro/collision/zipball/7c125dc2463f3e144ddc7e05e63077109508c94e",
+                "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e",
                 "shasum": ""
             },
             "require": {
-                "ext-tokenizer": "*",
-                "php": ">=7.0"
+                "facade/ignition-contracts": "^1.0",
+                "filp/whoops": "^2.4",
+                "php": "^7.2.5 || ^8.0",
+                "symfony/console": "^5.0"
             },
             "require-dev": {
-                "ircmaxell/php-yacc": "^0.0.7",
-                "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
+                "facade/ignition": "^2.0",
+                "fideloper/proxy": "^4.2",
+                "friendsofphp/php-cs-fixer": "^2.16",
+                "fruitcake/laravel-cors": "^1.0",
+                "laravel/framework": "^7.0",
+                "laravel/tinker": "^2.0",
+                "nunomaduro/larastan": "^0.6",
+                "orchestra/testbench": "^5.0",
+                "phpstan/phpstan": "^0.12.3",
+                "phpunit/phpunit": "^8.5.1 || ^9.0"
             },
-            "bin": [
-                "bin/php-parse"
-            ],
             "type": "library",
             "extra": {
-                "branch-alias": {
-                    "dev-master": "4.9-dev"
+                "laravel": {
+                    "providers": [
+                        "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider"
+                    ]
                 }
             },
             "autoload": {
                 "psr-4": {
-                    "PhpParser\\": "lib/PhpParser"
+                    "NunoMaduro\\Collision\\": "src/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
-                "BSD-3-Clause"
+                "MIT"
             ],
             "authors": [
                 {
-                    "name": "Nikita Popov"
+                    "name": "Nuno Maduro",
+                    "email": "enunomaduro@gmail.com"
                 }
             ],
-            "description": "A PHP parser written in PHP",
+            "description": "Cli error handling for console/command-line PHP applications.",
             "keywords": [
-                "parser",
-                "php"
+                "artisan",
+                "cli",
+                "command-line",
+                "console",
+                "error",
+                "handling",
+                "laravel",
+                "laravel-zero",
+                "php",
+                "symfony"
             ],
             "support": {
-                "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0"
+                "issues": "https://github.com/nunomaduro/collision/issues",
+                "source": "https://github.com/nunomaduro/collision"
             },
-            "time": "2021-09-20T12:20:58+00:00"
+            "funding": [
+                {
+                    "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/nunomaduro",
+                    "type": "github"
+                },
+                {
+                    "url": "https://www.patreon.com/nunomaduro",
+                    "type": "patreon"
+                }
+            ],
+            "time": "2020-10-29T15:12:23+00:00"
         },
         {
             "name": "phar-io/manifest",
@@ -8649,56 +8674,6 @@
             ],
             "time": "2021-09-25T07:38:51+00:00"
         },
-        {
-            "name": "react/promise",
-            "version": "v2.8.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/reactphp/promise.git",
-                "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4",
-                "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.4.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "React\\Promise\\": "src/"
-                },
-                "files": [
-                    "src/functions_include.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jan Sorgalla",
-                    "email": "jsorgalla@gmail.com"
-                }
-            ],
-            "description": "A lightweight implementation of CommonJS Promises/A for PHP",
-            "keywords": [
-                "promise",
-                "promises"
-            ],
-            "support": {
-                "issues": "https://github.com/reactphp/promise/issues",
-                "source": "https://github.com/reactphp/promise/tree/v2.8.0"
-            },
-            "time": "2020-05-12T15:16:56+00:00"
-        },
         {
             "name": "sebastian/cli-parser",
             "version": "1.0.1",
@@ -9664,33 +9639,37 @@
             "time": "2020-09-28T06:39:44+00:00"
         },
         {
-            "name": "seld/jsonlint",
-            "version": "1.8.3",
+            "name": "symfony/debug",
+            "version": "v4.4.31",
             "source": {
                 "type": "git",
-                "url": "https://github.com/Seldaek/jsonlint.git",
-                "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57"
+                "url": "https://github.com/symfony/debug.git",
+                "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9ad6ce79c342fbd44df10ea95511a1b24dee5b57",
-                "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57",
+                "url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0",
+                "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.3 || ^7.0 || ^8.0"
+                "php": ">=7.1.3",
+                "psr/log": "^1|^2|^3"
+            },
+            "conflict": {
+                "symfony/http-kernel": "<3.4"
             },
             "require-dev": {
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
+                "symfony/http-kernel": "^3.4|^4.0|^5.0"
             },
-            "bin": [
-                "bin/jsonlint"
-            ],
             "type": "library",
             "autoload": {
                 "psr-4": {
-                    "Seld\\JsonLint\\": "src/Seld/JsonLint/"
-                }
+                    "Symfony\\Component\\Debug\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
@@ -9698,81 +9677,34 @@
             ],
             "authors": [
                 {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be"
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
                 }
             ],
-            "description": "JSON Linter",
-            "keywords": [
-                "json",
-                "linter",
-                "parser",
-                "validator"
-            ],
+            "description": "Provides tools to ease debugging PHP code",
+            "homepage": "https://symfony.com",
             "support": {
-                "issues": "https://github.com/Seldaek/jsonlint/issues",
-                "source": "https://github.com/Seldaek/jsonlint/tree/1.8.3"
+                "source": "https://github.com/symfony/debug/tree/v4.4.31"
             },
             "funding": [
                 {
-                    "url": "https://github.com/Seldaek",
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
                     "type": "github"
                 },
                 {
-                    "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-11-11T09:19:24+00:00"
-        },
-        {
-            "name": "seld/phar-utils",
-            "version": "1.1.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/Seldaek/phar-utils.git",
-                "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/749042a2315705d2dfbbc59234dd9ceb22bf3ff0",
-                "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Seld\\PharUtils\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be"
-                }
-            ],
-            "description": "PHAR file format utilities, for when PHP phars you up",
-            "keywords": [
-                "phar"
-            ],
-            "support": {
-                "issues": "https://github.com/Seldaek/phar-utils/issues",
-                "source": "https://github.com/Seldaek/phar-utils/tree/1.1.2"
-            },
-            "time": "2021-08-19T21:01:38+00:00"
+            "time": "2021-09-24T13:30:14+00:00"
         },
         {
             "name": "symfony/dom-crawler",
@@ -9849,69 +9781,6 @@
             ],
             "time": "2021-08-29T19:32:13+00:00"
         },
-        {
-            "name": "symfony/filesystem",
-            "version": "v5.3.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/filesystem.git",
-                "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32",
-                "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.2.5",
-                "symfony/polyfill-ctype": "~1.8",
-                "symfony/polyfill-php80": "^1.16"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Filesystem\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Provides basic utilities for the filesystem",
-            "homepage": "https://symfony.com",
-            "support": {
-                "source": "https://github.com/symfony/filesystem/tree/v5.3.4"
-            },
-            "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-07-21T12:40:44+00:00"
-        },
         {
             "name": "theseer/tokenizer",
             "version": "1.2.1",
diff --git a/database/migrations/2018_08_04_115700_create_bookshelves_table.php b/database/migrations/2018_08_04_115700_create_bookshelves_table.php
index 04f46ce50..8dc2a72e9 100644
--- a/database/migrations/2018_08_04_115700_create_bookshelves_table.php
+++ b/database/migrations/2018_08_04_115700_create_bookshelves_table.php
@@ -120,11 +120,11 @@ class CreateBookshelvesTable extends Migration
         Schema::dropIfExists('bookshelves');
 
         // Drop related polymorphic items
-        DB::table('activities')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
-        DB::table('views')->where('viewable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
-        DB::table('entity_permissions')->where('restrictable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
-        DB::table('tags')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
-        DB::table('search_terms')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
-        DB::table('comments')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
+        DB::table('activities')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
+        DB::table('views')->where('viewable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
+        DB::table('entity_permissions')->where('restrictable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
+        DB::table('tags')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
+        DB::table('search_terms')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
+        DB::table('comments')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
     }
 }
diff --git a/phpunit.xml b/phpunit.xml
index 7e0da05d4..960f4c4c3 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -1,15 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
-         backupGlobals="false"
-         backupStaticAttributes="false"
          bootstrap="vendor/autoload.php"
-         colors="true"
-         convertErrorsToExceptions="true"
-         convertNoticesToExceptions="true"
-         convertWarningsToExceptions="true"
-         processIsolation="false"
-         stopOnFailure="false">
+         colors="true">
   <coverage>
     <include>
       <directory suffix=".php">app/</directory>
diff --git a/resources/lang/ar/auth.php b/resources/lang/ar/auth.php
index c0cc8bbc0..fa48d65e7 100644
--- a/resources/lang/ar/auth.php
+++ b/resources/lang/ar/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'المجال الخاص بالبريد الإلكتروني لا يملك حق الوصول لهذا التطبيق',
     'register_success' => 'شكراً لإنشاء حسابكم! تم تسجيلكم ودخولكم للحساب الخاص بكم.',
 
-
     // Password Reset
     'reset_password' => 'استعادة كلمة المرور',
     'reset_password_send_instructions' => 'أدخل بريدك الإلكتروني بالأسفل وسيتم إرسال رسالة برابط لاستعادة كلمة المرور.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'تم إرسال هذه الرسالة بسبب تلقينا لطلب استعادة كلمة المرور الخاصة بحسابكم.',
     'email_reset_not_requested' => 'إذا لم يتم طلب استعادة كلمة المرور من قبلكم، فلا حاجة لاتخاذ أية خطوات.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'تأكيد بريدكم الإلكتروني لتطبيق :appName',
     'email_confirm_greeting' => 'شكرا لانضمامكم إلى :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/ar/common.php b/resources/lang/ar/common.php
index de40e583e..53e18964d 100644
--- a/resources/lang/ar/common.php
+++ b/resources/lang/ar/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'الدور',
     'cover_image' => 'صورة الغلاف',
     'cover_image_description' => 'الصورة يجب أن تكون مقاربة لحجم 440×250 بكسل.',
-    
+
     // Actions
     'actions' => 'إجراءات',
     'view' => 'عرض',
diff --git a/resources/lang/ar/entities.php b/resources/lang/ar/entities.php
index c9e3f322c..e4888d0b2 100644
--- a/resources/lang/ar/entities.php
+++ b/resources/lang/ar/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'هل أنت متأكد من أنك تريد حذف هذه المراجعة؟',
     'revision_restore_confirm' => 'هل أنت متأكد من أنك تريد استعادة هذه المراجعة؟ سيتم استبدال محتوى الصفحة الحالية.',
     'revision_delete_success' => 'تم حذف المراجعة',
-    'revision_cannot_delete_latest' => 'لايمكن حذف آخر مراجعة.'
+    'revision_cannot_delete_latest' => 'لايمكن حذف آخر مراجعة.',
 ];
diff --git a/resources/lang/ar/passwords.php b/resources/lang/ar/passwords.php
index 4ab447d5d..33b8e9c3e 100644
--- a/resources/lang/ar/passwords.php
+++ b/resources/lang/ar/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'يجب أن تتكون كلمة المرور من ستة أحرف على الأقل وأن تطابق التأكيد.',
-    'user' => "لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.",
+    'user' => 'لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.',
     'token' => 'رمز إعادة تعيين كلمة المرور غير صالح لعنوان هذا البريد الإلكتروني.',
     'sent' => 'تم إرسال رابط تجديد كلمة المرور إلى بريدكم الإلكتروني!',
     'reset' => 'تم تجديد كلمة المرور الخاصة بكم!',
diff --git a/resources/lang/ar/settings.php b/resources/lang/ar/settings.php
index b4ccd9482..f3ebc3039 100755
--- a/resources/lang/ar/settings.php
+++ b/resources/lang/ar/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'الصيانة',
     'maint_image_cleanup' => 'تنظيف الصور',
-    'maint_image_cleanup_desc' => "مسح الصفحة ومراجعة المحتوى للتحقق من أي الصور والرسوم المستخدمة حاليًا وأي الصور زائدة عن الحاجة. تأكد من إنشاء قاعدة بيانات كاملة و نسخة احتياطية للصور قبل تشغيل هذا.",
+    'maint_image_cleanup_desc' => 'مسح الصفحة ومراجعة المحتوى للتحقق من أي الصور والرسوم المستخدمة حاليًا وأي الصور زائدة عن الحاجة. تأكد من إنشاء قاعدة بيانات كاملة و نسخة احتياطية للصور قبل تشغيل هذا.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'بدء التنظيف',
     'maint_image_cleanup_warning' => 'يوجد عدد :count من الصور المحتمل عدم استخدامها. تأكيد حذف الصور؟',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'حذف الدور',
     'role_delete_confirm' => 'سيتم حذف الدور المسمى \':roleName\'.',
     'role_delete_users_assigned' => 'هذا الدور له: عدد المستخدمين المعينين له. إذا كنت ترغب في ترحيل المستخدمين من هذا الدور ، فحدد دورًا جديدًا أدناه.',
-    'role_delete_no_migration' => "لا تقم بترجيل المستخدمين",
+    'role_delete_no_migration' => 'لا تقم بترجيل المستخدمين',
     'role_delete_sure' => 'تأكيد حذف الدور؟',
     'role_delete_success' => 'تم حذف الدور بنجاح',
     'role_edit' => 'تعديل الدور',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/bg/auth.php b/resources/lang/bg/auth.php
index d04796cfe..50499fc78 100644
--- a/resources/lang/bg/auth.php
+++ b/resources/lang/bg/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Този емейл домейн към момента няма достъп до приложението',
     'register_success' => 'Благодарим Ви за регистрацията! В момента сте регистриран и сте вписани в приложението.',
 
-
     // Password Reset
     'reset_password' => 'Нулиране на паролата',
     'reset_password_send_instructions' => 'Въведете емейла си и ще ви бъде изпратен емейл с линк за нулиране на паролата.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Вие получихте този емейл, защото поискахте вашата парола да бъде занулена.',
     'email_reset_not_requested' => 'Ако Вие не сте поискали зануляването на паролата, няма нужда от други действия.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Потвърди емейла си за :appName',
     'email_confirm_greeting' => 'Благодарим Ви, че се присъединихте към :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/bg/common.php b/resources/lang/bg/common.php
index 4b0f72a60..110487a41 100644
--- a/resources/lang/bg/common.php
+++ b/resources/lang/bg/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Роля',
     'cover_image' => 'Основно изображение',
     'cover_image_description' => 'Картината трябва да е приблизително 440х250 пиксела.',
-    
+
     // Actions
     'actions' => 'Действия',
     'view' => 'Преглед',
diff --git a/resources/lang/bg/entities.php b/resources/lang/bg/entities.php
index bfcfb2758..1db29c5e3 100644
--- a/resources/lang/bg/entities.php
+++ b/resources/lang/bg/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Наистина ли искате да изтриете тази версия?',
     'revision_restore_confirm' => 'Сигурни ли сте, че искате да изтриете тази версия? Настоящата страница ще бъде заместена.',
     'revision_delete_success' => 'Версията беше изтрита',
-    'revision_cannot_delete_latest' => 'Не може да изтриете последната версия.'
+    'revision_cannot_delete_latest' => 'Не може да изтриете последната версия.',
 ];
diff --git a/resources/lang/bg/passwords.php b/resources/lang/bg/passwords.php
index 871fdeea8..5fb192a44 100644
--- a/resources/lang/bg/passwords.php
+++ b/resources/lang/bg/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Паролите трябва да имат поне 8 символа и да съвпадат с потвърждението.',
-    'user' => "Не можем да намерим потребител с този имейл адрес.",
+    'user' => 'Не можем да намерим потребител с този имейл адрес.',
     'token' => 'Кодът за зануляване на паролата е невалиден за този емейл адрес.',
     'sent' => 'Пратихме връзка за нулиране на паролата до имейла ви!',
     'reset' => 'Вашата парола е нулирана!',
diff --git a/resources/lang/bg/settings.php b/resources/lang/bg/settings.php
index e6afe7101..2151e2e20 100644
--- a/resources/lang/bg/settings.php
+++ b/resources/lang/bg/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Maintenance',
     'maint_image_cleanup' => 'Cleanup Images',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Run Cleanup',
     'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Изтрий роля',
     'role_delete_confirm' => 'Това ще изтрие ролята \':roleName\'.',
     'role_delete_users_assigned' => 'В тази роля се намират :userCount потребители. Ако искате да преместите тези потребители в друга роля, моля изберете нова роля отдолу.',
-    'role_delete_no_migration' => "Не премествай потребителите в нова роля",
+    'role_delete_no_migration' => 'Не премествай потребителите в нова роля',
     'role_delete_sure' => 'Сигурни ли сте, че искате да изтриете тази роля?',
     'role_delete_success' => 'Ролята беше успешно изтрита',
     'role_edit' => 'Редактиране на роля',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/bs/auth.php b/resources/lang/bs/auth.php
index a5926fa2b..3a5517331 100644
--- a/resources/lang/bs/auth.php
+++ b/resources/lang/bs/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Ta e-mail domena nema pristup ovoj aplikaciji',
     'register_success' => 'Hvala na registraciji! Sada ste registrovani i prijavljeni.',
 
-
     // Password Reset
     'reset_password' => 'Resetuj Lozinku',
     'reset_password_send_instructions' => 'Unesite vašu e-mail adresu ispod i na nju ćemo vam poslati e-mail sa linkom za promjenu lozinke.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Primate ovaj e-mail jer smo dobili zahtjev za promjenu lozinke za vaš račun.',
     'email_reset_not_requested' => 'Ako niste zahtijevali promjenu lozinke ne trebate ništa više uraditi.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Potvrdite vaš e-mail na :appName',
     'email_confirm_greeting' => 'Hvala na pristupanju :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/bs/common.php b/resources/lang/bs/common.php
index 17ec0b765..a511a10be 100644
--- a/resources/lang/bs/common.php
+++ b/resources/lang/bs/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Uloga',
     'cover_image' => 'Naslovna slika',
     'cover_image_description' => 'Ova slika treba biti približno 440x250px.',
-    
+
     // Actions
     'actions' => 'Akcije',
     'view' => 'Prikaz',
diff --git a/resources/lang/bs/entities.php b/resources/lang/bs/entities.php
index 102019d2a..680053bc9 100644
--- a/resources/lang/bs/entities.php
+++ b/resources/lang/bs/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
     'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.',
     'revision_delete_success' => 'Revision deleted',
-    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.'
+    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.',
 ];
diff --git a/resources/lang/bs/passwords.php b/resources/lang/bs/passwords.php
index 0383e8af0..54880f4b5 100644
--- a/resources/lang/bs/passwords.php
+++ b/resources/lang/bs/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Lozinke moraju sadržavati najmanje osam karaktera i podudarati se sa potvrdom lozinke.',
-    'user' => "Ne možemo naći korisnika sa tom e-mail adresom.",
+    'user' => 'Ne možemo naći korisnika sa tom e-mail adresom.',
     'token' => 'Token za poništavanje lozinke nije validan za ovu e-mail adresu.',
     'sent' => 'Poslali smo link za poništavanje vaše lozinke na e-mail!',
     'reset' => 'Vaša lozinka je resetovana!',
diff --git a/resources/lang/bs/settings.php b/resources/lang/bs/settings.php
index 46df0d07d..335a1b436 100644
--- a/resources/lang/bs/settings.php
+++ b/resources/lang/bs/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Maintenance',
     'maint_image_cleanup' => 'Cleanup Images',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Run Cleanup',
     'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/ca/auth.php b/resources/lang/ca/auth.php
index 9febe36b7..e22ca74bf 100644
--- a/resources/lang/ca/auth.php
+++ b/resources/lang/ca/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Aquest domini de correu electrònic no té accés a aquesta aplicació',
     'register_success' => 'Gràcies per registrar-vos! Ja us hi heu registrat i heu iniciat la sessió.',
 
-
     // Password Reset
     'reset_password' => 'Restableix la contrasenya',
     'reset_password_send_instructions' => 'Introduïu la vostra adreça electrònica a continuació i us enviarem un correu electrònic amb un enllaç per a restablir la contrasenya.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Rebeu aquest correu electrònic perquè heu rebut una petició de restabliment de contrasenya per al vostre compte.',
     'email_reset_not_requested' => 'Si no heu demanat restablir la contrasenya, no cal que prengueu cap acció.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirmeu la vostra adreça electrònica a :appName',
     'email_confirm_greeting' => 'Gràcies per unir-vos a :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/ca/common.php b/resources/lang/ca/common.php
index 497395060..0f18099e7 100644
--- a/resources/lang/ca/common.php
+++ b/resources/lang/ca/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rol',
     'cover_image' => 'Imatge de portada',
     'cover_image_description' => 'Aquesta imatge hauria de fer aproximadament 440x250 px.',
-    
+
     // Actions
     'actions' => 'Accions',
     'view' => 'Visualitza',
diff --git a/resources/lang/ca/entities.php b/resources/lang/ca/entities.php
index 36466e920..d486fe512 100644
--- a/resources/lang/ca/entities.php
+++ b/resources/lang/ca/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Segur que voleu suprimir aquesta revisió?',
     'revision_restore_confirm' => 'Segur que voleu restaurar aquesta revisió? Se substituirà el contingut de la pàgina actual.',
     'revision_delete_success' => 'S\'ha suprimit la revisió',
-    'revision_cannot_delete_latest' => 'No es pot suprimir la darrera revisió.'
+    'revision_cannot_delete_latest' => 'No es pot suprimir la darrera revisió.',
 ];
diff --git a/resources/lang/ca/settings.php b/resources/lang/ca/settings.php
index 74e692798..4a1e66855 100755
--- a/resources/lang/ca/settings.php
+++ b/resources/lang/ca/settings.php
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Suprimeix el rol',
     'role_delete_confirm' => 'Se suprimirà el rol amb el nom \':roleName\'.',
     'role_delete_users_assigned' => 'Aquest rol té :userCount usuaris assignats. Si voleu migrar els usuaris d\'aquest rol, seleccioneu un rol nou a continuació.',
-    'role_delete_no_migration' => "No migris els usuaris",
+    'role_delete_no_migration' => 'No migris els usuaris',
     'role_delete_sure' => 'Segur que voleu suprimir aquest rol?',
     'role_delete_success' => 'Rol suprimit correctament',
     'role_edit' => 'Edita el rol',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/cs/auth.php b/resources/lang/cs/auth.php
index ad83a6926..f95242009 100644
--- a/resources/lang/cs/auth.php
+++ b/resources/lang/cs/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Registrace z této e-mailové domény nejsou povoleny',
     'register_success' => 'Děkujeme za registraci! Nyní jste zaregistrováni a přihlášeni.',
 
-
     // Password Reset
     'reset_password' => 'Obnovit heslo',
     'reset_password_send_instructions' => 'Níže zadejte svou e-mailovou adresu a bude vám zaslán e-mail s odkazem na obnovení hesla.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Tento e-mail jste obdrželi, protože jsme obdrželi žádost o obnovení hesla k vašemu účtu.',
     'email_reset_not_requested' => 'Pokud jste o obnovení hesla nežádali, není vyžadována žádná další akce.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Potvrďte svůj e-mail pro :appName',
     'email_confirm_greeting' => 'Díky že jste se přidali do :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/cs/common.php b/resources/lang/cs/common.php
index 14555a912..d837116ee 100644
--- a/resources/lang/cs/common.php
+++ b/resources/lang/cs/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Role',
     'cover_image' => 'Obrázek obálky',
     'cover_image_description' => 'Obrázek by měl být přibližně 440×250px.',
-    
+
     // Actions
     'actions' => 'Akce',
     'view' => 'Zobrazit',
diff --git a/resources/lang/cs/entities.php b/resources/lang/cs/entities.php
index d82d4c2ea..548c01a84 100644
--- a/resources/lang/cs/entities.php
+++ b/resources/lang/cs/entities.php
@@ -94,7 +94,7 @@ return [
     'shelves_edit' => 'Upravit knihovnu',
     'shelves_delete' => 'Odstranit knihovnu',
     'shelves_delete_named' => 'Odstranit knihovnu :name',
-    'shelves_delete_explain' => "Toto odstraní knihovnu ‚:name‘. Vložené knihy nebudou odstraněny.",
+    'shelves_delete_explain' => 'Toto odstraní knihovnu ‚:name‘. Vložené knihy nebudou odstraněny.',
     'shelves_delete_confirmation' => 'Opravdu chcete odstranit tuto knihovnu?',
     'shelves_permissions' => 'Oprávnění knihovny',
     'shelves_permissions_updated' => 'Oprávnění knihovny byla aktualizována',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Opravdu chcete odstranit tuto revizi?',
     'revision_restore_confirm' => 'Jste si jisti, že chcete obnovit tuto revizi? Aktuální obsah stránky bude nahrazen.',
     'revision_delete_success' => 'Revize odstraněna',
-    'revision_cannot_delete_latest' => 'Nelze odstranit poslední revizi.'
+    'revision_cannot_delete_latest' => 'Nelze odstranit poslední revizi.',
 ];
diff --git a/resources/lang/cs/passwords.php b/resources/lang/cs/passwords.php
index 40b12b607..b25e24f3c 100644
--- a/resources/lang/cs/passwords.php
+++ b/resources/lang/cs/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Heslo musí mít alespoň osm znaků a musí odpovídat potvrzení hesla.',
-    'user' => "Nemůžeme nalézt uživatele s touto e-mailovou adresou.",
+    'user' => 'Nemůžeme nalézt uživatele s touto e-mailovou adresou.',
     'token' => 'Token pro obnovení hesla není platný pro tuto e-mailovou adresu.',
     'sent' => 'Poslali jsme Vám e-mail s odkazem pro obnovení hesla!',
     'reset' => 'Vaše heslo bylo obnoveno!',
diff --git a/resources/lang/cs/settings.php b/resources/lang/cs/settings.php
index b2e840044..b4a726830 100644
--- a/resources/lang/cs/settings.php
+++ b/resources/lang/cs/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Údržba',
     'maint_image_cleanup' => 'Pročistění obrázků',
-    'maint_image_cleanup_desc' => "Prohledá stránky a jejich revize, aby zjistil, které obrázky a kresby jsou momentálně používány a které jsou zbytečné. Zajistěte plnou zálohu databáze a obrázků než se do toho pustíte.",
+    'maint_image_cleanup_desc' => 'Prohledá stránky a jejich revize, aby zjistil, které obrázky a kresby jsou momentálně používány a které jsou zbytečné. Zajistěte plnou zálohu databáze a obrázků než se do toho pustíte.',
     'maint_delete_images_only_in_revisions' => 'Odstranit i obrázky, které se vyskytují pouze ve starých revizích stránky',
     'maint_image_cleanup_run' => 'Spustit pročištění',
     'maint_image_cleanup_warning' => 'Nalezeno :count potenciálně nepoužitých obrázků. Jste si jisti, že je chcete odstranit?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Odstranit roli',
     'role_delete_confirm' => 'Role \':roleName\' bude odstraněna.',
     'role_delete_users_assigned' => 'Role je přiřazena :userCount uživatelům. Pokud jim chcete náhradou přidělit jinou roli, zvolte jednu z následujících.',
-    'role_delete_no_migration' => "Nepřiřazovat uživatelům náhradní roli",
+    'role_delete_no_migration' => 'Nepřiřazovat uživatelům náhradní roli',
     'role_delete_sure' => 'Opravdu chcete tuto roli odstranit?',
     'role_delete_success' => 'Role byla odstraněna',
     'role_edit' => 'Upravit roli',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/da/auth.php b/resources/lang/da/auth.php
index 8c9d86ea6..6b627c027 100644
--- a/resources/lang/da/auth.php
+++ b/resources/lang/da/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'E-Mail domænet har ikke adgang til denne applikation',
     'register_success' => 'Tak for din registrering. Du er nu registeret og logget ind.',
 
-
     // Password Reset
     'reset_password' => 'Nulstil adgangskode',
     'reset_password_send_instructions' => 'Indtast din E-Mail herunder og du vil blive sendt en E-Mail med et link til at nulstille din adgangskode.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Du modtager denne E-Mail fordi vi har modtaget en anmodning om at nulstille din adgangskode.',
     'email_reset_not_requested' => 'Hvis du ikke har anmodet om at få din adgangskode nulstillet, behøver du ikke at foretage dig noget.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Bekræft din E-Mail på :appName',
     'email_confirm_greeting' => 'Tak for at oprette dig på :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/da/common.php b/resources/lang/da/common.php
index 0e4269734..563aff97b 100644
--- a/resources/lang/da/common.php
+++ b/resources/lang/da/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rolle',
     'cover_image' => 'Coverbillede',
     'cover_image_description' => 'Dette billede skal være omtrent 440x250px.',
-    
+
     // Actions
     'actions' => 'Handlinger',
     'view' => 'Vis',
diff --git a/resources/lang/da/entities.php b/resources/lang/da/entities.php
index 0d9d67cb4..3c2f56474 100644
--- a/resources/lang/da/entities.php
+++ b/resources/lang/da/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Er du sikker på at du vil slette denne revision?',
     'revision_restore_confirm' => 'Er du sikker på at du ønsker at gendanne denne revision? Nuværende sideindhold vil blive erstattet.',
     'revision_delete_success' => 'Revision slettet',
-    'revision_cannot_delete_latest' => 'Kan ikke slette seneste revision.'
+    'revision_cannot_delete_latest' => 'Kan ikke slette seneste revision.',
 ];
diff --git a/resources/lang/da/passwords.php b/resources/lang/da/passwords.php
index 343fa2b85..39ed9418f 100644
--- a/resources/lang/da/passwords.php
+++ b/resources/lang/da/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Adgangskoder skal være mindst otte tegn og svare til bekræftelsen.',
-    'user' => "Vi kan ikke finde en bruger med den e-mail adresse.",
+    'user' => 'Vi kan ikke finde en bruger med den e-mail adresse.',
     'token' => 'Linket til nulstilling af adgangskode er ugyldigt for denne e-mail-adresse.',
     'sent' => 'Vi har sendt dig en e-mail med et link til at nulstille adgangskoden!',
     'reset' => 'Dit kodeord er blevet nulstillet!',
diff --git a/resources/lang/da/settings.php b/resources/lang/da/settings.php
index 804a67bba..83b27aaab 100644
--- a/resources/lang/da/settings.php
+++ b/resources/lang/da/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Vedligeholdelse',
     'maint_image_cleanup' => 'Ryd op i billeder',
-    'maint_image_cleanup_desc' => "Scanner side & revisionsindhold for at kontrollere, hvilke billeder og tegninger, der i øjeblikket er i brug, og hvilke billeder, der er overflødige. Sørg for, at du opretter en komplet database og billedbackup, før du kører dette.",
+    'maint_image_cleanup_desc' => 'Scanner side & revisionsindhold for at kontrollere, hvilke billeder og tegninger, der i øjeblikket er i brug, og hvilke billeder, der er overflødige. Sørg for, at du opretter en komplet database og billedbackup, før du kører dette.',
     'maint_delete_images_only_in_revisions' => 'Slet også billeder, der kun findes i gamle siderevisioner',
     'maint_image_cleanup_run' => 'Kør Oprydning',
     'maint_image_cleanup_warning' => 'der blev fundet :count potentielt ubrugte billeder. Er du sikker på, at du vil slette disse billeder?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Slet rolle',
     'role_delete_confirm' => 'Dette vil slette rollen med navnet \':roleName\'.',
     'role_delete_users_assigned' => 'Denne rolle er tildelt :userCount brugere. Hvis du vil rykke disse brugere fra denne rolle, kan du vælge en ny nedenunder.',
-    'role_delete_no_migration' => "Ryk ikke brugere",
+    'role_delete_no_migration' => 'Ryk ikke brugere',
     'role_delete_sure' => 'Er du sikker på, at du vil slette denne rolle?',
     'role_delete_success' => 'Rollen blev slettet',
     'role_edit' => 'Rediger rolle',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/de/auth.php b/resources/lang/de/auth.php
index efe82680d..2c0989272 100644
--- a/resources/lang/de/auth.php
+++ b/resources/lang/de/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Sie können sich mit dieser E-Mail nicht registrieren.',
     'register_success' => 'Vielen Dank für Ihre Registrierung! Die Daten sind gespeichert und Sie sind angemeldet.',
 
-
     // Password Reset
     'reset_password' => 'Passwort vergessen',
     'reset_password_send_instructions' => 'Bitte geben Sie Ihre E-Mail-Adresse ein. Danach erhalten Sie eine E-Mail mit einem Link zum Zurücksetzen Ihres Passwortes.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Sie erhalten diese E-Mail, weil jemand versucht hat, Ihr Passwort zurückzusetzen.',
     'email_reset_not_requested' => 'Wenn Sie das nicht waren, brauchen Sie nichts weiter zu tun.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Bestätigen Sie Ihre E-Mail-Adresse für :appName',
     'email_confirm_greeting' => 'Danke, dass Sie sich für :appName registriert haben!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Backup-Code hier eingeben',
     'mfa_verify_totp_desc' => 'Geben Sie den Code ein, der mit Ihrer mobilen App generiert wurde:',
     'mfa_setup_login_notification' => 'Multi-Faktor-Methode konfiguriert. Bitte melden Sie sich jetzt erneut mit der konfigurierten Methode an.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/de/common.php b/resources/lang/de/common.php
index bd75e1737..fddd735f4 100644
--- a/resources/lang/de/common.php
+++ b/resources/lang/de/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rolle',
     'cover_image' => 'Titelbild',
     'cover_image_description' => 'Das Bild sollte eine Auflösung von 440x250px haben.',
-    
+
     // Actions
     'actions' => 'Aktionen',
     'view' => 'Anzeigen',
diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php
index 200961c97..d23eb679f 100644
--- a/resources/lang/de/entities.php
+++ b/resources/lang/de/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Sind Sie sicher, dass Sie diese Revision löschen wollen?',
     'revision_restore_confirm' => 'Sind Sie sicher, dass Sie diese Revision wiederherstellen wollen? Der aktuelle Seiteninhalt wird ersetzt.',
     'revision_delete_success' => 'Revision gelöscht',
-    'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.'
+    'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.',
 ];
diff --git a/resources/lang/de/passwords.php b/resources/lang/de/passwords.php
index 3da092cb8..5f3762e16 100644
--- a/resources/lang/de/passwords.php
+++ b/resources/lang/de/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.',
-    'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.",
+    'user' => 'Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.',
     'token' => 'Der Link zum Zurücksetzen Ihres Passworts ist entweder ungültig oder abgelaufen.',
     'sent' => 'Der Link zum Zurücksetzen Ihres Passwortes wurde Ihnen per E-Mail zugesendet.',
     'reset' => 'Ihr Passwort wurde zurückgesetzt!',
diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php
index 5d6c19d10..1d1c47060 100644
--- a/resources/lang/de/settings.php
+++ b/resources/lang/de/settings.php
@@ -75,7 +75,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
     // Maintenance settings
     'maint' => 'Wartung',
     'maint_image_cleanup' => 'Bilder bereinigen',
-    'maint_image_cleanup_desc' => "Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstellen Sie vor dem Start ein Backup Ihrer Datenbank und Bilder.",
+    'maint_image_cleanup_desc' => 'Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstellen Sie vor dem Start ein Backup Ihrer Datenbank und Bilder.',
     'maint_delete_images_only_in_revisions' => 'Lösche auch Bilder, die nur in alten Seitenüberarbeitungen vorhanden sind',
     'maint_image_cleanup_run' => 'Reinigung starten',
     'maint_image_cleanup_warning' => ':count eventuell unbenutze Bilder wurden gefunden. Möchten Sie diese Bilder löschen?',
@@ -135,7 +135,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
     'role_delete' => 'Rolle löschen',
     'role_delete_confirm' => 'Sie möchten die Rolle ":roleName" löschen.',
     'role_delete_users_assigned' => 'Diese Rolle ist :userCount Benutzern zugeordnet. Sie können unten eine neue Rolle auswählen, die Sie diesen Benutzern zuordnen möchten.',
-    'role_delete_no_migration' => "Den Benutzern keine andere Rolle zuordnen",
+    'role_delete_no_migration' => 'Den Benutzern keine andere Rolle zuordnen',
     'role_delete_sure' => 'Sind Sie sicher, dass Sie diese Rolle löschen möchten?',
     'role_delete_success' => 'Rolle erfolgreich gelöscht',
     'role_edit' => 'Rolle bearbeiten',
@@ -276,6 +276,6 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/de_informal/auth.php b/resources/lang/de_informal/auth.php
index 70da5bae2..de845ba7d 100644
--- a/resources/lang/de_informal/auth.php
+++ b/resources/lang/de_informal/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Du kannst dich mit dieser E-Mail nicht registrieren.',
     'register_success' => 'Vielen Dank für deine Registrierung! Du bist jetzt registriert und eingeloggt.',
 
-
     // Password Reset
     'reset_password' => 'Passwort vergessen',
     'reset_password_send_instructions' => 'Bitte gib Deine E-Mail-Adresse ein. Danach erhältst Du eine E-Mail mit einem Link zum Zurücksetzen Deines Passwortes.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Du erhältsts diese E-Mail, weil jemand versucht hat, Dein Passwort zurückzusetzen.',
     'email_reset_not_requested' => 'Wenn du das zurücksetzen des Passworts nicht angefordert hast, ist keine weitere Aktion erforderlich.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Bestätige Deine E-Mail-Adresse für :appName',
     'email_confirm_greeting' => 'Danke, dass Du dich für :appName registrierst hast!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Backup-Code hier eingeben',
     'mfa_verify_totp_desc' => 'Geben Sie den Code ein, der mit Ihrer mobilen App generiert wurde:',
     'mfa_setup_login_notification' => 'Multi-Faktor-Methode konfiguriert. Bitte melden Sie sich jetzt erneut mit der konfigurierten Methode an.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/de_informal/common.php b/resources/lang/de_informal/common.php
index 898df928e..a3663396e 100644
--- a/resources/lang/de_informal/common.php
+++ b/resources/lang/de_informal/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rolle',
     'cover_image' => 'Titelbild',
     'cover_image_description' => 'Das Bild sollte eine Auflösung von 440x250px haben.',
-    
+
     // Actions
     'actions' => 'Aktionen',
     'view' => 'Anzeigen',
diff --git a/resources/lang/de_informal/entities.php b/resources/lang/de_informal/entities.php
index 712421b1f..c29a7db2c 100644
--- a/resources/lang/de_informal/entities.php
+++ b/resources/lang/de_informal/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Bist Du sicher, dass Du diese Revision löschen möchtest?',
     'revision_restore_confirm' => 'Sind Sie sicher, dass Sie diese Revision wiederherstellen wollen? Der aktuelle Seiteninhalt wird ersetzt.',
     'revision_delete_success' => 'Revision gelöscht',
-    'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.'
+    'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.',
 ];
diff --git a/resources/lang/de_informal/passwords.php b/resources/lang/de_informal/passwords.php
index 0dd28c019..b5b38d7fd 100644
--- a/resources/lang/de_informal/passwords.php
+++ b/resources/lang/de_informal/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.',
-    'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.",
+    'user' => 'Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.',
     'token' => 'Der Token zum Zurücksetzen des Passworts für diese E-Mail-Adresse ist ungültig.',
     'sent' => 'Wir haben dir einen Link zum Zurücksetzen des Passwortes per E-Mail geschickt!',
     'reset' => 'Dein Passwort wurde zurückgesetzt!',
diff --git a/resources/lang/de_informal/settings.php b/resources/lang/de_informal/settings.php
index 8fdae9863..d22f73e89 100644
--- a/resources/lang/de_informal/settings.php
+++ b/resources/lang/de_informal/settings.php
@@ -75,7 +75,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
     // Maintenance settings
     'maint' => 'Wartung',
     'maint_image_cleanup' => 'Bilder bereinigen',
-    'maint_image_cleanup_desc' => "Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstelle vor dem Start ein Backup Deiner Datenbank und Bilder.",
+    'maint_image_cleanup_desc' => 'Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstelle vor dem Start ein Backup Deiner Datenbank und Bilder.',
     'maint_delete_images_only_in_revisions' => 'Lösche auch Bilder, die nur in alten Seitenüberarbeitungen vorhanden sind',
     'maint_image_cleanup_run' => 'Reinigung starten',
     'maint_image_cleanup_warning' => ':count eventuell unbenutze Bilder wurden gefunden. Möchtest Du diese Bilder löschen?',
@@ -135,7 +135,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
     'role_delete' => 'Rolle löschen',
     'role_delete_confirm' => 'Du möchtest die Rolle ":roleName" löschen.',
     'role_delete_users_assigned' => 'Diese Rolle ist :userCount Benutzern zugeordnet. Du kannst unten eine neue Rolle auswählen, die Du diesen Benutzern zuordnen möchtest.',
-    'role_delete_no_migration' => "Den Benutzern keine andere Rolle zuordnen",
+    'role_delete_no_migration' => 'Den Benutzern keine andere Rolle zuordnen',
     'role_delete_sure' => 'Bist Du sicher, dass Du diese Rolle löschen möchtest?',
     'role_delete_success' => 'Rolle erfolgreich gelöscht',
     'role_edit' => 'Rolle bearbeiten',
@@ -276,6 +276,6 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php
index e4d4c425b..ee0ba2d21 100644
--- a/resources/lang/en/auth.php
+++ b/resources/lang/en/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'That email domain does not have access to this application',
     'register_success' => 'Thanks for signing up! You are now registered and signed in.',
 
-
     // Password Reset
     'reset_password' => 'Reset Password',
     'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.',
     'email_reset_not_requested' => 'If you did not request a password reset, no further action is required.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirm your email on :appName',
     'email_confirm_greeting' => 'Thanks for joining :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php
index f93fb034b..161891bf4 100644
--- a/resources/lang/en/common.php
+++ b/resources/lang/en/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Role',
     'cover_image' => 'Cover image',
     'cover_image_description' => 'This image should be approx 440x250px.',
-    
+
     // Actions
     'actions' => 'Actions',
     'view' => 'View',
diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php
index 0a4068eea..4871b6225 100644
--- a/resources/lang/en/entities.php
+++ b/resources/lang/en/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
     'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.',
     'revision_delete_success' => 'Revision deleted',
-    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.'
+    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.',
 ];
diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php
index 8c35d6849..688b0aad8 100755
--- a/resources/lang/en/settings.php
+++ b/resources/lang/en/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Maintenance',
     'maint_image_cleanup' => 'Cleanup Images',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Run Cleanup',
     'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/es/auth.php b/resources/lang/es/auth.php
index 70f069a12..8a7710afe 100644
--- a/resources/lang/es/auth.php
+++ b/resources/lang/es/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Este dominio de correo electrónico no tiene acceso a esta aplicación',
     'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y logueado.',
 
-
     // Password Reset
     'reset_password' => 'Resetear Contraseña',
     'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y le será enviado un correo con un link para la restauración',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Está recibiendo este correo electrónico debido a que recibimos una solicitud de reseteo de contraseña de su cuenta.',
     'email_reset_not_requested' => 'Si no ha solicitado un reseteo de la contraseña, no es requerida ninguna acción por su parte.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirme su correo electrónico en :appName',
     'email_confirm_greeting' => '¡Gracias por unirse a :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Introduce el código de respaldo aquí',
     'mfa_verify_totp_desc' => 'Introduzca el código, generado con tu aplicación móvil, a continuación:',
     'mfa_setup_login_notification' => 'Método de dos factores configurado. Por favor, inicia sesión de nuevo utilizando el método configurado.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/es/common.php b/resources/lang/es/common.php
index b8514a876..f36cd5eb0 100644
--- a/resources/lang/es/common.php
+++ b/resources/lang/es/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rol',
     'cover_image' => 'Imagen de portada',
     'cover_image_description' => 'Esta imagen debe ser aproximadamente de 440x250px.',
-    
+
     // Actions
     'actions' => 'Acciones',
     'view' => 'Ver',
diff --git a/resources/lang/es/entities.php b/resources/lang/es/entities.php
index 1a7b6df4f..a0bac5851 100644
--- a/resources/lang/es/entities.php
+++ b/resources/lang/es/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => '¿Está seguro de que desea eliminar esta revisión?',
     'revision_restore_confirm' => '¿Está seguro de que desea restaurar esta revisión? El contenido actual de la página será reemplazado.',
     'revision_delete_success' => 'Revisión eliminada',
-    'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.'
+    'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.',
 ];
diff --git a/resources/lang/es/passwords.php b/resources/lang/es/passwords.php
index 15e42d1ec..4a46134c4 100644
--- a/resources/lang/es/passwords.php
+++ b/resources/lang/es/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.',
-    'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.",
+    'user' => 'No podemos encontrar un usuario con esta dirección de correo electrónico.',
     'token' => 'El token de modificación de contraseña no es válido para esta dirección de correo electrónico.',
     'sent' => '¡Hemos enviado a su cuenta de e-mail un enlace para restaurar su contraseña!',
     'reset' => '¡Su contraseña ha sido restaurada!',
diff --git a/resources/lang/es/settings.php b/resources/lang/es/settings.php
index 81416e70e..8c3370c81 100644
--- a/resources/lang/es/settings.php
+++ b/resources/lang/es/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Mantenimiento',
     'maint_image_cleanup' => 'Limpiar imágenes',
-    'maint_image_cleanup_desc' => "Analiza las páginas y sus revisiones para comprobar qué imágenes y dibujos están siendo utilizadas y cuales no son necesarias. Asegúrate de crear una copia completa de la base de datos y de las imágenes antes de lanzar esta opción.",
+    'maint_image_cleanup_desc' => 'Analiza las páginas y sus revisiones para comprobar qué imágenes y dibujos están siendo utilizadas y cuales no son necesarias. Asegúrate de crear una copia completa de la base de datos y de las imágenes antes de lanzar esta opción.',
     'maint_delete_images_only_in_revisions' => 'Elimina también imágenes que sólo existen en antiguas revisiones de páginas',
     'maint_image_cleanup_run' => 'Lanzar limpieza',
     'maint_image_cleanup_warning' => 'Se han encontrado :count imágenes posiblemente no utilizadas . ¿Estás seguro de querer borrar estas imágenes?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Borrar rol',
     'role_delete_confirm' => 'Se borrará el rol con nombre  \':roleName\'.',
     'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.',
-    'role_delete_no_migration' => "No migrar usuarios",
+    'role_delete_no_migration' => 'No migrar usuarios',
     'role_delete_sure' => 'Está seguro que desea borrar este rol?',
     'role_delete_success' => 'Rol borrado satisfactoriamente',
     'role_edit' => 'Editar rol',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/es_AR/auth.php b/resources/lang/es_AR/auth.php
index cb18a9405..b419720a7 100644
--- a/resources/lang/es_AR/auth.php
+++ b/resources/lang/es_AR/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Este dominio de correo electrónico no tiene acceso a esta aplicación',
     'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y ha accedido a la aplicación.',
 
-
     // Password Reset
     'reset_password' => 'Restablecer la contraseña',
     'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y se le enviará un correo electrónico con un enlace para la restauración',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Ud. esta recibiendo este correo electrónico debido a que recibimos una solicitud de restauración de la contraseña de su cuenta.',
     'email_reset_not_requested' => 'Si ud. no solicitó un cambio de contraseña, no se requiere ninguna acción.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirme su correo electrónico en :appName',
     'email_confirm_greeting' => '¡Gracias por unirse a :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Introduzca el código de respaldo aquí',
     'mfa_verify_totp_desc' => 'A continuación, introduzca el código generado con su aplicación móvil:',
     'mfa_setup_login_notification' => 'Método de dos factores configurado. Por favor, inicie sesión nuevamente utilizando el método configurado.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/es_AR/common.php b/resources/lang/es_AR/common.php
index 05c76cb11..c4e8c62f3 100644
--- a/resources/lang/es_AR/common.php
+++ b/resources/lang/es_AR/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rol',
     'cover_image' => 'Imagen de cubierta',
     'cover_image_description' => 'Esta imagen debe ser de 440x250px aproximadamente.',
-    
+
     // Actions
     'actions' => 'Acciones',
     'view' => 'Ver',
diff --git a/resources/lang/es_AR/entities.php b/resources/lang/es_AR/entities.php
index bf08bdb51..a931e784c 100644
--- a/resources/lang/es_AR/entities.php
+++ b/resources/lang/es_AR/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => '¿Está seguro de que quiere eliminar esta revisión?',
     'revision_restore_confirm' => '¿Está seguro de que quiere restaurar esta revisión? Se reemplazará el contenido de la página actual.',
     'revision_delete_success' => 'Revisión eliminada',
-    'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.'
+    'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.',
 ];
diff --git a/resources/lang/es_AR/passwords.php b/resources/lang/es_AR/passwords.php
index f9e24939b..92e92a2b7 100644
--- a/resources/lang/es_AR/passwords.php
+++ b/resources/lang/es_AR/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.',
-    'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.",
+    'user' => 'No podemos encontrar un usuario con esta dirección de correo electrónico.',
     'token' => 'El token para restablecer la contraseña no es válido para esta dirección de correo electrónico.',
     'sent' => '¡Hemos enviado a su cuenta de correo electrónico un enlace para restaurar su contraseña!',
     'reset' => '¡Su contraseña fue restaurada!',
diff --git a/resources/lang/es_AR/settings.php b/resources/lang/es_AR/settings.php
index 46f72fa6b..922944674 100644
--- a/resources/lang/es_AR/settings.php
+++ b/resources/lang/es_AR/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Mantenimiento',
     'maint_image_cleanup' => 'Limpiar imágenes',
-    'maint_image_cleanup_desc' => "Analizar contenido de páginas y revisiones para detectar cuáles imágenes y dibujos están en uso y cuáles son redundantes. Asegúrese de crear un respaldo completo de imágenes y base de datos antes de ejecutar esta tarea.",
+    'maint_image_cleanup_desc' => 'Analizar contenido de páginas y revisiones para detectar cuáles imágenes y dibujos están en uso y cuáles son redundantes. Asegúrese de crear un respaldo completo de imágenes y base de datos antes de ejecutar esta tarea.',
     'maint_delete_images_only_in_revisions' => 'También elimina imágenes que sólo existen en antiguas revisiones de páginas',
     'maint_image_cleanup_run' => 'Ejecutar limpieza',
     'maint_image_cleanup_warning' => 'Se encontraron :count imágenes pontencialmente sin uso. Está seguro de que quiere eliminarlas?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Borrar rol',
     'role_delete_confirm' => 'Se borrará el rol con nombre  \':roleName\'.',
     'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si ud. quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.',
-    'role_delete_no_migration' => "No migrar usuarios",
+    'role_delete_no_migration' => 'No migrar usuarios',
     'role_delete_sure' => '¿Está seguro que desea borrar este rol?',
     'role_delete_success' => 'Rol borrado satisfactoriamente',
     'role_edit' => 'Editar rol',
@@ -274,6 +274,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/et/auth.php b/resources/lang/et/auth.php
index 6022d933b..bfce41079 100644
--- a/resources/lang/et/auth.php
+++ b/resources/lang/et/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Sellel e-posti domeenil ei ole rakendusele ligipääsu',
     'register_success' => 'Aitäh, et registreerusid! Oled nüüd sisse logitud.',
 
-
     // Password Reset
     'reset_password' => 'Lähtesta parool',
     'reset_password_send_instructions' => 'Siseta oma e-posti aadress ning sulle saadetakse link parooli lähtestamiseks.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Said selle e-kirja, sest meile laekus soov sinu konto parooli lähtestamiseks.',
     'email_reset_not_requested' => 'Kui sa ei soovinud parooli lähtestada, ei pea sa rohkem midagi tegema.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Kinnita oma :appName konto e-posti aadress',
     'email_confirm_greeting' => 'Aitäh, et liitusid rakendusega :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Sisesta varukood siia',
     'mfa_verify_totp_desc' => 'Sisesta oma mobiilirakenduse poolt genereeritud kood allpool:',
     'mfa_setup_login_notification' => 'Mitmeastmeline autentimine seadistatud. Logi nüüd uuesti sisse, kasutades seadistatud meetodit.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/et/common.php b/resources/lang/et/common.php
index d3349f5fb..acef3c1da 100644
--- a/resources/lang/et/common.php
+++ b/resources/lang/et/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Roll',
     'cover_image' => 'Kaanepilt',
     'cover_image_description' => 'See pilt peaks olema umbes 440x250 pikslit.',
-    
+
     // Actions
     'actions' => 'Tegevused',
     'view' => 'Vaata',
diff --git a/resources/lang/et/entities.php b/resources/lang/et/entities.php
index 0fabc32df..e685e2bc6 100644
--- a/resources/lang/et/entities.php
+++ b/resources/lang/et/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Kas oled kindel, et soovid selle redaktsiooni kustutada?',
     'revision_restore_confirm' => 'Kas oled kindel, et soovid selle redaktsiooni taastada? Lehe praegune sisu asendatakse.',
     'revision_delete_success' => 'Redaktsioon kustutatud',
-    'revision_cannot_delete_latest' => 'Kõige viimast redaktsiooni ei saa kustutada.'
+    'revision_cannot_delete_latest' => 'Kõige viimast redaktsiooni ei saa kustutada.',
 ];
diff --git a/resources/lang/et/passwords.php b/resources/lang/et/passwords.php
index 8559d60b2..6457887d3 100644
--- a/resources/lang/et/passwords.php
+++ b/resources/lang/et/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Paroolides peab olema vähemalt kaheksa tähemärki ja nad peavad omavahel ühtima.',
-    'user' => "Sellise e-posti aadressiga kasutajat ei leitud.",
+    'user' => 'Sellise e-posti aadressiga kasutajat ei leitud.',
     'token' => 'Parooli lähtestamise link ei kehti selle e-posti aadressiga.',
     'sent' => 'Parooli lähtestamise link saadeti e-postiga!',
     'reset' => 'Parool on lähtestatud!',
diff --git a/resources/lang/et/settings.php b/resources/lang/et/settings.php
index bb2dba47c..c6ca6425b 100644
--- a/resources/lang/et/settings.php
+++ b/resources/lang/et/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Hooldus',
     'maint_image_cleanup' => 'Pildifailide koristus',
-    'maint_image_cleanup_desc' => "Kontrollib lehtede ja redaktsioonide sisu, et leida pilte ja jooniseid, mis enam kasutusel ei ole. Enne selle käivitamist tee andmebaasist ja pildifailidest täielik varukoopia.",
+    'maint_image_cleanup_desc' => 'Kontrollib lehtede ja redaktsioonide sisu, et leida pilte ja jooniseid, mis enam kasutusel ei ole. Enne selle käivitamist tee andmebaasist ja pildifailidest täielik varukoopia.',
     'maint_delete_images_only_in_revisions' => 'Kustuta ka pildifailid, mis on kasutusel ainult vanades redaktsioonides',
     'maint_image_cleanup_run' => 'Käivita koristus',
     'maint_image_cleanup_warning' => 'Leiti :count potentsiaalselt kasutamata pildifaili. Kas oled kindel, et soovid need kustutada?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Kustuta roll',
     'role_delete_confirm' => 'See kustutab rolli nimega \':roleName\'.',
     'role_delete_users_assigned' => 'Selle rolliga on seotud :userCount kasutajat. Kui soovid neile selle asemel uue rolli määrata, siis vali see allpool.',
-    'role_delete_no_migration' => "Ära määra uut rolli",
+    'role_delete_no_migration' => 'Ära määra uut rolli',
     'role_delete_sure' => 'Kas oled kindel, et soovid selle rolli kustutada?',
     'role_delete_success' => 'Roll on kustutatud',
     'role_edit' => 'Muuda rolli',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/fa/auth.php b/resources/lang/fa/auth.php
index 4f950b77f..1b6340747 100644
--- a/resources/lang/fa/auth.php
+++ b/resources/lang/fa/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'دامنه پست الکترونیک به این برنامه دسترسی ندارد',
     'register_success' => 'از ثبت نام شما سپاسگزاریم! شما اکنون ثبت نام کرده و وارد سیستم شده اید.',
 
-
     // Password Reset
     'reset_password' => 'بازنشانی کلمه عبور',
     'reset_password_send_instructions' => 'پست الکترونیک خود را در کادر زیر وارد نموده تا یک پیام حاوی لینک بازنشانی کلمه عبور دریافت نمایید.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'شما این پیام را به علت درخواست بازنشانی کلمه عبور دریافت می نمایید.',
     'email_reset_not_requested' => 'در صورتی که درخواست بازنشانی کلمه عبور از سمت شما نمی باشد، نیاز به انجام هیچ فعالیتی ندارید.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'پست الکترونیک خود را در:appName تایید نمایید',
     'email_confirm_greeting' => 'برای پیوستن به :appName متشکریم!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/fa/common.php b/resources/lang/fa/common.php
index 6d3768de4..1081e48ff 100644
--- a/resources/lang/fa/common.php
+++ b/resources/lang/fa/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'نقش',
     'cover_image' => 'تصویر روی جلد',
     'cover_image_description' => 'سایز تصویر باید 440x250 باشد.',
-    
+
     // Actions
     'actions' => 'عملیات',
     'view' => 'نمایش',
diff --git a/resources/lang/fa/entities.php b/resources/lang/fa/entities.php
index 47335af8e..a2b5e945d 100644
--- a/resources/lang/fa/entities.php
+++ b/resources/lang/fa/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
     'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.',
     'revision_delete_success' => 'Revision deleted',
-    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.'
+    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.',
 ];
diff --git a/resources/lang/fa/passwords.php b/resources/lang/fa/passwords.php
index 06b8f8b50..6d342dbe8 100644
--- a/resources/lang/fa/passwords.php
+++ b/resources/lang/fa/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'گذرواژه باید حداقل هشت حرف و با تایید مطابقت داشته باشد.',
-    'user' => "ما کاربری با این نشانی ایمیل نداریم.",
+    'user' => 'ما کاربری با این نشانی ایمیل نداریم.',
     'token' => 'مشخصه‌ی بازگردانی رمز عبور معتبر نیست.',
     'sent' => 'لینک بازگردانی رمز عبور به ایمیل شما ارسال شد!',
     'reset' => 'رمز عبور شما بازگردانی شد!',
diff --git a/resources/lang/fa/settings.php b/resources/lang/fa/settings.php
index 46df0d07d..335a1b436 100644
--- a/resources/lang/fa/settings.php
+++ b/resources/lang/fa/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Maintenance',
     'maint_image_cleanup' => 'Cleanup Images',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Run Cleanup',
     'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/fr/auth.php b/resources/lang/fr/auth.php
index c608f02fb..de1793229 100644
--- a/resources/lang/fr/auth.php
+++ b/resources/lang/fr/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Cette adresse e-mail ne peut pas accéder à l\'application',
     'register_success' => 'Merci pour votre inscription. Vous êtes maintenant inscrit(e) et connecté(e)',
 
-
     // Password Reset
     'reset_password' => 'Réinitialiser le mot de passe',
     'reset_password_send_instructions' => 'Entrez votre adresse e-mail ci-dessous et un e-mail avec un lien de réinitialisation de mot de passe vous sera envoyé.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Vous recevez cet e-mail parce que nous avons reçu une demande de réinitialisation pour votre compte.',
     'email_reset_not_requested' => 'Si vous n\'avez pas effectué cette demande, vous pouvez ignorer cet e-mail.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirmez votre adresse e-mail pour :appName',
     'email_confirm_greeting' => 'Merci d\'avoir rejoint :appName !',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Saisissez un code de secours ici',
     'mfa_verify_totp_desc' => 'Entrez ci-dessous le code généré à l\'aide de votre application mobile :',
     'mfa_setup_login_notification' => 'Méthode multi-facteurs configurée. Veuillez maintenant vous reconnecter en utilisant la méthode configurée.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/fr/common.php b/resources/lang/fr/common.php
index e6e8bf1a2..494024785 100644
--- a/resources/lang/fr/common.php
+++ b/resources/lang/fr/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rôle',
     'cover_image' => 'Image de couverture',
     'cover_image_description' => 'Cette image doit faire environ 440x250 px.',
-    
+
     // Actions
     'actions' => 'Actions',
     'view' => 'Voir',
diff --git a/resources/lang/fr/entities.php b/resources/lang/fr/entities.php
index 360780a25..3742f584e 100644
--- a/resources/lang/fr/entities.php
+++ b/resources/lang/fr/entities.php
@@ -255,7 +255,7 @@ return [
     'tags' =>  'Mots-clés',
     'tag_name' =>  'Nom du tag',
     'tag_value' => 'Valeur du mot-clé (optionnel)',
-    'tags_explain' => "Ajouter des mots-clés pour catégoriser votre contenu.",
+    'tags_explain' => 'Ajouter des mots-clés pour catégoriser votre contenu.',
     'tags_add' => 'Ajouter un autre mot-clé',
     'tags_remove' => 'Supprimer le mot-clé',
     'attachments' => 'Fichiers joints',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Êtes-vous sûr de vouloir supprimer cette révision ?',
     'revision_restore_confirm' => 'Êtes-vous sûr de vouloir restaurer cette révision ? Le contenu courant de la page va être remplacé.',
     'revision_delete_success' => 'Révision supprimée',
-    'revision_cannot_delete_latest' => 'Impossible de supprimer la dernière révision.'
+    'revision_cannot_delete_latest' => 'Impossible de supprimer la dernière révision.',
 ];
diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php
index 18958c825..56c9adc7b 100644
--- a/resources/lang/fr/settings.php
+++ b/resources/lang/fr/settings.php
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Supprimer le rôle',
     'role_delete_confirm' => 'Ceci va supprimer le rôle \':roleName\'.',
     'role_delete_users_assigned' => 'Ce rôle a :userCount utilisateurs assignés. Vous pouvez choisir un rôle de remplacement pour ces utilisateurs.',
-    'role_delete_no_migration' => "Ne pas assigner de nouveau rôle",
+    'role_delete_no_migration' => 'Ne pas assigner de nouveau rôle',
     'role_delete_sure' => 'Êtes-vous sûr de vouloir supprimer ce rôle ?',
     'role_delete_success' => 'Le rôle a été supprimé avec succès',
     'role_edit' => 'Modifier le rôle',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/he/auth.php b/resources/lang/he/auth.php
index a078cfcf8..ab8b1e963 100644
--- a/resources/lang/he/auth.php
+++ b/resources/lang/he/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'לא ניתן להרשם באמצעות המייל שסופק',
     'register_success' => 'תודה על הרשמתך! ניתן כעת להתחבר',
 
-
     // Password Reset
     'reset_password' => 'איפוס סיסמא',
     'reset_password_send_instructions' => 'יש להזין את כתובת המייל למטה ואנו נשלח אלייך הוראות לאיפוס הסיסמא',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'קישור זה נשלח עקב בקשה לאיפוס סיסמא בחשבון שלך',
     'email_reset_not_requested' => 'אם לא ביקשת לאפס את סיסמתך, אפשר להתעלם ממייל זה',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'אמת אי-מייל ב :appName',
     'email_confirm_greeting' => 'תודה שהצטרפת אל :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/he/common.php b/resources/lang/he/common.php
index 475987f34..1a2e5b918 100644
--- a/resources/lang/he/common.php
+++ b/resources/lang/he/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'תפקיד',
     'cover_image' => 'תמונת נושא',
     'cover_image_description' => 'התמונה צריכה להיות בסביבות 440x250px',
-    
+
     // Actions
     'actions' => 'פעולות',
     'view' => 'הצג',
diff --git a/resources/lang/he/entities.php b/resources/lang/he/entities.php
index ac4e25c8b..5ad67afb8 100644
--- a/resources/lang/he/entities.php
+++ b/resources/lang/he/entities.php
@@ -94,7 +94,7 @@ return [
     'shelves_edit' => 'ערוך מדף',
     'shelves_delete' => 'מחק מדף',
     'shelves_delete_named' => 'מחיקת דף :name',
-    'shelves_delete_explain' => "פעולה זו תמחק את המדף :name - הספרים שמופיעים בו ימחקו גם כן!",
+    'shelves_delete_explain' => 'פעולה זו תמחק את המדף :name - הספרים שמופיעים בו ימחקו גם כן!',
     'shelves_delete_confirmation' => 'האם ברצונך למחוק את המדף?',
     'shelves_permissions' => 'הרשאות מדף',
     'shelves_permissions_updated' => 'הרשאות מדף עודכנו',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'האם ברצונך למחוק נוסח זה?',
     'revision_restore_confirm' => 'האם ברצונך לשחזר נוסח זה? תוכן הדף הנוכחי יעודכן לנוסח זה.',
     'revision_delete_success' => 'נוסח נמחק',
-    'revision_cannot_delete_latest' => 'לא ניתן למחוק את הנוסח האחרון'
+    'revision_cannot_delete_latest' => 'לא ניתן למחוק את הנוסח האחרון',
 ];
diff --git a/resources/lang/he/passwords.php b/resources/lang/he/passwords.php
index a94d7c30b..0b700f21e 100644
--- a/resources/lang/he/passwords.php
+++ b/resources/lang/he/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'הסיסמה חייבת להיות בעלת 8 תווים לפחות ולהתאים לאימות.',
-    'user' => "לא נמצא משתמש עם כתובת דוא\"ל זו.",
+    'user' => 'לא נמצא משתמש עם כתובת דוא"ל זו.',
     'token' => 'אסימון איפוס הסיסמה לא תקף עבור כתובת דוא"ל זו.',
     'sent' => 'שלחנו לך דוא"ל עם קישור לאיפוס הסיסמה!',
     'reset' => 'איפוס הסיסמה הושלם בהצלחה!',
diff --git a/resources/lang/he/settings.php b/resources/lang/he/settings.php
index 499ec3cd3..e8f25fe6c 100755
--- a/resources/lang/he/settings.php
+++ b/resources/lang/he/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'תחזוקה',
     'maint_image_cleanup' => 'ניקוי תמונות',
-    'maint_image_cleanup_desc' => "סורק את הדפים והגרסאות על מנת למצוא אילו תמונות לא בשימוש. יש לוודא גיבוי מלא של מסד הנתונים והתמונות לפני הרצה",
+    'maint_image_cleanup_desc' => 'סורק את הדפים והגרסאות על מנת למצוא אילו תמונות לא בשימוש. יש לוודא גיבוי מלא של מסד הנתונים והתמונות לפני הרצה',
     'maint_delete_images_only_in_revisions' => 'מחק בנוסף תמונות שקיימות בגרסאות ישנות של הדף בלבד',
     'maint_image_cleanup_run' => 'הפעל ניקוי תמונות',
     'maint_image_cleanup_warning' => 'נמצאו כ :count תמונות אשר לא בשימוש האם ברצונך להמשיך?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'מחק תפקיד',
     'role_delete_confirm' => 'פעולה זו תמחק את התפקיד: :roleName',
     'role_delete_users_assigned' => 'לתפקיד :userCount יש משתמשים אשר משויכים אליו. אם ברצונך להעבירם לתפקיד אחר אנא בחר תפקיד מלמטה',
-    'role_delete_no_migration' => "אל תעביר משתמשים לתפקיד",
+    'role_delete_no_migration' => 'אל תעביר משתמשים לתפקיד',
     'role_delete_sure' => 'האם אתה בטוח שברצונך למחוק את התפקיד?',
     'role_delete_success' => 'התפקיד נמחק בהצלחה',
     'role_edit' => 'ערוך תפקיד',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/hr/auth.php b/resources/lang/hr/auth.php
index 23014439a..b5f3bf61b 100644
--- a/resources/lang/hr/auth.php
+++ b/resources/lang/hr/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Ova e-mail adresa se ne može koristiti u ovoj aplikaciji',
     'register_success' => 'Hvala na prijavi! Sada ste registrirani i prijavljeni.',
 
-
     // Password Reset
     'reset_password' => 'Promijenite lozinku',
     'reset_password_send_instructions' => 'Upišite svoju e-mail adresu kako biste primili poveznicu za promjenu lozinke.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Primili ste ovu poruku jer je zatražena promjena lozinke za vaš račun.',
     'email_reset_not_requested' => 'Ako niste tražili promjenu lozinke slobodno zanemarite ovu poruku.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Potvrdite svoju e-mail adresu na :appName',
     'email_confirm_greeting' => 'Hvala na prijavi :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/hr/common.php b/resources/lang/hr/common.php
index bc51eed22..78018f8a9 100644
--- a/resources/lang/hr/common.php
+++ b/resources/lang/hr/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Uloga',
     'cover_image' => 'Naslovna slika',
     'cover_image_description' => 'Slika treba biti približno 440x250px.',
-    
+
     // Actions
     'actions' => 'Aktivnost',
     'view' => 'Pogled',
diff --git a/resources/lang/hr/entities.php b/resources/lang/hr/entities.php
index 5f3f8bedb..9e8a835f4 100644
--- a/resources/lang/hr/entities.php
+++ b/resources/lang/hr/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Jeste li sigurni da želite izbrisati ovaj ispravak?',
     'revision_restore_confirm' => 'Jeste li sigurni da želite vratiti ovaj ispravak? Trenutni sadržaj će biti zamijenjen.',
     'revision_delete_success' => 'Izbrisani ispravak',
-    'revision_cannot_delete_latest' => 'Posljednji ispravak se ne može izbrisati.'
+    'revision_cannot_delete_latest' => 'Posljednji ispravak se ne može izbrisati.',
 ];
diff --git a/resources/lang/hr/settings.php b/resources/lang/hr/settings.php
index 25b5e3186..38a2878f6 100644
--- a/resources/lang/hr/settings.php
+++ b/resources/lang/hr/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Održavanje',
     'maint_image_cleanup' => 'Čišćenje slika',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Izbriši slike koje postoje u prijašnjim revizijama',
     'maint_image_cleanup_run' => 'Pokreni čišćenje',
     'maint_image_cleanup_warning' => ':count moguće neiskorištene slike. Jeste li sigurni da želite izbrisati ove slike?',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/hu/auth.php b/resources/lang/hu/auth.php
index 7aaedf92d..fb207c904 100644
--- a/resources/lang/hu/auth.php
+++ b/resources/lang/hu/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Ebből az email tartományról nem lehet hozzáférni ehhez az alkalmazáshoz',
     'register_success' => 'Köszönjük a regisztrációt! A regisztráció és a bejelentkezés megtörtént.',
 
-
     // Password Reset
     'reset_password' => 'Jelszó visszaállítása',
     'reset_password_send_instructions' => 'Meg kell adni az email címet amire egy jelszó visszaállító hivatkozás lesz elküldve.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Ezt az emailt azért küldtük mert egy jelszó visszaállításra vonatkozó kérést kaptunk ebből a fiókból.',
     'email_reset_not_requested' => 'Ha nem történt jelszó visszaállításra vonatkozó kérés, akkor nincs szükség további intézkedésre.',
 
-
     // Email Confirmation
     'email_confirm_subject' => ':appName alkalmazásban beállított email címet meg kell erősíteni',
     'email_confirm_greeting' => ':appName köszöni a csatlakozást!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/hu/common.php b/resources/lang/hu/common.php
index 2e850aa2e..1c0116a1a 100644
--- a/resources/lang/hu/common.php
+++ b/resources/lang/hu/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Szerepkör',
     'cover_image' => 'Borítókép',
     'cover_image_description' => 'A kép méretének kb. 440x250px-nek kell lennie.',
-    
+
     // Actions
     'actions' => 'Műveletek',
     'view' => 'Megtekintés',
diff --git a/resources/lang/hu/entities.php b/resources/lang/hu/entities.php
index f78392ec2..905c9b0b7 100644
--- a/resources/lang/hu/entities.php
+++ b/resources/lang/hu/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Biztosan törölhető ez a változat?',
     'revision_restore_confirm' => 'Biztosan visszaállítható ez a változat? A oldal jelenlegi tartalma le lesz cserélve.',
     'revision_delete_success' => 'Változat törölve',
-    'revision_cannot_delete_latest' => 'A legutolsó változat nem törölhető.'
+    'revision_cannot_delete_latest' => 'A legutolsó változat nem törölhető.',
 ];
diff --git a/resources/lang/hu/passwords.php b/resources/lang/hu/passwords.php
index e06c6f6e3..f33be37d6 100644
--- a/resources/lang/hu/passwords.php
+++ b/resources/lang/hu/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'A jelszónak legalább hat karakterből kell állnia és egyeznie kell a megerősítéssel.',
-    'user' => "Nem található felhasználó ezzel az e-mail címmel.",
+    'user' => 'Nem található felhasználó ezzel az e-mail címmel.',
     'token' => 'The password reset token is invalid for this email address.',
     'sent' => 'E-mailben elküldtük a jelszó visszaállító hivatkozást!',
     'reset' => 'A jelszó visszaállítva!',
diff --git a/resources/lang/hu/settings.php b/resources/lang/hu/settings.php
index ea36c9641..57b640a99 100644
--- a/resources/lang/hu/settings.php
+++ b/resources/lang/hu/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Karbantartás',
     'maint_image_cleanup' => 'Képek tisztítása',
-    'maint_image_cleanup_desc' => "Végigolvassa az oldalakat és a tartalmak változatait, hogy leellenőrizze jelenleg mely képek és rajzok vannak használatban, és mely képek szerepelnek többször. A futtatása előtt feltétlen készíteni kell egy teljes adatbázis és lemezkép mentést.",
+    'maint_image_cleanup_desc' => 'Végigolvassa az oldalakat és a tartalmak változatait, hogy leellenőrizze jelenleg mely képek és rajzok vannak használatban, és mely képek szerepelnek többször. A futtatása előtt feltétlen készíteni kell egy teljes adatbázis és lemezkép mentést.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Tisztítás futtatása',
     'maint_image_cleanup_warning' => ':count potenciálisan nem használt képet találtam. Biztosan törölhetőek ezek a képek?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Szerepkör törlése',
     'role_delete_confirm' => 'Ez törölni fogja \':roleName\' szerepkört.',
     'role_delete_users_assigned' => 'Ehhez a szerepkörhöz :userCount felhasználó van hozzárendelve. Ha a felhasználókat át kell helyezni ebből a szerepkörből, akkor ki kell választani egy új szerepkört.',
-    'role_delete_no_migration' => "Nincs felhasználó áthelyezés",
+    'role_delete_no_migration' => 'Nincs felhasználó áthelyezés',
     'role_delete_sure' => 'Biztosan törölhető ez a szerepkör?',
     'role_delete_success' => 'Szerepkör sikeresen törölve',
     'role_edit' => 'Szerepkör szerkesztése',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/id/auth.php b/resources/lang/id/auth.php
index 84fc3a16e..f81ebde7a 100644
--- a/resources/lang/id/auth.php
+++ b/resources/lang/id/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Domain email tersebut tidak memiliki akses ke aplikasi ini',
     'register_success' => 'Terima kasih telah mendaftar! Anda sekarang terdaftar dan masuk.',
 
-
     // Password Reset
     'reset_password' => 'Atur ulang kata sandi',
     'reset_password_send_instructions' => 'Masukkan email Anda di bawah ini dan Anda akan dikirimi email dengan tautan pengaturan ulang kata sandi.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Anda menerima email ini karena kami menerima permintaan pengaturan ulang kata sandi untuk akun Anda.',
     'email_reset_not_requested' => 'Jika Anda tidak meminta pengaturan ulang kata sandi, tidak ada tindakan lebih lanjut yang diperlukan.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Konfirmasikan email Anda di :appName',
     'email_confirm_greeting' => 'Terima kasih telah bergabung :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/id/common.php b/resources/lang/id/common.php
index c9aac2ed2..e95233a01 100644
--- a/resources/lang/id/common.php
+++ b/resources/lang/id/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Peran',
     'cover_image' => 'Sampul gambar',
     'cover_image_description' => 'Gambar ini harus berukuran kira-kira 440x250 piksel.',
-    
+
     // Actions
     'actions' => 'Tindakan',
     'view' => 'Lihat',
diff --git a/resources/lang/id/entities.php b/resources/lang/id/entities.php
index 0b58563fa..cfb65f144 100644
--- a/resources/lang/id/entities.php
+++ b/resources/lang/id/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Anda yakin ingin menghapus revisi ini?',
     'revision_restore_confirm' => 'Apakah Anda yakin ingin memulihkan revisi ini? Konten halaman saat ini akan diganti.',
     'revision_delete_success' => 'Revisi dihapus',
-    'revision_cannot_delete_latest' => 'Tidak dapat menghapus revisi terakhir.'
+    'revision_cannot_delete_latest' => 'Tidak dapat menghapus revisi terakhir.',
 ];
diff --git a/resources/lang/id/passwords.php b/resources/lang/id/passwords.php
index 3ee2e4d57..c4578b8d1 100644
--- a/resources/lang/id/passwords.php
+++ b/resources/lang/id/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Kata sandi harus setidaknya delapan karakter dan sesuai dengan konfirmasi.',
-    'user' => "Kami tidak dapat menemukan pengguna dengan alamat email tersebut.",
+    'user' => 'Kami tidak dapat menemukan pengguna dengan alamat email tersebut.',
     'token' => 'Token setel ulang sandi tidak valid untuk alamat email ini.',
     'sent' => 'Kami telah mengirimkan email tautan pengaturan ulang kata sandi Anda!',
     'reset' => 'Kata sandi Anda telah disetel ulang!',
diff --git a/resources/lang/id/settings.php b/resources/lang/id/settings.php
index 95499acde..134b62150 100644
--- a/resources/lang/id/settings.php
+++ b/resources/lang/id/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Pemeliharaan',
     'maint_image_cleanup' => 'Gambar Bersihkan',
-    'maint_image_cleanup_desc' => "Pindai halaman & konten revisi untuk memeriksa gambar dan gambar mana yang saat ini digunakan dan gambar mana yang berlebihan. Pastikan Anda membuat database lengkap dan cadangan gambar sebelum menjalankan ini.",
+    'maint_image_cleanup_desc' => 'Pindai halaman & konten revisi untuk memeriksa gambar dan gambar mana yang saat ini digunakan dan gambar mana yang berlebihan. Pastikan Anda membuat database lengkap dan cadangan gambar sebelum menjalankan ini.',
     'maint_delete_images_only_in_revisions' => 'Hapus juga gambar yang hanya ada di revisi halaman lama',
     'maint_image_cleanup_run' => 'Jalankan Pembersihan',
     'maint_image_cleanup_warning' => ':count ditemukan gambar yang berpotensi tidak digunakan. Anda yakin ingin menghapus gambar-gambar ini?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Hapus Peran',
     'role_delete_confirm' => 'Ini akan menghapus peran dengan nama \':roleName\'.',
     'role_delete_users_assigned' => 'Peran ini memiliki :userCount pengguna yang ditugaskan padanya. Jika Anda ingin memindahkan pengguna dari peran ini pilih peran baru di bawah.',
-    'role_delete_no_migration' => "Jangan migrasikan pengguna",
+    'role_delete_no_migration' => 'Jangan migrasikan pengguna',
     'role_delete_sure' => 'Anda yakin ingin menghapus peran ini?',
     'role_delete_success' => 'Peran berhasil dihapus',
     'role_edit' => 'Edit Peran',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/it/auth.php b/resources/lang/it/auth.php
index 2a33a3184..7cd745137 100755
--- a/resources/lang/it/auth.php
+++ b/resources/lang/it/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Questo dominio della mail non ha accesso a questa applicazione',
     'register_success' => 'Grazie per la registrazione! Sei registrato e loggato.',
 
-
     // Password Reset
     'reset_password' => 'Reimposta Password',
     'reset_password_send_instructions' => 'Inserisci il tuo indirizzo sotto e ti verrà inviata una mail contenente un link per resettare la tua password.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Stai ricevendo questa mail perché abbiamo ricevuto una richiesta di reset della password per il tuo account.',
     'email_reset_not_requested' => 'Se non hai richiesto un reset della password, ignora questa mail.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Conferma email per :appName',
     'email_confirm_greeting' => 'Grazie per esserti registrato a :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Inserisci qui il codice di backup',
     'mfa_verify_totp_desc' => 'Inserisci il codice, generato tramite la tua app mobile, qui sotto:',
     'mfa_setup_login_notification' => 'Metodo multi-fattore configurato, si prega di effettuare nuovamente il login utilizzando il metodo configurato.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/it/common.php b/resources/lang/it/common.php
index bcd3aadf9..dc148f9f1 100755
--- a/resources/lang/it/common.php
+++ b/resources/lang/it/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Ruolo',
     'cover_image' => 'Immagine di copertina',
     'cover_image_description' => 'Questa immagine dovrebbe essere approssimativamente 440x250px.',
-    
+
     // Actions
     'actions' => 'Azioni',
     'view' => 'Visualizza',
diff --git a/resources/lang/it/entities.php b/resources/lang/it/entities.php
index 64354b751..507e502a0 100755
--- a/resources/lang/it/entities.php
+++ b/resources/lang/it/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Sei sicuro di voler eliminare questa revisione?',
     'revision_restore_confirm' => 'Sei sicuro di voler ripristinare questa revisione? Il contenuto della pagina verrà rimpiazzato.',
     'revision_delete_success' => 'Revisione cancellata',
-    'revision_cannot_delete_latest' => 'Impossibile eliminare l\'ultima revisione.'
+    'revision_cannot_delete_latest' => 'Impossibile eliminare l\'ultima revisione.',
 ];
diff --git a/resources/lang/it/passwords.php b/resources/lang/it/passwords.php
index 7099d54f3..03afdbe2d 100755
--- a/resources/lang/it/passwords.php
+++ b/resources/lang/it/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'La password deve avere almeno sei caratteri e corrispondere alla conferma.',
-    'user' => "Non possiamo trovare un utente per quella mail.",
+    'user' => 'Non possiamo trovare un utente per quella mail.',
     'token' => 'Il token per reimpostare la password non è valido per questo indirizzo email.',
     'sent' => 'Ti abbiamo inviato via mail il link per reimpostare la password!',
     'reset' => 'La tua password è stata reimpostata!',
diff --git a/resources/lang/it/settings.php b/resources/lang/it/settings.php
index 3abb1c45e..6227dbf17 100755
--- a/resources/lang/it/settings.php
+++ b/resources/lang/it/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Manutenzione',
     'maint_image_cleanup' => 'Pulizia Immagini',
-    'maint_image_cleanup_desc' => "Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare backup completo del database e delle immagini prima di eseguire la pulizia.",
+    'maint_image_cleanup_desc' => 'Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare backup completo del database e delle immagini prima di eseguire la pulizia.',
     'maint_delete_images_only_in_revisions' => 'Elimina anche le immagini che esistono solo nelle vecchie revisioni della pagina',
     'maint_image_cleanup_run' => 'Esegui Pulizia',
     'maint_image_cleanup_warning' => ':count immagini potenzialmente inutilizzate sono state trovate. Sei sicuro di voler eliminare queste immagini?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Elimina Ruolo',
     'role_delete_confirm' => 'Questo eliminerà il ruolo con il nome \':roleName\'.',
     'role_delete_users_assigned' => 'Questo ruolo ha :userCount utenti assegnati. Se vuoi migrare gli utenti da questo ruolo selezionane uno nuovo sotto.',
-    'role_delete_no_migration' => "Non migrare gli utenti",
+    'role_delete_no_migration' => 'Non migrare gli utenti',
     'role_delete_sure' => 'Sei sicuro di voler eliminare questo ruolo?',
     'role_delete_success' => 'Ruolo eliminato correttamente',
     'role_edit' => 'Modifica Ruolo',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/ja/auth.php b/resources/lang/ja/auth.php
index 98f56e73e..ff7c3a68b 100644
--- a/resources/lang/ja/auth.php
+++ b/resources/lang/ja/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'このEmailドメインでの登録は許可されていません。',
     'register_success' => '登録が完了し、ログインできるようになりました!',
 
-
     // Password Reset
     'reset_password' => 'パスワードリセット',
     'reset_password_send_instructions' => '以下にEメールアドレスを入力すると、パスワードリセットリンクが記載されたメールが送信されます。',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'このメールは、パスワードリセットがリクエストされたため送信されています。',
     'email_reset_not_requested' => 'もしパスワードリセットを希望しない場合、操作は不要です。',
 
-
     // Email Confirmation
     'email_confirm_subject' => ':appNameのメールアドレス確認',
     'email_confirm_greeting' => ':appNameへ登録してくださりありがとうございます!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => '多要素認証が構成されました。設定された手段を利用して再度ログインしてください。',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/ja/common.php b/resources/lang/ja/common.php
index f7a0fdad6..873d367d7 100644
--- a/resources/lang/ja/common.php
+++ b/resources/lang/ja/common.php
@@ -20,7 +20,7 @@ return [
     'role' => '権限',
     'cover_image' => 'カバー画像',
     'cover_image_description' => 'この画像はおよそ440x250pxの大きさが必要です。',
-    
+
     // Actions
     'actions' => '実行',
     'view' => '表示',
diff --git a/resources/lang/ja/entities.php b/resources/lang/ja/entities.php
index 62d806eec..5a1941057 100644
--- a/resources/lang/ja/entities.php
+++ b/resources/lang/ja/entities.php
@@ -94,7 +94,7 @@ return [
     'shelves_edit' => '本棚を編集',
     'shelves_delete' => '本棚を削除',
     'shelves_delete_named' => '本棚「:name」を削除',
-    'shelves_delete_explain' => "これにより、この本棚「:name」が削除されます。含まれているブックは削除されません。",
+    'shelves_delete_explain' => 'これにより、この本棚「:name」が削除されます。含まれているブックは削除されません。',
     'shelves_delete_confirmation' => '本当にこの本棚を削除してよろしいですか?',
     'shelves_permissions' => 'Bookshelf Permissions',
     'shelves_permissions_updated' => 'Bookshelf Permissions Updated',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'このリビジョンを削除しますか?',
     'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.',
     'revision_delete_success' => 'リビジョンを削除しました',
-    'revision_cannot_delete_latest' => '最新のリビジョンを削除できません。'
+    'revision_cannot_delete_latest' => '最新のリビジョンを削除できません。',
 ];
diff --git a/resources/lang/ja/passwords.php b/resources/lang/ja/passwords.php
index cf4d43114..40493f6ce 100644
--- a/resources/lang/ja/passwords.php
+++ b/resources/lang/ja/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'パスワードは6文字以上である必要があります。',
-    'user' => "このEメールアドレスに一致するユーザが見つかりませんでした。",
+    'user' => 'このEメールアドレスに一致するユーザが見つかりませんでした。',
     'token' => 'このメールアドレスのパスワードリセットトークンは無効です。',
     'sent' => 'パスワードリセットリンクを送信しました。',
     'reset' => 'パスワードはリセットされました。',
diff --git a/resources/lang/ja/settings.php b/resources/lang/ja/settings.php
index 4e2af0212..76da40deb 100644
--- a/resources/lang/ja/settings.php
+++ b/resources/lang/ja/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'メンテナンス',
     'maint_image_cleanup' => '画像のクリーンアップ',
-    'maint_image_cleanup_desc' => "ページや履歴の内容をスキャンして、どの画像や図面が現在使用されているか、どの画像が余っているかをチェックします。この機能を実行する前に、データベースと画像の完全なバックアップを作成してください。",
+    'maint_image_cleanup_desc' => 'ページや履歴の内容をスキャンして、どの画像や図面が現在使用されているか、どの画像が余っているかをチェックします。この機能を実行する前に、データベースと画像の完全なバックアップを作成してください。',
     'maint_delete_images_only_in_revisions' => 'また、古いページのリビジョンにしか存在しない画像も削除します。',
     'maint_image_cleanup_run' => 'クリーンアップを実行',
     'maint_image_cleanup_warning' => ':count 個、使用されていない可能性のある画像が見つかりました。これらの画像を削除してもよろしいですか?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => '役割を削除',
     'role_delete_confirm' => '役割「:roleName」を削除します。',
     'role_delete_users_assigned' => 'この役割は:userCount人のユーザに付与されています。該当するユーザを他の役割へ移行できます。',
-    'role_delete_no_migration' => "ユーザを移行しない",
+    'role_delete_no_migration' => 'ユーザを移行しない',
     'role_delete_sure' => '本当に役割を削除してよろしいですか?',
     'role_delete_success' => '役割を削除しました',
     'role_edit' => '役割を編集',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/ko/auth.php b/resources/lang/ko/auth.php
index ce65f3ecc..3cff67d4d 100644
--- a/resources/lang/ko/auth.php
+++ b/resources/lang/ko/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => '이 메일 주소로는 이 사이트에 접근할 수 없습니다.',
     'register_success' => '가입했습니다! 이제 로그인할 수 있습니다.',
 
-
     // Password Reset
     'reset_password' => '비밀번호 바꾸기',
     'reset_password_send_instructions' => '메일 주소를 입력하세요. 이 주소로 해당 과정을 위한 링크를 보낼 것입니다.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => '비밀번호를 바꿉니다.',
     'email_reset_not_requested' => '원하지 않는다면 이 과정은 필요 없습니다.',
 
-
     // Email Confirmation
     'email_confirm_subject' => ':appName 메일 인증',
     'email_confirm_greeting' => ':appName로 가입해 주셔서 감사합니다!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/ko/common.php b/resources/lang/ko/common.php
index 2349ab735..26b52744d 100644
--- a/resources/lang/ko/common.php
+++ b/resources/lang/ko/common.php
@@ -20,7 +20,7 @@ return [
     'role' => '권한',
     'cover_image' => '대표 이미지',
     'cover_image_description' => '이미지 규격은 440x250px 내외입니다.',
-    
+
     // Actions
     'actions' => '활동',
     'view' => '보기',
diff --git a/resources/lang/ko/entities.php b/resources/lang/ko/entities.php
index 46dced1ec..41d4dfb01 100644
--- a/resources/lang/ko/entities.php
+++ b/resources/lang/ko/entities.php
@@ -94,7 +94,7 @@ return [
     'shelves_edit' => '서가 바꾸기',
     'shelves_delete' => '서가 삭제하기',
     'shelves_delete_named' => ':name 삭제하기',
-    'shelves_delete_explain' => ":name을 지웁니다. 책자는 지우지 않습니다.",
+    'shelves_delete_explain' => ':name을 지웁니다. 책자는 지우지 않습니다.',
     'shelves_delete_confirmation' => '이 서가를 지울 건가요?',
     'shelves_permissions' => '서가 권한',
     'shelves_permissions_updated' => '서가 권한 바꿈',
@@ -255,7 +255,7 @@ return [
     'tags' =>  '꼬리표',
     'tag_name' =>  '꼬리표 이름',
     'tag_value' => '리스트 값 (선택 사항)',
-    'tags_explain' => "태그로 문서를 분류하세요.",
+    'tags_explain' => '태그로 문서를 분류하세요.',
     'tags_add' => '태그 추가',
     'tags_remove' => '태그 삭제',
     'attachments' => '첨부 파일',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => '이 수정본을 지울 건가요?',
     'revision_restore_confirm' => '이 수정본을 되돌릴 건가요? 현재 판본을 바꿉니다.',
     'revision_delete_success' => '수정본 지움',
-    'revision_cannot_delete_latest' => '현재 판본은 지울 수 없습니다.'
+    'revision_cannot_delete_latest' => '현재 판본은 지울 수 없습니다.',
 ];
diff --git a/resources/lang/ko/errors.php b/resources/lang/ko/errors.php
index b52ee91bc..e4ed5ccb3 100644
--- a/resources/lang/ko/errors.php
+++ b/resources/lang/ko/errors.php
@@ -28,7 +28,7 @@ return [
     'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system',
     'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization',
     'social_no_action_defined' => '무슨 활동인지 알 수 없습니다.',
-    'social_login_bad_response' => ":socialAccount에 로그인할 수 없습니다. : \\n:error",
+    'social_login_bad_response' => ':socialAccount에 로그인할 수 없습니다. : \\n:error',
     'social_account_in_use' => ':socialAccount(을)를 가진 사용자가 있습니다. :socialAccount로 로그인하세요.',
     'social_account_email_in_use' => ':email(을)를 가진 사용자가 있습니다. 쓰고 있는 계정을 :socialAccount에 연결하세요.',
     'social_account_existing' => ':socialAccount(와)과 연결 상태입니다.',
diff --git a/resources/lang/ko/passwords.php b/resources/lang/ko/passwords.php
index f93902aef..461afc74b 100644
--- a/resources/lang/ko/passwords.php
+++ b/resources/lang/ko/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => '여덟 글자를 넘어야 합니다.',
-    'user' => "메일 주소를 가진 사용자가 없습니다.",
+    'user' => '메일 주소를 가진 사용자가 없습니다.',
     'token' => '비밀번호 재설정 토큰이 이 이메일 주소에 유효하지 않습니다.',
     'sent' => '메일을 보냈습니다.',
     'reset' => '비밀번호를 바꿨습니다.',
diff --git a/resources/lang/ko/settings.php b/resources/lang/ko/settings.php
index f9c0290a6..de5b59d50 100755
--- a/resources/lang/ko/settings.php
+++ b/resources/lang/ko/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => '데이터',
     'maint_image_cleanup' => '이미지 정리',
-    'maint_image_cleanup_desc' => "중복한 이미지를 찾습니다. 실행하기 전에 이미지를 백업하세요.",
+    'maint_image_cleanup_desc' => '중복한 이미지를 찾습니다. 실행하기 전에 이미지를 백업하세요.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => '실행',
     'maint_image_cleanup_warning' => '이미지 :count개를 지울 건가요?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => '권한 제거',
     'role_delete_confirm' => ':roleName(을)를 지웁니다.',
     'role_delete_users_assigned' => '이 권한을 가진 사용자 :userCount명에 할당할 권한을 고르세요.',
-    'role_delete_no_migration' => "할당하지 않음",
+    'role_delete_no_migration' => '할당하지 않음',
     'role_delete_sure' => '이 권한을 지울 건가요?',
     'role_delete_success' => '권한 지움',
     'role_edit' => '권한 수정',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/lt/auth.php b/resources/lang/lt/auth.php
index f9bf271f6..e4a17eae5 100644
--- a/resources/lang/lt/auth.php
+++ b/resources/lang/lt/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Elektroninio pašto domenas neturi prieigos prie šios programos',
     'register_success' => 'Ačiū už prisijungimą! Dabar jūs užsiregistravote ir prisijungėte.',
 
-
     // Password Reset
     'reset_password' => 'Pakeisti slaptažodį',
     'reset_password_send_instructions' => 'Įveskite savo elektroninį paštą žemiau ir jums bus išsiųstas elektroninis laiškas su slaptažodžio nustatymo nuoroda.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Šį laišką gaunate, nes mes gavome slaptažodžio atnaujinimo užklausą iš jūsų paskyros.',
     'email_reset_not_requested' => 'Jeigu jums nereikia slaptažodžio atnaujinimo, tolimesnių veiksmų atlikti nereikia.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Patvirtinkite savo elektroninį paštą :appName',
     'email_confirm_greeting' => 'Ačiū už prisijungimą prie :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/lt/common.php b/resources/lang/lt/common.php
index 7ed434b98..f1766a615 100644
--- a/resources/lang/lt/common.php
+++ b/resources/lang/lt/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Vaidmuo',
     'cover_image' => 'Viršelio nuotrauka',
     'cover_image_description' => 'Ši nuotrauka turi būti maždaug 440x250px.',
-    
+
     // Actions
     'actions' => 'Veiksmai',
     'view' => 'Rodyti',
diff --git a/resources/lang/lt/entities.php b/resources/lang/lt/entities.php
index f1eda39e0..4266f61de 100644
--- a/resources/lang/lt/entities.php
+++ b/resources/lang/lt/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Esate tikri, kad norite ištrinti šią peržiūrą?',
     'revision_restore_confirm' => 'Esate tikri, kad norite atkurti šią peržiūrą? Dabartinis puslapio turinys bus pakeistas.',
     'revision_delete_success' => 'Peržiūra ištrinta',
-    'revision_cannot_delete_latest' => 'Negalima išrinti vėliausios peržiūros'
+    'revision_cannot_delete_latest' => 'Negalima išrinti vėliausios peržiūros',
 ];
diff --git a/resources/lang/lt/settings.php b/resources/lang/lt/settings.php
index c69694951..8d55646db 100644
--- a/resources/lang/lt/settings.php
+++ b/resources/lang/lt/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Priežiūra',
     'maint_image_cleanup' => 'Išvalykite vaizdus',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Taip pat ištrinkite vaizdus, kurie yra tik senuose puslapių pataisymuose',
     'maint_image_cleanup_run' => 'Paleisti valymą',
     'maint_image_cleanup_warning' => ':count potencialiai nepanaudoti vaizdai rasti. Ar esate tikri, kad norite ištrinti šiuos vaizdus?',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/lv/auth.php b/resources/lang/lv/auth.php
index 497509d54..e228bed00 100644
--- a/resources/lang/lv/auth.php
+++ b/resources/lang/lv/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'E-pasta domēnam nav piekļuves pie šīs aplikācijas',
     'register_success' => 'Paldies par reģistrēšanos! Tagad varat pieslēgties.',
 
-
     // Password Reset
     'reset_password' => 'Atiestatīt paroli',
     'reset_password_send_instructions' => 'Ievadiet savu e-pastu zemāk un nosūtīsim e-pastu ar paroles atiestatīšanas saiti.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Jūs saņemat šo e-pastu, jo mēs saņēmām Jūsu profila paroles atiestatīšanas pieprasījumu.',
     'email_reset_not_requested' => 'Ja Jūs nepieprasījāt paroles atiestatīšanu, tad tālākas darbības nav nepieciešamas.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Apstiprinat savu :appName e-pastu',
     'email_confirm_greeting' => 'Paldies, ka pievienojāties :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/lv/common.php b/resources/lang/lv/common.php
index 23cd07d7d..3bc022e42 100644
--- a/resources/lang/lv/common.php
+++ b/resources/lang/lv/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Loma',
     'cover_image' => 'Vāka attēls',
     'cover_image_description' => 'Šim attēlam būtu jābūt aptuveni 440x250px.',
-    
+
     // Actions
     'actions' => 'Darbības',
     'view' => 'Skatīt',
diff --git a/resources/lang/lv/entities.php b/resources/lang/lv/entities.php
index 4cfca7aa5..f5ef3b06c 100644
--- a/resources/lang/lv/entities.php
+++ b/resources/lang/lv/entities.php
@@ -94,7 +94,7 @@ return [
     'shelves_edit' => 'Labot grāmatplauktu',
     'shelves_delete' => 'Dzēst grāmatplauktu',
     'shelves_delete_named' => 'Dzēst grāmatplauktu :name',
-    'shelves_delete_explain' => "Tiks dzēsts grāmatplaukts ar nosaukumu \":name\". Tajā ievietotās grāmatas netiks dzēstas.",
+    'shelves_delete_explain' => 'Tiks dzēsts grāmatplaukts ar nosaukumu ":name". Tajā ievietotās grāmatas netiks dzēstas.',
     'shelves_delete_confirmation' => 'Vai esat pārliecināts, ka vēlaties dzēst šo grāmatplauktu?',
     'shelves_permissions' => 'Grāmatplaukta atļaujas',
     'shelves_permissions_updated' => 'Grāmatplaukta atļaujas atjauninātas',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Vai esat pārliecināts, ka vēlaties dzēst šo revīziju?',
     'revision_restore_confirm' => 'Vai tiešām vēlaties atjaunot šo revīziju? Pašreizējais lapas saturs tiks aizvietots.',
     'revision_delete_success' => 'Revīzija dzēsta',
-    'revision_cannot_delete_latest' => 'Nevar dzēst pašreizējo revīziju.'
+    'revision_cannot_delete_latest' => 'Nevar dzēst pašreizējo revīziju.',
 ];
diff --git a/resources/lang/lv/passwords.php b/resources/lang/lv/passwords.php
index 7d939574f..5824e71e6 100644
--- a/resources/lang/lv/passwords.php
+++ b/resources/lang/lv/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Parolēm jābūt vismaz astoņu simbolu garām un jāatbilst apstiprinājumam.',
-    'user' => "Mēs nevaram atrast lietotāju ar šādu e-pasta adresi.",
+    'user' => 'Mēs nevaram atrast lietotāju ar šādu e-pasta adresi.',
     'token' => 'Paroles atiestatīšanas atslēga neatbilst šai e-pasta adresei.',
     'sent' => 'Esam nosūtījuši paroles atiestatīšanas saiti!',
     'reset' => 'Parole ir atiestatīta!',
diff --git a/resources/lang/lv/settings.php b/resources/lang/lv/settings.php
index 79aca4e54..1ecc00524 100644
--- a/resources/lang/lv/settings.php
+++ b/resources/lang/lv/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Apkope',
     'maint_image_cleanup' => 'Tīrīt neizmantotās bildes',
-    'maint_image_cleanup_desc' => "Pārbauda lapu un lapu versiju saturu, lai noteiktu, kuri attēli pašlaik tiek izmantoti, un kuri nav nepieciešami. Pārliecinieties, ka ir veikta pilna datubāzes un attēlu rezerves kopija pirms šīs darbības.",
+    'maint_image_cleanup_desc' => 'Pārbauda lapu un lapu versiju saturu, lai noteiktu, kuri attēli pašlaik tiek izmantoti, un kuri nav nepieciešami. Pārliecinieties, ka ir veikta pilna datubāzes un attēlu rezerves kopija pirms šīs darbības.',
     'maint_delete_images_only_in_revisions' => 'Dzēst arī attēlus, kas izmantoti tikai vecās lapu satura versijās',
     'maint_image_cleanup_run' => 'Veikt tīrīšanu',
     'maint_image_cleanup_warning' => ':count iespējami neizmantoti attēli atrasti. Vai tiešām vēlaties izdzēst šos attēlus?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Dzēst grupu',
     'role_delete_confirm' => 'Loma \':roleName\' tiks dzēsta.',
     'role_delete_users_assigned' => 'Šajā grupā ir pievienoti :userCount lietotāji. Ja vēlaties pārvietot lietotājus no šīs grupas, tad izvēlaties kādu no zemāk redzamajām grupām.',
-    'role_delete_no_migration' => "Nepārvietot lietotājus",
+    'role_delete_no_migration' => 'Nepārvietot lietotājus',
     'role_delete_sure' => 'Vai tiešām vēlaties dzēst grupu?',
     'role_delete_success' => 'Grupa veiksmīgi dzēsta',
     'role_edit' => 'Rediģēt grupu',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/nb/auth.php b/resources/lang/nb/auth.php
index 4c1f55577..a59e18bb5 100644
--- a/resources/lang/nb/auth.php
+++ b/resources/lang/nb/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Du kan ikke bruke det domenet for å registrere en konto.',
     'register_success' => 'Takk for registreringen! Du kan nå logge inn på tjenesten.',
 
-
     // Password Reset
     'reset_password' => 'Nullstille passord',
     'reset_password_send_instructions' => 'Oppgi e-posten som er koblet til kontoen din, så sender vi en epost hvor du kan nullstille passordet.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Du mottar denne eposten fordi det er blitt bedt om en nullstilling av passord på denne kontoen.',
     'email_reset_not_requested' => 'Om det ikke var deg, så trenger du ikke foreta deg noe.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Bekreft epost-adressen for :appName',
     'email_confirm_greeting' => 'Takk for at du registrerte deg for :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Skriv inn sikkerhetskode her',
     'mfa_verify_totp_desc' => 'Skriv inn koden, generert ved hjelp av mobilapplikasjonen, nedenfor:',
     'mfa_setup_login_notification' => 'Flerfaktorautentisering er konfigurert, vennligst logg inn på nytt med denne metoden.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/nb/common.php b/resources/lang/nb/common.php
index 8ba4e7474..cd01b132f 100644
--- a/resources/lang/nb/common.php
+++ b/resources/lang/nb/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rolle',
     'cover_image' => 'Bokomslag',
     'cover_image_description' => 'Bildet bør være ca. 440x250px.',
-    
+
     // Actions
     'actions' => 'Handlinger',
     'view' => 'Vis',
diff --git a/resources/lang/nb/entities.php b/resources/lang/nb/entities.php
index 705c33875..756ee5c71 100644
--- a/resources/lang/nb/entities.php
+++ b/resources/lang/nb/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Vil du slette revisjonen?',
     'revision_restore_confirm' => 'Vil du gjenopprette revisjonen? Innholdet på siden vil bli overskrevet med denne revisjonen.',
     'revision_delete_success' => 'Revisjonen ble slettet',
-    'revision_cannot_delete_latest' => 'CKan ikke slette siste revisjon.'
+    'revision_cannot_delete_latest' => 'CKan ikke slette siste revisjon.',
 ];
diff --git a/resources/lang/nb/passwords.php b/resources/lang/nb/passwords.php
index 8c3215b42..b7afdaa80 100644
--- a/resources/lang/nb/passwords.php
+++ b/resources/lang/nb/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Passord må inneholde minst åtte tegn og samsvarer med bekreftelsen.',
-    'user' => "Vi finner ikke en bruker med den e-postadressen.",
+    'user' => 'Vi finner ikke en bruker med den e-postadressen.',
     'token' => 'Passordet for tilbakestilling av passord er ugyldig for denne e-postadressen.',
     'sent' => 'Vi har sendt e-postadressen til tilbakestilling av passordet ditt!',
     'reset' => 'Passordet ditt har blitt tilbakestilt!',
diff --git a/resources/lang/nb/settings.php b/resources/lang/nb/settings.php
index 134208d7d..5a6a0fb06 100644
--- a/resources/lang/nb/settings.php
+++ b/resources/lang/nb/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Vedlikehold',
     'maint_image_cleanup' => 'Bildeopprydding',
-    'maint_image_cleanup_desc' => "Skanner side og revisjonsinnhold for å sjekke hvilke bilder og tegninger som for øyeblikket er i bruk, og hvilke bilder som er overflødige. Forsikre deg om at du lager en full database og sikkerhetskopiering av bilder før du kjører denne.",
+    'maint_image_cleanup_desc' => 'Skanner side og revisjonsinnhold for å sjekke hvilke bilder og tegninger som for øyeblikket er i bruk, og hvilke bilder som er overflødige. Forsikre deg om at du lager en full database og sikkerhetskopiering av bilder før du kjører denne.',
     'maint_delete_images_only_in_revisions' => 'Slett også bilder som bare finnes i game siderevisjoner',
     'maint_image_cleanup_run' => 'Kjør opprydding',
     'maint_image_cleanup_warning' => ':count potensielt ubrukte bilder ble funnet. Er du sikker på at du vil slette disse bildene?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Rolle slettet',
     'role_delete_confirm' => 'Dette vil slette rollen «:roleName».',
     'role_delete_users_assigned' => 'Denne rollen har :userCount kontoer koblet opp mot seg. Velg hvilke rolle du vil flytte disse til.',
-    'role_delete_no_migration' => "Ikke flytt kontoer",
+    'role_delete_no_migration' => 'Ikke flytt kontoer',
     'role_delete_sure' => 'Er du sikker på at du vil slette rollen?',
     'role_delete_success' => 'Rollen ble slettet',
     'role_edit' => 'Endre rolle',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/nl/auth.php b/resources/lang/nl/auth.php
index f57b2ecc7..3cec0a94d 100644
--- a/resources/lang/nl/auth.php
+++ b/resources/lang/nl/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Dit e-maildomein is niet toegestaan',
     'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en aangemeld.',
 
-
     // Password Reset
     'reset_password' => 'Wachtwoord herstellen',
     'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Je ontvangt deze e-mail omdat je een wachtwoord herstel verzoek had verzonden.',
     'email_reset_not_requested' => 'Als je geen wachtwoord herstel hebt aangevraagd, hoef je niets te doen.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Bevestig je e-mailadres op :appName',
     'email_confirm_greeting' => 'Bedankt voor je aanmelding op :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/nl/common.php b/resources/lang/nl/common.php
index c53df6f2c..793e87b11 100644
--- a/resources/lang/nl/common.php
+++ b/resources/lang/nl/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rol',
     'cover_image' => 'Omslagfoto',
     'cover_image_description' => 'Deze afbeelding moet ongeveer 440x250px zijn.',
-    
+
     // Actions
     'actions' => 'Acties',
     'view' => 'Bekijk',
diff --git a/resources/lang/nl/entities.php b/resources/lang/nl/entities.php
index e08ae3e62..3c3148a8b 100644
--- a/resources/lang/nl/entities.php
+++ b/resources/lang/nl/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Weet u zeker dat u deze revisie wilt verwijderen?',
     'revision_restore_confirm' => 'Weet u zeker dat u deze revisie wilt herstellen? De huidige pagina-inhoud wordt vervangen.',
     'revision_delete_success' => 'Revisie verwijderd',
-    'revision_cannot_delete_latest' => 'Kan de laatste revisie niet verwijderen.'
+    'revision_cannot_delete_latest' => 'Kan de laatste revisie niet verwijderen.',
 ];
diff --git a/resources/lang/nl/passwords.php b/resources/lang/nl/passwords.php
index 4b27f03c2..5f90eb0df 100644
--- a/resources/lang/nl/passwords.php
+++ b/resources/lang/nl/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Wachtwoorden moeten overeenkomen en minimaal zes tekens lang zijn.',
-    'user' => "We kunnen niemand vinden met dat e-mailadres.",
+    'user' => 'We kunnen niemand vinden met dat e-mailadres.',
     'token' => 'Het wachtwoord reset token is ongeldig voor dit e-mailadres.',
     'sent' => 'We hebben je een link gestuurd om je wachtwoord te herstellen!',
     'reset' => 'Je wachtwoord is hersteld!',
diff --git a/resources/lang/nl/settings.php b/resources/lang/nl/settings.php
index df5c93b97..ad94d0f2c 100644
--- a/resources/lang/nl/settings.php
+++ b/resources/lang/nl/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Onderhoud',
     'maint_image_cleanup' => 'Afbeeldingen opschonen',
-    'maint_image_cleanup_desc' => "Scant pagina- en revisie inhoud om te controleren welke afbeeldingen en tekeningen momenteel worden gebruikt en welke afbeeldingen overbodig zijn. Zorg ervoor dat je een volledige database en afbeelding backup maakt voordat je dit uitvoert.",
+    'maint_image_cleanup_desc' => 'Scant pagina- en revisie inhoud om te controleren welke afbeeldingen en tekeningen momenteel worden gebruikt en welke afbeeldingen overbodig zijn. Zorg ervoor dat je een volledige database en afbeelding backup maakt voordat je dit uitvoert.',
     'maint_delete_images_only_in_revisions' => 'Ook afbeeldingen die alleen in oude pagina revisies bestaan verwijderen',
     'maint_image_cleanup_run' => 'Opschonen uitvoeren',
     'maint_image_cleanup_warning' => ':count potentieel ongebruikte afbeeldingen gevonden. Weet u zeker dat u deze afbeeldingen wilt verwijderen?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Rol Verwijderen',
     'role_delete_confirm' => 'Dit verwijdert de rol \':roleName\'.',
     'role_delete_users_assigned' => 'Er zijn :userCount gebruikers met deze rol. Selecteer hieronder een nieuwe rol als je deze gebruikers een andere rol wilt geven.',
-    'role_delete_no_migration' => "Geen gebruikers migreren",
+    'role_delete_no_migration' => 'Geen gebruikers migreren',
     'role_delete_sure' => 'Weet je zeker dat je deze rol wilt verwijderen?',
     'role_delete_success' => 'Rol succesvol verwijderd',
     'role_edit' => 'Rol Bewerken',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/pl/auth.php b/resources/lang/pl/auth.php
index a1f66fdbe..2f42fc70a 100644
--- a/resources/lang/pl/auth.php
+++ b/resources/lang/pl/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Adresy e-mail z tej domeny nie mają dostępu do tej aplikacji',
     'register_success' => 'Dziękujemy za rejestrację! Zostałeś zalogowany automatycznie.',
 
-
     // Password Reset
     'reset_password' => 'Resetowanie hasła',
     'reset_password_send_instructions' => 'Wprowadź adres e-mail powiązany z Twoim kontem, by otrzymać link do resetowania hasła.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Otrzymujesz tę wiadomość ponieważ ktoś zażądał zresetowania hasła do Twojego konta.',
     'email_reset_not_requested' => 'Jeśli to nie Ty złożyłeś żądanie zresetowania hasła, zignoruj tę wiadomość.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Potwierdź swój adres e-mail w :appName',
     'email_confirm_greeting' => 'Dziękujemy za dołączenie do :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Wprowadź kod zapasowy tutaj',
     'mfa_verify_totp_desc' => 'Wprowadź kod, wygenerowany przy użyciu aplikacji mobilnej poniżej:',
     'mfa_setup_login_notification' => 'Metoda wieloskładnikowa skonfigurowana, zaloguj się ponownie za pomocą skonfigurowanej metody.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/pl/common.php b/resources/lang/pl/common.php
index 1e718a63c..e9bb14011 100644
--- a/resources/lang/pl/common.php
+++ b/resources/lang/pl/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rola',
     'cover_image' => 'Zdjęcie z okładki',
     'cover_image_description' => 'Ten obraz powinien posiadać wymiary około 440x250px.',
-    
+
     // Actions
     'actions' => 'Akcje',
     'view' => 'Widok',
diff --git a/resources/lang/pl/entities.php b/resources/lang/pl/entities.php
index af1f7eecd..31d40a63e 100644
--- a/resources/lang/pl/entities.php
+++ b/resources/lang/pl/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Czy na pewno chcesz usunąć tę wersję?',
     'revision_restore_confirm' => 'Czu ma pewno chcesz przywrócić tą wersję? Aktualna zawartość strony zostanie nadpisana.',
     'revision_delete_success' => 'Usunięto wersję',
-    'revision_cannot_delete_latest' => 'Nie można usunąć najnowszej wersji.'
+    'revision_cannot_delete_latest' => 'Nie można usunąć najnowszej wersji.',
 ];
diff --git a/resources/lang/pl/passwords.php b/resources/lang/pl/passwords.php
index 7b67bf38d..dad844f74 100644
--- a/resources/lang/pl/passwords.php
+++ b/resources/lang/pl/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Hasło musi zawierać co najmniej 6 znaków i być zgodne z powtórzeniem.',
-    'user' => "Nie znaleziono użytkownika o takim adresie e-mail.",
+    'user' => 'Nie znaleziono użytkownika o takim adresie e-mail.',
     'token' => 'Token resetowania hasła jest nieprawidłowy dla tego adresu e-mail.',
     'sent' => 'Wysłaliśmy Ci link do resetowania hasła!',
     'reset' => 'Twoje hasło zostało zresetowane!',
diff --git a/resources/lang/pl/settings.php b/resources/lang/pl/settings.php
index b9abe3311..fde8cc209 100644
--- a/resources/lang/pl/settings.php
+++ b/resources/lang/pl/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Konserwacja',
     'maint_image_cleanup' => 'Czyszczenie obrazków',
-    'maint_image_cleanup_desc' => "Skanuje zawartość strony i poprzednie wersje, aby sprawdzić, które obrazy i rysunki są aktualnie używane, a które obrazy są zbędne. Przed uruchomieniem tej opcji należy utworzyć pełną kopię zapasową bazy danych i obrazków.",
+    'maint_image_cleanup_desc' => 'Skanuje zawartość strony i poprzednie wersje, aby sprawdzić, które obrazy i rysunki są aktualnie używane, a które obrazy są zbędne. Przed uruchomieniem tej opcji należy utworzyć pełną kopię zapasową bazy danych i obrazków.',
     'maint_delete_images_only_in_revisions' => 'Usuń również obrazy, które istnieją tylko w starych rewizjach strony',
     'maint_image_cleanup_run' => 'Uruchom czyszczenie',
     'maint_image_cleanup_warning' => 'Znaleziono :count potencjalnie niepotrzebnych obrazków. Czy na pewno chcesz je usunąć?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Usuń rolę',
     'role_delete_confirm' => 'To spowoduje usunięcie roli \':roleName\'.',
     'role_delete_users_assigned' => 'Tę rolę ma przypisanych :userCount użytkowników. Jeśli chcesz zmigrować użytkowników z tej roli, wybierz nową poniżej.',
-    'role_delete_no_migration' => "Nie migruj użytkowników",
+    'role_delete_no_migration' => 'Nie migruj użytkowników',
     'role_delete_sure' => 'Czy na pewno chcesz usunąć tę rolę?',
     'role_delete_success' => 'Rola usunięta pomyślnie',
     'role_edit' => 'Edytuj rolę',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/pt/auth.php b/resources/lang/pt/auth.php
index 849bfc22e..41fdd40df 100644
--- a/resources/lang/pt/auth.php
+++ b/resources/lang/pt/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'O domínio de e-mail usado não tem acesso permitido a esta aplicação',
     'register_success' => 'Obrigado por se registar! Você está agora registado e com a sessão iniciada.',
 
-
     // Password Reset
     'reset_password' => 'Redefinir Senha',
     'reset_password_send_instructions' => 'Insira o seu endereço de e-mail abaixo, e uma mensagem com o link de redefinição de palavra-passe será lhe enviada.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Você recebeu este e-mail pois recebemos uma solicitação de redefinição de senha para a sua conta.',
     'email_reset_not_requested' => 'Caso não tenha sido você a solicitar a redefinição de senha, ignore este e-mail.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirme o seu endereço de e-mail para :appName',
     'email_confirm_greeting' => 'Obrigado por se registar em :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/pt/common.php b/resources/lang/pt/common.php
index d2d18a2e4..0e6e468d6 100644
--- a/resources/lang/pt/common.php
+++ b/resources/lang/pt/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Cargo',
     'cover_image' => 'Imagem de capa',
     'cover_image_description' => 'Esta imagem deve ser aproximadamente 440x250px.',
-    
+
     // Actions
     'actions' => 'Ações',
     'view' => 'Visualizar',
diff --git a/resources/lang/pt/entities.php b/resources/lang/pt/entities.php
index 07e2d5f64..1ebd805d4 100644
--- a/resources/lang/pt/entities.php
+++ b/resources/lang/pt/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Tem a certeza de que deseja eliminar esta revisão?',
     'revision_restore_confirm' => 'Tem a certeza que deseja restaurar esta revisão? O conteúdo atual da página será substituído.',
     'revision_delete_success' => 'Revisão excluída',
-    'revision_cannot_delete_latest' => 'Não é possível eliminar a revisão mais recente.'
+    'revision_cannot_delete_latest' => 'Não é possível eliminar a revisão mais recente.',
 ];
diff --git a/resources/lang/pt/passwords.php b/resources/lang/pt/passwords.php
index e468b9f68..bf30e0e13 100644
--- a/resources/lang/pt/passwords.php
+++ b/resources/lang/pt/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'As palavras-passe devem ter no mínimo oito caracteres e serem iguais à confirmação.',
-    'user' => "Não pudemos encontrar um utilizador com o endereço de e-mail fornecido.",
+    'user' => 'Não pudemos encontrar um utilizador com o endereço de e-mail fornecido.',
     'token' => 'O token de redefinição de senha é inválido para este endereço de e-mail.',
     'sent' => 'Enviamos o link de redefinição de palavra-passe para o seu e-mail!',
     'reset' => 'A sua palavra-passe foi redefinida com sucesso!',
diff --git a/resources/lang/pt/settings.php b/resources/lang/pt/settings.php
index 83a3f5da0..31e5e87ab 100644
--- a/resources/lang/pt/settings.php
+++ b/resources/lang/pt/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Manutenção',
     'maint_image_cleanup' => 'Limpeza de Imagens',
-    'maint_image_cleanup_desc' => "Examina páginas e reviste os seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar uma cópia de segurança completa da base de dados e imagens antes de executar esta ação.",
+    'maint_image_cleanup_desc' => 'Examina páginas e reviste os seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar uma cópia de segurança completa da base de dados e imagens antes de executar esta ação.',
     'maint_delete_images_only_in_revisions' => 'Eliminar também imagens que existam apenas em revisões de página antigas',
     'maint_image_cleanup_run' => 'Executar Limpeza',
     'maint_image_cleanup_warning' => ':count imagens potencialmente não utilizadas foram encontradas. Tem certeza de que deseja eliminar estas imagens?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Excluir Cargo',
     'role_delete_confirm' => 'A ação vai eliminar o cargo de nome \':roleName\'.',
     'role_delete_users_assigned' => 'Esse cargo tem :userCount utilizadores vinculados nele. Se quiser migrar utilizadores deste cargo para outro, selecione um novo cargo.',
-    'role_delete_no_migration' => "Não migrar utilizadores",
+    'role_delete_no_migration' => 'Não migrar utilizadores',
     'role_delete_sure' => 'Tem certeza que deseja excluir este cargo?',
     'role_delete_success' => 'Cargo excluído com sucesso',
     'role_edit' => 'Editar Cargo',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/pt_BR/auth.php b/resources/lang/pt_BR/auth.php
index a5f0c18bc..707bea034 100644
--- a/resources/lang/pt_BR/auth.php
+++ b/resources/lang/pt_BR/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'O domínio de e-mail usado não tem acesso permitido a essa aplicação',
     'register_success' => 'Obrigado por se cadastrar! Você agora encontra-se cadastrado(a) e logado(a).',
 
-
     // Password Reset
     'reset_password' => 'Redefinir Senha',
     'reset_password_send_instructions' => 'Insira seu e-mail abaixo e uma mensagem com o link de redefinição de senha lhe será enviada.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Você recebeu esse e-mail pois recebemos uma solicitação de redefinição de senha para a sua conta.',
     'email_reset_not_requested' => 'Caso não tenha sido você a solicitar a redefinição de senha, ignore esse e-mail.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirme seu e-mail para :appName',
     'email_confirm_greeting' => 'Obrigado por se cadastrar em :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/pt_BR/common.php b/resources/lang/pt_BR/common.php
index 1435a380d..5a3fa2528 100644
--- a/resources/lang/pt_BR/common.php
+++ b/resources/lang/pt_BR/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Cargo',
     'cover_image' => 'Imagem de capa',
     'cover_image_description' => 'Esta imagem deve ser aproximadamente 440x250px.',
-    
+
     // Actions
     'actions' => 'Ações',
     'view' => 'Visualizar',
diff --git a/resources/lang/pt_BR/entities.php b/resources/lang/pt_BR/entities.php
index 14ce2a832..fc4119932 100644
--- a/resources/lang/pt_BR/entities.php
+++ b/resources/lang/pt_BR/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Tem certeza de que deseja excluir esta revisão?',
     'revision_restore_confirm' => 'Tem certeza que deseja restaurar esta revisão? O conteúdo atual da página será substituído.',
     'revision_delete_success' => 'Revisão excluída',
-    'revision_cannot_delete_latest' => 'Não é possível excluir a revisão mais recente.'
+    'revision_cannot_delete_latest' => 'Não é possível excluir a revisão mais recente.',
 ];
diff --git a/resources/lang/pt_BR/passwords.php b/resources/lang/pt_BR/passwords.php
index fde9e2937..8343ad57a 100644
--- a/resources/lang/pt_BR/passwords.php
+++ b/resources/lang/pt_BR/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Senhas devem ter ao menos oito caracteres e ser iguais à confirmação.',
-    'user' => "Não pudemos encontrar um usuário com o e-mail fornecido.",
+    'user' => 'Não pudemos encontrar um usuário com o e-mail fornecido.',
     'token' => 'O token de redefinição de senha é inválido para este endereço de e-mail.',
     'sent' => 'Enviamos o link de redefinição de senha para o seu e-mail!',
     'reset' => 'Sua senha foi redefinida com sucesso!',
diff --git a/resources/lang/pt_BR/settings.php b/resources/lang/pt_BR/settings.php
index e2d29f459..b73a006e8 100644
--- a/resources/lang/pt_BR/settings.php
+++ b/resources/lang/pt_BR/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Manutenção',
     'maint_image_cleanup' => 'Limpeza de Imagens',
-    'maint_image_cleanup_desc' => "Examina páginas e revisa seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar um backup completo do banco de dados e imagens antes de executar esta ação.",
+    'maint_image_cleanup_desc' => 'Examina páginas e revisa seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar um backup completo do banco de dados e imagens antes de executar esta ação.',
     'maint_delete_images_only_in_revisions' => 'Também excluir imagens que existem apenas em revisões de página antigas',
     'maint_image_cleanup_run' => 'Executar Limpeza',
     'maint_image_cleanup_warning' => ':count imagens potencialmente não utilizadas foram encontradas. Tem certeza de que deseja excluir estas imagens?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Excluir Cargo',
     'role_delete_confirm' => 'A ação vai excluír o cargo de nome \':roleName\'.',
     'role_delete_users_assigned' => 'Esse cargo tem :userCount usuários vinculados a ele. Se quiser migrar usuários desse cargo para outro, selecione um novo cargo.',
-    'role_delete_no_migration' => "Não migre os usuários",
+    'role_delete_no_migration' => 'Não migre os usuários',
     'role_delete_sure' => 'Tem certeza que deseja excluir esse cargo?',
     'role_delete_success' => 'Cargo excluído com sucesso',
     'role_edit' => 'Editar Cargo',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/ru/auth.php b/resources/lang/ru/auth.php
index 8410e40e4..69b0b20d3 100644
--- a/resources/lang/ru/auth.php
+++ b/resources/lang/ru/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Данный домен электронной почты недоступен для регистрации',
     'register_success' => 'Спасибо за регистрацию! Регистрация и вход в систему выполнены.',
 
-
     // Password Reset
     'reset_password' => 'Сброс пароля',
     'reset_password_send_instructions' => 'Введите свой адрес электронной почты ниже, и вам будет отправлено письмо со ссылкой для сброса пароля.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Вы получили это письмо, потому что запросили сброс пароля для вашей учетной записи.',
     'email_reset_not_requested' => 'Если вы не запрашивали сброса пароля, то никаких дополнительных действий не требуется.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Подтвердите ваш почтовый адрес на :appName',
     'email_confirm_greeting' => 'Благодарим за участие :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Введите резервный код',
     'mfa_verify_totp_desc' => 'Введите код, сгенерированный с помощью мобильного приложения, ниже:',
     'mfa_setup_login_notification' => 'Двухфакторный метод настроен, пожалуйста, войдите снова, используя сконфигурированный метод.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/ru/common.php b/resources/lang/ru/common.php
index 6e2a31931..8b6fbda73 100644
--- a/resources/lang/ru/common.php
+++ b/resources/lang/ru/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Роль',
     'cover_image' => 'Обложка',
     'cover_image_description' => 'Изображение должно быть размером около 440x250px.',
-    
+
     // Actions
     'actions' => 'Действия',
     'view' => 'Просмотр',
diff --git a/resources/lang/ru/entities.php b/resources/lang/ru/entities.php
index 0bcb7c1d4..d5418955c 100644
--- a/resources/lang/ru/entities.php
+++ b/resources/lang/ru/entities.php
@@ -255,7 +255,7 @@ return [
     'tags' =>  'Теги',
     'tag_name' =>  'Имя тега',
     'tag_value' => 'Значение тега (опционально)',
-    'tags_explain' => "Добавьте теги, чтобы лучше классифицировать ваш контент. \\n Вы можете присвоить значение тегу для более глубокой организации.",
+    'tags_explain' => 'Добавьте теги, чтобы лучше классифицировать ваш контент. \\n Вы можете присвоить значение тегу для более глубокой организации.',
     'tags_add' => 'Добавить тег',
     'tags_remove' => 'Удалить этот тег',
     'attachments' => 'Вложения',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Удалить эту версию?',
     'revision_restore_confirm' => 'Вы уверены, что хотите восстановить эту версию? Текущее содержимое страницы будет заменено.',
     'revision_delete_success' => 'Версия удалена',
-    'revision_cannot_delete_latest' => 'Нельзя удалить последнюю версию.'
+    'revision_cannot_delete_latest' => 'Нельзя удалить последнюю версию.',
 ];
diff --git a/resources/lang/ru/errors.php b/resources/lang/ru/errors.php
index 1edef426c..ae7bac814 100644
--- a/resources/lang/ru/errors.php
+++ b/resources/lang/ru/errors.php
@@ -28,7 +28,7 @@ return [
     'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system',
     'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization',
     'social_no_action_defined' => 'Действие не определено',
-    'social_login_bad_response' => "При попытке входа с :socialAccount произошла ошибка: \\n:error",
+    'social_login_bad_response' => 'При попытке входа с :socialAccount произошла ошибка: \\n:error',
     'social_account_in_use' => 'Этот :socialAccount аккаунт уже используется, попробуйте войти с параметрами :socialAccount.',
     'social_account_email_in_use' => 'Электронный ящик :email уже используется. Если у вас уже есть учетная запись, вы можете подключить свою учетную запись :socialAccount из настроек своего профиля.',
     'social_account_existing' => 'Этот :socialAccount уже привязан к вашему профилю.',
diff --git a/resources/lang/ru/passwords.php b/resources/lang/ru/passwords.php
index 433c70454..6880c0db6 100644
--- a/resources/lang/ru/passwords.php
+++ b/resources/lang/ru/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Пароль должен содержать не менее восьми символов и совпадать с подтверждением.',
-    'user' => "Пользователя с данным адресом электронной почты не существует.",
+    'user' => 'Пользователя с данным адресом электронной почты не существует.',
     'token' => 'Токен сброса пароля недействителен для этого адреса электронной почты.',
     'sent' => 'Ссылка для сброса пароля отправлена на вашу почту!',
     'reset' => 'Ваш пароль был сброшен!',
diff --git a/resources/lang/ru/settings.php b/resources/lang/ru/settings.php
index cfa802f34..79c5d90c6 100755
--- a/resources/lang/ru/settings.php
+++ b/resources/lang/ru/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Обслуживание',
     'maint_image_cleanup' => 'Очистка изображений',
-    'maint_image_cleanup_desc' => "Сканирует содержимое страниц и предыдущих версий и определяет изображения, которые не используются. Убедитесь, что у вас есть резервная копия базы данных и папки изображений перед запуском этой функции.",
+    'maint_image_cleanup_desc' => 'Сканирует содержимое страниц и предыдущих версий и определяет изображения, которые не используются. Убедитесь, что у вас есть резервная копия базы данных и папки изображений перед запуском этой функции.',
     'maint_delete_images_only_in_revisions' => 'Также удалять изображения, которые существуют только в старой версии страницы',
     'maint_image_cleanup_run' => 'Выполнить очистку',
     'maint_image_cleanup_warning' => 'Найдено :count возможно бесполезных изображений. Вы уверены, что хотите удалить эти изображения?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Удалить роль',
     'role_delete_confirm' => 'Это удалит роль с именем \':roleName\'.',
     'role_delete_users_assigned' => 'Эта роль назначена :userCount пользователям. Если вы хотите перенести их, выберите новую роль ниже.',
-    'role_delete_no_migration' => "Не переносить пользователей",
+    'role_delete_no_migration' => 'Не переносить пользователей',
     'role_delete_sure' => 'Вы уверены что хотите удалить данную роль?',
     'role_delete_success' => 'Роль успешно удалена',
     'role_edit' => 'Редактировать роль',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/sk/auth.php b/resources/lang/sk/auth.php
index f79e79cca..cb978baf5 100644
--- a/resources/lang/sk/auth.php
+++ b/resources/lang/sk/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Táto e-mailová doména nemá prístup k tejto aplikácii',
     'register_success' => 'Ďakujeme za registráciu! Teraz ste registrovaný a prihlásený.',
 
-
     // Password Reset
     'reset_password' => 'Resetovanie hesla',
     'reset_password_send_instructions' => 'Nižšie zadajte svoj e-mail, na ktorý Vám zašleme odkaz pre resetovanie hesla.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Tento e-mail ste obdržali, pretože sme dostali požiadavku na resetovanie hesla pre Váš účet.',
     'email_reset_not_requested' => 'Ak ste nepožiadali o resetovanie hesla, nemusíte robiť nič.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Potvrdiť e-mail na :appName',
     'email_confirm_greeting' => 'Ďakujeme, že ste sa pridali k :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Zadajte záložný kód',
     'mfa_verify_totp_desc' => 'Zadajte kód vygenerovaný vašou mobilnou aplikáciou:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/sk/common.php b/resources/lang/sk/common.php
index b9913db59..f84e62989 100644
--- a/resources/lang/sk/common.php
+++ b/resources/lang/sk/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rola',
     'cover_image' => 'Obal knihy',
     'cover_image_description' => 'Tento obrázok by mal byť približne 300 x 170 pixelov.',
-    
+
     // Actions
     'actions' => 'Akcie',
     'view' => 'Zobraziť',
diff --git a/resources/lang/sk/entities.php b/resources/lang/sk/entities.php
index e7531795f..114421118 100644
--- a/resources/lang/sk/entities.php
+++ b/resources/lang/sk/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Naozaj chcete túto revíziu odstrániť?',
     'revision_restore_confirm' => 'Naozaj chcete obnoviť túto revíziu? Aktuálny obsah stránky sa nahradí.',
     'revision_delete_success' => 'Revízia bola vymazaná',
-    'revision_cannot_delete_latest' => 'Nie je možné vymazať poslednú revíziu.'
+    'revision_cannot_delete_latest' => 'Nie je možné vymazať poslednú revíziu.',
 ];
diff --git a/resources/lang/sk/passwords.php b/resources/lang/sk/passwords.php
index 5b80f62da..9894b91b3 100644
--- a/resources/lang/sk/passwords.php
+++ b/resources/lang/sk/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Heslo musí obsahovať aspoň osem znakov a musí byť rovnaké ako potvrdzujúce.',
-    'user' => "Nenašli sme používateľa s takou emailovou adresou.",
+    'user' => 'Nenašli sme používateľa s takou emailovou adresou.',
     'token' => 'Token na obnovenie hesla je pre túto e-mailovú adresu neplatný.',
     'sent' => 'Poslali sme Vám email s odkazom na reset hesla!',
     'reset' => 'Vaše heslo bolo resetované!',
diff --git a/resources/lang/sk/settings.php b/resources/lang/sk/settings.php
index 875239aca..b738c9465 100644
--- a/resources/lang/sk/settings.php
+++ b/resources/lang/sk/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Údržba',
     'maint_image_cleanup' => 'Prečistenie obrázkov',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Spustiť prečistenie',
     'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Zmazať rolu',
     'role_delete_confirm' => 'Toto zmaže rolu menom \':roleName\'.',
     'role_delete_users_assigned' => 'Túto rolu má priradenú :userCount používateľov. Ak chcete premigrovať používateľov z tejto roly, vyberte novú rolu nižšie.',
-    'role_delete_no_migration' => "Nemigrovať používateľov",
+    'role_delete_no_migration' => 'Nemigrovať používateľov',
     'role_delete_sure' => 'Ste si istý, že chcete zmazať túto rolu?',
     'role_delete_success' => 'Rola úspešne zmazaná',
     'role_edit' => 'Upraviť rolu',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/sl/auth.php b/resources/lang/sl/auth.php
index b6c41666a..77203cde9 100644
--- a/resources/lang/sl/auth.php
+++ b/resources/lang/sl/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Ta e-poštna domena nima dostopa do te aplikacije',
     'register_success' => 'Hvala za registracijo! Sedaj ste registrirani in prijavljeni.',
 
-
     // Password Reset
     'reset_password' => 'Ponastavi geslo',
     'reset_password_send_instructions' => 'Spodaj vpišite vaš e-poštni naslov in prejeli boste e-pošto s povezavo za ponastavitev gesla.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'To e-poštno sporočilo ste prejeli, ker smo prejeli zahtevo za ponastavitev gesla za vaš račun.',
     'email_reset_not_requested' => 'Če niste zahtevali ponastavitve gesla, vam ni potrebno ničesar storiti.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Potrdi svojo e-pošto za :appName',
     'email_confirm_greeting' => 'Hvala ker ste se pridružili :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/sl/common.php b/resources/lang/sl/common.php
index 9f478e75d..d58467ecf 100644
--- a/resources/lang/sl/common.php
+++ b/resources/lang/sl/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Vloga',
     'cover_image' => 'Naslovna slika',
     'cover_image_description' => 'Slika naj bo velika približno 440x250px.',
-    
+
     // Actions
     'actions' => 'Dejanja',
     'view' => 'Pogled',
diff --git a/resources/lang/sl/entities.php b/resources/lang/sl/entities.php
index 4ad1aea00..e524d4140 100644
--- a/resources/lang/sl/entities.php
+++ b/resources/lang/sl/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Ali ste prepričani, da želite izbrisati to revizijo?',
     'revision_restore_confirm' => 'Ali ste prepričani da želite obnoviti to revizijo? Vsebina trenutne strani bo zamenjana.',
     'revision_delete_success' => 'Revizija izbrisana',
-    'revision_cannot_delete_latest' => 'Ne morem izbrisati zadnje revizije.'
+    'revision_cannot_delete_latest' => 'Ne morem izbrisati zadnje revizije.',
 ];
diff --git a/resources/lang/sl/passwords.php b/resources/lang/sl/passwords.php
index e9e195fe9..4a3b791b5 100644
--- a/resources/lang/sl/passwords.php
+++ b/resources/lang/sl/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Gesla morajo biti najmanj osem znakov dolga in se morajo ujemati s potrditvijo.',
-    'user' => "Ne moremo najti uporabnika s tem e-poštnim naslovom.",
+    'user' => 'Ne moremo najti uporabnika s tem e-poštnim naslovom.',
     'token' => 'Žeton za ponastavitev gesla ni veljaven za ta e-poštni naslov.',
     'sent' => 'Poslali smo vam povezavo za ponastavitev gesla!',
     'reset' => 'Vaše geslo je bilo ponastavljeno!',
diff --git a/resources/lang/sl/settings.php b/resources/lang/sl/settings.php
index a25488d15..c0f636456 100644
--- a/resources/lang/sl/settings.php
+++ b/resources/lang/sl/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Vzdrževanje',
     'maint_image_cleanup' => 'Odstrani /počisti slike',
-    'maint_image_cleanup_desc' => "Pregleda vsebino strani in revizij ter ugotovi, katere slike in risbe so v uporabi in katere so odvečne. Preden to poženeš, naredi popolno varnostno kopijo podatkovne zbirke in slik.",
+    'maint_image_cleanup_desc' => 'Pregleda vsebino strani in revizij ter ugotovi, katere slike in risbe so v uporabi in katere so odvečne. Preden to poženeš, naredi popolno varnostno kopijo podatkovne zbirke in slik.',
     'maint_delete_images_only_in_revisions' => 'Izbriši tudi slike, ki obstajajo le v starih različicah strani',
     'maint_image_cleanup_run' => 'Zaženi čiščenje',
     'maint_image_cleanup_warning' => 'Najdenih je bilo :count verjetno neuporabljenih slik. Ali si prepričan, da želiš odstraniti izbrane slike?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Brisanje vloge',
     'role_delete_confirm' => 'Izbrisana bo vloga z imenom \':roleName\'.',
     'role_delete_users_assigned' => 'Ta vloga ima dodeljenih :userCount uporabnikov. V kolikor želite uporabnike preseliti iz te vloge, spodaj izberite novo vlogo.',
-    'role_delete_no_migration' => "Ne prenašaj uporabnikov",
+    'role_delete_no_migration' => 'Ne prenašaj uporabnikov',
     'role_delete_sure' => 'Ali ste prepričani, da želite izbrisati to vlogo?',
     'role_delete_success' => 'Vloga uspešno izbrisana',
     'role_edit' => 'Uredi vlogo',
@@ -274,6 +274,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/sv/auth.php b/resources/lang/sv/auth.php
index 1d1a81c74..2cf218b5a 100644
--- a/resources/lang/sv/auth.php
+++ b/resources/lang/sv/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Den e-postadressen har inte tillgång till den här applikationen',
     'register_success' => 'Tack för din registrering! Du är nu registerad och inloggad.',
 
-
     // Password Reset
     'reset_password' => 'Återställ lösenord',
     'reset_password_send_instructions' => 'Ange din e-postadress nedan så skickar vi ett mail med en länk för att återställa ditt lösenord.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Du får detta mail eftersom vi fått en begäran om att återställa lösenordet till ditt konto.',
     'email_reset_not_requested' => 'Om du inte begärt att få ditt lösenord återställt behöver du inte göra någonting',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Bekräfta din e-post på :appName',
     'email_confirm_greeting' => 'Tack för att du gått med i :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/sv/common.php b/resources/lang/sv/common.php
index 177a8abef..3be74d566 100644
--- a/resources/lang/sv/common.php
+++ b/resources/lang/sv/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Roll',
     'cover_image' => 'Omslagsbild',
     'cover_image_description' => 'Bilden bör vara cirka 440x250px stor.',
-    
+
     // Actions
     'actions' => 'Åtgärder',
     'view' => 'Visa',
diff --git a/resources/lang/sv/entities.php b/resources/lang/sv/entities.php
index 80eb570c9..1eadf1f74 100644
--- a/resources/lang/sv/entities.php
+++ b/resources/lang/sv/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Är du säker på att du vill radera den här versionen?',
     'revision_restore_confirm' => 'Är du säker på att du vill använda denna revision? Det nuvarande innehållet kommer att ersättas.',
     'revision_delete_success' => 'Revisionen raderad',
-    'revision_cannot_delete_latest' => 'Det går inte att ta bort den senaste versionen.'
+    'revision_cannot_delete_latest' => 'Det går inte att ta bort den senaste versionen.',
 ];
diff --git a/resources/lang/sv/passwords.php b/resources/lang/sv/passwords.php
index 640309b88..9bd8dbc02 100644
--- a/resources/lang/sv/passwords.php
+++ b/resources/lang/sv/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Lösenord måste vara minst sex tecken långa och anges likadant två gånger.',
-    'user' => "Det finns ingen användare med den e-postadressen.",
+    'user' => 'Det finns ingen användare med den e-postadressen.',
     'token' => 'Lösenordsåterställningstoken är ogiltig för denna e-postadress.',
     'sent' => 'Vi har mailat dig en länk för att återställa ditt lösenord!',
     'reset' => 'Ditt lösenord har blivit återställt!',
diff --git a/resources/lang/sv/settings.php b/resources/lang/sv/settings.php
index 9065407f7..61326e496 100644
--- a/resources/lang/sv/settings.php
+++ b/resources/lang/sv/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Underhåll',
     'maint_image_cleanup' => 'Rensa bilder',
-    'maint_image_cleanup_desc' => "Söker igenom innehåll i sidor & revisioner för att se vilka bilder och teckningar som är i bruk och vilka som är överflödiga. Se till att ta en komplett backup av databas och bilder innan du kör detta.",
+    'maint_image_cleanup_desc' => 'Söker igenom innehåll i sidor & revisioner för att se vilka bilder och teckningar som är i bruk och vilka som är överflödiga. Se till att ta en komplett backup av databas och bilder innan du kör detta.',
     'maint_delete_images_only_in_revisions' => 'Ta också bort bilder som bara finns i gamla sidrevideringar',
     'maint_image_cleanup_run' => 'Kör rensning',
     'maint_image_cleanup_warning' => 'Hittade :count bilder som potentiellt inte används. Vill du verkligen ta bort dessa bilder?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Ta bort roll',
     'role_delete_confirm' => 'Rollen med namn \':roleName\' kommer att tas bort.',
     'role_delete_users_assigned' => 'Det finns :userCount användare som tillhör den här rollen. Om du vill migrera användarna från den här rollen, välj en ny roll nedan.',
-    'role_delete_no_migration' => "Migrera inte användare",
+    'role_delete_no_migration' => 'Migrera inte användare',
     'role_delete_sure' => 'Är du säker på att du vill ta bort den här rollen?',
     'role_delete_success' => 'Rollen har tagits bort',
     'role_edit' => 'Redigera roll',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/th/auth.php b/resources/lang/th/auth.php
index d64fce93a..8ff408021 100644
--- a/resources/lang/th/auth.php
+++ b/resources/lang/th/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'That email domain does not have access to this application',
     'register_success' => 'Thanks for signing up! You are now registered and signed in.',
 
-
     // Password Reset
     'reset_password' => 'Reset Password',
     'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.',
     'email_reset_not_requested' => 'If you did not request a password reset, no further action is required.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Confirm your email on :appName',
     'email_confirm_greeting' => 'Thanks for joining :appName!',
@@ -73,5 +71,5 @@ return [
     'user_invite_page_welcome' => 'Welcome to :appName!',
     'user_invite_page_text' => 'To finalise your account and gain access you need to set a password which will be used to log-in to :appName on future visits.',
     'user_invite_page_confirm_button' => 'Confirm Password',
-    'user_invite_success' => 'Password set, you now have access to :appName!'
-];
\ No newline at end of file
+    'user_invite_success' => 'Password set, you now have access to :appName!',
+];
diff --git a/resources/lang/th/common.php b/resources/lang/th/common.php
index e87bd11a5..e3bec6837 100644
--- a/resources/lang/th/common.php
+++ b/resources/lang/th/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Role',
     'cover_image' => 'Cover image',
     'cover_image_description' => 'This image should be approx 440x250px.',
-    
+
     // Actions
     'actions' => 'Actions',
     'view' => 'View',
diff --git a/resources/lang/th/entities.php b/resources/lang/th/entities.php
index f64867a56..67c451319 100644
--- a/resources/lang/th/entities.php
+++ b/resources/lang/th/entities.php
@@ -312,5 +312,5 @@ return [
     'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
     'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.',
     'revision_delete_success' => 'Revision deleted',
-    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.'
-];
\ No newline at end of file
+    'revision_cannot_delete_latest' => 'Cannot delete the latest revision.',
+];
diff --git a/resources/lang/th/settings.php b/resources/lang/th/settings.php
index 2bd314cf0..c2e4ee734 100644
--- a/resources/lang/th/settings.php
+++ b/resources/lang/th/settings.php
@@ -67,7 +67,7 @@ return [
     // Maintenance settings
     'maint' => 'Maintenance',
     'maint_image_cleanup' => 'Cleanup Images',
-    'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+    'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.',
     'maint_image_cleanup_ignore_revisions' => 'Ignore images in revisions',
     'maint_image_cleanup_run' => 'Run Cleanup',
     'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
@@ -224,6 +224,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/tr/auth.php b/resources/lang/tr/auth.php
index 0ce90d4d0..62c7653bf 100644
--- a/resources/lang/tr/auth.php
+++ b/resources/lang/tr/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Bu e-posta sağlayıcısının uygulamaya erişim izni bulunmuyor',
     'register_success' => 'Kaydolduğunuz için teşekkürler! Artık kayıtlı bir kullanıcı olarak giriş yaptınız.',
 
-
     // Password Reset
     'reset_password' => 'Şifreyi Sıfırla',
     'reset_password_send_instructions' => 'Aşağıya gireceğiniz e-posta adresine şifre sıfırlama bağlantısı gönderilecektir.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Hesap şifrenizi sıfırlama isteğinde bulunduğunuz için bu e-postayı aldınız.',
     'email_reset_not_requested' => 'Şifre sıfırlama isteğinde bulunmadıysanız herhangi bir işlem yapmanıza gerek yoktur.',
 
-
     // Email Confirmation
     'email_confirm_subject' => ':appName için girdiğiniz e-posta adresini doğrulayın',
     'email_confirm_greeting' => ':appName uygulamasına katıldığınız için teşekkürler!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/tr/common.php b/resources/lang/tr/common.php
index 1f19a62f4..add3767af 100644
--- a/resources/lang/tr/common.php
+++ b/resources/lang/tr/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Rol',
     'cover_image' => 'Kapak resmi',
     'cover_image_description' => 'Bu görsel yaklaşık 440x250px boyutlarında olmalıdır.',
-    
+
     // Actions
     'actions' => 'İşlemler',
     'view' => 'Görüntüle',
diff --git a/resources/lang/tr/entities.php b/resources/lang/tr/entities.php
index 9b0a15c5d..c562ec824 100644
--- a/resources/lang/tr/entities.php
+++ b/resources/lang/tr/entities.php
@@ -255,7 +255,7 @@ return [
     'tags' =>  'Etiketler',
     'tag_name' =>  'Etiket İsmi',
     'tag_value' => 'Etiket Değeri (Opsiyonel)',
-    'tags_explain' => "İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.",
+    'tags_explain' => 'İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.',
     'tags_add' => 'Başka etiket ekle',
     'tags_remove' => 'Bu etiketi sil',
     'attachments' => 'Ekler',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Bu revizyonu silmek istediğinize emin misiniz?',
     'revision_restore_confirm' => 'Bu revizyonu yeniden yüklemek istediğinize emin misiniz? Sayfanın şu anki içeriği değiştirilecektir.',
     'revision_delete_success' => 'Revizyon silindi',
-    'revision_cannot_delete_latest' => 'Son revizyonu silemezsiniz.'
+    'revision_cannot_delete_latest' => 'Son revizyonu silemezsiniz.',
 ];
diff --git a/resources/lang/tr/passwords.php b/resources/lang/tr/passwords.php
index ba1fd913f..890f2d628 100644
--- a/resources/lang/tr/passwords.php
+++ b/resources/lang/tr/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Şifreniz en az 6 karakterden oluşmalı ve her iki şifre de birbiri ile eşleşmelidir.',
-    'user' => "Bu e-posta adresine sahip bir kullanıcı bulamadık.",
+    'user' => 'Bu e-posta adresine sahip bir kullanıcı bulamadık.',
     'token' => 'Şifre sıfırlama anahtarı, bu e-posta adresi için geçersizdir.',
     'sent' => 'Şifre sıfırlama bağlantısını e-posta adresinize gönderdik!',
     'reset' => 'Şifreniz sıfırlandı!',
diff --git a/resources/lang/tr/settings.php b/resources/lang/tr/settings.php
index b95f28b39..766e01fad 100755
--- a/resources/lang/tr/settings.php
+++ b/resources/lang/tr/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Bakım',
     'maint_image_cleanup' => 'Görselleri Temizle',
-    'maint_image_cleanup_desc' => "Sayfaları ve revizyon içeriklerini tarayarak hangi görsellerin ve çizimlerin kullanımda olduğunu ve hangilerinin gereksiz olduğunu tespit eder. Bunu başlatmadan önce veritabanının ve görsellerin tam bir yedeğinin alındığından emin olun.",
+    'maint_image_cleanup_desc' => 'Sayfaları ve revizyon içeriklerini tarayarak hangi görsellerin ve çizimlerin kullanımda olduğunu ve hangilerinin gereksiz olduğunu tespit eder. Bunu başlatmadan önce veritabanının ve görsellerin tam bir yedeğinin alındığından emin olun.',
     'maint_delete_images_only_in_revisions' => 'Eski sayfa revizyonlarındaki görselleri de sil',
     'maint_image_cleanup_run' => 'Temizliği Başlat',
     'maint_image_cleanup_warning' => 'Muhtemelen kullanılmayan :count adet görsel bulundu. Bu görselleri silmek istediğinize emin misiniz?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Rolü Sil',
     'role_delete_confirm' => 'Bu işlem, \':roleName\' adlı rolü silecektir.',
     'role_delete_users_assigned' => 'Bu role atanmış :userCount adet kullanıcı var. Eğer bu kullanıcıların rollerini değiştirmek istiyorsanız, aşağıdan yeni bir rol seçin.',
-    'role_delete_no_migration' => "Kullanıcıları taşıma",
+    'role_delete_no_migration' => 'Kullanıcıları taşıma',
     'role_delete_sure' => 'Bu rolü silmek istediğinize emin misiniz?',
     'role_delete_success' => 'Rol başarıyla silindi',
     'role_edit' => 'Rolü Düzenle',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/uk/auth.php b/resources/lang/uk/auth.php
index 52625b60f..6bab87fc1 100644
--- a/resources/lang/uk/auth.php
+++ b/resources/lang/uk/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Цей домен електронної пошти заборонений для реєстрації',
     'register_success' => 'Дякуємо за реєстрацію! Ви зареєстровані та ввійшли в систему.',
 
-
     // Password Reset
     'reset_password' => 'Скинути пароль',
     'reset_password_send_instructions' => 'Введіть адресу електронної пошти нижче, і вам буде надіслано електронне повідомлення з посиланням на зміну пароля.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Ви отримали цей електронний лист, оскільки до нас надійшов запит на скидання пароля для вашого облікового запису.',
     'email_reset_not_requested' => 'Якщо ви не надсилали запит на скидання пароля, подальші дії не потрібні.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Підтвердьте свою електронну пошту на :appName',
     'email_confirm_greeting' => 'Дякуємо, що приєдналися до :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/uk/common.php b/resources/lang/uk/common.php
index 734c566e5..f07f713c6 100644
--- a/resources/lang/uk/common.php
+++ b/resources/lang/uk/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Роль',
     'cover_image' => 'Обкладинка',
     'cover_image_description' => 'Це зображення має бути приблизно 440x250px.',
-    
+
     // Actions
     'actions' => 'Дії',
     'view' => 'Подивитись',
diff --git a/resources/lang/uk/entities.php b/resources/lang/uk/entities.php
index 6f9b4dae8..f5955c0e9 100644
--- a/resources/lang/uk/entities.php
+++ b/resources/lang/uk/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Ви впевнені, що хочете видалити цю версію?',
     'revision_restore_confirm' => 'Дійсно відновити цю версію? Вміст поточної сторінки буде замінено.',
     'revision_delete_success' => 'Версія видалена',
-    'revision_cannot_delete_latest' => 'Неможливо видалити останню версію.'
+    'revision_cannot_delete_latest' => 'Неможливо видалити останню версію.',
 ];
diff --git a/resources/lang/uk/passwords.php b/resources/lang/uk/passwords.php
index 90c31777c..62a02073d 100644
--- a/resources/lang/uk/passwords.php
+++ b/resources/lang/uk/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Пароль повинен містити не менше восьми символів і збігатись з підтвердженням.',
-    'user' => "Ми не можемо знайти користувача з цією адресою електронної пошти.",
+    'user' => 'Ми не можемо знайти користувача з цією адресою електронної пошти.',
     'token' => 'Токен скидання пароля недійсний для цієї адреси електронної пошти.',
     'sent' => 'Ми надіслали Вам електронний лист із посиланням для скидання пароля!',
     'reset' => 'Ваш пароль скинуто!',
diff --git a/resources/lang/uk/settings.php b/resources/lang/uk/settings.php
index 602fa9bcd..afdbd657d 100644
--- a/resources/lang/uk/settings.php
+++ b/resources/lang/uk/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Обслуговування',
     'maint_image_cleanup' => 'Очищення зображень',
-    'maint_image_cleanup_desc' => "Сканує вміст сторінки та версій, щоб перевірити, які зображення та малюнки в даний час використовуються, а також які зображення зайві. Переконайтеся, що ви створили повну резервну копію бази даних та зображення, перш ніж запускати це.",
+    'maint_image_cleanup_desc' => 'Сканує вміст сторінки та версій, щоб перевірити, які зображення та малюнки в даний час використовуються, а також які зображення зайві. Переконайтеся, що ви створили повну резервну копію бази даних та зображення, перш ніж запускати це.',
     'maint_delete_images_only_in_revisions' => 'Також видалити зображення, що існують лише в старих версіях сторінки',
     'maint_image_cleanup_run' => 'Запустити очищення',
     'maint_image_cleanup_warning' => ':count потенційно невикористаних зображень було знайдено. Ви впевнені, що хочете видалити ці зображення?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Видалити роль',
     'role_delete_confirm' => 'Це призведе до видалення ролі з назвою \':roleName\'.',
     'role_delete_users_assigned' => 'Цій ролі належать :userCount користувачі(в). Якщо ви хочете перенести користувачів із цієї ролі, виберіть нову роль нижче.',
-    'role_delete_no_migration' => "Не мігрувати користувачів",
+    'role_delete_no_migration' => 'Не мігрувати користувачів',
     'role_delete_sure' => 'Ви впевнені, що хочете видалити цю роль?',
     'role_delete_success' => 'Роль успішно видалена',
     'role_edit' => 'Редагувати роль',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/vi/auth.php b/resources/lang/vi/auth.php
index e95d26ac6..0475570dd 100644
--- a/resources/lang/vi/auth.php
+++ b/resources/lang/vi/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => 'Tên miền của email không có quyền truy cập tới ứng dụng này',
     'register_success' => 'Cảm ơn bạn đã đăng kí! Bạn đã được xác nhận và đăng nhập.',
 
-
     // Password Reset
     'reset_password' => 'Đặt lại mật khẩu',
     'reset_password_send_instructions' => 'Nhập email vào ô dưới đây và bạn sẽ nhận được một email với liên kết để đặt lại mật khẩu.',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => 'Bạn nhận được email này bởi vì chúng tôi nhận được một yêu cầu đặt lại mật khẩu cho tài khoản của bạn.',
     'email_reset_not_requested' => 'Nếu bạn không yêu cầu đặt lại mật khẩu, không cần có bất cứ hành động nào khác.',
 
-
     // Email Confirmation
     'email_confirm_subject' => 'Xác nhận email trên :appName',
     'email_confirm_greeting' => 'Cảm ơn bạn đã tham gia :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Nhập mã xác thực của bạn tại đây',
     'mfa_verify_totp_desc' => 'Nhập mã do ứng dụng di động của bạn tạo ra vào dưới đây:',
     'mfa_setup_login_notification' => 'Đã cài đặt xác thực nhiều bước, bạn vui lòng đăng nhập lại sử dụng phương thức đã cài đặt.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/vi/common.php b/resources/lang/vi/common.php
index f118d34c3..2a1de7863 100644
--- a/resources/lang/vi/common.php
+++ b/resources/lang/vi/common.php
@@ -20,7 +20,7 @@ return [
     'role' => 'Quyền',
     'cover_image' => 'Ảnh bìa',
     'cover_image_description' => 'Ảnh nên có kích thước 440x250px.',
-    
+
     // Actions
     'actions' => 'Hành động',
     'view' => 'Xem',
diff --git a/resources/lang/vi/entities.php b/resources/lang/vi/entities.php
index 8162509d7..58e1d6b1f 100644
--- a/resources/lang/vi/entities.php
+++ b/resources/lang/vi/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => 'Bạn có chắc bạn muốn xóa phiên bản này?',
     'revision_restore_confirm' => 'Bạn có chắc bạn muốn khôi phục phiên bản này? Nội dung trang hiện tại sẽ được thay thế.',
     'revision_delete_success' => 'Phiên bản đã được xóa',
-    'revision_cannot_delete_latest' => 'Không thể xóa phiên bản mới nhất.'
+    'revision_cannot_delete_latest' => 'Không thể xóa phiên bản mới nhất.',
 ];
diff --git a/resources/lang/vi/passwords.php b/resources/lang/vi/passwords.php
index 65b42b4d8..e31974161 100644
--- a/resources/lang/vi/passwords.php
+++ b/resources/lang/vi/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => 'Mật khẩu phải có tối thiểu 8 ký tự và và phải trùng với mật khẩu xác nhận.',
-    'user' => "Chúng tôi không tìm thấy người dùng với địa chỉ email đó.",
+    'user' => 'Chúng tôi không tìm thấy người dùng với địa chỉ email đó.',
     'token' => 'Mã token đặt lại mật khẩu cho địa chỉ email này không hợp lệ.',
     'sent' => 'Chúng tôi đã gửi email chứa liên kết đặt lại mật khẩu cho bạn!',
     'reset' => 'Mật khẩu của bạn đã được đặt lại!',
diff --git a/resources/lang/vi/settings.php b/resources/lang/vi/settings.php
index 25dd2da0e..d4d5322f1 100644
--- a/resources/lang/vi/settings.php
+++ b/resources/lang/vi/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => 'Bảo trì',
     'maint_image_cleanup' => 'Dọn dẹp ảnh',
-    'maint_image_cleanup_desc' => "Quét nội dung trang và phiên bản để kiểm tra xem các ảnh và hình vẽ nào đang được sử dụng và ảnh nào dư thừa. Đảm bảo rằng bạn đã tạo bản sao lưu toàn dữ liệu và ảnh trước khi chạy chức năng này.",
+    'maint_image_cleanup_desc' => 'Quét nội dung trang và phiên bản để kiểm tra xem các ảnh và hình vẽ nào đang được sử dụng và ảnh nào dư thừa. Đảm bảo rằng bạn đã tạo bản sao lưu toàn dữ liệu và ảnh trước khi chạy chức năng này.',
     'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
     'maint_image_cleanup_run' => 'Chạy Dọn dẹp',
     'maint_image_cleanup_warning' => 'Đã tìm thấy :count ảnh có thể không được sử dụng. Bạn muốn chắc rằng muốn xóa các ảnh này?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => 'Xóa quyền',
     'role_delete_confirm' => 'Chức năng này sẽ xóa quyền với tên \':roleName\'.',
     'role_delete_users_assigned' => 'Quyền này có :userCount người dùng được gán. Nếu bạn muốn di dời các người dùng từ quyền này hãy chọn một quyền mới bên dưới.',
-    'role_delete_no_migration' => "Không di dời các người dùng",
+    'role_delete_no_migration' => 'Không di dời các người dùng',
     'role_delete_sure' => 'Bạn có chắc rằng muốn xóa quyền này?',
     'role_delete_success' => 'Quyền đã được xóa thành công',
     'role_edit' => 'Sửa quyền',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/zh_CN/auth.php b/resources/lang/zh_CN/auth.php
index a31ee20e7..8411eb866 100644
--- a/resources/lang/zh_CN/auth.php
+++ b/resources/lang/zh_CN/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => '该Email域名无权访问此应用程序',
     'register_success' => '感谢您注册:appName,您现在已经登录。',
 
-
     // Password Reset
     'reset_password' => '重置密码',
     'reset_password_send_instructions' => '在下面输入您的Email地址,您将收到一封带有密码重置链接的邮件。',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => '您收到此电子邮件是因为我们收到了您的帐户的密码重置请求。',
     'email_reset_not_requested' => '如果您没有要求重置密码,则不需要采取进一步的操作。',
 
-
     // Email Confirmation
     'email_confirm_subject' => '确认您在:appName的Email地址',
     'email_confirm_greeting' => '感谢您加入:appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => '在这里输入备用认证码',
     'mfa_verify_totp_desc' => '在下面输入您的移动 App 生成的认证码:',
     'mfa_setup_login_notification' => '多重身份认证已设置,请使用新配置的方法重新登录。',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/zh_CN/common.php b/resources/lang/zh_CN/common.php
index 6c2fa668b..42d0eb87f 100644
--- a/resources/lang/zh_CN/common.php
+++ b/resources/lang/zh_CN/common.php
@@ -20,7 +20,7 @@ return [
     'role' => '角色',
     'cover_image' => '封面图片',
     'cover_image_description' => '该图像大小需要为440x250px。',
-    
+
     // Actions
     'actions' => '操作',
     'view' => '浏览',
diff --git a/resources/lang/zh_CN/entities.php b/resources/lang/zh_CN/entities.php
index f3414179b..4b2d17eca 100644
--- a/resources/lang/zh_CN/entities.php
+++ b/resources/lang/zh_CN/entities.php
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => '您确定要删除此修订版吗?',
     'revision_restore_confirm' => '您确定要恢复到此修订版吗?恢复后原有内容将会被替换。',
     'revision_delete_success' => '修订删除',
-    'revision_cannot_delete_latest' => '无法删除最新版本。'
+    'revision_cannot_delete_latest' => '无法删除最新版本。',
 ];
diff --git a/resources/lang/zh_CN/passwords.php b/resources/lang/zh_CN/passwords.php
index 8d8272ee0..712120f60 100644
--- a/resources/lang/zh_CN/passwords.php
+++ b/resources/lang/zh_CN/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => '密码必须至少包含六个字符并与确认相符。',
-    'user' => "使用该Email地址的用户不存在。",
+    'user' => '使用该Email地址的用户不存在。',
     'token' => '重置密码链接无法发送至此邮件地址。',
     'sent' => '我们已经通过Email发送您的密码重置链接!',
     'reset' => '您的密码已被重置!',
diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php
index 6fa0e84d4..3f4d7bead 100755
--- a/resources/lang/zh_CN/settings.php
+++ b/resources/lang/zh_CN/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => '维护',
     'maint_image_cleanup' => '清理图像',
-    'maint_image_cleanup_desc' => "扫描页面和修订内容以检查哪些图片是正在使用的以及哪些图片是多余的。确保在运行前完整备份数据库和图片。",
+    'maint_image_cleanup_desc' => '扫描页面和修订内容以检查哪些图片是正在使用的以及哪些图片是多余的。确保在运行前完整备份数据库和图片。',
     'maint_delete_images_only_in_revisions' => '同时删除只存在于旧的页面修订中的图片',
     'maint_image_cleanup_run' => '运行清理',
     'maint_image_cleanup_warning' => '发现了 :count 张可能未使用的图像。您确定要删除这些图像吗?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => '删除角色',
     'role_delete_confirm' => '这将会删除名为 \':roleName\' 的角色.',
     'role_delete_users_assigned' => '有:userCount位用户属于此角色。如果您想将此角色中的用户迁移,请在下面选择一个新角色。',
-    'role_delete_no_migration' => "不要迁移用户",
+    'role_delete_no_migration' => '不要迁移用户',
     'role_delete_sure' => '您确定要删除这个角色?',
     'role_delete_success' => '角色删除成功',
     'role_edit' => '编辑角色',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/resources/lang/zh_TW/auth.php b/resources/lang/zh_TW/auth.php
index 89fc6f55a..a12c12178 100644
--- a/resources/lang/zh_TW/auth.php
+++ b/resources/lang/zh_TW/auth.php
@@ -38,7 +38,6 @@ return [
     'registration_email_domain_invalid' => '這個電子郵件網域沒有權限使用',
     'register_success' => '感謝您註冊!您已註冊完成並可登入。',
 
-
     // Password Reset
     'reset_password' => '重設密碼',
     'reset_password_send_instructions' => '在下方輸入您的電子郵件,您將收到一封帶有密碼重設連結的郵件。',
@@ -49,7 +48,6 @@ return [
     'email_reset_text' => '您收到此電子郵件是因為我們收到了您的帳號的密碼重設請求。',
     'email_reset_not_requested' => '如果您沒有要求重設密碼,則不需要採取進一步的操作。',
 
-
     // Email Confirmation
     'email_confirm_subject' => '確認您在 :appName 的電子郵件',
     'email_confirm_greeting' => '感謝您加入 :appName!',
@@ -109,4 +107,4 @@ return [
     'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
-];
\ No newline at end of file
+];
diff --git a/resources/lang/zh_TW/common.php b/resources/lang/zh_TW/common.php
index b358111fd..8209bf4d0 100644
--- a/resources/lang/zh_TW/common.php
+++ b/resources/lang/zh_TW/common.php
@@ -20,7 +20,7 @@ return [
     'role' => '角色',
     'cover_image' => '封面圖片',
     'cover_image_description' => '此圖片大小應約為 440x250px。',
-    
+
     // Actions
     'actions' => '動作',
     'view' => '檢視',
diff --git a/resources/lang/zh_TW/entities.php b/resources/lang/zh_TW/entities.php
index e35a0795a..a19e53860 100644
--- a/resources/lang/zh_TW/entities.php
+++ b/resources/lang/zh_TW/entities.php
@@ -94,7 +94,7 @@ return [
     'shelves_edit' => '編輯書架',
     'shelves_delete' => '刪除書架',
     'shelves_delete_named' => '刪除書架 :name',
-    'shelves_delete_explain' => "這將刪除名為「:name」的書架。但其中的書本不會被刪除。",
+    'shelves_delete_explain' => '這將刪除名為「:name」的書架。但其中的書本不會被刪除。',
     'shelves_delete_confirmation' => '您確定要刪除此書架嗎?',
     'shelves_permissions' => '書架權限',
     'shelves_permissions_updated' => '書架權限已更新',
@@ -321,5 +321,5 @@ return [
     'revision_delete_confirm' => '您確定要刪除此修訂版本嗎?',
     'revision_restore_confirm' => '您確定要還原此修訂版本嗎? 目前頁面內容將被替換。',
     'revision_delete_success' => '修訂版本已刪除',
-    'revision_cannot_delete_latest' => '無法刪除最新修訂版本。'
+    'revision_cannot_delete_latest' => '無法刪除最新修訂版本。',
 ];
diff --git a/resources/lang/zh_TW/passwords.php b/resources/lang/zh_TW/passwords.php
index f4d8dc30c..614b9e2bf 100644
--- a/resources/lang/zh_TW/passwords.php
+++ b/resources/lang/zh_TW/passwords.php
@@ -7,7 +7,7 @@
 return [
 
     'password' => '密碼必須至少八個字元,並與確認密碼相符。',
-    'user' => "沒有使用這個電子郵件位址的使用者。",
+    'user' => '沒有使用這個電子郵件位址的使用者。',
     'token' => '這個電子郵件地址的密碼重設權杖無效。',
     'sent' => '我們已經透過電子郵件發送您的密碼重設連結。',
     'reset' => '您的密碼已被重設!',
diff --git a/resources/lang/zh_TW/settings.php b/resources/lang/zh_TW/settings.php
index 53871de45..9d0439a37 100644
--- a/resources/lang/zh_TW/settings.php
+++ b/resources/lang/zh_TW/settings.php
@@ -72,7 +72,7 @@ return [
     // Maintenance settings
     'maint' => '維護',
     'maint_image_cleanup' => '清理圖片',
-    'maint_image_cleanup_desc' => "掃描頁面與修訂版本內容來檢查目前使用了哪些圖片,而哪些圖片又是多餘的。請確保您在執行這個動作前建立了完整的資料庫與映像檔備份。",
+    'maint_image_cleanup_desc' => '掃描頁面與修訂版本內容來檢查目前使用了哪些圖片,而哪些圖片又是多餘的。請確保您在執行這個動作前建立了完整的資料庫與映像檔備份。',
     'maint_delete_images_only_in_revisions' => '也刪除僅存在於舊的頁面修訂版本中存在的圖片',
     'maint_image_cleanup_run' => '執行清理',
     'maint_image_cleanup_warning' => '發現了 :count 張可能未使用的圖片。您確定要刪除這些圖片嗎?',
@@ -132,7 +132,7 @@ return [
     'role_delete' => '刪除角色',
     'role_delete_confirm' => '這將會刪除名為「:roleName」的角色.',
     'role_delete_users_assigned' => '有 :userCount 位使用者屬於此角色。如果您想將此角色中的使用者遷移,請在下面選擇一個新角色。',
-    'role_delete_no_migration' => "不要遷移使用者",
+    'role_delete_no_migration' => '不要遷移使用者',
     'role_delete_sure' => '您確定要刪除此角色?',
     'role_delete_success' => '角色刪除成功',
     'role_edit' => '編輯角色',
@@ -273,6 +273,6 @@ return [
         'vi' => 'Tiếng Việt',
         'zh_CN' => '简体中文',
         'zh_TW' => '繁體中文',
-    ]
+    ],
     //!////////////////////////////////
 ];
diff --git a/tests/Api/AttachmentsApiTest.php b/tests/Api/AttachmentsApiTest.php
index 40624dcdf..ceab5d49a 100644
--- a/tests/Api/AttachmentsApiTest.php
+++ b/tests/Api/AttachmentsApiTest.php
@@ -325,6 +325,6 @@ class AttachmentsApiTest extends TestCase
      */
     protected function getTestFile(string $fileName): UploadedFile
     {
-        return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', 55, null, true);
+        return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', null, true);
     }
 }
diff --git a/tests/Auth/MfaConfigurationTest.php b/tests/Auth/MfaConfigurationTest.php
index 59a2a41b5..fab94817c 100644
--- a/tests/Auth/MfaConfigurationTest.php
+++ b/tests/Auth/MfaConfigurationTest.php
@@ -39,7 +39,7 @@ class MfaConfigurationTest extends TestCase
         $this->assertTrue($svg === $revisitSvg);
         $secret = decrypt(session()->get('mfa-setup-totp-secret'));
 
-        $resp->assertSee(htmlentities("?secret={$secret}&issuer=BookStack&algorithm=SHA1&digits=6&period=30"));
+        $resp->assertSee("?secret={$secret}&issuer=BookStack&algorithm=SHA1&digits=6&period=30");
 
         // Successful confirmation
         $google2fa = new Google2FA();
@@ -180,7 +180,7 @@ class MfaConfigurationTest extends TestCase
 
         $resp = $this->get('/mfa/totp/generate');
         $resp->assertSeeText('Mobile App Setup');
-        $resp->assertDontSee('otpauth://totp/BookStack:guest%40example.com');
-        $resp->assertSee('otpauth://totp/BookStack:admin%40admin.com');
+        $resp->assertDontSee('otpauth://totp/BookStack:guest%40example.com', false);
+        $resp->assertSee('otpauth://totp/BookStack:admin%40admin.com', false);
     }
 }
diff --git a/tests/Auth/Saml2Test.php b/tests/Auth/Saml2Test.php
index 7fb8d6ddb..c534b2d78 100644
--- a/tests/Auth/Saml2Test.php
+++ b/tests/Auth/Saml2Test.php
@@ -49,7 +49,7 @@ class Saml2Test extends TestCase
         $req = $this->get('/saml2/metadata');
         $req->assertSee('https://example.com/super-cats');
         $req->assertSee('md:ContactPerson');
-        $req->assertSee('<md:GivenName>Barry Scott</md:GivenName>');
+        $req->assertSee('<md:GivenName>Barry Scott</md:GivenName>', false);
     }
 
     public function test_login_option_shows_on_login_page()
diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php
index 1780ddee8..afd6a1a06 100644
--- a/tests/Entity/BookShelfTest.php
+++ b/tests/Entity/BookShelfTest.php
@@ -290,7 +290,7 @@ class BookShelfTest extends TestCase
         $shelf = Bookshelf::first();
         $resp = $this->asAdmin()->get($shelf->getUrl('/permissions'));
         $resp->assertSeeText('Copy Permissions');
-        $resp->assertSee("action=\"{$shelf->getUrl('/copy-permissions')}\"");
+        $resp->assertSee("action=\"{$shelf->getUrl('/copy-permissions')}\"", false);
 
         $child = $shelf->books()->first();
         $editorRole = $this->getEditor()->roles()->first();
diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php
index fa63c0bf9..53ee6faf9 100644
--- a/tests/Entity/BookTest.php
+++ b/tests/Entity/BookTest.php
@@ -187,7 +187,7 @@ class BookTest extends TestCase
             'name' => 'информация',
         ]);
 
-        $this->assertEquals('informatsiya', $book->slug);
+        $this->assertEquals('informaciya', $book->slug);
 
         $book = $this->newBook([
             'name' => '¿Qué?',
diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php
index 3bf51556e..b613f80a1 100644
--- a/tests/Entity/CommentTest.php
+++ b/tests/Entity/CommentTest.php
@@ -88,7 +88,7 @@ class CommentTest extends TestCase
         ]);
 
         $pageView = $this->get($page->getUrl());
-        $pageView->assertSee('<h1>My Title</h1>');
+        $pageView->assertSee('<h1>My Title</h1>', false);
     }
 
     public function test_html_cannot_be_injected_via_comment_content()
@@ -102,7 +102,7 @@ class CommentTest extends TestCase
         ]);
 
         $pageView = $this->get($page->getUrl());
-        $pageView->assertDontSee($script);
+        $pageView->assertDontSee($script, false);
         $pageView->assertSee('sometextinthecomment');
 
         $comment = $page->comments()->first();
@@ -111,7 +111,7 @@ class CommentTest extends TestCase
         ]);
 
         $pageView = $this->get($page->getUrl());
-        $pageView->assertDontSee($script);
+        $pageView->assertDontSee($script, false);
         $pageView->assertSee('sometextinthecommentupdated');
     }
 }
diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php
index c8397b695..9ea336db8 100644
--- a/tests/Entity/ExportTest.php
+++ b/tests/Entity/ExportTest.php
@@ -139,7 +139,7 @@ class ExportTest extends TestCase
         $this->setSettings(['app-custom-head' => $customHeadContent]);
 
         $resp = $this->asEditor()->get($page->getUrl('/export/html'));
-        $resp->assertSee($customHeadContent);
+        $resp->assertSee($customHeadContent, false);
     }
 
     public function test_page_html_export_does_not_break_with_only_comments_in_custom_head()
@@ -151,7 +151,7 @@ class ExportTest extends TestCase
 
         $resp = $this->asEditor()->get($page->getUrl('/export/html'));
         $resp->assertStatus(200);
-        $resp->assertSee($customHeadContent);
+        $resp->assertSee($customHeadContent, false);
     }
 
     public function test_page_html_export_use_absolute_dates()
@@ -188,7 +188,7 @@ class ExportTest extends TestCase
         Storage::disk('local')->delete('uploads/images/gallery/svg_test.svg');
 
         $resp->assertStatus(200);
-        $resp->assertSee('<img src="data:image/svg+xml;base64');
+        $resp->assertSee('<img src="data:image/svg+xml;base64', false);
     }
 
     public function test_page_image_containment_works_on_multiple_images_within_a_single_line()
@@ -224,9 +224,9 @@ class ExportTest extends TestCase
         $storageDisk->delete('uploads/images/gallery/svg_test.svg');
         $storageDisk->delete('uploads/svg_test.svg');
 
-        $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg');
+        $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg', false);
         $resp->assertSee('http://localhost/uploads/svg_test.svg');
-        $resp->assertSee('src="/uploads/svg_test.svg"');
+        $resp->assertSee('src="/uploads/svg_test.svg"', false);
     }
 
     public function test_page_export_contained_html_does_not_allow_upward_traversal_with_local()
@@ -333,7 +333,7 @@ class ExportTest extends TestCase
         $page->save();
 
         $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
-        $resp->assertSee("# Dogcat\n\n<p class=\"callout info\">Some callout text</p>\n\nAnother line");
+        $resp->assertSee("# Dogcat\n\n<p class=\"callout info\">Some callout text</p>\n\nAnother line", false);
     }
 
     public function test_page_markdown_export_handles_bookstacks_wysiwyg_codeblock_format()
@@ -345,7 +345,7 @@ class ExportTest extends TestCase
         $page->save();
 
         $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
-        $resp->assertSee("# Dogcat\n\n```JavaScript\nvar a = 'cat';\n```\n\nAnother line");
+        $resp->assertSee("# Dogcat\n\n```JavaScript\nvar a = 'cat';\n```\n\nAnother line", false);
     }
 
     public function test_chapter_markdown_export()
diff --git a/tests/Entity/PageContentTest.php b/tests/Entity/PageContentTest.php
index ca2a24131..dd996b926 100644
--- a/tests/Entity/PageContentTest.php
+++ b/tests/Entity/PageContentTest.php
@@ -74,7 +74,7 @@ class PageContentTest extends TestCase
 
         $this->asEditor();
         $pageResp = $this->get($page->getUrl());
-        $pageResp->assertSee($content);
+        $pageResp->assertSee($content, false);
     }
 
     public function test_page_includes_rendered_on_book_export()
@@ -106,7 +106,7 @@ class PageContentTest extends TestCase
 
         $pageView = $this->get($page->getUrl());
         $pageView->assertStatus(200);
-        $pageView->assertDontSee($script);
+        $pageView->assertDontSee($script, false);
         $pageView->assertSee('abc123abc123');
     }
 
@@ -260,8 +260,8 @@ class PageContentTest extends TestCase
 
         $pageView = $this->get($page->getUrl());
         $pageView->assertStatus(200);
-        $pageView->assertDontSee($script);
-        $pageView->assertSee('<p>Hello</p>');
+        $pageView->assertDontSee($script, false);
+        $pageView->assertSee('<p>Hello</p>', false);
     }
 
     public function test_more_complex_inline_on_attributes_escaping_scenarios()
@@ -301,7 +301,7 @@ class PageContentTest extends TestCase
         $page->save();
 
         $pageView = $this->get($page->getUrl());
-        $pageView->assertSee($script);
+        $pageView->assertSee($script, false);
         $pageView->assertDontSee('abc123abc123');
     }
 
@@ -338,8 +338,8 @@ class PageContentTest extends TestCase
         $page->save();
 
         $pageView = $this->get($page->getUrl());
-        $pageView->assertSee($script);
-        $pageView->assertDontSee('<p>Hello</p>');
+        $pageView->assertSee($script, false);
+        $pageView->assertDontSee('<p>Hello</p>', false);
     }
 
     public function test_duplicate_ids_does_not_break_page_render()
@@ -545,7 +545,7 @@ class PageContentTest extends TestCase
 
         $pageView = $this->get($page->getUrl());
         $pageView->assertStatus(200);
-        $pageView->assertSee($content);
+        $pageView->assertSee($content, false);
     }
 
     public function test_base64_images_get_extracted_from_page_content()
diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php
index 5248ae152..3178bd8ce 100644
--- a/tests/Permissions/RolesTest.php
+++ b/tests/Permissions/RolesTest.php
@@ -173,11 +173,11 @@ class RolesTest extends TestCase
     public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision()
     {
         $usersLink = 'href="' . url('/settings/users') . '"';
-        $this->actingAs($this->user)->get('/')->assertDontSee($usersLink);
+        $this->actingAs($this->user)->get('/')->assertDontSee($usersLink, false);
         $this->giveUserPermissions($this->user, ['users-manage']);
-        $this->actingAs($this->user)->get('/')->assertSee($usersLink);
+        $this->actingAs($this->user)->get('/')->assertSee($usersLink, false);
         $this->giveUserPermissions($this->user, ['settings-manage', 'users-manage']);
-        $this->actingAs($this->user)->get('/')->assertDontSee($usersLink);
+        $this->actingAs($this->user)->get('/')->assertDontSee($usersLink, false);
     }
 
     public function test_user_cannot_change_email_unless_they_have_manage_users_permission()
diff --git a/tests/SecurityHeaderTest.php b/tests/SecurityHeaderTest.php
index 10551fc55..78691badb 100644
--- a/tests/SecurityHeaderTest.php
+++ b/tests/SecurityHeaderTest.php
@@ -76,7 +76,7 @@ class SecurityHeaderTest extends TestCase
 
         $nonce = app()->make(CspService::class)->getNonce();
         $this->assertStringContainsString('nonce-' . $nonce, $scriptHeader);
-        $resp->assertSee('<script nonce="' . $nonce . '">console.log("cat");</script>');
+        $resp->assertSee('<script nonce="' . $nonce . '">console.log("cat");</script>', false);
     }
 
     public function test_script_csp_nonce_changes_per_request()
diff --git a/tests/Settings/CustomHeadContentTest.php b/tests/Settings/CustomHeadContentTest.php
index 94ef4711d..36c8a4c0f 100644
--- a/tests/Settings/CustomHeadContentTest.php
+++ b/tests/Settings/CustomHeadContentTest.php
@@ -11,21 +11,21 @@ class CustomHeadContentTest extends TestCase
     {
         $this->setSettings(['app-custom-head' => '<script>console.log("cat");</script>']);
         $resp = $this->get('/login');
-        $resp->assertSee('console.log("cat")');
+        $resp->assertSee('console.log("cat")', false);
     }
 
     public function test_configured_content_does_not_show_on_settings_page()
     {
         $this->setSettings(['app-custom-head' => '<script>console.log("cat");</script>']);
         $resp = $this->asAdmin()->get('/settings');
-        $resp->assertDontSee('console.log("cat")');
+        $resp->assertDontSee('console.log("cat")', false);
     }
 
     public function test_divs_in_js_preserved_in_configured_content()
     {
         $this->setSettings(['app-custom-head' => '<script><div id="hello">cat</div></script>']);
         $resp = $this->get('/login');
-        $resp->assertSee('<div id="hello">cat</div>');
+        $resp->assertSee('<div id="hello">cat</div>', false);
     }
 
     public function test_nonce_application_handles_edge_cases()
@@ -61,6 +61,6 @@ const b = `<script`;
 
         $this->setSettings(['app-custom-head' => $content]);
         $resp = $this->get('/login');
-        $resp->assertSee($expectedOutput);
+        $resp->assertSee($expectedOutput, false);
     }
 }
diff --git a/tests/Settings/FooterLinksTest.php b/tests/Settings/FooterLinksTest.php
index 55c3e107d..f1b5d4294 100644
--- a/tests/Settings/FooterLinksTest.php
+++ b/tests/Settings/FooterLinksTest.php
@@ -31,10 +31,10 @@ class FooterLinksTest extends TestCase
         ]]);
 
         $resp = $this->asAdmin()->get('/settings');
-        $resp->assertSee('value="My custom link"');
-        $resp->assertSee('value="Another Link"');
-        $resp->assertSee('value="https://example.com/link-a"');
-        $resp->assertSee('value="https://example.com/link-b"');
+        $resp->assertSee('value="My custom link"', false);
+        $resp->assertSee('value="Another Link"', false);
+        $resp->assertSee('value="https://example.com/link-a"', false);
+        $resp->assertSee('value="https://example.com/link-b"', false);
     }
 
     public function test_footer_links_show_on_pages()
diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php
index 04952d223..d96fcb710 100644
--- a/tests/SharedTestHelpers.php
+++ b/tests/SharedTestHelpers.php
@@ -22,10 +22,10 @@ use GuzzleHttp\Client;
 use GuzzleHttp\Handler\MockHandler;
 use GuzzleHttp\HandlerStack;
 use GuzzleHttp\Middleware;
-use Illuminate\Foundation\Testing\Assert as PHPUnit;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Support\Env;
 use Illuminate\Support\Facades\Log;
+use Illuminate\Testing\Assert as PHPUnit;
 use Mockery;
 use Monolog\Handler\TestHandler;
 use Monolog\Logger;
@@ -127,7 +127,7 @@ trait SharedTestHelpers
     /**
      * Create and return a new test chapter.
      */
-    public function newChapter(array $input = ['name' => 'test chapter', 'description' => 'My new test chapter'], Book $book): Chapter
+    public function newChapter(array $input, Book $book): Chapter
     {
         return app(ChapterRepo::class)->create($input, $book);
     }
diff --git a/tests/TestResponse.php b/tests/TestResponse.php
index 79f173c9b..5e2be3ac3 100644
--- a/tests/TestResponse.php
+++ b/tests/TestResponse.php
@@ -2,7 +2,7 @@
 
 namespace Tests;
 
-use Illuminate\Foundation\Testing\TestResponse as BaseTestResponse;
+use Illuminate\Testing\TestResponse as BaseTestResponse;
 use PHPUnit\Framework\Assert as PHPUnit;
 use Symfony\Component\DomCrawler\Crawler;
 
diff --git a/tests/Uploads/AttachmentTest.php b/tests/Uploads/AttachmentTest.php
index 60fd370b6..588b7054a 100644
--- a/tests/Uploads/AttachmentTest.php
+++ b/tests/Uploads/AttachmentTest.php
@@ -17,13 +17,13 @@ class AttachmentTest extends TestCase
      */
     protected function getTestFile(string $fileName): UploadedFile
     {
-        return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', 55, null, true);
+        return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', null, true);
     }
 
     /**
      * Uploads a file with the given name.
      */
-    protected function uploadFile(string $name, int $uploadedTo = 0): \Illuminate\Foundation\Testing\TestResponse
+    protected function uploadFile(string $name, int $uploadedTo = 0): \Illuminate\Testing\TestResponse
     {
         $file = $this->getTestFile($name);
 
diff --git a/tests/Uploads/DrawioTest.php b/tests/Uploads/DrawioTest.php
index 422de472a..1fc3d1049 100644
--- a/tests/Uploads/DrawioTest.php
+++ b/tests/Uploads/DrawioTest.php
@@ -61,7 +61,7 @@ class DrawioTest extends TestCase
         $editor = $this->getEditor();
 
         $resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
-        $resp->assertSee('drawio-url="http://cats.com?dog=tree"');
+        $resp->assertSee('drawio-url="http://cats.com?dog=tree"', false);
     }
 
     public function test_drawio_url_can_be_disabled()
@@ -71,10 +71,10 @@ class DrawioTest extends TestCase
         $editor = $this->getEditor();
 
         $resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
-        $resp->assertSee('drawio-url="https://embed.diagrams.net/?embed=1&amp;proto=json&amp;spin=1"');
+        $resp->assertSee('drawio-url="https://embed.diagrams.net/?embed=1&amp;proto=json&amp;spin=1"', false);
 
         config()->set('services.drawio', false);
         $resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
-        $resp->assertDontSee('drawio-url');
+        $resp->assertDontSee('drawio-url', false);
     }
 }

From f139cded789908efce3ac2ed1be26b947df647db Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Sat, 30 Oct 2021 21:29:59 +0100
Subject: [PATCH 2/6] Laravel 8 shift squash & merge (#3029)

* Temporarily moved back config path
* Apply Laravel coding style
* Shift exception handler
* Shift HTTP kernel and middleware
* Shift service providers
* Convert options array to fluent methods
* Shift to class based routes
* Shift console routes
* Ignore temporary framework files
* Shift to class based factories
* Namespace seeders
* Shift PSR-4 autoloading
* Shift config files
* Default config files
* Shift Laravel dependencies
* Shift return type of base TestCase methods
* Shift cleanup
* Applied stylci style changes
* Reverted config files location
* Applied manual changes to Laravel 8 shift

Co-authored-by: Shift <shift@laravelshift.com>
---
 app/Actions/Comment.php                       |   2 +
 app/Actions/Tag.php                           |   3 +
 app/Auth/Role.php                             |   3 +
 app/Auth/User.php                             |   2 +
 app/Config/app.php                            |  11 +-
 app/Config/auth.php                           |  15 +-
 app/Config/broadcasting.php                   |  84 ++-
 app/Config/cache.php                          | 105 ++-
 app/Config/filesystems.php                    |  13 +-
 app/Config/logging.php                        |  13 +-
 app/Config/queue.php                          |  24 +-
 app/Entities/Models/Book.php                  |   3 +
 app/Entities/Models/Bookshelf.php             |   3 +
 app/Entities/Models/Chapter.php               |   3 +
 app/Entities/Models/Page.php                  |   3 +
 app/Exceptions/Handler.php                    |   1 +
 app/Http/Kernel.php                           |   2 +-
 ...p => PreventRequestsDuringMaintenance.php} |   4 +-
 .../Middleware/RedirectIfAuthenticated.php    |  42 +-
 app/Http/Middleware/TrustHosts.php            |   2 +-
 app/Http/Middleware/TrustProxies.php          |   4 +-
 app/Providers/AppServiceProvider.php          |   4 +
 app/Providers/EventServiceProvider.php        |   1 -
 app/Providers/RouteServiceProvider.php        |  41 +-
 app/Uploads/Image.php                         |   2 +
 composer.json                                 |  33 +-
 composer.lock                                 | 629 ++++++++++--------
 database/factories/Actions/CommentFactory.php |  32 +
 database/factories/Actions/TagFactory.php     |  28 +
 database/factories/Auth/RoleFactory.php       |  28 +
 database/factories/Auth/UserFactory.php       |  35 +
 .../factories/Entities/Models/BookFactory.php |  30 +
 .../Entities/Models/BookshelfFactory.php      |  30 +
 .../Entities/Models/ChapterFactory.php        |  30 +
 .../factories/Entities/Models/PageFactory.php |  34 +
 database/factories/ModelFactory.php           |  96 ---
 database/factories/Uploads/ImageFactory.php   |  31 +
 database/{seeds => seeders}/.gitkeep          |   0
 .../{seeds => seeders}/DatabaseSeeder.php     |   2 +
 .../{seeds => seeders}/DummyContentSeeder.php |  23 +-
 .../{seeds => seeders}/LargeContentSeeder.php |  10 +-
 public/index.php                              |  63 +-
 routes/api.php                                |  87 +--
 routes/console.php                            |  19 +
 routes/web.php                                | 435 ++++++------
 storage/framework/.gitignore                  |  12 +-
 tests/AuditLogTest.php                        |   2 +-
 tests/Auth/AuthTest.php                       |   8 +-
 tests/Auth/LdapTest.php                       |  28 +-
 tests/Auth/OidcTest.php                       |   4 +-
 tests/Auth/Saml2Test.php                      |   8 +-
 tests/Auth/SocialAuthTest.php                 |   8 +-
 tests/Entity/BookShelfTest.php                |   2 +-
 tests/Entity/BookTest.php                     |   4 +-
 tests/Entity/ChapterTest.php                  |   2 +-
 tests/Entity/CommentSettingTest.php           |   2 +-
 tests/Entity/CommentTest.php                  |   6 +-
 tests/Entity/PageDraftTest.php                |   2 +-
 tests/Entity/PageEditorTest.php               |   2 +-
 tests/Entity/PageTest.php                     |   2 +-
 tests/Entity/SortTest.php                     |   2 +-
 tests/Entity/TagTest.php                      |  58 +-
 tests/HomepageTest.php                        |   2 +-
 tests/LanguageTest.php                        |   2 +-
 tests/Permissions/EntityPermissionsTest.php   |   2 +-
 tests/Permissions/RolesTest.php               |  14 +-
 tests/SharedTestHelpers.php                   |   8 +-
 tests/ThemeTest.php                           |   2 +-
 tests/Uploads/AvatarTest.php                  |   8 +-
 tests/User/UserManagementTest.php             |   2 +-
 tests/User/UserProfileTest.php                |   8 +-
 71 files changed, 1349 insertions(+), 916 deletions(-)
 mode change 100755 => 100644 app/Config/app.php
 rename app/Http/Middleware/{CheckForMaintenanceMode.php => PreventRequestsDuringMaintenance.php} (58%)
 create mode 100644 database/factories/Actions/CommentFactory.php
 create mode 100644 database/factories/Actions/TagFactory.php
 create mode 100644 database/factories/Auth/RoleFactory.php
 create mode 100644 database/factories/Auth/UserFactory.php
 create mode 100644 database/factories/Entities/Models/BookFactory.php
 create mode 100644 database/factories/Entities/Models/BookshelfFactory.php
 create mode 100644 database/factories/Entities/Models/ChapterFactory.php
 create mode 100644 database/factories/Entities/Models/PageFactory.php
 delete mode 100644 database/factories/ModelFactory.php
 create mode 100644 database/factories/Uploads/ImageFactory.php
 rename database/{seeds => seeders}/.gitkeep (100%)
 rename database/{seeds => seeders}/DatabaseSeeder.php (92%)
 rename database/{seeds => seeders}/DummyContentSeeder.php (71%)
 rename database/{seeds => seeders}/LargeContentSeeder.php (60%)
 create mode 100644 routes/console.php

diff --git a/app/Actions/Comment.php b/app/Actions/Comment.php
index 34fd84709..885ba6ed1 100644
--- a/app/Actions/Comment.php
+++ b/app/Actions/Comment.php
@@ -4,6 +4,7 @@ namespace BookStack\Actions;
 
 use BookStack\Model;
 use BookStack\Traits\HasCreatorAndUpdater;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\MorphTo;
 
 /**
@@ -15,6 +16,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
  */
 class Comment extends Model
 {
+    use HasFactory;
     use HasCreatorAndUpdater;
 
     protected $fillable = ['text', 'parent_id'];
diff --git a/app/Actions/Tag.php b/app/Actions/Tag.php
index ce0954f00..db9328b7d 100644
--- a/app/Actions/Tag.php
+++ b/app/Actions/Tag.php
@@ -3,10 +3,13 @@
 namespace BookStack\Actions;
 
 use BookStack\Model;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\MorphTo;
 
 class Tag extends Model
 {
+    use HasFactory;
+
     protected $fillable = ['name', 'value', 'order'];
     protected $hidden = ['id', 'entity_id', 'entity_type', 'created_at', 'updated_at'];
 
diff --git a/app/Auth/Role.php b/app/Auth/Role.php
index fc2e39aa9..71da88e19 100644
--- a/app/Auth/Role.php
+++ b/app/Auth/Role.php
@@ -7,6 +7,7 @@ use BookStack\Auth\Permissions\RolePermission;
 use BookStack\Interfaces\Loggable;
 use BookStack\Model;
 use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 
@@ -23,6 +24,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
  */
 class Role extends Model implements Loggable
 {
+    use HasFactory;
+
     protected $fillable = ['display_name', 'description', 'external_auth_id'];
 
     /**
diff --git a/app/Auth/User.php b/app/Auth/User.php
index aa8b44e9f..68e2ad625 100644
--- a/app/Auth/User.php
+++ b/app/Auth/User.php
@@ -18,6 +18,7 @@ use Illuminate\Auth\Passwords\CanResetPassword;
 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -43,6 +44,7 @@ use Illuminate\Support\Collection;
  */
 class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable, Sluggable
 {
+    use HasFactory;
     use Authenticatable;
     use CanResetPassword;
     use Notifiable;
diff --git a/app/Config/app.php b/app/Config/app.php
old mode 100755
new mode 100644
index f90a7dd76..44e382cdc
--- a/app/Config/app.php
+++ b/app/Config/app.php
@@ -143,7 +143,6 @@ return [
 
     // Class aliases, Registered on application start
     'aliases' => [
-
         // Laravel
         'App'          => Illuminate\Support\Facades\App::class,
         'Arr'          => Illuminate\Support\Arr::class,
@@ -155,21 +154,23 @@ return [
         'Config'       => Illuminate\Support\Facades\Config::class,
         'Cookie'       => Illuminate\Support\Facades\Cookie::class,
         'Crypt'        => Illuminate\Support\Facades\Crypt::class,
+        'Date'         => Illuminate\Support\Facades\Date::class,
         'DB'           => Illuminate\Support\Facades\DB::class,
         'Eloquent'     => Illuminate\Database\Eloquent\Model::class,
         'Event'        => Illuminate\Support\Facades\Event::class,
         'File'         => Illuminate\Support\Facades\File::class,
+        'Gate'         => Illuminate\Support\Facades\Gate::class,
         'Hash'         => Illuminate\Support\Facades\Hash::class,
-        'Input'        => Illuminate\Support\Facades\Input::class,
-        'Inspiring'    => Illuminate\Foundation\Inspiring::class,
+        'Http'         => Illuminate\Support\Facades\Http::class,
         'Lang'         => Illuminate\Support\Facades\Lang::class,
         'Log'          => Illuminate\Support\Facades\Log::class,
         'Mail'         => Illuminate\Support\Facades\Mail::class,
         'Notification' => Illuminate\Support\Facades\Notification::class,
         'Password'     => Illuminate\Support\Facades\Password::class,
         'Queue'        => Illuminate\Support\Facades\Queue::class,
+        'RateLimiter'  => Illuminate\Support\Facades\RateLimiter::class,
         'Redirect'     => Illuminate\Support\Facades\Redirect::class,
-        'Redis'        => Illuminate\Support\Facades\Redis::class,
+        // 'Redis'        => Illuminate\Support\Facades\Redis::class,
         'Request'      => Illuminate\Support\Facades\Request::class,
         'Response'     => Illuminate\Support\Facades\Response::class,
         'Route'        => Illuminate\Support\Facades\Route::class,
@@ -180,6 +181,8 @@ return [
         'URL'          => Illuminate\Support\Facades\URL::class,
         'Validator'    => Illuminate\Support\Facades\Validator::class,
         'View'         => Illuminate\Support\Facades\View::class,
+
+        // Laravel Packages
         'Socialite'    => Laravel\Socialite\Facades\Socialite::class,
 
         // Third Party
diff --git a/app/Config/auth.php b/app/Config/auth.php
index 88c22e70a..1e1a9d350 100644
--- a/app/Config/auth.php
+++ b/app/Config/auth.php
@@ -10,7 +10,6 @@
 
 return [
 
-    // Method of authentication to use
     // Options: standard, ldap, saml2, oidc
     'method' => env('AUTH_METHOD', 'standard'),
 
@@ -45,7 +44,7 @@ return [
             'provider' => 'external',
         ],
         'api' => [
-            'driver' => 'api-token',
+            'driver'   => 'api-token',
         ],
     ],
 
@@ -58,10 +57,16 @@ return [
             'driver' => 'eloquent',
             'model'  => \BookStack\Auth\User::class,
         ],
+
         'external' => [
             'driver' => 'external-users',
             'model'  => \BookStack\Auth\User::class,
         ],
+
+        // 'users' => [
+        //     'driver' => 'database',
+        //     'table' => 'users',
+        // ],
     ],
 
     // Resetting Passwords
@@ -78,4 +83,10 @@ return [
         ],
     ],
 
+    // Password Confirmation Timeout
+    // Here you may define the amount of seconds before a password confirmation
+    // times out and the user is prompted to re-enter their password via the
+    // confirmation screen. By default, the timeout lasts for three hours.
+    'password_timeout' => 10800,
+
 ];
diff --git a/app/Config/broadcasting.php b/app/Config/broadcasting.php
index 5e929d373..be0d7376c 100644
--- a/app/Config/broadcasting.php
+++ b/app/Config/broadcasting.php
@@ -1,51 +1,79 @@
 <?php
 
 /**
- * Broadcasting configuration options.
+ * Caching configuration options.
  *
  * Changes to these config files are not supported by BookStack and may break upon updates.
  * Configuration should be altered via the `.env` file or environment variables.
  * Do not edit this file unless you're happy to maintain any changes yourself.
  */
 
+// MEMCACHED - Split out configuration into an array
+if (env('CACHE_DRIVER') === 'memcached') {
+    $memcachedServerKeys = ['host', 'port', 'weight'];
+    $memcachedServers = explode(',', trim(env('MEMCACHED_SERVERS', '127.0.0.1:11211:100'), ','));
+    foreach ($memcachedServers as $index => $memcachedServer) {
+        $memcachedServerDetails = explode(':', $memcachedServer);
+        if (count($memcachedServerDetails) < 2) {
+            $memcachedServerDetails[] = '11211';
+        }
+        if (count($memcachedServerDetails) < 3) {
+            $memcachedServerDetails[] = '100';
+        }
+        $memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails);
+    }
+}
+
 return [
 
-    // Default Broadcaster
-    // This option controls the default broadcaster that will be used by the
-    // framework when an event needs to be broadcast. This can be set to
-    // any of the connections defined in the "connections" array below.
-    'default' => env('BROADCAST_DRIVER', 'pusher'),
+    // Default cache store to use
+    // Can be overridden at cache call-time
+    'default' => env('CACHE_DRIVER', 'file'),
 
-    // Broadcast Connections
-    // Here you may define all of the broadcast connections that will be used
-    // to broadcast events to other systems or over websockets. Samples of
-    // each available type of connection are provided inside this array.
-    'connections' => [
+    // Available caches stores
+    'stores' => [
 
-        'pusher' => [
-            'driver'  => 'pusher',
-            'key'     => env('PUSHER_APP_KEY'),
-            'secret'  => env('PUSHER_APP_SECRET'),
-            'app_id'  => env('PUSHER_APP_ID'),
-            'options' => [
-                'cluster' => env('PUSHER_APP_CLUSTER'),
-                'useTLS'  => true,
-            ],
+        'apc' => [
+            'driver' => 'apc',
+        ],
+
+        'array' => [
+            'driver'    => 'array',
+            'serialize' => false,
+        ],
+
+        'database' => [
+            'driver'          => 'database',
+            'table'           => 'cache',
+            'connection'      => null,
+            'lock_connection' => null,
+        ],
+
+        'file' => [
+            'driver' => 'file',
+            'path'   => storage_path('framework/cache'),
+        ],
+
+        'memcached' => [
+            'driver'  => 'memcached',
+            'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [],
+            'options' => [],
         ],
 
         'redis' => [
-            'driver'     => 'redis',
-            'connection' => 'default',
+            'driver'          => 'redis',
+            'connection'      => 'default',
+            'lock_connection' => 'default',
         ],
 
-        'log' => [
-            'driver' => 'log',
-        ],
-
-        'null' => [
-            'driver' => 'null',
+        'octane' => [
+            'driver' => 'octane',
         ],
 
     ],
 
+    // Cache key prefix
+    // Used to prevent collisions in shared cache systems.
+    'prefix' => env('CACHE_PREFIX', 'bookstack_cache'),
+
 ];
diff --git a/app/Config/cache.php b/app/Config/cache.php
index f9b7ed1d2..6fd4807da 100644
--- a/app/Config/cache.php
+++ b/app/Config/cache.php
@@ -1,36 +1,36 @@
 <?php
 
-/**
- * Caching configuration options.
- *
- * Changes to these config files are not supported by BookStack and may break upon updates.
- * Configuration should be altered via the `.env` file or environment variables.
- * Do not edit this file unless you're happy to maintain any changes yourself.
- */
-
-// MEMCACHED - Split out configuration into an array
-if (env('CACHE_DRIVER') === 'memcached') {
-    $memcachedServerKeys = ['host', 'port', 'weight'];
-    $memcachedServers = explode(',', trim(env('MEMCACHED_SERVERS', '127.0.0.1:11211:100'), ','));
-    foreach ($memcachedServers as $index => $memcachedServer) {
-        $memcachedServerDetails = explode(':', $memcachedServer);
-        if (count($memcachedServerDetails) < 2) {
-            $memcachedServerDetails[] = '11211';
-        }
-        if (count($memcachedServerDetails) < 3) {
-            $memcachedServerDetails[] = '100';
-        }
-        $memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails);
-    }
-}
+use Illuminate\Support\Str;
 
 return [
 
-    // Default cache store to use
-    // Can be overridden at cache call-time
+    /*
+    |--------------------------------------------------------------------------
+    | Default Cache Store
+    |--------------------------------------------------------------------------
+    |
+    | This option controls the default cache connection that gets used while
+    | using this caching library. This connection is used when another is
+    | not explicitly specified when executing a given caching function.
+    |
+    */
+
     'default' => env('CACHE_DRIVER', 'file'),
 
-    // Available caches stores
+    /*
+    |--------------------------------------------------------------------------
+    | Cache Stores
+    |--------------------------------------------------------------------------
+    |
+    | Here you may define all of the cache "stores" for your application as
+    | well as their drivers. You may even define multiple stores for the
+    | same cache driver to group types of items stored in your caches.
+    |
+    | Supported drivers: "apc", "array", "database", "file",
+    |         "memcached", "redis", "dynamodb", "octane", "null"
+    |
+    */
+
     'stores' => [
 
         'apc' => [
@@ -38,13 +38,15 @@ return [
         ],
 
         'array' => [
-            'driver' => 'array',
+            'driver'    => 'array',
+            'serialize' => false,
         ],
 
         'database' => [
-            'driver'     => 'database',
-            'table'      => 'cache',
-            'connection' => null,
+            'driver'          => 'database',
+            'table'           => 'cache',
+            'connection'      => null,
+            'lock_connection' => null,
         ],
 
         'file' => [
@@ -53,19 +55,50 @@ return [
         ],
 
         'memcached' => [
-            'driver'  => 'memcached',
+            'driver'        => 'memcached',
+            'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
+            'sasl'          => [
+                env('MEMCACHED_USERNAME'),
+                env('MEMCACHED_PASSWORD'),
+            ],
+            'options' => [
+                // Memcached::OPT_CONNECT_TIMEOUT => 2000,
+            ],
             'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [],
         ],
 
         'redis' => [
-            'driver'     => 'redis',
-            'connection' => 'default',
+            'driver'          => 'redis',
+            'connection'      => 'default',
+            'lock_connection' => 'default',
+        ],
+
+        'dynamodb' => [
+            'driver'   => 'dynamodb',
+            'key'      => env('AWS_ACCESS_KEY_ID'),
+            'secret'   => env('AWS_SECRET_ACCESS_KEY'),
+            'region'   => env('AWS_DEFAULT_REGION', 'us-east-1'),
+            'table'    => env('DYNAMODB_CACHE_TABLE', 'cache'),
+            'endpoint' => env('DYNAMODB_ENDPOINT'),
+        ],
+
+        'octane' => [
+            'driver' => 'octane',
         ],
 
     ],
 
-    // Cache key prefix
-    // Used to prevent collisions in shared cache systems.
-    'prefix' => env('CACHE_PREFIX', 'bookstack_cache'),
+    /*
+    |--------------------------------------------------------------------------
+    | Cache Key Prefix
+    |--------------------------------------------------------------------------
+    |
+    | When utilizing a RAM based store such as APC or Memcached, there might
+    | be other applications utilizing the same cache. So, we'll specify a
+    | value to get prefixed to all our keys so we can avoid collisions.
+    |
+    */
+
+    'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache'),
 
 ];
diff --git a/app/Config/filesystems.php b/app/Config/filesystems.php
index a6b05c8c4..4d59ba919 100644
--- a/app/Config/filesystems.php
+++ b/app/Config/filesystems.php
@@ -25,9 +25,6 @@ return [
     // file storage service, such as s3, to store publicly accessible assets.
     'url' => env('STORAGE_URL', false),
 
-    // Default Cloud Filesystem Disk
-    'cloud' => 's3',
-
     // Available filesystem disks
     // Only local, local_secure & s3 are supported by BookStack
     'disks' => [
@@ -35,6 +32,7 @@ return [
         'local' => [
             'driver' => 'local',
             'root'   => public_path(),
+            'visibility' => 'public',
         ],
 
         'local_secure_attachments' => [
@@ -45,6 +43,7 @@ return [
         'local_secure_images' => [
             'driver' => 'local',
             'root'   => storage_path('uploads/images/'),
+            'visibility' => 'public',
         ],
 
         's3' => [
@@ -59,4 +58,12 @@ return [
 
     ],
 
+    // Symbolic Links
+    // Here you may configure the symbolic links that will be created when the
+    // `storage:link` Artisan command is executed. The array keys should be
+    // the locations of the links and the values should be their targets.
+    'links' => [
+        public_path('storage') => storage_path('app/public'),
+    ],
+
 ];
diff --git a/app/Config/logging.php b/app/Config/logging.php
index 220aa0607..2b80147c8 100644
--- a/app/Config/logging.php
+++ b/app/Config/logging.php
@@ -49,16 +49,9 @@ return [
             'days'   => 7,
         ],
 
-        'slack' => [
-            'driver'   => 'slack',
-            'url'      => env('LOG_SLACK_WEBHOOK_URL'),
-            'username' => 'Laravel Log',
-            'emoji'    => ':boom:',
-            'level'    => 'critical',
-        ],
-
         'stderr' => [
             'driver'  => 'monolog',
+            'level'   => 'debug',
             'handler' => StreamHandler::class,
             'with'    => [
                 'stream' => 'php://stderr',
@@ -99,6 +92,10 @@ return [
         'testing' => [
             'driver' => 'testing',
         ],
+
+        'emergency' => [
+            'path' => storage_path('logs/laravel.log'),
+        ],
     ],
 
     // Failed Login Message
diff --git a/app/Config/queue.php b/app/Config/queue.php
index 0c79fcdd2..0f5ee3ce5 100644
--- a/app/Config/queue.php
+++ b/app/Config/queue.php
@@ -22,25 +22,29 @@ return [
         ],
 
         'database' => [
-            'driver'      => 'database',
-            'table'       => 'jobs',
-            'queue'       => 'default',
-            'retry_after' => 90,
+            'driver'       => 'database',
+            'table'        => 'jobs',
+            'queue'        => 'default',
+            'retry_after'  => 90,
+            'after_commit' => false,
         ],
 
         'redis' => [
-            'driver'      => 'redis',
-            'connection'  => 'default',
-            'queue'       => env('REDIS_QUEUE', 'default'),
-            'retry_after' => 90,
-            'block_for'   => null,
+            'driver'       => 'redis',
+            'connection'   => 'default',
+            'queue'        => env('REDIS_QUEUE', 'default'),
+            'retry_after'  => 90,
+            'block_for'    => null,
+            'after_commit' => false,
         ],
 
     ],
 
     // Failed queue job logging
     'failed' => [
-        'database' => 'mysql', 'table' => 'failed_jobs',
+        'driver'   => 'database-uuids',
+        'database' => 'mysql',
+        'table'    => 'failed_jobs',
     ],
 
 ];
diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php
index 1e4591bd7..982df5c90 100644
--- a/app/Entities/Models/Book.php
+++ b/app/Entities/Models/Book.php
@@ -4,6 +4,7 @@ namespace BookStack\Entities\Models;
 
 use BookStack\Uploads\Image;
 use Exception;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -21,6 +22,8 @@ use Illuminate\Support\Collection;
  */
 class Book extends Entity implements HasCoverImage
 {
+    use HasFactory;
+
     public $searchFactor = 2;
 
     protected $fillable = ['name', 'description'];
diff --git a/app/Entities/Models/Bookshelf.php b/app/Entities/Models/Bookshelf.php
index f427baf49..8fe9dbe41 100644
--- a/app/Entities/Models/Bookshelf.php
+++ b/app/Entities/Models/Bookshelf.php
@@ -3,11 +3,14 @@
 namespace BookStack\Entities\Models;
 
 use BookStack\Uploads\Image;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 
 class Bookshelf extends Entity implements HasCoverImage
 {
+    use HasFactory;
+
     protected $table = 'bookshelves';
 
     public $searchFactor = 3;
diff --git a/app/Entities/Models/Chapter.php b/app/Entities/Models/Chapter.php
index f6f8427a3..abf496b44 100644
--- a/app/Entities/Models/Chapter.php
+++ b/app/Entities/Models/Chapter.php
@@ -2,6 +2,7 @@
 
 namespace BookStack\Entities\Models;
 
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Support\Collection;
 
 /**
@@ -12,6 +13,8 @@ use Illuminate\Support\Collection;
  */
 class Chapter extends BookChild
 {
+    use HasFactory;
+
     public $searchFactor = 1.3;
 
     protected $fillable = ['name', 'description', 'priority', 'book_id'];
diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php
index 452965667..fbe0db41b 100644
--- a/app/Entities/Models/Page.php
+++ b/app/Entities/Models/Page.php
@@ -6,6 +6,7 @@ use BookStack\Entities\Tools\PageContent;
 use BookStack\Uploads\Attachment;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Permissions;
@@ -25,6 +26,8 @@ use Permissions;
  */
 class Page extends BookChild
 {
+    use HasFactory;
+
     public static $listAttributes = ['name', 'id', 'slug', 'book_id', 'chapter_id', 'draft', 'template', 'text', 'created_at', 'updated_at', 'priority'];
     public static $contentAttributes = ['name', 'id', 'slug', 'book_id', 'chapter_id', 'draft', 'template', 'html', 'text', 'created_at', 'updated_at', 'priority'];
 
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 63b5cfc5a..3b4ad4a4d 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -28,6 +28,7 @@ class Handler extends ExceptionHandler
      * @var array
      */
     protected $dontFlash = [
+        'current_password',
         'password',
         'password_confirmation',
     ];
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 7a09493af..91dbdd963 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -11,7 +11,7 @@ class Kernel extends HttpKernel
      * These middleware are run during every request to your application.
      */
     protected $middleware = [
-        \BookStack\Http\Middleware\CheckForMaintenanceMode::class,
+        \BookStack\Http\Middleware\PreventRequestsDuringMaintenance::class,
         \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
         \BookStack\Http\Middleware\TrimStrings::class,
         \BookStack\Http\Middleware\TrustProxies::class,
diff --git a/app/Http/Middleware/CheckForMaintenanceMode.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php
similarity index 58%
rename from app/Http/Middleware/CheckForMaintenanceMode.php
rename to app/Http/Middleware/PreventRequestsDuringMaintenance.php
index 0c7683836..dfb9592e1 100644
--- a/app/Http/Middleware/CheckForMaintenanceMode.php
+++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php
@@ -2,9 +2,9 @@
 
 namespace BookStack\Http\Middleware;
 
-use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
+use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
 
-class CheckForMaintenanceMode extends Middleware
+class PreventRequestsDuringMaintenance extends Middleware
 {
     /**
      * The URIs that should be reachable while maintenance mode is enabled.
diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php
index 6853809ea..76e64a3b9 100644
--- a/app/Http/Middleware/RedirectIfAuthenticated.php
+++ b/app/Http/Middleware/RedirectIfAuthenticated.php
@@ -2,45 +2,31 @@
 
 namespace BookStack\Http\Middleware;
 
+use BookStack\Providers\RouteServiceProvider;
 use Closure;
-use Illuminate\Contracts\Auth\Guard;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
 
 class RedirectIfAuthenticated
 {
-    /**
-     * The Guard implementation.
-     *
-     * @var Guard
-     */
-    protected $auth;
-
-    /**
-     * Create a new filter instance.
-     *
-     * @param Guard $auth
-     *
-     * @return void
-     */
-    public function __construct(Guard $auth)
-    {
-        $this->auth = $auth;
-    }
-
     /**
      * Handle an incoming request.
      *
-     * @param \Illuminate\Http\Request $request
-     * @param \Closure                 $next
-     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @param  string|null  ...$guards
      * @return mixed
      */
-    public function handle($request, Closure $next)
+    public function handle(Request $request, Closure $next, ...$guards)
     {
-        $requireConfirmation = setting('registration-confirmation');
-        if ($this->auth->check() && (!$requireConfirmation || ($requireConfirmation && $this->auth->user()->email_confirmed))) {
-            return redirect('/');
+        $guards = empty($guards) ? [null] : $guards;
+
+        foreach ($guards as $guard) {
+            if (Auth::guard($guard)->check()) {
+                return redirect(RouteServiceProvider::HOME);
+            }
         }
 
         return $next($request);
     }
-}
+}
\ No newline at end of file
diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php
index b0550cfc7..7bd89ee51 100644
--- a/app/Http/Middleware/TrustHosts.php
+++ b/app/Http/Middleware/TrustHosts.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace App\Http\Middleware;
+namespace BookStack\Http\Middleware;
 
 use Illuminate\Http\Middleware\TrustHosts as Middleware;
 
diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php
index 3f8b32eb2..0fe0247b8 100644
--- a/app/Http/Middleware/TrustProxies.php
+++ b/app/Http/Middleware/TrustProxies.php
@@ -3,7 +3,7 @@
 namespace BookStack\Http\Middleware;
 
 use Closure;
-use Fideloper\Proxy\TrustProxies as Middleware;
+use Illuminate\Http\Middleware\TrustProxies as Middleware;
 use Illuminate\Http\Request;
 
 class TrustProxies extends Middleware
@@ -20,7 +20,7 @@ class TrustProxies extends Middleware
      *
      * @var int
      */
-    protected $headers = Request::HEADER_X_FORWARDED_ALL;
+    protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;
 
     /**
      * Handle the request, Set the correct user-configured proxy information.
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 34a3a290f..fc712632e 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -16,6 +16,7 @@ use BookStack\Util\CspService;
 use GuzzleHttp\Client;
 use Illuminate\Contracts\Cache\Repository;
 use Illuminate\Database\Eloquent\Relations\Relation;
+use Illuminate\Pagination\Paginator;
 use Illuminate\Support\Facades\Blade;
 use Illuminate\Support\Facades\Schema;
 use Illuminate\Support\Facades\URL;
@@ -60,6 +61,9 @@ class AppServiceProvider extends ServiceProvider
 
         // View Composers
         View::composer('entities.breadcrumbs', BreadcrumbsViewComposer::class);
+
+        // Set paginator to use bootstrap-style pagination
+        Paginator::useBootstrap();
     }
 
     /**
diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php
index a826185d8..659843ce3 100644
--- a/app/Providers/EventServiceProvider.php
+++ b/app/Providers/EventServiceProvider.php
@@ -30,6 +30,5 @@ class EventServiceProvider extends ServiceProvider
      */
     public function boot()
     {
-        parent::boot();
     }
 }
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
index b60443a45..ac3307f2d 100644
--- a/app/Providers/RouteServiceProvider.php
+++ b/app/Providers/RouteServiceProvider.php
@@ -2,11 +2,23 @@
 
 namespace BookStack\Providers;
 
+use Illuminate\Cache\RateLimiting\Limit;
 use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\RateLimiter;
 use Illuminate\Support\Facades\Route;
 
 class RouteServiceProvider extends ServiceProvider
 {
+    /**
+     * The path to the "home" route for your application.
+     *
+     * This is used by Laravel authentication to redirect users after login.
+     *
+     * @var string
+     */
+    public const HOME = '/';
+
     /**
      * This namespace is applied to the controller routes in your routes file.
      *
@@ -14,7 +26,6 @@ class RouteServiceProvider extends ServiceProvider
      *
      * @var string
      */
-    protected $namespace = 'BookStack\Http\Controllers';
 
     /**
      * Define your route model bindings, pattern filters, etc.
@@ -23,18 +34,12 @@ class RouteServiceProvider extends ServiceProvider
      */
     public function boot()
     {
-        parent::boot();
-    }
+        $this->configureRateLimiting();
 
-    /**
-     * Define the routes for the application.
-     *
-     * @return void
-     */
-    public function map()
-    {
-        $this->mapWebRoutes();
-        $this->mapApiRoutes();
+        $this->routes(function () {
+            $this->mapWebRoutes();
+            $this->mapApiRoutes();
+        });
     }
 
     /**
@@ -71,4 +76,16 @@ class RouteServiceProvider extends ServiceProvider
             require base_path('routes/api.php');
         });
     }
+
+    /**
+     * Configure the rate limiters for the application.
+     *
+     * @return void
+     */
+    protected function configureRateLimiting()
+    {
+        RateLimiter::for('api', function (Request $request) {
+            return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
+        });
+    }
 }
diff --git a/app/Uploads/Image.php b/app/Uploads/Image.php
index 4e0abc85b..bdf10f080 100644
--- a/app/Uploads/Image.php
+++ b/app/Uploads/Image.php
@@ -5,6 +5,7 @@ namespace BookStack\Uploads;
 use BookStack\Entities\Models\Page;
 use BookStack\Model;
 use BookStack\Traits\HasCreatorAndUpdater;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 
 /**
  * @property int    $id
@@ -18,6 +19,7 @@ use BookStack\Traits\HasCreatorAndUpdater;
  */
 class Image extends Model
 {
+    use HasFactory;
     use HasCreatorAndUpdater;
 
     protected $fillable = ['name'];
diff --git a/composer.json b/composer.json
index b50cee762..c1d5c1e4b 100644
--- a/composer.json
+++ b/composer.json
@@ -20,11 +20,13 @@
         "barryvdh/laravel-dompdf": "^0.9.0",
         "barryvdh/laravel-snappy": "^0.4.8",
         "doctrine/dbal": "^3.1",
-        "fideloper/proxy": "^4.4.1",
         "filp/whoops": "^2.14",
+        "guzzlehttp/guzzle": "^7.4",
         "intervention/image": "^2.7",
-        "laravel/framework": "^7.29",
+        "laravel/framework": "^8.68",
         "laravel/socialite": "^5.2",
+        "laravel/tinker": "^2.5",
+        "laravel/ui": "^3.3",
         "league/commonmark": "^1.5",
         "league/flysystem-aws-s3-v3": "^1.0.29",
         "league/html-to-markdown": "^5.0.0",
@@ -32,33 +34,28 @@
         "onelogin/php-saml": "^4.0",
         "phpseclib/phpseclib": "~3.0",
         "pragmarx/google2fa": "^8.0",
-        "predis/predis": "^1.1.6",
+        "predis/predis": "^1.1",
         "socialiteproviders/discord": "^4.1",
         "socialiteproviders/gitlab": "^4.1",
         "socialiteproviders/microsoft-azure": "^4.1",
         "socialiteproviders/okta": "^4.1",
         "socialiteproviders/slack": "^4.1",
         "socialiteproviders/twitch": "^5.3",
-        "ssddanbrown/htmldiff": "^1.0.1",
-        "laravel/ui": "^2.5",
-        "guzzlehttp/guzzle": "^7.4.0",
-        "laravel/tinker": "^2.5"
+        "ssddanbrown/htmldiff": "^1.0.1"
     },
     "require-dev": {
         "barryvdh/laravel-debugbar": "^3.6",
         "fakerphp/faker": "^1.13.0",
-        "mockery/mockery": "^1.3.3",
+        "mockery/mockery": "^1.4.2",
         "phpunit/phpunit": "^9.5.3",
         "symfony/dom-crawler": "^5.3",
-        "nunomaduro/collision": "^4.3"
+        "nunomaduro/collision": "^5.0"
     },
     "autoload": {
-        "classmap": [
-            "database/seeds",
-            "database/factories"
-        ],
         "psr-4": {
-            "BookStack\\": "app/"
+            "BookStack\\": "app/",
+            "Database\\Factories\\": "database/factories/",
+            "Database\\Seeders\\": "database/seeders/"
         },
         "files": [
             "app/helpers.php"
@@ -70,6 +67,10 @@
         }
     },
     "scripts": {
+        "post-autoload-dump": [
+            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
+            "@php artisan package:discover --ansi"
+        ],
         "post-root-package-install": [
             "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
         ],
@@ -83,10 +84,6 @@
             "@php artisan cache:clear",
             "@php artisan view:clear"
         ],
-        "post-autoload-dump": [
-            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
-            "@php artisan package:discover --ansi"
-        ],
         "refresh-test-database": [
             "@php artisan migrate:refresh --database=mysql_testing",
             "@php artisan db:seed --class=DummyContentSeeder --database=mysql_testing"
diff --git a/composer.lock b/composer.lock
index f07d61062..17e57df71 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "491a3de7d49182613d0c81032a7001e1",
+    "content-hash": "9a5d92382b2955dd7de41de5fa9f86b5",
     "packages": [
         {
             "name": "aws/aws-crt-php",
@@ -58,16 +58,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.199.4",
+            "version": "3.199.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5"
+                "reference": "fda176884d2952cffc7e67209470bff49609339c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/047f6ce04b1de9320ca00bf393d6f03b9d036fa5",
-                "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fda176884d2952cffc7e67209470bff49609339c",
+                "reference": "fda176884d2952cffc7e67209470bff49609339c",
                 "shasum": ""
             },
             "require": {
@@ -143,9 +143,9 @@
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.199.4"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.199.7"
             },
-            "time": "2021-10-26T18:14:35+00:00"
+            "time": "2021-10-29T18:25:02+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -1101,30 +1101,32 @@
         },
         {
             "name": "dragonmantank/cron-expression",
-            "version": "v2.3.1",
+            "version": "v3.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dragonmantank/cron-expression.git",
-                "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2"
+                "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/65b2d8ee1f10915efb3b55597da3404f096acba2",
-                "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2",
+                "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c",
+                "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.0|^8.0"
+                "php": "^7.2|^8.0",
+                "webmozart/assert": "^1.7.0"
+            },
+            "replace": {
+                "mtdowling/cron-expression": "^1.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0"
+                "phpstan/extension-installer": "^1.0",
+                "phpstan/phpstan": "^0.12",
+                "phpstan/phpstan-webmozart-assert": "^0.12.7",
+                "phpunit/phpunit": "^7.0|^8.0|^9.0"
             },
             "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
             "autoload": {
                 "psr-4": {
                     "Cron\\": "src/Cron/"
@@ -1135,11 +1137,6 @@
                 "MIT"
             ],
             "authors": [
-                {
-                    "name": "Michael Dowling",
-                    "email": "mtdowling@gmail.com",
-                    "homepage": "https://github.com/mtdowling"
-                },
                 {
                     "name": "Chris Tankersley",
                     "email": "chris@ctankersley.com",
@@ -1153,7 +1150,7 @@
             ],
             "support": {
                 "issues": "https://github.com/dragonmantank/cron-expression/issues",
-                "source": "https://github.com/dragonmantank/cron-expression/tree/v2.3.1"
+                "source": "https://github.com/dragonmantank/cron-expression/tree/v3.1.0"
             },
             "funding": [
                 {
@@ -1161,7 +1158,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-10-13T00:52:37+00:00"
+            "time": "2020-11-24T19:55:57+00:00"
         },
         {
             "name": "egulias/email-validator",
@@ -1231,64 +1228,6 @@
             ],
             "time": "2020-12-29T14:50:06+00:00"
         },
-        {
-            "name": "fideloper/proxy",
-            "version": "4.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/fideloper/TrustedProxy.git",
-                "reference": "c073b2bd04d1c90e04dc1b787662b558dd65ade0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/c073b2bd04d1c90e04dc1b787662b558dd65ade0",
-                "reference": "c073b2bd04d1c90e04dc1b787662b558dd65ade0",
-                "shasum": ""
-            },
-            "require": {
-                "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0",
-                "php": ">=5.4.0"
-            },
-            "require-dev": {
-                "illuminate/http": "^5.0|^6.0|^7.0|^8.0|^9.0",
-                "mockery/mockery": "^1.0",
-                "phpunit/phpunit": "^6.0"
-            },
-            "type": "library",
-            "extra": {
-                "laravel": {
-                    "providers": [
-                        "Fideloper\\Proxy\\TrustedProxyServiceProvider"
-                    ]
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Fideloper\\Proxy\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Chris Fidao",
-                    "email": "fideloper@gmail.com"
-                }
-            ],
-            "description": "Set trusted proxies for Laravel",
-            "keywords": [
-                "load balancing",
-                "proxy",
-                "trusted proxy"
-            ],
-            "support": {
-                "issues": "https://github.com/fideloper/TrustedProxy/issues",
-                "source": "https://github.com/fideloper/TrustedProxy/tree/4.4.1"
-            },
-            "time": "2020-10-22T13:48:01+00:00"
-        },
         {
             "name": "filp/whoops",
             "version": "2.14.4",
@@ -1360,6 +1299,67 @@
             ],
             "time": "2021-10-03T12:00:00+00:00"
         },
+        {
+            "name": "graham-campbell/result-type",
+            "version": "v1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/GrahamCampbell/Result-Type.git",
+                "reference": "296c015dc30ec4322168c5ad3ee5cc11dae827ac"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/296c015dc30ec4322168c5ad3ee5cc11dae827ac",
+                "reference": "296c015dc30ec4322168c5ad3ee5cc11dae827ac",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^8.0",
+                "phpoption/phpoption": "^1.8"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "GrahamCampbell\\ResultType\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk"
+                }
+            ],
+            "description": "An Implementation Of The Result Type",
+            "keywords": [
+                "Graham Campbell",
+                "GrahamCampbell",
+                "Result Type",
+                "Result-Type",
+                "result"
+            ],
+            "support": {
+                "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
+                "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.3"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-10-17T19:48:54+00:00"
+        },
         {
             "name": "guzzlehttp/guzzle",
             "version": "7.4.0",
@@ -1843,60 +1843,63 @@
         },
         {
             "name": "laravel/framework",
-            "version": "v7.30.4",
+            "version": "v8.68.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3"
+                "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/9dd38140dc2924daa1a020a3d7a45f9ceff03df3",
-                "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/abe985ff1fb82dd04aab03bc1dc56e83fe61a59f",
+                "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f",
                 "shasum": ""
             },
             "require": {
                 "doctrine/inflector": "^1.4|^2.0",
-                "dragonmantank/cron-expression": "^2.3.1",
+                "dragonmantank/cron-expression": "^3.0.2",
                 "egulias/email-validator": "^2.1.10",
                 "ext-json": "*",
                 "ext-mbstring": "*",
                 "ext-openssl": "*",
-                "league/commonmark": "^1.3",
+                "laravel/serializable-closure": "^1.0",
+                "league/commonmark": "^1.3|^2.0.2",
                 "league/flysystem": "^1.1",
                 "monolog/monolog": "^2.0",
-                "nesbot/carbon": "^2.31",
+                "nesbot/carbon": "^2.53.1",
                 "opis/closure": "^3.6",
-                "php": "^7.2.5|^8.0",
+                "php": "^7.3|^8.0",
                 "psr/container": "^1.0",
+                "psr/log": "^1.0 || ^2.0",
                 "psr/simple-cache": "^1.0",
-                "ramsey/uuid": "^3.7|^4.0",
-                "swiftmailer/swiftmailer": "^6.0",
-                "symfony/console": "^5.0",
-                "symfony/error-handler": "^5.0",
-                "symfony/finder": "^5.0",
-                "symfony/http-foundation": "^5.0",
-                "symfony/http-kernel": "^5.0",
-                "symfony/mime": "^5.0",
-                "symfony/polyfill-php73": "^1.17",
-                "symfony/process": "^5.0",
-                "symfony/routing": "^5.0",
-                "symfony/var-dumper": "^5.0",
+                "ramsey/uuid": "^4.2.2",
+                "swiftmailer/swiftmailer": "^6.3",
+                "symfony/console": "^5.1.4",
+                "symfony/error-handler": "^5.1.4",
+                "symfony/finder": "^5.1.4",
+                "symfony/http-foundation": "^5.1.4",
+                "symfony/http-kernel": "^5.1.4",
+                "symfony/mime": "^5.1.4",
+                "symfony/process": "^5.1.4",
+                "symfony/routing": "^5.1.4",
+                "symfony/var-dumper": "^5.1.4",
                 "tijsverkoyen/css-to-inline-styles": "^2.2.2",
-                "vlucas/phpdotenv": "^4.0",
+                "vlucas/phpdotenv": "^5.2",
                 "voku/portable-ascii": "^1.4.8"
             },
             "conflict": {
                 "tightenco/collect": "<5.5.33"
             },
             "provide": {
-                "psr/container-implementation": "1.0"
+                "psr/container-implementation": "1.0",
+                "psr/simple-cache-implementation": "1.0"
             },
             "replace": {
                 "illuminate/auth": "self.version",
                 "illuminate/broadcasting": "self.version",
                 "illuminate/bus": "self.version",
                 "illuminate/cache": "self.version",
+                "illuminate/collections": "self.version",
                 "illuminate/config": "self.version",
                 "illuminate/console": "self.version",
                 "illuminate/container": "self.version",
@@ -1909,6 +1912,7 @@
                 "illuminate/hashing": "self.version",
                 "illuminate/http": "self.version",
                 "illuminate/log": "self.version",
+                "illuminate/macroable": "self.version",
                 "illuminate/mail": "self.version",
                 "illuminate/notifications": "self.version",
                 "illuminate/pagination": "self.version",
@@ -1924,22 +1928,23 @@
                 "illuminate/view": "self.version"
             },
             "require-dev": {
-                "aws/aws-sdk-php": "^3.155",
-                "doctrine/dbal": "^2.6",
-                "filp/whoops": "^2.8",
-                "guzzlehttp/guzzle": "^6.3.1|^7.0.1",
+                "aws/aws-sdk-php": "^3.198.1",
+                "doctrine/dbal": "^2.13.3|^3.1.2",
+                "filp/whoops": "^2.14.3",
+                "guzzlehttp/guzzle": "^6.5.5|^7.0.1",
                 "league/flysystem-cached-adapter": "^1.0",
-                "mockery/mockery": "~1.3.3|^1.4.2",
-                "moontoast/math": "^1.1",
-                "orchestra/testbench-core": "^5.8",
+                "mockery/mockery": "^1.4.4",
+                "orchestra/testbench-core": "^6.23",
                 "pda/pheanstalk": "^4.0",
-                "phpunit/phpunit": "^8.4|^9.3.3",
-                "predis/predis": "^1.1.1",
-                "symfony/cache": "^5.0"
+                "phpunit/phpunit": "^8.5.19|^9.5.8",
+                "predis/predis": "^1.1.9",
+                "symfony/cache": "^5.1.4"
             },
             "suggest": {
-                "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).",
-                "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).",
+                "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.198.1).",
+                "brianium/paratest": "Required to run tests in parallel (^6.0).",
+                "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.2).",
+                "ext-bcmath": "Required to use the multiple_of validation rule.",
                 "ext-ftp": "Required to use the Flysystem FTP driver.",
                 "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().",
                 "ext-memcached": "Required to use the memcache cache driver.",
@@ -1947,38 +1952,43 @@
                 "ext-posix": "Required to use all features of the queue worker.",
                 "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).",
                 "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
-                "filp/whoops": "Required for friendly error pages in development (^2.8).",
-                "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).",
+                "filp/whoops": "Required for friendly error pages in development (^2.14.3).",
+                "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).",
                 "laravel/tinker": "Required to use the tinker console command (^2.0).",
                 "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).",
                 "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).",
                 "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).",
-                "mockery/mockery": "Required to use mocking (~1.3.3|^1.4.2).",
-                "moontoast/math": "Required to use ordered UUIDs (^1.1).",
+                "mockery/mockery": "Required to use mocking (^1.4.4).",
                 "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).",
                 "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).",
-                "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.3.3).",
-                "predis/predis": "Required to use the predis connector (^1.1.2).",
+                "phpunit/phpunit": "Required to use assertions and run tests (^8.5.19|^9.5.8).",
+                "predis/predis": "Required to use the predis connector (^1.1.9).",
                 "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
-                "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).",
-                "symfony/cache": "Required to PSR-6 cache bridge (^5.0).",
-                "symfony/filesystem": "Required to create relative storage directory symbolic links (^5.0).",
+                "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0|^6.0).",
+                "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).",
+                "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1.4).",
                 "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).",
                 "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)."
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "7.x-dev"
+                    "dev-master": "8.x-dev"
                 }
             },
             "autoload": {
                 "files": [
+                    "src/Illuminate/Collections/helpers.php",
+                    "src/Illuminate/Events/functions.php",
                     "src/Illuminate/Foundation/helpers.php",
                     "src/Illuminate/Support/helpers.php"
                 ],
                 "psr-4": {
-                    "Illuminate\\": "src/Illuminate/"
+                    "Illuminate\\": "src/Illuminate/",
+                    "Illuminate\\Support\\": [
+                        "src/Illuminate/Macroable/",
+                        "src/Illuminate/Collections/"
+                    ]
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -2001,7 +2011,66 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2021-01-21T14:10:48+00:00"
+            "time": "2021-10-27T12:31:46+00:00"
+        },
+        {
+            "name": "laravel/serializable-closure",
+            "version": "v1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/laravel/serializable-closure.git",
+                "reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/6cfc678735f22ccedad761b8cae2bab14c3d8e5b",
+                "reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.3|^8.0"
+            },
+            "require-dev": {
+                "pestphp/pest": "^1.18",
+                "phpstan/phpstan": "^0.12.98",
+                "symfony/var-dumper": "^5.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Laravel\\SerializableClosure\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                },
+                {
+                    "name": "Nuno Maduro",
+                    "email": "nuno@laravel.com"
+                }
+            ],
+            "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.",
+            "keywords": [
+                "closure",
+                "laravel",
+                "serializable"
+            ],
+            "support": {
+                "issues": "https://github.com/laravel/serializable-closure/issues",
+                "source": "https://github.com/laravel/serializable-closure"
+            },
+            "time": "2021-10-07T14:00:57+00:00"
         },
         {
             "name": "laravel/socialite",
@@ -2142,26 +2211,30 @@
         },
         {
             "name": "laravel/ui",
-            "version": "v2.5.0",
+            "version": "v3.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/ui.git",
-                "reference": "d01a705763c243b07be795e9d1bb47f89260f73d"
+                "reference": "07d725813350c695c779382cbd6dac0ab8665537"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/ui/zipball/d01a705763c243b07be795e9d1bb47f89260f73d",
-                "reference": "d01a705763c243b07be795e9d1bb47f89260f73d",
+                "url": "https://api.github.com/repos/laravel/ui/zipball/07d725813350c695c779382cbd6dac0ab8665537",
+                "reference": "07d725813350c695c779382cbd6dac0ab8665537",
                 "shasum": ""
             },
             "require": {
-                "illuminate/console": "^7.0",
-                "illuminate/filesystem": "^7.0",
-                "illuminate/support": "^7.0",
-                "php": "^7.2.5|^8.0"
+                "illuminate/console": "^8.42",
+                "illuminate/filesystem": "^8.42",
+                "illuminate/support": "^8.42",
+                "illuminate/validation": "^8.42",
+                "php": "^7.3|^8.0"
             },
             "type": "library",
             "extra": {
+                "branch-alias": {
+                    "dev-master": "3.x-dev"
+                },
                 "laravel": {
                     "providers": [
                         "Laravel\\Ui\\UiServiceProvider"
@@ -2190,10 +2263,9 @@
                 "ui"
             ],
             "support": {
-                "issues": "https://github.com/laravel/ui/issues",
-                "source": "https://github.com/laravel/ui/tree/v2.5.0"
+                "source": "https://github.com/laravel/ui/tree/v3.3.0"
             },
-            "time": "2020-11-03T19:45:19+00:00"
+            "time": "2021-05-25T16:45:33+00:00"
         },
         {
             "name": "league/commonmark",
@@ -3436,16 +3508,16 @@
         },
         {
             "name": "phpseclib/phpseclib",
-            "version": "3.0.10",
+            "version": "3.0.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpseclib/phpseclib.git",
-                "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187"
+                "reference": "6e794226a35159eb06f355efe59a0075a16551dd"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/62fcc5a94ac83b1506f52d7558d828617fac9187",
-                "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187",
+                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/6e794226a35159eb06f355efe59a0075a16551dd",
+                "reference": "6e794226a35159eb06f355efe59a0075a16551dd",
                 "shasum": ""
             },
             "require": {
@@ -3527,7 +3599,7 @@
             ],
             "support": {
                 "issues": "https://github.com/phpseclib/phpseclib/issues",
-                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.10"
+                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.11"
             },
             "funding": [
                 {
@@ -3543,7 +3615,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-16T04:24:45+00:00"
+            "time": "2021-10-27T03:01:46+00:00"
         },
         {
             "name": "pragmarx/google2fa",
@@ -4851,16 +4923,16 @@
         },
         {
             "name": "symfony/console",
-            "version": "v5.3.7",
+            "version": "v5.3.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a"
+                "reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a",
-                "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a",
+                "url": "https://api.github.com/repos/symfony/console/zipball/d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3",
+                "reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3",
                 "shasum": ""
             },
             "require": {
@@ -4930,7 +5002,7 @@
                 "terminal"
             ],
             "support": {
-                "source": "https://github.com/symfony/console/tree/v5.3.7"
+                "source": "https://github.com/symfony/console/tree/v5.3.10"
             },
             "funding": [
                 {
@@ -4946,7 +5018,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-25T20:02:16+00:00"
+            "time": "2021-10-26T09:30:15+00:00"
         },
         {
             "name": "symfony/css-selector",
@@ -5455,16 +5527,16 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v5.3.7",
+            "version": "v5.3.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5"
+                "reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e36c8e5502b4f3f0190c675f1c1f1248a64f04e5",
-                "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9f34f02e8a5fdc7a56bafe011cea1ce97300e54c",
+                "reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c",
                 "shasum": ""
             },
             "require": {
@@ -5508,7 +5580,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.7"
+                "source": "https://github.com/symfony/http-foundation/tree/v5.3.10"
             },
             "funding": [
                 {
@@ -5524,20 +5596,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-27T11:20:35+00:00"
+            "time": "2021-10-11T15:41:55+00:00"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v5.3.9",
+            "version": "v5.3.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-kernel.git",
-                "reference": "ceaf46a992f60e90645e7279825a830f733a17c5"
+                "reference": "703e4079920468e9522b72cf47fd76ce8d795e86"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ceaf46a992f60e90645e7279825a830f733a17c5",
-                "reference": "ceaf46a992f60e90645e7279825a830f733a17c5",
+                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/703e4079920468e9522b72cf47fd76ce8d795e86",
+                "reference": "703e4079920468e9522b72cf47fd76ce8d795e86",
                 "shasum": ""
             },
             "require": {
@@ -5620,7 +5692,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.9"
+                "source": "https://github.com/symfony/http-kernel/tree/v5.3.10"
             },
             "funding": [
                 {
@@ -5636,7 +5708,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-28T10:25:11+00:00"
+            "time": "2021-10-29T08:36:48+00:00"
         },
         {
             "name": "symfony/mime",
@@ -6762,16 +6834,16 @@
         },
         {
             "name": "symfony/string",
-            "version": "v5.3.7",
+            "version": "v5.3.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git",
-                "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5"
+                "reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5",
-                "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5",
+                "url": "https://api.github.com/repos/symfony/string/zipball/d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c",
+                "reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c",
                 "shasum": ""
             },
             "require": {
@@ -6825,7 +6897,7 @@
                 "utf8"
             ],
             "support": {
-                "source": "https://github.com/symfony/string/tree/v5.3.7"
+                "source": "https://github.com/symfony/string/tree/v5.3.10"
             },
             "funding": [
                 {
@@ -6841,20 +6913,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-26T08:00:08+00:00"
+            "time": "2021-10-27T18:21:46+00:00"
         },
         {
             "name": "symfony/translation",
-            "version": "v5.3.9",
+            "version": "v5.3.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation.git",
-                "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886"
+                "reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation/zipball/6e69f3551c1a3356cf6ea8d019bf039a0f8b6886",
-                "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/6ef197aea2ac8b9cd63e0da7522b3771714035aa",
+                "reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa",
                 "shasum": ""
             },
             "require": {
@@ -6920,7 +6992,7 @@
             "description": "Provides tools to internationalize your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/translation/tree/v5.3.9"
+                "source": "https://github.com/symfony/translation/tree/v5.3.10"
             },
             "funding": [
                 {
@@ -6936,7 +7008,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-08-26T08:22:53+00:00"
+            "time": "2021-10-10T06:43:24+00:00"
         },
         {
             "name": "symfony/translation-contracts",
@@ -7018,16 +7090,16 @@
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v5.3.8",
+            "version": "v5.3.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da"
+                "reference": "875432adb5f5570fff21036fd22aee244636b7d1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eaaea4098be1c90c8285543e1356a09c8aa5c8da",
-                "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/875432adb5f5570fff21036fd22aee244636b7d1",
+                "reference": "875432adb5f5570fff21036fd22aee244636b7d1",
                 "shasum": ""
             },
             "require": {
@@ -7086,7 +7158,7 @@
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v5.3.8"
+                "source": "https://github.com/symfony/var-dumper/tree/v5.3.10"
             },
             "funding": [
                 {
@@ -7102,7 +7174,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-24T15:59:58+00:00"
+            "time": "2021-10-26T09:30:15+00:00"
         },
         {
             "name": "tijsverkoyen/css-to-inline-styles",
@@ -7159,37 +7231,39 @@
         },
         {
             "name": "vlucas/phpdotenv",
-            "version": "v4.2.1",
+            "version": "v5.3.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/vlucas/phpdotenv.git",
-                "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c"
+                "reference": "accaddf133651d4b5cf81a119f25296736ffc850"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/d38f4d1edcbe32515a0ad593cbd4c858e337263c",
-                "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c",
+                "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/accaddf133651d4b5cf81a119f25296736ffc850",
+                "reference": "accaddf133651d4b5cf81a119f25296736ffc850",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.5.9 || ^7.0 || ^8.0",
-                "phpoption/phpoption": "^1.7.3",
-                "symfony/polyfill-ctype": "^1.17"
+                "ext-pcre": "*",
+                "graham-campbell/result-type": "^1.0.2",
+                "php": "^7.1.3 || ^8.0",
+                "phpoption/phpoption": "^1.8",
+                "symfony/polyfill-ctype": "^1.23",
+                "symfony/polyfill-mbstring": "^1.23.1",
+                "symfony/polyfill-php80": "^1.23.1"
             },
             "require-dev": {
                 "bamarni/composer-bin-plugin": "^1.4.1",
                 "ext-filter": "*",
-                "ext-pcre": "*",
-                "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.21"
+                "phpunit/phpunit": "^7.5.20 || ^8.5.21 || ^9.5.10"
             },
             "suggest": {
-                "ext-filter": "Required to use the boolean validator.",
-                "ext-pcre": "Required to use most of the library."
+                "ext-filter": "Required to use the boolean validator."
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.2-dev"
+                    "dev-master": "5.3-dev"
                 }
             },
             "autoload": {
@@ -7219,7 +7293,7 @@
             ],
             "support": {
                 "issues": "https://github.com/vlucas/phpdotenv/issues",
-                "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.1"
+                "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.1"
             },
             "funding": [
                 {
@@ -7231,7 +7305,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-10-02T19:17:08+00:00"
+            "time": "2021-10-02T19:24:42+00:00"
         },
         {
             "name": "voku/portable-ascii",
@@ -7306,6 +7380,64 @@
                 }
             ],
             "time": "2020-11-12T00:07:28+00:00"
+        },
+        {
+            "name": "webmozart/assert",
+            "version": "1.10.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/webmozarts/assert.git",
+                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
+                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2 || ^8.0",
+                "symfony/polyfill-ctype": "^1.8"
+            },
+            "conflict": {
+                "phpstan/phpstan": "<0.12.20",
+                "vimeo/psalm": "<4.6.1 || 4.6.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.5.13"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.10-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Webmozart\\Assert\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Assertions to validate method input/output with nice error messages.",
+            "keywords": [
+                "assert",
+                "check",
+                "validate"
+            ],
+            "support": {
+                "issues": "https://github.com/webmozarts/assert/issues",
+                "source": "https://github.com/webmozarts/assert/tree/1.10.0"
+            },
+            "time": "2021-03-09T10:59:23+00:00"
         }
     ],
     "packages-dev": [
@@ -7829,35 +7961,34 @@
         },
         {
             "name": "nunomaduro/collision",
-            "version": "v4.3.0",
+            "version": "v5.10.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nunomaduro/collision.git",
-                "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e"
+                "reference": "3004cfa49c022183395eabc6d0e5207dfe498d00"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nunomaduro/collision/zipball/7c125dc2463f3e144ddc7e05e63077109508c94e",
-                "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e",
+                "url": "https://api.github.com/repos/nunomaduro/collision/zipball/3004cfa49c022183395eabc6d0e5207dfe498d00",
+                "reference": "3004cfa49c022183395eabc6d0e5207dfe498d00",
                 "shasum": ""
             },
             "require": {
                 "facade/ignition-contracts": "^1.0",
-                "filp/whoops": "^2.4",
-                "php": "^7.2.5 || ^8.0",
+                "filp/whoops": "^2.14.3",
+                "php": "^7.3 || ^8.0",
                 "symfony/console": "^5.0"
             },
             "require-dev": {
-                "facade/ignition": "^2.0",
-                "fideloper/proxy": "^4.2",
-                "friendsofphp/php-cs-fixer": "^2.16",
-                "fruitcake/laravel-cors": "^1.0",
-                "laravel/framework": "^7.0",
-                "laravel/tinker": "^2.0",
-                "nunomaduro/larastan": "^0.6",
-                "orchestra/testbench": "^5.0",
-                "phpstan/phpstan": "^0.12.3",
-                "phpunit/phpunit": "^8.5.1 || ^9.0"
+                "brianium/paratest": "^6.1",
+                "fideloper/proxy": "^4.4.1",
+                "fruitcake/laravel-cors": "^2.0.3",
+                "laravel/framework": "8.x-dev",
+                "nunomaduro/larastan": "^0.6.2",
+                "nunomaduro/mock-final-classes": "^1.0",
+                "orchestra/testbench": "^6.0",
+                "phpstan/phpstan": "^0.12.64",
+                "phpunit/phpunit": "^9.5.0"
             },
             "type": "library",
             "extra": {
@@ -7913,7 +8044,7 @@
                     "type": "patreon"
                 }
             ],
-            "time": "2020-10-29T15:12:23+00:00"
+            "time": "2021-09-20T15:06:32+00:00"
         },
         {
             "name": "phar-io/manifest",
@@ -8255,23 +8386,23 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "9.2.7",
+            "version": "9.2.8",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218"
+                "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218",
-                "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cf04e88a2e3c56fc1a65488afd493325b4c1bc3e",
+                "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e",
                 "shasum": ""
             },
             "require": {
                 "ext-dom": "*",
                 "ext-libxml": "*",
                 "ext-xmlwriter": "*",
-                "nikic/php-parser": "^4.12.0",
+                "nikic/php-parser": "^4.13.0",
                 "php": ">=7.3",
                 "phpunit/php-file-iterator": "^3.0.3",
                 "phpunit/php-text-template": "^2.0.2",
@@ -8320,7 +8451,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
-                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7"
+                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.8"
             },
             "funding": [
                 {
@@ -8328,7 +8459,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-09-17T05:39:03+00:00"
+            "time": "2021-10-30T08:01:38+00:00"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -9830,64 +9961,6 @@
                 }
             ],
             "time": "2021-07-28T10:34:58+00:00"
-        },
-        {
-            "name": "webmozart/assert",
-            "version": "1.10.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/webmozarts/assert.git",
-                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
-                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^7.2 || ^8.0",
-                "symfony/polyfill-ctype": "^1.8"
-            },
-            "conflict": {
-                "phpstan/phpstan": "<0.12.20",
-                "vimeo/psalm": "<4.6.1 || 4.6.2"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^8.5.13"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.10-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Webmozart\\Assert\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                }
-            ],
-            "description": "Assertions to validate method input/output with nice error messages.",
-            "keywords": [
-                "assert",
-                "check",
-                "validate"
-            ],
-            "support": {
-                "issues": "https://github.com/webmozarts/assert/issues",
-                "source": "https://github.com/webmozarts/assert/tree/1.10.0"
-            },
-            "time": "2021-03-09T10:59:23+00:00"
         }
     ],
     "aliases": [],
diff --git a/database/factories/Actions/CommentFactory.php b/database/factories/Actions/CommentFactory.php
new file mode 100644
index 000000000..e81f3fe2c
--- /dev/null
+++ b/database/factories/Actions/CommentFactory.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Database\Factories\Actions;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class CommentFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Actions\Comment::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        $text = $this->faker->paragraph(1);
+        $html = '<p>' . $text . '</p>';
+
+        return [
+            'html'      => $html,
+            'text'      => $text,
+            'parent_id' => null,
+        ];
+    }
+}
diff --git a/database/factories/Actions/TagFactory.php b/database/factories/Actions/TagFactory.php
new file mode 100644
index 000000000..8d5c77e09
--- /dev/null
+++ b/database/factories/Actions/TagFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Database\Factories\Actions;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class TagFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Actions\Tag::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'name'  => $this->faker->city,
+            'value' => $this->faker->sentence(3),
+        ];
+    }
+}
diff --git a/database/factories/Auth/RoleFactory.php b/database/factories/Auth/RoleFactory.php
new file mode 100644
index 000000000..a952e0487
--- /dev/null
+++ b/database/factories/Auth/RoleFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Database\Factories\Auth;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class RoleFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Auth\Role::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'display_name' => $this->faker->sentence(3),
+            'description'  => $this->faker->sentence(10),
+        ];
+    }
+}
diff --git a/database/factories/Auth/UserFactory.php b/database/factories/Auth/UserFactory.php
new file mode 100644
index 000000000..77d63ac68
--- /dev/null
+++ b/database/factories/Auth/UserFactory.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Database\Factories\Auth;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Str;
+
+class UserFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Auth\User::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        $name = $this->faker->name;
+
+        return [
+            'name'            => $name,
+            'email'           => $this->faker->email,
+            'slug'            => \Illuminate\Support\Str::slug($name . '-' . \Illuminate\Support\Str::random(5)),
+            'password'        => Str::random(10),
+            'remember_token'  => Str::random(10),
+            'email_confirmed' => 1,
+        ];
+    }
+}
diff --git a/database/factories/Entities/Models/BookFactory.php b/database/factories/Entities/Models/BookFactory.php
new file mode 100644
index 000000000..0613800a1
--- /dev/null
+++ b/database/factories/Entities/Models/BookFactory.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Database\Factories\Entities\Models;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Str;
+
+class BookFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Entities\Models\Book::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'name'        => $this->faker->sentence,
+            'slug'        => Str::random(10),
+            'description' => $this->faker->paragraph,
+        ];
+    }
+}
diff --git a/database/factories/Entities/Models/BookshelfFactory.php b/database/factories/Entities/Models/BookshelfFactory.php
new file mode 100644
index 000000000..66dd1c111
--- /dev/null
+++ b/database/factories/Entities/Models/BookshelfFactory.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Database\Factories\Entities\Models;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Str;
+
+class BookshelfFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Entities\Models\Bookshelf::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'name'        => $this->faker->sentence,
+            'slug'        => Str::random(10),
+            'description' => $this->faker->paragraph,
+        ];
+    }
+}
diff --git a/database/factories/Entities/Models/ChapterFactory.php b/database/factories/Entities/Models/ChapterFactory.php
new file mode 100644
index 000000000..4fcd69c39
--- /dev/null
+++ b/database/factories/Entities/Models/ChapterFactory.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Database\Factories\Entities\Models;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Str;
+
+class ChapterFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Entities\Models\Chapter::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'name'        => $this->faker->sentence,
+            'slug'        => Str::random(10),
+            'description' => $this->faker->paragraph,
+        ];
+    }
+}
diff --git a/database/factories/Entities/Models/PageFactory.php b/database/factories/Entities/Models/PageFactory.php
new file mode 100644
index 000000000..c83e0f828
--- /dev/null
+++ b/database/factories/Entities/Models/PageFactory.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Database\Factories\Entities\Models;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Str;
+
+class PageFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Entities\Models\Page::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        $html = '<p>' . implode('</p>', $this->faker->paragraphs(5)) . '</p>';
+
+        return [
+            'name'           => $this->faker->sentence,
+            'slug'           => Str::random(10),
+            'html'           => $html,
+            'text'           => strip_tags($html),
+            'revision_count' => 1,
+        ];
+    }
+}
diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php
deleted file mode 100644
index dc0645540..000000000
--- a/database/factories/ModelFactory.php
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-
-/*
-|--------------------------------------------------------------------------
-| Model Factories
-|--------------------------------------------------------------------------
-|
-| Here you may define all of your model factories. Model factories give
-| you a convenient way to create models for testing and seeding your
-| database. Just tell the factory how a default model should look.
-|
-*/
-
-$factory->define(\BookStack\Auth\User::class, function ($faker) {
-    $name = $faker->name;
-
-    return [
-        'name'            => $name,
-        'email'           => $faker->email,
-        'slug'            => \Illuminate\Support\Str::slug($name . '-' . \Illuminate\Support\Str::random(5)),
-        'password'        => Str::random(10),
-        'remember_token'  => Str::random(10),
-        'email_confirmed' => 1,
-    ];
-});
-
-$factory->define(\BookStack\Entities\Models\Bookshelf::class, function ($faker) {
-    return [
-        'name'        => $faker->sentence,
-        'slug'        => Str::random(10),
-        'description' => $faker->paragraph,
-    ];
-});
-
-$factory->define(\BookStack\Entities\Models\Book::class, function ($faker) {
-    return [
-        'name'        => $faker->sentence,
-        'slug'        => Str::random(10),
-        'description' => $faker->paragraph,
-    ];
-});
-
-$factory->define(\BookStack\Entities\Models\Chapter::class, function ($faker) {
-    return [
-        'name'        => $faker->sentence,
-        'slug'        => Str::random(10),
-        'description' => $faker->paragraph,
-    ];
-});
-
-$factory->define(\BookStack\Entities\Models\Page::class, function ($faker) {
-    $html = '<p>' . implode('</p>', $faker->paragraphs(5)) . '</p>';
-
-    return [
-        'name'           => $faker->sentence,
-        'slug'           => Str::random(10),
-        'html'           => $html,
-        'text'           => strip_tags($html),
-        'revision_count' => 1,
-    ];
-});
-
-$factory->define(\BookStack\Auth\Role::class, function ($faker) {
-    return [
-        'display_name' => $faker->sentence(3),
-        'description'  => $faker->sentence(10),
-    ];
-});
-
-$factory->define(\BookStack\Actions\Tag::class, function ($faker) {
-    return [
-        'name'  => $faker->city,
-        'value' => $faker->sentence(3),
-    ];
-});
-
-$factory->define(\BookStack\Uploads\Image::class, function ($faker) {
-    return [
-        'name'        => $faker->slug . '.jpg',
-        'url'         => $faker->url,
-        'path'        => $faker->url,
-        'type'        => 'gallery',
-        'uploaded_to' => 0,
-    ];
-});
-
-$factory->define(\BookStack\Actions\Comment::class, function ($faker) {
-    $text = $faker->paragraph(1);
-    $html = '<p>' . $text . '</p>';
-
-    return [
-        'html'      => $html,
-        'text'      => $text,
-        'parent_id' => null,
-    ];
-});
diff --git a/database/factories/Uploads/ImageFactory.php b/database/factories/Uploads/ImageFactory.php
new file mode 100644
index 000000000..c6d0e0801
--- /dev/null
+++ b/database/factories/Uploads/ImageFactory.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Database\Factories\Uploads;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class ImageFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = \BookStack\Uploads\Image::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'name'        => $this->faker->slug . '.jpg',
+            'url'         => $this->faker->url,
+            'path'        => $this->faker->url,
+            'type'        => 'gallery',
+            'uploaded_to' => 0,
+        ];
+    }
+}
diff --git a/database/seeds/.gitkeep b/database/seeders/.gitkeep
similarity index 100%
rename from database/seeds/.gitkeep
rename to database/seeders/.gitkeep
diff --git a/database/seeds/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
similarity index 92%
rename from database/seeds/DatabaseSeeder.php
rename to database/seeders/DatabaseSeeder.php
index 069765eb4..21eaefb19 100644
--- a/database/seeds/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -1,5 +1,7 @@
 <?php
 
+namespace Database\Seeders;
+
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Seeder;
 
diff --git a/database/seeds/DummyContentSeeder.php b/database/seeders/DummyContentSeeder.php
similarity index 71%
rename from database/seeds/DummyContentSeeder.php
rename to database/seeders/DummyContentSeeder.php
index 7463a3b37..d54732b26 100644
--- a/database/seeds/DummyContentSeeder.php
+++ b/database/seeders/DummyContentSeeder.php
@@ -1,5 +1,7 @@
 <?php
 
+namespace Database\Seeders;
+
 use BookStack\Api\ApiToken;
 use BookStack\Auth\Permissions\PermissionService;
 use BookStack\Auth\Permissions\RolePermission;
@@ -10,6 +12,7 @@ use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Page;
 use BookStack\Entities\Tools\SearchIndex;
 use Illuminate\Database\Seeder;
+use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Str;
 
 class DummyContentSeeder extends Seeder
@@ -22,36 +25,36 @@ class DummyContentSeeder extends Seeder
     public function run()
     {
         // Create an editor user
-        $editorUser = factory(User::class)->create();
+        $editorUser = User::factory()->create();
         $editorRole = Role::getRole('editor');
         $editorUser->attachRole($editorRole);
 
         // Create a viewer user
-        $viewerUser = factory(User::class)->create();
+        $viewerUser = User::factory()->create();
         $role = Role::getRole('viewer');
         $viewerUser->attachRole($role);
 
         $byData = ['created_by' => $editorUser->id, 'updated_by' => $editorUser->id, 'owned_by' => $editorUser->id];
 
-        factory(\BookStack\Entities\Models\Book::class, 5)->create($byData)
+        \BookStack\Entities\Models\Book::factory()->count(5)->create($byData)
             ->each(function ($book) use ($byData) {
-                $chapters = factory(Chapter::class, 3)->create($byData)
+                $chapters = Chapter::factory()->count(3)->create($byData)
                     ->each(function ($chapter) use ($book, $byData) {
-                        $pages = factory(Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id]));
+                        $pages = Page::factory()->count(3)->make(array_merge($byData, ['book_id' => $book->id]));
                         $chapter->pages()->saveMany($pages);
                     });
-                $pages = factory(Page::class, 3)->make($byData);
+                $pages = Page::factory()->count(3)->make($byData);
                 $book->chapters()->saveMany($chapters);
                 $book->pages()->saveMany($pages);
             });
 
-        $largeBook = factory(\BookStack\Entities\Models\Book::class)->create(array_merge($byData, ['name' => 'Large book' . Str::random(10)]));
-        $pages = factory(Page::class, 200)->make($byData);
-        $chapters = factory(Chapter::class, 50)->make($byData);
+        $largeBook = \BookStack\Entities\Models\Book::factory()->create(array_merge($byData, ['name' => 'Large book' . Str::random(10)]));
+        $pages = Page::factory()->count(200)->make($byData);
+        $chapters = Chapter::factory()->count(50)->make($byData);
         $largeBook->pages()->saveMany($pages);
         $largeBook->chapters()->saveMany($chapters);
 
-        $shelves = factory(Bookshelf::class, 10)->create($byData);
+        $shelves = Bookshelf::factory()->count(10)->create($byData);
         $largeBook->shelves()->attach($shelves->pluck('id'));
 
         // Assign API permission to editor role and create an API key
diff --git a/database/seeds/LargeContentSeeder.php b/database/seeders/LargeContentSeeder.php
similarity index 60%
rename from database/seeds/LargeContentSeeder.php
rename to database/seeders/LargeContentSeeder.php
index 535626b8f..2fbf4a5c9 100644
--- a/database/seeds/LargeContentSeeder.php
+++ b/database/seeders/LargeContentSeeder.php
@@ -1,5 +1,7 @@
 <?php
 
+namespace Database\Seeders;
+
 use BookStack\Auth\Permissions\PermissionService;
 use BookStack\Auth\Role;
 use BookStack\Auth\User;
@@ -19,13 +21,13 @@ class LargeContentSeeder extends Seeder
     public function run()
     {
         // Create an editor user
-        $editorUser = factory(User::class)->create();
+        $editorUser = User::factory()->create();
         $editorRole = Role::getRole('editor');
         $editorUser->attachRole($editorRole);
 
-        $largeBook = factory(\BookStack\Entities\Models\Book::class)->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
-        $pages = factory(Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
-        $chapters = factory(Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
+        $largeBook = \BookStack\Entities\Models\Book::factory()->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
+        $pages = Page::factory()->count(200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
+        $chapters = Chapter::factory()->count(50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
         $largeBook->pages()->saveMany($pages);
         $largeBook->chapters()->saveMany($chapters);
         app(PermissionService::class)->buildJointPermissions();
diff --git a/public/index.php b/public/index.php
index 7e4ef97c7..c2f34d4bf 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1,21 +1,33 @@
 <?php
 
-/**
- * Laravel - A PHP Framework For Web Artisans.
- *
- * @author   Taylor Otwell <taylor@laravel.com>
- */
+use Illuminate\Contracts\Http\Kernel;
+use BookStack\Http\Request;
+
 define('LARAVEL_START', microtime(true));
 
+/*
+|--------------------------------------------------------------------------
+| Check If The Application Is Under Maintenance
+|--------------------------------------------------------------------------
+|
+| If the application is in maintenance / demo mode via the "down" command
+| we will load this file so that any pre-rendered content can be shown
+| instead of starting the framework, which could cause an exception.
+|
+*/
+
+if (file_exists(__DIR__ . '/../storage/framework/maintenance.php')) {
+    require __DIR__ . '/../storage/framework/maintenance.php';
+}
+
 /*
 |--------------------------------------------------------------------------
 | Register The Auto Loader
 |--------------------------------------------------------------------------
 |
 | Composer provides a convenient, automatically generated class loader for
-| our application. We just need to utilize it! We'll simply require it
-| into the script here so that we don't have to worry about manual
-| loading any of our classes later on. It feels great to relax.
+| this application. We just need to utilize it! We'll simply require it
+| into the script here so we don't need to manually load our classes.
 |
 */
 
@@ -23,37 +35,22 @@ require __DIR__ . '/../vendor/autoload.php';
 
 /*
 |--------------------------------------------------------------------------
-| Turn On The Lights
+| Run The Application
 |--------------------------------------------------------------------------
 |
-| We need to illuminate PHP development, so let us turn on the lights.
-| This bootstraps the framework and gets it ready for use, then it
-| will load up this application so that we can run it and send
-| the responses back to the browser and delight our users.
+| Once we have the application, we can handle the incoming request using
+| the application's HTTP kernel. Then, we will send the response back
+| to this client's browser, allowing them to enjoy our application.
 |
 */
 
 $app = require_once __DIR__ . '/../bootstrap/app.php';
-$app->alias('request', \BookStack\Http\Request::class);
+$app->alias('request', Request::class);
 
-/*
-|--------------------------------------------------------------------------
-| Run The Application
-|--------------------------------------------------------------------------
-|
-| Once we have the application, we can handle the incoming request
-| through the kernel, and send the associated response back to
-| the client's browser allowing them to enjoy the creative
-| and wonderful application we have prepared for them.
-|
-*/
+$kernel = $app->make(Kernel::class);
 
-$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
+$response = tap($kernel->handle(
+    $request = Request::capture()
+))->send();
 
-$response = $kernel->handle(
-    $request = \BookStack\Http\Request::capture()
-);
-
-$response->send();
-
-$kernel->terminate($request, $response);
+$kernel->terminate($request, $response);
\ No newline at end of file
diff --git a/routes/api.php b/routes/api.php
index 49521bb89..4ba499462 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -1,53 +1,64 @@
 <?php
 
+use BookStack\Http\Controllers\Api\ApiDocsController;
+use BookStack\Http\Controllers\Api\AttachmentApiController;
+use BookStack\Http\Controllers\Api\BookApiController;
+use BookStack\Http\Controllers\Api\BookExportApiController;
+use BookStack\Http\Controllers\Api\BookshelfApiController;
+use BookStack\Http\Controllers\Api\ChapterApiController;
+use BookStack\Http\Controllers\Api\ChapterExportApiController;
+use BookStack\Http\Controllers\Api\PageApiController;
+use BookStack\Http\Controllers\Api\PageExportApiController;
+use Illuminate\Support\Facades\Route;
+
 /**
  * Routes for the BookStack API.
  * Routes have a uri prefix of /api/.
  * Controllers are all within app/Http/Controllers/Api.
  */
-Route::get('docs.json', 'ApiDocsController@json');
+Route::get('docs.json', [ApiDocsController::class, 'json']);
 
-Route::get('attachments', 'AttachmentApiController@list');
-Route::post('attachments', 'AttachmentApiController@create');
-Route::get('attachments/{id}', 'AttachmentApiController@read');
-Route::put('attachments/{id}', 'AttachmentApiController@update');
-Route::delete('attachments/{id}', 'AttachmentApiController@delete');
+Route::get('attachments', [AttachmentApiController::class, 'list']);
+Route::post('attachments', [AttachmentApiController::class, 'create']);
+Route::get('attachments/{id}', [AttachmentApiController::class, 'read']);
+Route::put('attachments/{id}', [AttachmentApiController::class, 'update']);
+Route::delete('attachments/{id}', [AttachmentApiController::class, 'delete']);
 
-Route::get('books', 'BookApiController@list');
-Route::post('books', 'BookApiController@create');
-Route::get('books/{id}', 'BookApiController@read');
-Route::put('books/{id}', 'BookApiController@update');
-Route::delete('books/{id}', 'BookApiController@delete');
+Route::get('books', [BookApiController::class, 'list']);
+Route::post('books', [BookApiController::class, 'create']);
+Route::get('books/{id}', [BookApiController::class, 'read']);
+Route::put('books/{id}', [BookApiController::class, 'update']);
+Route::delete('books/{id}', [BookApiController::class, 'delete']);
 
-Route::get('books/{id}/export/html', 'BookExportApiController@exportHtml');
-Route::get('books/{id}/export/pdf', 'BookExportApiController@exportPdf');
-Route::get('books/{id}/export/plaintext', 'BookExportApiController@exportPlainText');
-Route::get('books/{id}/export/markdown', 'BookExportApiController@exportMarkdown');
+Route::get('books/{id}/export/html', [BookExportApiController::class, 'exportHtml']);
+Route::get('books/{id}/export/pdf', [BookExportApiController::class, 'exportPdf']);
+Route::get('books/{id}/export/plaintext', [BookExportApiController::class, 'exportPlainText']);
+Route::get('books/{id}/export/markdown', [BookExportApiController::class, 'exportMarkdown']);
 
-Route::get('chapters', 'ChapterApiController@list');
-Route::post('chapters', 'ChapterApiController@create');
-Route::get('chapters/{id}', 'ChapterApiController@read');
-Route::put('chapters/{id}', 'ChapterApiController@update');
-Route::delete('chapters/{id}', 'ChapterApiController@delete');
+Route::get('chapters', [ChapterApiController::class, 'list']);
+Route::post('chapters', [ChapterApiController::class, 'create']);
+Route::get('chapters/{id}', [ChapterApiController::class, 'read']);
+Route::put('chapters/{id}', [ChapterApiController::class, 'update']);
+Route::delete('chapters/{id}', [ChapterApiController::class, 'delete']);
 
-Route::get('chapters/{id}/export/html', 'ChapterExportApiController@exportHtml');
-Route::get('chapters/{id}/export/pdf', 'ChapterExportApiController@exportPdf');
-Route::get('chapters/{id}/export/plaintext', 'ChapterExportApiController@exportPlainText');
-Route::get('chapters/{id}/export/markdown', 'ChapterExportApiController@exportMarkdown');
+Route::get('chapters/{id}/export/html', [ChapterExportApiController::class, 'exportHtml']);
+Route::get('chapters/{id}/export/pdf', [ChapterExportApiController::class, 'exportPdf']);
+Route::get('chapters/{id}/export/plaintext', [ChapterExportApiController::class, 'exportPlainText']);
+Route::get('chapters/{id}/export/markdown', [ChapterExportApiController::class, 'exportMarkdown']);
 
-Route::get('pages', 'PageApiController@list');
-Route::post('pages', 'PageApiController@create');
-Route::get('pages/{id}', 'PageApiController@read');
-Route::put('pages/{id}', 'PageApiController@update');
-Route::delete('pages/{id}', 'PageApiController@delete');
+Route::get('pages', [PageApiController::class, 'list']);
+Route::post('pages', [PageApiController::class, 'create']);
+Route::get('pages/{id}', [PageApiController::class, 'read']);
+Route::put('pages/{id}', [PageApiController::class, 'update']);
+Route::delete('pages/{id}', [PageApiController::class, 'delete']);
 
-Route::get('pages/{id}/export/html', 'PageExportApiController@exportHtml');
-Route::get('pages/{id}/export/pdf', 'PageExportApiController@exportPdf');
-Route::get('pages/{id}/export/plaintext', 'PageExportApiController@exportPlainText');
-Route::get('pages/{id}/export/markdown', 'PageExportApiController@exportMarkDown');
+Route::get('pages/{id}/export/html', [PageExportApiController::class, 'exportHtml']);
+Route::get('pages/{id}/export/pdf', [PageExportApiController::class, 'exportPdf']);
+Route::get('pages/{id}/export/plaintext', [PageExportApiController::class, 'exportPlainText']);
+Route::get('pages/{id}/export/markdown', [PageExportApiController::class, 'exportMarkDown']);
 
-Route::get('shelves', 'BookshelfApiController@list');
-Route::post('shelves', 'BookshelfApiController@create');
-Route::get('shelves/{id}', 'BookshelfApiController@read');
-Route::put('shelves/{id}', 'BookshelfApiController@update');
-Route::delete('shelves/{id}', 'BookshelfApiController@delete');
+Route::get('shelves', [BookshelfApiController::class, 'list']);
+Route::post('shelves', [BookshelfApiController::class, 'create']);
+Route::get('shelves/{id}', [BookshelfApiController::class, 'read']);
+Route::put('shelves/{id}', [BookshelfApiController::class, 'update']);
+Route::delete('shelves/{id}', [BookshelfApiController::class, 'delete']);
diff --git a/routes/console.php b/routes/console.php
new file mode 100644
index 000000000..e05f4c9a1
--- /dev/null
+++ b/routes/console.php
@@ -0,0 +1,19 @@
+<?php
+
+use Illuminate\Foundation\Inspiring;
+use Illuminate\Support\Facades\Artisan;
+
+/*
+|--------------------------------------------------------------------------
+| Console Routes
+|--------------------------------------------------------------------------
+|
+| This file is where you may define all of your Closure based console
+| commands. Each Closure is bound to a command instance allowing a
+| simple approach to interacting with each command's IO methods.
+|
+*/
+
+Artisan::command('inspire', function () {
+    $this->comment(Inspiring::quote());
+})->purpose('Display an inspiring quote');
diff --git a/routes/web.php b/routes/web.php
index a5f35fb8a..419a1e7f5 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,287 +1,318 @@
 <?php
 
-Route::get('/status', 'StatusController@show');
-Route::get('/robots.txt', 'HomeController@robots');
+use BookStack\Http\Controllers\Api;
+use BookStack\Http\Controllers\AttachmentController;
+use BookStack\Http\Controllers\AuditLogController;
+use BookStack\Http\Controllers\Auth;
+use BookStack\Http\Controllers\BookController;
+use BookStack\Http\Controllers\BookExportController;
+use BookStack\Http\Controllers\BookshelfController;
+use BookStack\Http\Controllers\BookSortController;
+use BookStack\Http\Controllers\ChapterController;
+use BookStack\Http\Controllers\ChapterExportController;
+use BookStack\Http\Controllers\CommentController;
+use BookStack\Http\Controllers\FavouriteController;
+use BookStack\Http\Controllers\HomeController;
+use BookStack\Http\Controllers\Images;
+use BookStack\Http\Controllers\MaintenanceController;
+use BookStack\Http\Controllers\PageController;
+use BookStack\Http\Controllers\PageExportController;
+use BookStack\Http\Controllers\PageRevisionController;
+use BookStack\Http\Controllers\PageTemplateController;
+use BookStack\Http\Controllers\RecycleBinController;
+use BookStack\Http\Controllers\RoleController;
+use BookStack\Http\Controllers\SearchController;
+use BookStack\Http\Controllers\SettingController;
+use BookStack\Http\Controllers\StatusController;
+use BookStack\Http\Controllers\TagController;
+use BookStack\Http\Controllers\UserApiTokenController;
+use BookStack\Http\Controllers\UserController;
+use BookStack\Http\Controllers\UserProfileController;
+use BookStack\Http\Controllers\UserSearchController;
+use Illuminate\Support\Facades\Route;
+
+Route::get('/status', [StatusController::class, 'show']);
+Route::get('/robots.txt', [HomeController::class, 'robots']);
 
 // Authenticated routes...
-Route::group(['middleware' => 'auth'], function () {
+Route::middleware('auth')->group(function () {
 
     // Secure images routing
-    Route::get('/uploads/images/{path}', 'Images\ImageController@showImage')
+    Route::get('/uploads/images/{path}', [Images\ImageController::class, 'showImage'])
         ->where('path', '.*$');
 
     // API docs routes
-    Route::get('/api/docs', 'Api\ApiDocsController@display');
+    Route::get('/api/docs', [Api\ApiDocsController::class, 'display']);
 
-    Route::get('/pages/recently-updated', 'PageController@showRecentlyUpdated');
+    Route::get('/pages/recently-updated', [PageController::class, 'showRecentlyUpdated']);
 
     // Shelves
-    Route::get('/create-shelf', 'BookshelfController@create');
-    Route::group(['prefix' => 'shelves'], function () {
-        Route::get('/', 'BookshelfController@index');
-        Route::post('/', 'BookshelfController@store');
-        Route::get('/{slug}/edit', 'BookshelfController@edit');
-        Route::get('/{slug}/delete', 'BookshelfController@showDelete');
-        Route::get('/{slug}', 'BookshelfController@show');
-        Route::put('/{slug}', 'BookshelfController@update');
-        Route::delete('/{slug}', 'BookshelfController@destroy');
-        Route::get('/{slug}/permissions', 'BookshelfController@showPermissions');
-        Route::put('/{slug}/permissions', 'BookshelfController@permissions');
-        Route::post('/{slug}/copy-permissions', 'BookshelfController@copyPermissions');
+    Route::get('/create-shelf', [BookshelfController::class, 'create']);
+    Route::prefix('shelves')->group(function () {
+        Route::get('/', [BookshelfController::class, 'index']);
+        Route::post('/', [BookshelfController::class, 'store']);
+        Route::get('/{slug}/edit', [BookshelfController::class, 'edit']);
+        Route::get('/{slug}/delete', [BookshelfController::class, 'showDelete']);
+        Route::get('/{slug}', [BookshelfController::class, 'show']);
+        Route::put('/{slug}', [BookshelfController::class, 'update']);
+        Route::delete('/{slug}', [BookshelfController::class, 'destroy']);
+        Route::get('/{slug}/permissions', [BookshelfController::class, 'showPermissions']);
+        Route::put('/{slug}/permissions', [BookshelfController::class, 'permissions']);
+        Route::post('/{slug}/copy-permissions', [BookshelfController::class, 'copyPermissions']);
 
-        Route::get('/{shelfSlug}/create-book', 'BookController@create');
-        Route::post('/{shelfSlug}/create-book', 'BookController@store');
+        Route::get('/{shelfSlug}/create-book', [BookController::class, 'create']);
+        Route::post('/{shelfSlug}/create-book', [BookController::class, 'store']);
     });
 
-    Route::get('/create-book', 'BookController@create');
-    Route::group(['prefix' => 'books'], function () {
+    Route::get('/create-book', [BookController::class, 'create']);
+    Route::prefix('books')->group(function () {
 
         // Books
-        Route::get('/', 'BookController@index');
-        Route::post('/', 'BookController@store');
-        Route::get('/{slug}/edit', 'BookController@edit');
-        Route::put('/{slug}', 'BookController@update');
-        Route::delete('/{id}', 'BookController@destroy');
-        Route::get('/{slug}/sort-item', 'BookSortController@showItem');
-        Route::get('/{slug}', 'BookController@show');
-        Route::get('/{bookSlug}/permissions', 'BookController@showPermissions');
-        Route::put('/{bookSlug}/permissions', 'BookController@permissions');
-        Route::get('/{slug}/delete', 'BookController@showDelete');
-        Route::get('/{bookSlug}/sort', 'BookSortController@show');
-        Route::put('/{bookSlug}/sort', 'BookSortController@update');
-        Route::get('/{bookSlug}/export/html', 'BookExportController@html');
-        Route::get('/{bookSlug}/export/pdf', 'BookExportController@pdf');
-        Route::get('/{bookSlug}/export/markdown', 'BookExportController@markdown');
-        Route::get('/{bookSlug}/export/zip', 'BookExportController@zip');
-        Route::get('/{bookSlug}/export/plaintext', 'BookExportController@plainText');
+        Route::get('/', [BookController::class, 'index']);
+        Route::post('/', [BookController::class, 'store']);
+        Route::get('/{slug}/edit', [BookController::class, 'edit']);
+        Route::put('/{slug}', [BookController::class, 'update']);
+        Route::delete('/{id}', [BookController::class, 'destroy']);
+        Route::get('/{slug}/sort-item', [BookSortController::class, 'showItem']);
+        Route::get('/{slug}', [BookController::class, 'show']);
+        Route::get('/{bookSlug}/permissions', [BookController::class, 'showPermissions']);
+        Route::put('/{bookSlug}/permissions', [BookController::class, 'permissions']);
+        Route::get('/{slug}/delete', [BookController::class, 'showDelete']);
+        Route::get('/{bookSlug}/sort', [BookSortController::class, 'show']);
+        Route::put('/{bookSlug}/sort', [BookSortController::class, 'update']);
+        Route::get('/{bookSlug}/export/html', [BookExportController::class, 'html']);
+        Route::get('/{bookSlug}/export/pdf', [BookExportController::class, 'pdf']);
+        Route::get('/{bookSlug}/export/markdown', [BookExportController::class, 'markdown']);
+        Route::get('/{bookSlug}/export/zip', [BookExportController::class, 'zip']);
+        Route::get('/{bookSlug}/export/plaintext', [BookExportController::class, 'plainText']);
 
         // Pages
-        Route::get('/{bookSlug}/create-page', 'PageController@create');
-        Route::post('/{bookSlug}/create-guest-page', 'PageController@createAsGuest');
-        Route::get('/{bookSlug}/draft/{pageId}', 'PageController@editDraft');
-        Route::post('/{bookSlug}/draft/{pageId}', 'PageController@store');
-        Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show');
-        Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageExportController@pdf');
-        Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageExportController@html');
-        Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', 'PageExportController@markdown');
-        Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageExportController@plainText');
-        Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit');
-        Route::get('/{bookSlug}/page/{pageSlug}/move', 'PageController@showMove');
-        Route::put('/{bookSlug}/page/{pageSlug}/move', 'PageController@move');
-        Route::get('/{bookSlug}/page/{pageSlug}/copy', 'PageController@showCopy');
-        Route::post('/{bookSlug}/page/{pageSlug}/copy', 'PageController@copy');
-        Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete');
-        Route::get('/{bookSlug}/draft/{pageId}/delete', 'PageController@showDeleteDraft');
-        Route::get('/{bookSlug}/page/{pageSlug}/permissions', 'PageController@showPermissions');
-        Route::put('/{bookSlug}/page/{pageSlug}/permissions', 'PageController@permissions');
-        Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update');
-        Route::delete('/{bookSlug}/page/{pageSlug}', 'PageController@destroy');
-        Route::delete('/{bookSlug}/draft/{pageId}', 'PageController@destroyDraft');
+        Route::get('/{bookSlug}/create-page', [PageController::class, 'create']);
+        Route::post('/{bookSlug}/create-guest-page', [PageController::class, 'createAsGuest']);
+        Route::get('/{bookSlug}/draft/{pageId}', [PageController::class, 'editDraft']);
+        Route::post('/{bookSlug}/draft/{pageId}', [PageController::class, 'store']);
+        Route::get('/{bookSlug}/page/{pageSlug}', [PageController::class, 'show']);
+        Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', [PageExportController::class, 'pdf']);
+        Route::get('/{bookSlug}/page/{pageSlug}/export/html', [PageExportController::class, 'html']);
+        Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', [PageExportController::class, 'markdown']);
+        Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', [PageExportController::class, 'plainText']);
+        Route::get('/{bookSlug}/page/{pageSlug}/edit', [PageController::class, 'edit']);
+        Route::get('/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'showMove']);
+        Route::put('/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'move']);
+        Route::get('/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'showCopy']);
+        Route::post('/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'copy']);
+        Route::get('/{bookSlug}/page/{pageSlug}/delete', [PageController::class, 'showDelete']);
+        Route::get('/{bookSlug}/draft/{pageId}/delete', [PageController::class, 'showDeleteDraft']);
+        Route::get('/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'showPermissions']);
+        Route::put('/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'permissions']);
+        Route::put('/{bookSlug}/page/{pageSlug}', [PageController::class, 'update']);
+        Route::delete('/{bookSlug}/page/{pageSlug}', [PageController::class, 'destroy']);
+        Route::delete('/{bookSlug}/draft/{pageId}', [PageController::class, 'destroyDraft']);
 
         // Revisions
-        Route::get('/{bookSlug}/page/{pageSlug}/revisions', 'PageRevisionController@index');
-        Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', 'PageRevisionController@show');
-        Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', 'PageRevisionController@changes');
-        Route::put('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', 'PageRevisionController@restore');
-        Route::delete('/{bookSlug}/page/{pageSlug}/revisions/{revId}/delete', 'PageRevisionController@destroy');
+        Route::get('/{bookSlug}/page/{pageSlug}/revisions', [PageRevisionController::class, 'index']);
+        Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', [PageRevisionController::class, 'show']);
+        Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', [PageRevisionController::class, 'changes']);
+        Route::put('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', [PageRevisionController::class, 'restore']);
+        Route::delete('/{bookSlug}/page/{pageSlug}/revisions/{revId}/delete', [PageRevisionController::class, 'destroy']);
 
         // Chapters
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/create-page', 'PageController@create');
-        Route::post('/{bookSlug}/chapter/{chapterSlug}/create-guest-page', 'PageController@createAsGuest');
-        Route::get('/{bookSlug}/create-chapter', 'ChapterController@create');
-        Route::post('/{bookSlug}/create-chapter', 'ChapterController@store');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@show');
-        Route::put('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@update');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/move', 'ChapterController@showMove');
-        Route::put('/{bookSlug}/chapter/{chapterSlug}/move', 'ChapterController@move');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/edit', 'ChapterController@edit');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@showPermissions');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', 'ChapterExportController@pdf');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', 'ChapterExportController@html');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', 'ChapterExportController@markdown');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', 'ChapterExportController@plainText');
-        Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@permissions');
-        Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', 'ChapterController@showDelete');
-        Route::delete('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@destroy');
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/create-page', [PageController::class, 'create']);
+        Route::post('/{bookSlug}/chapter/{chapterSlug}/create-guest-page', [PageController::class, 'createAsGuest']);
+        Route::get('/{bookSlug}/create-chapter', [ChapterController::class, 'create']);
+        Route::post('/{bookSlug}/create-chapter', [ChapterController::class, 'store']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'show']);
+        Route::put('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'update']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'showMove']);
+        Route::put('/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'move']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/edit', [ChapterController::class, 'edit']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'showPermissions']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ChapterExportController::class, 'pdf']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', [ChapterExportController::class, 'html']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', [ChapterExportController::class, 'markdown']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', [ChapterExportController::class, 'plainText']);
+        Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'permissions']);
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', [ChapterController::class, 'showDelete']);
+        Route::delete('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'destroy']);
     });
 
     // User Profile routes
-    Route::get('/user/{slug}', 'UserProfileController@show');
+    Route::get('/user/{slug}', [UserProfileController::class, 'show']);
 
     // Image routes
-    Route::get('/images/gallery', 'Images\GalleryImageController@list');
-    Route::post('/images/gallery', 'Images\GalleryImageController@create');
-    Route::get('/images/drawio', 'Images\DrawioImageController@list');
-    Route::get('/images/drawio/base64/{id}', 'Images\DrawioImageController@getAsBase64');
-    Route::post('/images/drawio', 'Images\DrawioImageController@create');
-    Route::get('/images/edit/{id}', 'Images\ImageController@edit');
-    Route::put('/images/{id}', 'Images\ImageController@update');
-    Route::delete('/images/{id}', 'Images\ImageController@destroy');
+    Route::get('/images/gallery', [Images\GalleryImageController::class, 'list']);
+    Route::post('/images/gallery', [Images\GalleryImageController::class, 'create']);
+    Route::get('/images/drawio', [Images\DrawioImageController::class, 'list']);
+    Route::get('/images/drawio/base64/{id}', [Images\DrawioImageController::class, 'getAsBase64']);
+    Route::post('/images/drawio', [Images\DrawioImageController::class, 'create']);
+    Route::get('/images/edit/{id}', [Images\ImageController::class, 'edit']);
+    Route::put('/images/{id}', [Images\ImageController::class, 'update']);
+    Route::delete('/images/{id}', [Images\ImageController::class, 'destroy']);
 
     // Attachments routes
-    Route::get('/attachments/{id}', 'AttachmentController@get');
-    Route::post('/attachments/upload', 'AttachmentController@upload');
-    Route::post('/attachments/upload/{id}', 'AttachmentController@uploadUpdate');
-    Route::post('/attachments/link', 'AttachmentController@attachLink');
-    Route::put('/attachments/{id}', 'AttachmentController@update');
-    Route::get('/attachments/edit/{id}', 'AttachmentController@getUpdateForm');
-    Route::get('/attachments/get/page/{pageId}', 'AttachmentController@listForPage');
-    Route::put('/attachments/sort/page/{pageId}', 'AttachmentController@sortForPage');
-    Route::delete('/attachments/{id}', 'AttachmentController@delete');
+    Route::get('/attachments/{id}', [AttachmentController::class, 'get']);
+    Route::post('/attachments/upload', [AttachmentController::class, 'upload']);
+    Route::post('/attachments/upload/{id}', [AttachmentController::class, 'uploadUpdate']);
+    Route::post('/attachments/link', [AttachmentController::class, 'attachLink']);
+    Route::put('/attachments/{id}', [AttachmentController::class, 'update']);
+    Route::get('/attachments/edit/{id}', [AttachmentController::class, 'getUpdateForm']);
+    Route::get('/attachments/get/page/{pageId}', [AttachmentController::class, 'listForPage']);
+    Route::put('/attachments/sort/page/{pageId}', [AttachmentController::class, 'sortForPage']);
+    Route::delete('/attachments/{id}', [AttachmentController::class, 'delete']);
 
     // AJAX routes
-    Route::put('/ajax/page/{id}/save-draft', 'PageController@saveDraft');
-    Route::get('/ajax/page/{id}', 'PageController@getPageAjax');
-    Route::delete('/ajax/page/{id}', 'PageController@ajaxDestroy');
+    Route::put('/ajax/page/{id}/save-draft', [PageController::class, 'saveDraft']);
+    Route::get('/ajax/page/{id}', [PageController::class, 'getPageAjax']);
+    Route::delete('/ajax/page/{id}', [PageController::class, 'ajaxDestroy']);
 
     // Tag routes (AJAX)
-    Route::group(['prefix' => 'ajax/tags'], function () {
-        Route::get('/suggest/names', 'TagController@getNameSuggestions');
-        Route::get('/suggest/values', 'TagController@getValueSuggestions');
+    Route::prefix('ajax/tags')->group(function () {
+        Route::get('/suggest/names', [TagController::class, 'getNameSuggestions']);
+        Route::get('/suggest/values', [TagController::class, 'getValueSuggestions']);
     });
 
-    Route::get('/ajax/search/entities', 'SearchController@searchEntitiesAjax');
+    Route::get('/ajax/search/entities', [SearchController::class, 'searchEntitiesAjax']);
 
     // Comments
-    Route::post('/comment/{pageId}', 'CommentController@savePageComment');
-    Route::put('/comment/{id}', 'CommentController@update');
-    Route::delete('/comment/{id}', 'CommentController@destroy');
+    Route::post('/comment/{pageId}', [CommentController::class, 'savePageComment']);
+    Route::put('/comment/{id}', [CommentController::class, 'update']);
+    Route::delete('/comment/{id}', [CommentController::class, 'destroy']);
 
     // Links
-    Route::get('/link/{id}', 'PageController@redirectFromLink');
+    Route::get('/link/{id}', [PageController::class, 'redirectFromLink']);
 
     // Search
-    Route::get('/search', 'SearchController@search');
-    Route::get('/search/book/{bookId}', 'SearchController@searchBook');
-    Route::get('/search/chapter/{bookId}', 'SearchController@searchChapter');
-    Route::get('/search/entity/siblings', 'SearchController@searchSiblings');
+    Route::get('/search', [SearchController::class, 'search']);
+    Route::get('/search/book/{bookId}', [SearchController::class, 'searchBook']);
+    Route::get('/search/chapter/{bookId}', [SearchController::class, 'searchChapter']);
+    Route::get('/search/entity/siblings', [SearchController::class, 'searchSiblings']);
 
     // User Search
-    Route::get('/search/users/select', 'UserSearchController@forSelect');
+    Route::get('/search/users/select', [UserSearchController::class, 'forSelect']);
 
     // Template System
-    Route::get('/templates', 'PageTemplateController@list');
-    Route::get('/templates/{templateId}', 'PageTemplateController@get');
+    Route::get('/templates', [PageTemplateController::class, 'list']);
+    Route::get('/templates/{templateId}', [PageTemplateController::class, 'get']);
 
     // Favourites
-    Route::get('/favourites', 'FavouriteController@index');
-    Route::post('/favourites/add', 'FavouriteController@add');
-    Route::post('/favourites/remove', 'FavouriteController@remove');
+    Route::get('/favourites', [FavouriteController::class, 'index']);
+    Route::post('/favourites/add', [FavouriteController::class, 'add']);
+    Route::post('/favourites/remove', [FavouriteController::class, 'remove']);
 
     // Other Pages
-    Route::get('/', 'HomeController@index');
-    Route::get('/home', 'HomeController@index');
-    Route::get('/custom-head-content', 'HomeController@customHeadContent');
+    Route::get('/', [HomeController::class, 'index']);
+    Route::get('/home', [HomeController::class, 'index']);
+    Route::get('/custom-head-content', [HomeController::class, 'customHeadContent']);
 
     // Settings
-    Route::group(['prefix' => 'settings'], function () {
-        Route::get('/', 'SettingController@index')->name('settings');
-        Route::post('/', 'SettingController@update');
+    Route::prefix('settings')->group(function () {
+        Route::get('/', [SettingController::class, 'index'])->name('settings');
+        Route::post('/', [SettingController::class, 'update']);
 
         // Maintenance
-        Route::get('/maintenance', 'MaintenanceController@index');
-        Route::delete('/maintenance/cleanup-images', 'MaintenanceController@cleanupImages');
-        Route::post('/maintenance/send-test-email', 'MaintenanceController@sendTestEmail');
+        Route::get('/maintenance', [MaintenanceController::class, 'index']);
+        Route::delete('/maintenance/cleanup-images', [MaintenanceController::class, 'cleanupImages']);
+        Route::post('/maintenance/send-test-email', [MaintenanceController::class, 'sendTestEmail']);
 
         // Recycle Bin
-        Route::get('/recycle-bin', 'RecycleBinController@index');
-        Route::post('/recycle-bin/empty', 'RecycleBinController@empty');
-        Route::get('/recycle-bin/{id}/destroy', 'RecycleBinController@showDestroy');
-        Route::delete('/recycle-bin/{id}', 'RecycleBinController@destroy');
-        Route::get('/recycle-bin/{id}/restore', 'RecycleBinController@showRestore');
-        Route::post('/recycle-bin/{id}/restore', 'RecycleBinController@restore');
+        Route::get('/recycle-bin', [RecycleBinController::class, 'index']);
+        Route::post('/recycle-bin/empty', [RecycleBinController::class, 'empty']);
+        Route::get('/recycle-bin/{id}/destroy', [RecycleBinController::class, 'showDestroy']);
+        Route::delete('/recycle-bin/{id}', [RecycleBinController::class, 'destroy']);
+        Route::get('/recycle-bin/{id}/restore', [RecycleBinController::class, 'showRestore']);
+        Route::post('/recycle-bin/{id}/restore', [RecycleBinController::class, 'restore']);
 
         // Audit Log
-        Route::get('/audit', 'AuditLogController@index');
+        Route::get('/audit', [AuditLogController::class, 'index']);
 
         // Users
-        Route::get('/users', 'UserController@index');
-        Route::get('/users/create', 'UserController@create');
-        Route::get('/users/{id}/delete', 'UserController@delete');
-        Route::patch('/users/{id}/switch-books-view', 'UserController@switchBooksView');
-        Route::patch('/users/{id}/switch-shelves-view', 'UserController@switchShelvesView');
-        Route::patch('/users/{id}/switch-shelf-view', 'UserController@switchShelfView');
-        Route::patch('/users/{id}/change-sort/{type}', 'UserController@changeSort');
-        Route::patch('/users/{id}/update-expansion-preference/{key}', 'UserController@updateExpansionPreference');
-        Route::patch('/users/toggle-dark-mode', 'UserController@toggleDarkMode');
-        Route::post('/users/create', 'UserController@store');
-        Route::get('/users/{id}', 'UserController@edit');
-        Route::put('/users/{id}', 'UserController@update');
-        Route::delete('/users/{id}', 'UserController@destroy');
+        Route::get('/users', [UserController::class, 'index']);
+        Route::get('/users/create', [UserController::class, 'create']);
+        Route::get('/users/{id}/delete', [UserController::class, 'delete']);
+        Route::patch('/users/{id}/switch-books-view', [UserController::class, 'switchBooksView']);
+        Route::patch('/users/{id}/switch-shelves-view', [UserController::class, 'switchShelvesView']);
+        Route::patch('/users/{id}/switch-shelf-view', [UserController::class, 'switchShelfView']);
+        Route::patch('/users/{id}/change-sort/{type}', [UserController::class, 'changeSort']);
+        Route::patch('/users/{id}/update-expansion-preference/{key}', [UserController::class, 'updateExpansionPreference']);
+        Route::patch('/users/toggle-dark-mode', [UserController::class, 'toggleDarkMode']);
+        Route::post('/users/create', [UserController::class, 'store']);
+        Route::get('/users/{id}', [UserController::class, 'edit']);
+        Route::put('/users/{id}', [UserController::class, 'update']);
+        Route::delete('/users/{id}', [UserController::class, 'destroy']);
 
         // User API Tokens
-        Route::get('/users/{userId}/create-api-token', 'UserApiTokenController@create');
-        Route::post('/users/{userId}/create-api-token', 'UserApiTokenController@store');
-        Route::get('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@edit');
-        Route::put('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@update');
-        Route::get('/users/{userId}/api-tokens/{tokenId}/delete', 'UserApiTokenController@delete');
-        Route::delete('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@destroy');
+        Route::get('/users/{userId}/create-api-token', [UserApiTokenController::class, 'create']);
+        Route::post('/users/{userId}/create-api-token', [UserApiTokenController::class, 'store']);
+        Route::get('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'edit']);
+        Route::put('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'update']);
+        Route::get('/users/{userId}/api-tokens/{tokenId}/delete', [UserApiTokenController::class, 'delete']);
+        Route::delete('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'destroy']);
 
         // Roles
-        Route::get('/roles', 'RoleController@list');
-        Route::get('/roles/new', 'RoleController@create');
-        Route::post('/roles/new', 'RoleController@store');
-        Route::get('/roles/delete/{id}', 'RoleController@showDelete');
-        Route::delete('/roles/delete/{id}', 'RoleController@delete');
-        Route::get('/roles/{id}', 'RoleController@edit');
-        Route::put('/roles/{id}', 'RoleController@update');
+        Route::get('/roles', [RoleController::class, 'list']);
+        Route::get('/roles/new', [RoleController::class, 'create']);
+        Route::post('/roles/new', [RoleController::class, 'store']);
+        Route::get('/roles/delete/{id}', [RoleController::class, 'showDelete']);
+        Route::delete('/roles/delete/{id}', [RoleController::class, 'delete']);
+        Route::get('/roles/{id}', [RoleController::class, 'edit']);
+        Route::put('/roles/{id}', [RoleController::class, 'update']);
     });
 });
 
 // MFA routes
-Route::group(['middleware' => 'mfa-setup'], function () {
-    Route::get('/mfa/setup', 'Auth\MfaController@setup');
-    Route::get('/mfa/totp/generate', 'Auth\MfaTotpController@generate');
-    Route::post('/mfa/totp/confirm', 'Auth\MfaTotpController@confirm');
-    Route::get('/mfa/backup_codes/generate', 'Auth\MfaBackupCodesController@generate');
-    Route::post('/mfa/backup_codes/confirm', 'Auth\MfaBackupCodesController@confirm');
+Route::middleware('mfa-setup')->group(function () {
+    Route::get('/mfa/setup', [Auth\MfaController::class, 'setup']);
+    Route::get('/mfa/totp/generate', [Auth\MfaTotpController::class, 'generate']);
+    Route::post('/mfa/totp/confirm', [Auth\MfaTotpController::class, 'confirm']);
+    Route::get('/mfa/backup_codes/generate', [Auth\MfaBackupCodesController::class, 'generate']);
+    Route::post('/mfa/backup_codes/confirm', [Auth\MfaBackupCodesController::class, 'confirm']);
 });
-Route::group(['middleware' => 'guest'], function () {
-    Route::get('/mfa/verify', 'Auth\MfaController@verify');
-    Route::post('/mfa/totp/verify', 'Auth\MfaTotpController@verify');
-    Route::post('/mfa/backup_codes/verify', 'Auth\MfaBackupCodesController@verify');
+Route::middleware('guest')->group(function () {
+    Route::get('/mfa/verify', [Auth\MfaController::class, 'verify']);
+    Route::post('/mfa/totp/verify', [Auth\MfaTotpController::class, 'verify']);
+    Route::post('/mfa/backup_codes/verify', [Auth\MfaBackupCodesController::class, 'verify']);
 });
-Route::delete('/mfa/{method}/remove', 'Auth\MfaController@remove')->middleware('auth');
+Route::delete('/mfa/{method}/remove', [Auth\MfaController::class, 'remove'])->middleware('auth');
 
 // Social auth routes
-Route::get('/login/service/{socialDriver}', 'Auth\SocialController@login');
-Route::get('/login/service/{socialDriver}/callback', 'Auth\SocialController@callback');
-Route::post('/login/service/{socialDriver}/detach', 'Auth\SocialController@detach')->middleware('auth');
-Route::get('/register/service/{socialDriver}', 'Auth\SocialController@register');
+Route::get('/login/service/{socialDriver}', [Auth\SocialController::class, 'login']);
+Route::get('/login/service/{socialDriver}/callback', [Auth\SocialController::class, 'callback']);
+Route::post('/login/service/{socialDriver}/detach', [Auth\SocialController::class, 'detach'])->middleware('auth');
+Route::get('/register/service/{socialDriver}', [Auth\SocialController::class, 'register']);
 
 // Login/Logout routes
-Route::get('/login', 'Auth\LoginController@getLogin');
-Route::post('/login', 'Auth\LoginController@login');
-Route::get('/logout', 'Auth\LoginController@logout');
-Route::get('/register', 'Auth\RegisterController@getRegister');
-Route::get('/register/confirm', 'Auth\ConfirmEmailController@show');
-Route::get('/register/confirm/awaiting', 'Auth\ConfirmEmailController@showAwaiting');
-Route::post('/register/confirm/resend', 'Auth\ConfirmEmailController@resend');
-Route::get('/register/confirm/{token}', 'Auth\ConfirmEmailController@confirm');
-Route::post('/register', 'Auth\RegisterController@postRegister');
+Route::get('/login', [Auth\LoginController::class, 'getLogin']);
+Route::post('/login', [Auth\LoginController::class, 'login']);
+Route::get('/logout', [Auth\LoginController::class, 'logout']);
+Route::get('/register', [Auth\RegisterController::class, 'getRegister']);
+Route::get('/register/confirm', [Auth\ConfirmEmailController::class, 'show']);
+Route::get('/register/confirm/awaiting', [Auth\ConfirmEmailController::class, 'showAwaiting']);
+Route::post('/register/confirm/resend', [Auth\ConfirmEmailController::class, 'resend']);
+Route::get('/register/confirm/{token}', [Auth\ConfirmEmailController::class, 'confirm']);
+Route::post('/register', [Auth\RegisterController::class, 'postRegister']);
 
 // SAML routes
-Route::post('/saml2/login', 'Auth\Saml2Controller@login');
-Route::get('/saml2/logout', 'Auth\Saml2Controller@logout');
-Route::get('/saml2/metadata', 'Auth\Saml2Controller@metadata');
-Route::get('/saml2/sls', 'Auth\Saml2Controller@sls');
-Route::post('/saml2/acs', 'Auth\Saml2Controller@startAcs');
-Route::get('/saml2/acs', 'Auth\Saml2Controller@processAcs');
+Route::post('/saml2/login', [Auth\Saml2Controller::class, 'login']);
+Route::get('/saml2/logout', [Auth\Saml2Controller::class, 'logout']);
+Route::get('/saml2/metadata', [Auth\Saml2Controller::class, 'metadata']);
+Route::get('/saml2/sls', [Auth\Saml2Controller::class, 'sls']);
+Route::post('/saml2/acs', [Auth\Saml2Controller::class, 'startAcs']);
+Route::get('/saml2/acs', [Auth\Saml2Controller::class, 'processAcs']);
 
 // OIDC routes
-Route::post('/oidc/login', 'Auth\OidcController@login');
-Route::get('/oidc/callback', 'Auth\OidcController@callback');
+Route::post('/oidc/login', [Auth\OidcController::class, 'login']);
+Route::get('/oidc/callback', [Auth\OidcController::class, 'callback']);
 
 // User invitation routes
-Route::get('/register/invite/{token}', 'Auth\UserInviteController@showSetPassword');
-Route::post('/register/invite/{token}', 'Auth\UserInviteController@setPassword');
+Route::get('/register/invite/{token}', [Auth\UserInviteController::class, 'showSetPassword']);
+Route::post('/register/invite/{token}', [Auth\UserInviteController::class, 'setPassword']);
 
 // Password reset link request routes...
-Route::get('/password/email', 'Auth\ForgotPasswordController@showLinkRequestForm');
-Route::post('/password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
+Route::get('/password/email', [Auth\ForgotPasswordController::class, 'showLinkRequestForm']);
+Route::post('/password/email', [Auth\ForgotPasswordController::class, 'sendResetLinkEmail']);
 
 // Password reset routes...
-Route::get('/password/reset/{token}', 'Auth\ResetPasswordController@showResetForm');
-Route::post('/password/reset', 'Auth\ResetPasswordController@reset');
+Route::get('/password/reset/{token}', [Auth\ResetPasswordController::class, 'showResetForm']);
+Route::post('/password/reset', [Auth\ResetPasswordController::class, 'reset']);
 
-Route::fallback('HomeController@notFound')->name('fallback');
+Route::fallback([HomeController::class, 'notFound'])->name('fallback');
diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore
index 953edb7a9..05c4471f2 100755
--- a/storage/framework/.gitignore
+++ b/storage/framework/.gitignore
@@ -1,7 +1,9 @@
-config.php
-routes.php
 compiled.php
-services.json
-events.scanned.php
-routes.scanned.php
+config.php
 down
+events.scanned.php
+maintenance.php
+routes.php
+routes.scanned.php
+schedule-*
+services.json
diff --git a/tests/AuditLogTest.php b/tests/AuditLogTest.php
index 8d13670ca..f909cd79a 100644
--- a/tests/AuditLogTest.php
+++ b/tests/AuditLogTest.php
@@ -17,7 +17,7 @@ class AuditLogTest extends TestCase
     /** @var ActivityService */
     protected $activityService;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->activityService = app(ActivityService::class);
diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php
index 79f00bed0..66ab09d3c 100644
--- a/tests/Auth/AuthTest.php
+++ b/tests/Auth/AuthTest.php
@@ -44,7 +44,7 @@ class AuthTest extends TestCase
     {
         // Set settings and get user instance
         $this->setSettings(['registration-enabled' => 'true']);
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
 
         // Test form and ensure user is created
         $this->get('/register')
@@ -102,7 +102,7 @@ class AuthTest extends TestCase
 
         // Set settings and get user instance
         $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']);
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
 
         // Go through registration process
         $resp = $this->post('/register', $user->only('name', 'email', 'password'));
@@ -140,7 +140,7 @@ class AuthTest extends TestCase
     public function test_restricted_registration()
     {
         $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true', 'registration-restrict' => 'example.com']);
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
 
         // Go through registration process
         $this->post('/register', $user->only('name', 'email', 'password'))
@@ -166,7 +166,7 @@ class AuthTest extends TestCase
     public function test_restricted_registration_with_confirmation_disabled()
     {
         $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'false', 'registration-restrict' => 'example.com']);
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
 
         // Go through registration process
         $this->post('/register', $user->only('name', 'email', 'password'))
diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php
index 9e0729a8e..d00e8cf15 100644
--- a/tests/Auth/LdapTest.php
+++ b/tests/Auth/LdapTest.php
@@ -20,7 +20,7 @@ class LdapTest extends TestCase
     protected $mockUser;
     protected $resourceId = 'resource-test';
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         if (!defined('LDAP_OPT_REFERRALS')) {
@@ -42,7 +42,7 @@ class LdapTest extends TestCase
         ]);
         $this->mockLdap = \Mockery::mock(Ldap::class);
         $this->app[Ldap::class] = $this->mockLdap;
-        $this->mockUser = factory(User::class)->make();
+        $this->mockUser = User::factory()->make();
     }
 
     protected function runFailedAuthLogin()
@@ -264,9 +264,9 @@ class LdapTest extends TestCase
 
     public function test_login_maps_roles_and_retains_existing_roles()
     {
-        $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
-        $roleToReceive2 = factory(Role::class)->create(['display_name' => 'LdapTester Second']);
-        $existingRole = factory(Role::class)->create(['display_name' => 'ldaptester-existing']);
+        $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']);
+        $roleToReceive2 = Role::factory()->create(['display_name' => 'LdapTester Second']);
+        $existingRole = Role::factory()->create(['display_name' => 'ldaptester-existing']);
         $this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
         $this->mockUser->attachRole($existingRole);
 
@@ -310,8 +310,8 @@ class LdapTest extends TestCase
 
     public function test_login_maps_roles_and_removes_old_roles_if_set()
     {
-        $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
-        $existingRole = factory(Role::class)->create(['display_name' => 'ldaptester-existing']);
+        $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']);
+        $existingRole = Role::factory()->create(['display_name' => 'ldaptester-existing']);
         $this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
         $this->mockUser->attachRole($existingRole);
 
@@ -350,15 +350,15 @@ class LdapTest extends TestCase
 
     public function test_external_auth_id_visible_in_roles_page_when_ldap_active()
     {
-        $role = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']);
+        $role = Role::factory()->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']);
         $this->asAdmin()->get('/settings/roles/' . $role->id)
             ->assertSee('ex-auth-a');
     }
 
     public function test_login_maps_roles_using_external_auth_ids_if_set()
     {
-        $roleToReceive = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'test-second-param, ex-auth-a']);
-        $roleToNotReceive = factory(Role::class)->create(['display_name' => 'ex-auth-a', 'external_auth_id' => 'test-second-param']);
+        $roleToReceive = Role::factory()->create(['display_name' => 'ldaptester', 'external_auth_id' => 'test-second-param, ex-auth-a']);
+        $roleToNotReceive = Role::factory()->create(['display_name' => 'ex-auth-a', 'external_auth_id' => 'test-second-param']);
 
         app('config')->set([
             'services.ldap.user_to_groups'     => true,
@@ -395,8 +395,8 @@ class LdapTest extends TestCase
 
     public function test_login_group_mapping_does_not_conflict_with_default_role()
     {
-        $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
-        $roleToReceive2 = factory(Role::class)->create(['display_name' => 'LdapTester Second']);
+        $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']);
+        $roleToReceive2 = Role::factory()->create(['display_name' => 'LdapTester Second']);
         $this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
 
         setting()->put('registration-role', $roleToReceive->id);
@@ -641,8 +641,8 @@ class LdapTest extends TestCase
 
     public function test_login_with_email_confirmation_required_maps_groups_but_shows_confirmation_screen()
     {
-        $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
-        $user = factory(User::class)->make();
+        $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']);
+        $user = User::factory()->make();
         setting()->put('registration-confirmation', 'true');
 
         app('config')->set([
diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php
index 6c806aa8e..e7665a679 100644
--- a/tests/Auth/OidcTest.php
+++ b/tests/Auth/OidcTest.php
@@ -16,7 +16,7 @@ class OidcTest extends TestCase
     protected $keyFilePath;
     protected $keyFile;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         // Set default config for OpenID Connect
@@ -41,7 +41,7 @@ class OidcTest extends TestCase
         ]);
     }
 
-    public function tearDown(): void
+    protected function tearDown(): void
     {
         parent::tearDown();
         if (file_exists($this->keyFilePath)) {
diff --git a/tests/Auth/Saml2Test.php b/tests/Auth/Saml2Test.php
index c534b2d78..aac2710a8 100644
--- a/tests/Auth/Saml2Test.php
+++ b/tests/Auth/Saml2Test.php
@@ -8,7 +8,7 @@ use Tests\TestCase;
 
 class Saml2Test extends TestCase
 {
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         // Set default config for SAML2
@@ -119,7 +119,7 @@ class Saml2Test extends TestCase
             'saml2.remove_from_groups' => false,
         ]);
 
-        $memberRole = factory(Role::class)->create(['external_auth_id' => 'member']);
+        $memberRole = Role::factory()->create(['external_auth_id' => 'member']);
         $adminRole = Role::getSystemRole('admin');
 
         $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]);
@@ -141,7 +141,7 @@ class Saml2Test extends TestCase
         $acsPost = $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]);
         $user = User::query()->where('external_auth_id', '=', 'user')->first();
 
-        $randomRole = factory(Role::class)->create(['external_auth_id' => 'random']);
+        $randomRole = Role::factory()->create(['external_auth_id' => 'random']);
         $user->attachRole($randomRole);
         $this->assertContains($randomRole->id, $user->roles()->pluck('id'));
 
@@ -295,7 +295,7 @@ class Saml2Test extends TestCase
             'saml2.remove_from_groups' => false,
         ]);
 
-        $memberRole = factory(Role::class)->create(['external_auth_id' => 'member']);
+        $memberRole = Role::factory()->create(['external_auth_id' => 'member']);
         $adminRole = Role::getSystemRole('admin');
 
         $acsPost = $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]);
diff --git a/tests/Auth/SocialAuthTest.php b/tests/Auth/SocialAuthTest.php
index f70263dd2..90d7e37aa 100644
--- a/tests/Auth/SocialAuthTest.php
+++ b/tests/Auth/SocialAuthTest.php
@@ -15,7 +15,7 @@ class SocialAuthTest extends TestCase
 {
     public function test_social_registration()
     {
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
 
         $this->setSettings(['registration-enabled' => 'true']);
         config(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
@@ -118,7 +118,7 @@ class SocialAuthTest extends TestCase
             'APP_URL'                   => 'http://localhost',
         ]);
 
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
@@ -156,7 +156,7 @@ class SocialAuthTest extends TestCase
             'APP_URL'                   => 'http://localhost', 'services.google.auto_register' => true, 'services.google.auto_confirm' => true,
         ]);
 
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
@@ -188,7 +188,7 @@ class SocialAuthTest extends TestCase
 
     public function test_social_registration_with_no_name_uses_email_as_name()
     {
-        $user = factory(User::class)->make(['email' => 'nonameuser@example.com']);
+        $user = User::factory()->make(['email' => 'nonameuser@example.com']);
 
         $this->setSettings(['registration-enabled' => 'true']);
         config(['GITHUB_APP_ID' => 'abc123', 'GITHUB_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php
index afd6a1a06..fcbc17ea9 100644
--- a/tests/Entity/BookShelfTest.php
+++ b/tests/Entity/BookShelfTest.php
@@ -37,7 +37,7 @@ class BookShelfTest extends TestCase
 
     public function test_shelves_shows_in_header_if_have_any_shelve_view_permission()
     {
-        $user = factory(User::class)->create();
+        $user = User::factory()->create();
         $this->giveUserPermissions($user, ['image-create-all']);
         $shelf = Bookshelf::first();
         $userRole = $user->roles()->first();
diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php
index 53ee6faf9..2894fbb98 100644
--- a/tests/Entity/BookTest.php
+++ b/tests/Entity/BookTest.php
@@ -9,7 +9,7 @@ class BookTest extends TestCase
 {
     public function test_create()
     {
-        $book = factory(Book::class)->make([
+        $book = Book::factory()->make([
             'name' => 'My First Book',
         ]);
 
@@ -29,7 +29,7 @@ class BookTest extends TestCase
 
     public function test_create_uses_different_slugs_when_name_reused()
     {
-        $book = factory(Book::class)->make([
+        $book = Book::factory()->make([
             'name' => 'My First Book',
         ]);
 
diff --git a/tests/Entity/ChapterTest.php b/tests/Entity/ChapterTest.php
index ea29ece5d..9868dc030 100644
--- a/tests/Entity/ChapterTest.php
+++ b/tests/Entity/ChapterTest.php
@@ -13,7 +13,7 @@ class ChapterTest extends TestCase
         /** @var Book $book */
         $book = Book::query()->first();
 
-        $chapter = factory(Chapter::class)->make([
+        $chapter = Chapter::factory()->make([
             'name' => 'My First Chapter',
         ]);
 
diff --git a/tests/Entity/CommentSettingTest.php b/tests/Entity/CommentSettingTest.php
index d8caa7358..23607f5a7 100644
--- a/tests/Entity/CommentSettingTest.php
+++ b/tests/Entity/CommentSettingTest.php
@@ -9,7 +9,7 @@ class CommentSettingTest extends TestCase
 {
     protected $page;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->page = Page::query()->first();
diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php
index b613f80a1..1e8ecbcac 100644
--- a/tests/Entity/CommentTest.php
+++ b/tests/Entity/CommentTest.php
@@ -13,7 +13,7 @@ class CommentTest extends TestCase
         $this->asAdmin();
         $page = Page::first();
 
-        $comment = factory(Comment::class)->make(['parent_id' => 2]);
+        $comment = Comment::factory()->make(['parent_id' => 2]);
         $resp = $this->postJson("/comment/$page->id", $comment->getAttributes());
 
         $resp->assertStatus(200);
@@ -36,7 +36,7 @@ class CommentTest extends TestCase
         $this->asAdmin();
         $page = Page::first();
 
-        $comment = factory(Comment::class)->make();
+        $comment = Comment::factory()->make();
         $this->postJson("/comment/$page->id", $comment->getAttributes());
 
         $comment = $page->comments()->first();
@@ -60,7 +60,7 @@ class CommentTest extends TestCase
         $this->asAdmin();
         $page = Page::first();
 
-        $comment = factory(Comment::class)->make();
+        $comment = Comment::factory()->make();
         $this->postJson("/comment/$page->id", $comment->getAttributes());
 
         $comment = $page->comments()->first();
diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php
index 4fb7d7ab6..9e2ceff51 100644
--- a/tests/Entity/PageDraftTest.php
+++ b/tests/Entity/PageDraftTest.php
@@ -20,7 +20,7 @@ class PageDraftTest extends TestCase
      */
     protected $pageRepo;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->page = Page::query()->first();
diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php
index 9b0a8f188..652bc1336 100644
--- a/tests/Entity/PageEditorTest.php
+++ b/tests/Entity/PageEditorTest.php
@@ -11,7 +11,7 @@ class PageEditorTest extends TestCase
     /** @var Page */
     protected $page;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->page = Page::query()->first();
diff --git a/tests/Entity/PageTest.php b/tests/Entity/PageTest.php
index 313fc77f0..32459a84a 100644
--- a/tests/Entity/PageTest.php
+++ b/tests/Entity/PageTest.php
@@ -14,7 +14,7 @@ class PageTest extends TestCase
     {
         /** @var Chapter $chapter */
         $chapter = Chapter::query()->first();
-        $page = factory(Page::class)->make([
+        $page = Page::factory()->make([
             'name' => 'My First Page',
         ]);
 
diff --git a/tests/Entity/SortTest.php b/tests/Entity/SortTest.php
index 5cfc5c3c5..89279bfcf 100644
--- a/tests/Entity/SortTest.php
+++ b/tests/Entity/SortTest.php
@@ -12,7 +12,7 @@ class SortTest extends TestCase
 {
     protected $book;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->book = Book::first();
diff --git a/tests/Entity/TagTest.php b/tests/Entity/TagTest.php
index 74da37f4a..9b3fb1532 100644
--- a/tests/Entity/TagTest.php
+++ b/tests/Entity/TagTest.php
@@ -19,7 +19,7 @@ class TagTest extends TestCase
         $entity = $class::first();
 
         if (is_null($tags)) {
-            $tags = factory(Tag::class, $this->defaultTagCount)->make();
+            $tags = Tag::factory()->count($this->defaultTagCount)->make();
         }
 
         $entity->tags()->saveMany($tags);
@@ -31,63 +31,63 @@ class TagTest extends TestCase
     {
         // Create some tags with similar names to test with
         $attrs = collect();
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'city']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'city']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'county']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'planet']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'plans']));
         $page = $this->getEntityWithTags(Page::class, $attrs->all());
 
-        $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->assertExactJson([]);
-        $this->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country', 'county']);
-        $this->get('/ajax/tags/suggest/names?search=cou')->assertExactJson(['country', 'county']);
-        $this->get('/ajax/tags/suggest/names?search=pla')->assertExactJson(['planet', 'plans']);
+        $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->assertSimilarJson([]);
+        $this->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country', 'county']);
+        $this->get('/ajax/tags/suggest/names?search=cou')->assertSimilarJson(['country', 'county']);
+        $this->get('/ajax/tags/suggest/names?search=pla')->assertSimilarJson(['planet', 'plans']);
     }
 
     public function test_tag_value_suggestions()
     {
         // Create some tags with similar values to test with
         $attrs = collect();
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country', 'value' => 'cats']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color', 'value' => 'cattery']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'city', 'value' => 'castle']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county', 'value' => 'dog']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet', 'value' => 'catapult']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans', 'value' => 'dodgy']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country', 'value' => 'cats']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color', 'value' => 'cattery']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'city', 'value' => 'castle']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'county', 'value' => 'dog']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'planet', 'value' => 'catapult']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'plans', 'value' => 'dodgy']));
         $page = $this->getEntityWithTags(Page::class, $attrs->all());
 
-        $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->assertExactJson([]);
-        $this->get('/ajax/tags/suggest/values?search=cat')->assertExactJson(['cats', 'cattery', 'catapult']);
-        $this->get('/ajax/tags/suggest/values?search=do')->assertExactJson(['dog', 'dodgy']);
-        $this->get('/ajax/tags/suggest/values?search=cas')->assertExactJson(['castle']);
+        $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->assertSimilarJson([]);
+        $this->get('/ajax/tags/suggest/values?search=cat')->assertSimilarJson(['cats', 'cattery', 'catapult']);
+        $this->get('/ajax/tags/suggest/values?search=do')->assertSimilarJson(['dog', 'dodgy']);
+        $this->get('/ajax/tags/suggest/values?search=cas')->assertSimilarJson(['castle']);
     }
 
     public function test_entity_permissions_effect_tag_suggestions()
     {
         // Create some tags with similar names to test with and save to a page
         $attrs = collect();
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color']));
         $page = $this->getEntityWithTags(Page::class, $attrs->all());
 
-        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']);
-        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']);
+        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
+        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
 
         // Set restricted permission the page
         $page->restricted = true;
         $page->save();
         $page->rebuildPermissions();
 
-        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']);
-        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertExactJson([]);
+        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
+        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson([]);
     }
 
     public function test_tags_shown_on_search_listing()
     {
         $tags = [
-            factory(Tag::class)->make(['name' => 'category', 'value' => 'buckets']),
-            factory(Tag::class)->make(['name' => 'color', 'value' => 'red']),
+            Tag::factory()->make(['name' => 'category', 'value' => 'buckets']),
+            Tag::factory()->make(['name' => 'color', 'value' => 'red']),
         ];
 
         $page = $this->getEntityWithTags(Page::class, $tags);
diff --git a/tests/HomepageTest.php b/tests/HomepageTest.php
index e27b78774..dc1b22779 100644
--- a/tests/HomepageTest.php
+++ b/tests/HomepageTest.php
@@ -167,7 +167,7 @@ class HomepageTest extends TestCase
 
     public function test_new_users_dont_have_any_recently_viewed()
     {
-        $user = factory(User::class)->create();
+        $user = User::factory()->create();
         $viewRole = Role::getRole('Viewer');
         $user->attachRole($viewRole);
 
diff --git a/tests/LanguageTest.php b/tests/LanguageTest.php
index a9070248e..ef44af0ee 100644
--- a/tests/LanguageTest.php
+++ b/tests/LanguageTest.php
@@ -9,7 +9,7 @@ class LanguageTest extends TestCase
     /**
      * LanguageTest constructor.
      */
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->langs = array_diff(scandir(resource_path('lang')), ['..', '.']);
diff --git a/tests/Permissions/EntityPermissionsTest.php b/tests/Permissions/EntityPermissionsTest.php
index bb011cfc6..96d4792b9 100644
--- a/tests/Permissions/EntityPermissionsTest.php
+++ b/tests/Permissions/EntityPermissionsTest.php
@@ -23,7 +23,7 @@ class EntityPermissionsTest extends TestCase
      */
     protected $viewer;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->user = $this->getEditor();
diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php
index 3178bd8ce..c880bdd00 100644
--- a/tests/Permissions/RolesTest.php
+++ b/tests/Permissions/RolesTest.php
@@ -19,7 +19,7 @@ class RolesTest extends TestCase
 {
     protected $user;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->user = $this->getViewer();
@@ -769,7 +769,7 @@ class RolesTest extends TestCase
         $this->giveUserPermissions($this->user, ['image-update-all']);
         /** @var Page $page */
         $page = Page::query()->first();
-        $image = factory(Image::class)->create([
+        $image = Image::factory()->create([
             'uploaded_to' => $page->id,
             'created_by'  => $this->user->id,
             'updated_by'  => $this->user->id,
@@ -789,7 +789,7 @@ class RolesTest extends TestCase
         $admin = $this->getAdmin();
         /** @var Page $page */
         $page = Page::query()->first();
-        $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
+        $image = Image::factory()->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
 
         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403);
 
@@ -825,14 +825,14 @@ class RolesTest extends TestCase
     {
         $admin = $this->getAdmin();
         // Book links
-        $book = factory(Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
+        $book = Book::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
         $this->regenEntityPermissions($book);
         $this->actingAs($this->getViewer())->get($book->getUrl())
             ->assertDontSee('Create a new page')
             ->assertDontSee('Add a chapter');
 
         // Chapter links
-        $chapter = factory(Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
+        $chapter = Chapter::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
         $this->regenEntityPermissions($chapter);
         $this->actingAs($this->getViewer())->get($chapter->getUrl())
             ->assertDontSee('Create a new page')
@@ -926,14 +926,14 @@ class RolesTest extends TestCase
 
     private function addComment(Page $page): TestResponse
     {
-        $comment = factory(Comment::class)->make();
+        $comment = Comment::factory()->make();
 
         return $this->postJson("/comment/$page->id", $comment->only('text', 'html'));
     }
 
     private function updateComment(Comment $comment): TestResponse
     {
-        $commentData = factory(Comment::class)->make();
+        $commentData = Comment::factory()->make();
 
         return $this->putJson("/comment/{$comment->id}", $commentData->only('text', 'html'));
     }
diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php
index d96fcb710..cbf49bf71 100644
--- a/tests/SharedTestHelpers.php
+++ b/tests/SharedTestHelpers.php
@@ -210,7 +210,7 @@ trait SharedTestHelpers
     protected function createNewRole(array $permissions = []): Role
     {
         $permissionRepo = app(PermissionsRepo::class);
-        $roleData = factory(Role::class)->make()->toArray();
+        $roleData = Role::factory()->make()->toArray();
         $roleData['permissions'] = array_flip($permissions);
 
         return $permissionRepo->saveNewRole($roleData);
@@ -228,9 +228,9 @@ trait SharedTestHelpers
         }
 
         $userAttrs = ['created_by' => $creatorUser->id, 'owned_by' => $creatorUser->id, 'updated_by' => $updaterUser->id];
-        $book = factory(Book::class)->create($userAttrs);
-        $chapter = factory(Chapter::class)->create(array_merge(['book_id' => $book->id], $userAttrs));
-        $page = factory(Page::class)->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs));
+        $book = Book::factory()->create($userAttrs);
+        $chapter = Chapter::factory()->create(array_merge(['book_id' => $book->id], $userAttrs));
+        $page = Page::factory()->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs));
         $restrictionService = $this->app[PermissionService::class];
         $restrictionService->buildJointPermissionsForEntity($book);
 
diff --git a/tests/ThemeTest.php b/tests/ThemeTest.php
index 2cab765ae..9aa7873b0 100644
--- a/tests/ThemeTest.php
+++ b/tests/ThemeTest.php
@@ -150,7 +150,7 @@ class ThemeTest extends TestCase
         Theme::listen(ThemeEvents::AUTH_REGISTER, $callback);
         $this->setSettings(['registration-enabled' => 'true']);
 
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']);
 
         $this->assertCount(2, $args);
diff --git a/tests/Uploads/AvatarTest.php b/tests/Uploads/AvatarTest.php
index cf568d07c..d10b5cfc6 100644
--- a/tests/Uploads/AvatarTest.php
+++ b/tests/Uploads/AvatarTest.php
@@ -42,7 +42,7 @@ class AvatarTest extends TestCase
         config()->set([
             'services.disable_services' => false,
         ]);
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $this->assertImageFetchFrom('https://www.gravatar.com/avatar/' . md5(strtolower($user->email)) . '?s=500&d=identicon');
 
         $user = $this->createUserRequest($user);
@@ -60,7 +60,7 @@ class AvatarTest extends TestCase
             'services.avatar_url'       => 'https://example.com/${email}/${hash}/${size}',
         ]);
 
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $url = 'https://example.com/' . urlencode(strtolower($user->email)) . '/' . md5(strtolower($user->email)) . '/500';
         $this->assertImageFetchFrom($url);
 
@@ -74,7 +74,7 @@ class AvatarTest extends TestCase
             'services.disable_services' => true,
         ]);
 
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
 
         $http = $this->mock(HttpFetcher::class);
         $http->shouldNotReceive('fetch');
@@ -93,7 +93,7 @@ class AvatarTest extends TestCase
 
         $logger = $this->withTestLogger();
 
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $this->createUserRequest($user);
         $this->assertTrue($logger->hasError('Failed to save user avatar image'));
     }
diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php
index ed2fb5f04..5a36b85df 100644
--- a/tests/User/UserManagementTest.php
+++ b/tests/User/UserManagementTest.php
@@ -15,7 +15,7 @@ class UserManagementTest extends TestCase
     public function test_user_creation()
     {
         /** @var User $user */
-        $user = factory(User::class)->make();
+        $user = User::factory()->make();
         $adminRole = Role::getRole('admin');
 
         $resp = $this->asAdmin()->get('/settings/users');
diff --git a/tests/User/UserProfileTest.php b/tests/User/UserProfileTest.php
index 3942efa8e..c3888f8c5 100644
--- a/tests/User/UserProfileTest.php
+++ b/tests/User/UserProfileTest.php
@@ -14,7 +14,7 @@ class UserProfileTest extends TestCase
      */
     protected $user;
 
-    public function setUp(): void
+    protected function setUp(): void
     {
         parent::setUp();
         $this->user = User::all()->last();
@@ -42,7 +42,7 @@ class UserProfileTest extends TestCase
 
     public function test_profile_page_shows_created_content_counts()
     {
-        $newUser = factory(User::class)->create();
+        $newUser = User::factory()->create();
 
         $this->asAdmin()->get('/user/' . $newUser->slug)
             ->assertSee($newUser->name)
@@ -61,7 +61,7 @@ class UserProfileTest extends TestCase
 
     public function test_profile_page_shows_recent_activity()
     {
-        $newUser = factory(User::class)->create();
+        $newUser = User::factory()->create();
         $this->actingAs($newUser);
         $entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
         Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE);
@@ -75,7 +75,7 @@ class UserProfileTest extends TestCase
 
     public function test_user_activity_has_link_leading_to_profile()
     {
-        $newUser = factory(User::class)->create();
+        $newUser = User::factory()->create();
         $this->actingAs($newUser);
         $entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
         Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE);

From 98b23fd7ab98008319f461cafc829cc6f48d1b07 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Sat, 30 Oct 2021 22:03:36 +0100
Subject: [PATCH 3/6] Moved from debugbar to clockwork

---
 app/Config/clockwork.php     | 415 +++++++++++++++++++++++++++++++++++
 composer.json                |   2 +-
 composer.lock                | 227 ++++---------------
 readme.md                    |  10 +-
 storage/clockwork/.gitignore |   3 +
 5 files changed, 462 insertions(+), 195 deletions(-)
 create mode 100644 app/Config/clockwork.php
 create mode 100644 storage/clockwork/.gitignore

diff --git a/app/Config/clockwork.php b/app/Config/clockwork.php
new file mode 100644
index 000000000..ff9929d52
--- /dev/null
+++ b/app/Config/clockwork.php
@@ -0,0 +1,415 @@
+<?php
+
+return [
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Enable Clockwork
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork is enabled by default only when your application is in debug mode. Here you can explicitly enable or
+	| disable Clockwork. When disabled, no data is collected and the api and web ui are inactive.
+	|
+	*/
+
+	'enable' => env('CLOCKWORK_ENABLE', false),
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Features
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| You can enable or disable various Clockwork features here. Some features have additional settings (eg. slow query
+	| threshold for database queries).
+	|
+	*/
+
+	'features' => [
+
+		// Cache usage stats and cache queries including results
+		'cache' => [
+			'enabled' => true,
+
+			// Collect cache queries
+			'collect_queries' => true,
+
+			// Collect values from cache queries (high performance impact with a very high number of queries)
+			'collect_values' => false
+		],
+
+		// Database usage stats and queries
+		'database' => [
+			'enabled' => true,
+
+			// Collect database queries (high performance impact with a very high number of queries)
+			'collect_queries' => true,
+
+			// Collect details of models updates (high performance impact with a lot of model updates)
+			'collect_models_actions' => true,
+
+			// Collect details of retrieved models (very high performance impact with a lot of models retrieved)
+			'collect_models_retrieved' => false,
+
+			// Query execution time threshold in miliseconds after which the query will be marked as slow
+			'slow_threshold' => null,
+
+			// Collect only slow database queries
+			'slow_only' => false,
+
+			// Detect and report duplicate (N+1) queries
+			'detect_duplicate_queries' => false
+		],
+
+		// Dispatched events
+		'events' => [
+			'enabled' => true,
+
+			// Ignored events (framework events are ignored by default)
+			'ignored_events' => [
+				// App\Events\UserRegistered::class,
+				// 'user.registered'
+			],
+		],
+
+		// Laravel log (you can still log directly to Clockwork with laravel log disabled)
+		'log' => [
+			'enabled' => true
+		],
+
+		// Sent notifications
+		'notifications' => [
+			'enabled' => true,
+		],
+
+		// Performance metrics
+		'performance' => [
+			// Allow collecting of client metrics. Requires separate clockwork-browser npm package.
+			'client_metrics' => true
+		],
+
+		// Dispatched queue jobs
+		'queue' => [
+			'enabled' => true
+		],
+
+		// Redis commands
+		'redis' => [
+			'enabled' => true
+		],
+
+		// Routes list
+		'routes' => [
+			'enabled' => false,
+
+			// Collect only routes from particular namespaces (only application routes by default)
+			'only_namespaces' => [ 'App' ]
+		],
+
+		// Rendered views
+		'views' => [
+			'enabled' => true,
+
+			// Collect views including view data (high performance impact with a high number of views)
+			'collect_data' => false,
+
+			// Use Twig profiler instead of Laravel events for apps using laravel-twigbridge (more precise, but does
+			// not support collecting view data)
+			'use_twig_profiler' => false
+		]
+
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Enable web UI
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork comes with a web UI accessibla via http://your.app/clockwork. Here you can enable or disable this
+	| feature. You can also set a custom path for the web UI.
+	|
+	*/
+
+	'web' => true,
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Enable toolbar
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork can show a toolbar with basic metrics on all responses. Here you can enable or disable this feature.
+	| Requires a separate clockwork-browser npm library.
+	| For installation instructions see https://underground.works/clockwork/#docs-viewing-data
+	|
+	*/
+
+	'toolbar' => true,
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| HTTP requests collection
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork collects data about HTTP requests to your app. Here you can choose which requests should be collected.
+	|
+	*/
+
+	'requests' => [
+		// With on-demand mode enabled, Clockwork will only profile requests when the browser extension is open or you
+		// manually pass a "clockwork-profile" cookie or get/post data key.
+		// Optionally you can specify a "secret" that has to be passed as the value to enable profiling.
+		'on_demand' => false,
+
+		// Collect only errors (requests with HTTP 4xx and 5xx responses)
+		'errors_only' => false,
+
+		// Response time threshold in miliseconds after which the request will be marked as slow
+		'slow_threshold' => null,
+
+		// Collect only slow requests
+		'slow_only' => false,
+
+		// Sample the collected requests (eg. set to 100 to collect only 1 in 100 requests)
+		'sample' => false,
+
+		// List of URIs that should not be collected
+		'except' => [
+			'/horizon/.*', // Laravel Horizon requests
+			'/telescope/.*', // Laravel Telescope requests
+			'/_debugbar/.*', // Laravel DebugBar requests
+		],
+
+		// List of URIs that should be collected, any other URI will not be collected if not empty
+		'only' => [
+			// '/api/.*'
+		],
+
+		// Don't collect OPTIONS requests, mostly used in the CSRF pre-flight requests and are rarely of interest
+		'except_preflight' => true
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Artisan commands collection
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork can collect data about executed artisan commands. Here you can enable and configure which commands
+	| should be collected.
+	|
+	*/
+
+	'artisan' => [
+		// Enable or disable collection of executed Artisan commands
+		'collect' => false,
+
+		// List of commands that should not be collected (built-in commands are not collected by default)
+		'except' => [
+			// 'inspire'
+		],
+
+		// List of commands that should be collected, any other command will not be collected if not empty
+		'only' => [
+			// 'inspire'
+		],
+
+		// Enable or disable collection of command output
+		'collect_output' => false,
+
+		// Enable or disable collection of built-in Laravel commands
+		'except_laravel_commands' => true
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Queue jobs collection
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork can collect data about executed queue jobs. Here you can enable and configure which queue jobs should
+	| be collected.
+	|
+	*/
+
+	'queue' => [
+		// Enable or disable collection of executed queue jobs
+		'collect' => false,
+
+		// List of queue jobs that should not be collected
+		'except' => [
+			// App\Jobs\ExpensiveJob::class
+		],
+
+		// List of queue jobs that should be collected, any other queue job will not be collected if not empty
+		'only' => [
+			// App\Jobs\BuggyJob::class
+		]
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Tests collection
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork can collect data about executed tests. Here you can enable and configure which tests should be
+	| collected.
+	|
+	*/
+
+	'tests' => [
+		// Enable or disable collection of ran tests
+		'collect' => false,
+
+		// List of tests that should not be collected
+		'except' => [
+			// Tests\Unit\ExampleTest::class
+		]
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Enable data collection when Clockwork is disabled
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| You can enable this setting to collect data even when Clockwork is disabled. Eg. for future analysis.
+	|
+	*/
+
+	'collect_data_always' => false,
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Metadata storage
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Configure how is the metadata collected by Clockwork stored. Two options are available:
+	|   - files - A simple fast storage implementation storing data in one-per-request files.
+	|   - sql - Stores requests in a sql database. Supports MySQL, Postgresql, Sqlite and requires PDO.
+	|
+	*/
+
+	'storage' => 'files',
+
+	// Path where the Clockwork metadata is stored
+	'storage_files_path' => storage_path('clockwork'),
+
+	// Compress the metadata files using gzip, trading a little bit of performance for lower disk usage
+	'storage_files_compress' => false,
+
+	// SQL database to use, can be a name of database configured in database.php or a path to a sqlite file
+	'storage_sql_database' => storage_path('clockwork.sqlite'),
+
+	// SQL table name to use, the table is automatically created and udpated when needed
+	'storage_sql_table' => 'clockwork',
+
+	// Maximum lifetime of collected metadata in minutes, older requests will automatically be deleted, false to disable
+	'storage_expiration' => 60 * 24 * 7,
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Authentication
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork can be configured to require authentication before allowing access to the collected data. This might be
+	| useful when the application is publicly accessible. Setting to true will enable a simple authentication with a
+	| pre-configured password. You can also pass a class name of a custom implementation.
+	|
+	*/
+
+	'authentication' => false,
+
+	// Password for the simple authentication
+	'authentication_password' => 'VerySecretPassword',
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Stack traces collection
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork can collect stack traces for log messages and certain data like database queries. Here you can set
+	| whether to collect stack traces, limit the number of collected frames and set further configuration. Collecting
+	| long stack traces considerably increases metadata size.
+	|
+	*/
+
+	'stack_traces' => [
+		// Enable or disable collecting of stack traces
+		'enabled' => true,
+
+		// Limit the number of frames to be collected
+		'limit' => 10,
+
+		// List of vendor names to skip when determining caller, common vendors are automatically added
+		'skip_vendors' => [
+			// 'phpunit'
+		],
+
+		// List of namespaces to skip when determining caller
+		'skip_namespaces' => [
+			// 'Laravel'
+		],
+
+		// List of class names to skip when determining caller
+		'skip_classes' => [
+			// App\CustomLog::class
+		]
+
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Serialization
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork serializes the collected data to json for storage and transfer. Here you can configure certain aspects
+	| of serialization. Serialization has a large effect on the cpu time and memory usage.
+	|
+	*/
+
+	// Maximum depth of serialized multi-level arrays and objects
+	'serialization_depth' => 10,
+
+	// A list of classes that will never be serialized (eg. a common service container class)
+	'serialization_blackbox' => [
+		\Illuminate\Container\Container::class,
+		\Illuminate\Foundation\Application::class,
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Register helpers
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork comes with a "clock" global helper function. You can use this helper to quickly log something and to
+	| access the Clockwork instance.
+	|
+	*/
+
+	'register_helpers' => true,
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Send Headers for AJAX request
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| When trying to collect data the AJAX method can sometimes fail if it is missing required headers. For example, an
+	| API might require a version number using Accept headers to route the HTTP request to the correct codebase.
+	|
+	*/
+
+	'headers' => [
+		// 'Accept' => 'application/vnd.com.whatever.v1+json',
+	],
+
+	/*
+	|------------------------------------------------------------------------------------------------------------------
+	| Server-Timing
+	|------------------------------------------------------------------------------------------------------------------
+	|
+	| Clockwork supports the W3C Server Timing specification, which allows for collecting a simple performance metrics
+	| in a cross-browser way. Eg. in Chrome, your app, database and timeline event timings will be shown in the Dev
+	| Tools network tab. This setting specifies the max number of timeline events that will be sent. Setting to false
+	| will disable the feature.
+	|
+	*/
+
+	'server_timing' => 10
+
+];
diff --git a/composer.json b/composer.json
index c1d5c1e4b..c4d9cd904 100644
--- a/composer.json
+++ b/composer.json
@@ -44,8 +44,8 @@
         "ssddanbrown/htmldiff": "^1.0.1"
     },
     "require-dev": {
-        "barryvdh/laravel-debugbar": "^3.6",
         "fakerphp/faker": "^1.13.0",
+        "itsgoingd/clockwork": "^5.1",
         "mockery/mockery": "^1.4.2",
         "phpunit/phpunit": "^9.5.3",
         "symfony/dom-crawler": "^5.3",
diff --git a/composer.lock b/composer.lock
index 17e57df71..7231c82c4 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "9a5d92382b2955dd7de41de5fa9f86b5",
+    "content-hash": "0dfe612653577a14906a0bb031c67a97",
     "packages": [
         {
             "name": "aws/aws-crt-php",
@@ -7441,91 +7441,6 @@
         }
     ],
     "packages-dev": [
-        {
-            "name": "barryvdh/laravel-debugbar",
-            "version": "v3.6.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/barryvdh/laravel-debugbar.git",
-                "reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3c2d678269ba60e178bcd93e36f6a91c36b727f1",
-                "reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1",
-                "shasum": ""
-            },
-            "require": {
-                "illuminate/routing": "^6|^7|^8",
-                "illuminate/session": "^6|^7|^8",
-                "illuminate/support": "^6|^7|^8",
-                "maximebf/debugbar": "^1.17.2",
-                "php": ">=7.2",
-                "symfony/debug": "^4.3|^5",
-                "symfony/finder": "^4.3|^5"
-            },
-            "require-dev": {
-                "mockery/mockery": "^1.3.3",
-                "orchestra/testbench-dusk": "^4|^5|^6",
-                "phpunit/phpunit": "^8.5|^9.0",
-                "squizlabs/php_codesniffer": "^3.5"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.6-dev"
-                },
-                "laravel": {
-                    "providers": [
-                        "Barryvdh\\Debugbar\\ServiceProvider"
-                    ],
-                    "aliases": {
-                        "Debugbar": "Barryvdh\\Debugbar\\Facade"
-                    }
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Barryvdh\\Debugbar\\": "src/"
-                },
-                "files": [
-                    "src/helpers.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Barry vd. Heuvel",
-                    "email": "barryvdh@gmail.com"
-                }
-            ],
-            "description": "PHP Debugbar integration for Laravel",
-            "keywords": [
-                "debug",
-                "debugbar",
-                "laravel",
-                "profiler",
-                "webprofiler"
-            ],
-            "support": {
-                "issues": "https://github.com/barryvdh/laravel-debugbar/issues",
-                "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.4"
-            },
-            "funding": [
-                {
-                    "url": "https://fruitcake.nl",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/barryvdh",
-                    "type": "github"
-                }
-            ],
-            "time": "2021-10-21T10:57:31+00:00"
-        },
         {
             "name": "doctrine/instantiator",
             "version": "1.4.0",
@@ -7765,41 +7680,38 @@
             "time": "2020-07-09T08:09:16+00:00"
         },
         {
-            "name": "maximebf/debugbar",
-            "version": "v1.17.2",
+            "name": "itsgoingd/clockwork",
+            "version": "v5.1.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/maximebf/php-debugbar.git",
-                "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418"
+                "url": "https://github.com/itsgoingd/clockwork.git",
+                "reference": "b963dee47429a49c9669981cfa9a8362ce209278"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/3541f09f09c003c4a9ff7ddb0eb3361a7f14d418",
-                "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418",
+                "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/b963dee47429a49c9669981cfa9a8362ce209278",
+                "reference": "b963dee47429a49c9669981cfa9a8362ce209278",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.1|^8",
-                "psr/log": "^1|^2|^3",
-                "symfony/var-dumper": "^2.6|^3|^4|^5"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^7.5.20 || ^9.4.2"
-            },
-            "suggest": {
-                "kriswallsmith/assetic": "The best way to manage assets",
-                "monolog/monolog": "Log using Monolog",
-                "predis/predis": "Redis storage"
+                "ext-json": "*",
+                "php": ">=5.6",
+                "psr/log": "1.*"
             },
             "type": "library",
             "extra": {
-                "branch-alias": {
-                    "dev-master": "1.17-dev"
+                "laravel": {
+                    "providers": [
+                        "Clockwork\\Support\\Laravel\\ClockworkServiceProvider"
+                    ],
+                    "aliases": {
+                        "Clockwork": "Clockwork\\Support\\Laravel\\Facade"
+                    }
                 }
             },
             "autoload": {
                 "psr-4": {
-                    "DebugBar\\": "src/DebugBar/"
+                    "Clockwork\\": "Clockwork/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -7808,26 +7720,33 @@
             ],
             "authors": [
                 {
-                    "name": "Maxime Bouroumeau-Fuseau",
-                    "email": "maxime.bouroumeau@gmail.com",
-                    "homepage": "http://maximebf.com"
-                },
-                {
-                    "name": "Barry vd. Heuvel",
-                    "email": "barryvdh@gmail.com"
+                    "name": "itsgoingd",
+                    "email": "itsgoingd@luzer.sk",
+                    "homepage": "https://twitter.com/itsgoingd"
                 }
             ],
-            "description": "Debug bar in the browser for php application",
-            "homepage": "https://github.com/maximebf/php-debugbar",
+            "description": "php dev tools in your browser",
+            "homepage": "https://underground.works/clockwork",
             "keywords": [
-                "debug",
-                "debugbar"
+                "Devtools",
+                "debugging",
+                "laravel",
+                "logging",
+                "lumen",
+                "profiling",
+                "slim"
             ],
             "support": {
-                "issues": "https://github.com/maximebf/php-debugbar/issues",
-                "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.2"
+                "issues": "https://github.com/itsgoingd/clockwork/issues",
+                "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.0"
             },
-            "time": "2021-10-18T09:39:00+00:00"
+            "funding": [
+                {
+                    "url": "https://github.com/itsgoingd",
+                    "type": "github"
+                }
+            ],
+            "time": "2021-08-07T23:04:17+00:00"
         },
         {
             "name": "mockery/mockery",
@@ -9769,74 +9688,6 @@
             ],
             "time": "2020-09-28T06:39:44+00:00"
         },
-        {
-            "name": "symfony/debug",
-            "version": "v4.4.31",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/debug.git",
-                "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0",
-                "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.1.3",
-                "psr/log": "^1|^2|^3"
-            },
-            "conflict": {
-                "symfony/http-kernel": "<3.4"
-            },
-            "require-dev": {
-                "symfony/http-kernel": "^3.4|^4.0|^5.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Debug\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Provides tools to ease debugging PHP code",
-            "homepage": "https://symfony.com",
-            "support": {
-                "source": "https://github.com/symfony/debug/tree/v4.4.31"
-            },
-            "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-09-24T13:30:14+00:00"
-        },
         {
             "name": "symfony/dom-crawler",
             "version": "v5.3.7",
diff --git a/readme.md b/readme.md
index 17ac9641b..0c9cf66e9 100644
--- a/readme.md
+++ b/readme.md
@@ -187,11 +187,8 @@ These are the great open-source projects used to help build BookStack:
 * [Dropzone.js](http://www.dropzonejs.com/)
 * [clipboard.js](https://clipboardjs.com/)
 * [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists)
-* [BarryVD](https://github.com/barryvdh)
-    * [Debugbar](https://github.com/barryvdh/laravel-debugbar)
-    * [Dompdf](https://github.com/barryvdh/laravel-dompdf)
-    * [Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy)
-    * [Laravel IDE helper](https://github.com/barryvdh/laravel-ide-helper)
+* [BarryVD/Dompdf](https://github.com/barryvdh/laravel-dompdf)
+* [BarryVD/Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy)
 * [WKHTMLtoPDF](http://wkhtmltopdf.org/index.html)
 * [diagrams.net](https://github.com/jgraph/drawio)
 * [OneLogin's SAML PHP Toolkit](https://github.com/onelogin/php-saml)
@@ -200,4 +197,5 @@ These are the great open-source projects used to help build BookStack:
 * [StyleCI](https://styleci.io/)
 * [pragmarx/google2fa](https://github.com/antonioribeiro/google2fa)
 * [Bacon/BaconQrCode](https://github.com/Bacon/BaconQrCode)
-* [phpseclib](https://github.com/phpseclib/phpseclib)
\ No newline at end of file
+* [phpseclib](https://github.com/phpseclib/phpseclib)
+* [Clockwork](https://github.com/itsgoingd/clockwork)
\ No newline at end of file
diff --git a/storage/clockwork/.gitignore b/storage/clockwork/.gitignore
new file mode 100644
index 000000000..3fac1bff8
--- /dev/null
+++ b/storage/clockwork/.gitignore
@@ -0,0 +1,3 @@
+*.json
+*.json.gz
+index

From cccee0808f6a9c67e11da14368fc1ed917b6cd96 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Thu, 4 Nov 2021 22:02:21 +0000
Subject: [PATCH 4/6] Updated API examples with date format changes

Updated to full ISO-8601 to reflect change in Laravel 7.
---
 dev/api/responses/attachments-create.json |  4 ++--
 dev/api/responses/attachments-list.json   |  8 ++++----
 dev/api/responses/attachments-read.json   |  4 ++--
 dev/api/responses/attachments-update.json |  4 ++--
 dev/api/responses/books-create.json       |  4 ++--
 dev/api/responses/books-list.json         |  8 ++++----
 dev/api/responses/books-read.json         |  8 ++++----
 dev/api/responses/books-update.json       |  4 ++--
 dev/api/responses/chapters-create.json    | 16 ++++++++--------
 dev/api/responses/chapters-list.json      |  8 ++++----
 dev/api/responses/chapters-read.json      | 12 ++++++------
 dev/api/responses/chapters-update.json    | 16 ++++++++--------
 dev/api/responses/pages-create.json       |  4 ++--
 dev/api/responses/pages-list.json         | 12 ++++++------
 dev/api/responses/pages-read.json         |  4 ++--
 dev/api/responses/pages-update.json       |  4 ++--
 dev/api/responses/shelves-create.json     |  4 ++--
 dev/api/responses/shelves-list.json       | 12 ++++++------
 dev/api/responses/shelves-read.json       |  8 ++++----
 dev/api/responses/shelves-update.json     |  4 ++--
 20 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/dev/api/responses/attachments-create.json b/dev/api/responses/attachments-create.json
index 5af524e1a..ee1b21ac0 100644
--- a/dev/api/responses/attachments-create.json
+++ b/dev/api/responses/attachments-create.json
@@ -7,6 +7,6 @@
   "order": 2,
   "created_by": 1,
   "updated_by": 1,
-  "created_at": "2021-10-20 06:35:46",
-  "updated_at": "2021-10-20 06:35:46"
+  "created_at": "2021-10-20T06:35:46.000000Z",
+  "updated_at": "2021-10-20T06:35:46.000000Z"
 }
\ No newline at end of file
diff --git a/dev/api/responses/attachments-list.json b/dev/api/responses/attachments-list.json
index 946dd542a..af652d5ed 100644
--- a/dev/api/responses/attachments-list.json
+++ b/dev/api/responses/attachments-list.json
@@ -7,8 +7,8 @@
       "uploaded_to": 8,
       "external": false,
       "order": 1,
-      "created_at": "2021-10-11 06:18:49",
-      "updated_at": "2021-10-20 06:31:10",
+      "created_at": "2021-10-11T06:18:49.000000Z",
+      "updated_at": "2021-10-20T06:31:10.000000Z",
       "created_by": 1,
       "updated_by": 1
     },
@@ -19,8 +19,8 @@
       "uploaded_to": 9,
       "external": true,
       "order": 1,
-      "created_at": "2021-10-20 06:30:11",
-      "updated_at": "2021-10-20 06:30:11",
+      "created_at": "2021-10-20T06:30:11.000000Z",
+      "updated_at": "2021-10-20T06:30:11.000000Z",
       "created_by": 1,
       "updated_by": 1
     }
diff --git a/dev/api/responses/attachments-read.json b/dev/api/responses/attachments-read.json
index e22f4e5fe..48d6f72e6 100644
--- a/dev/api/responses/attachments-read.json
+++ b/dev/api/responses/attachments-read.json
@@ -15,8 +15,8 @@
     "name": "Admin",
     "slug": "admin"
   },
-  "created_at": "2021-10-20 06:35:46",
-  "updated_at": "2021-10-20 06:37:11",
+  "created_at": "2021-10-20T06:35:46.000000Z",
+  "updated_at": "2021-10-20T06:37:11.000000Z",
   "links": {
     "html": "<a target=\"_blank\" href=\"https://bookstack.local/attachments/5\">My updated attachment</a>",
     "markdown": "[My updated attachment](https://bookstack.local/attachments/5)"
diff --git a/dev/api/responses/attachments-update.json b/dev/api/responses/attachments-update.json
index 8054b0e48..43689eb61 100644
--- a/dev/api/responses/attachments-update.json
+++ b/dev/api/responses/attachments-update.json
@@ -7,6 +7,6 @@
   "order": 2,
   "created_by": 1,
   "updated_by": 1,
-  "created_at": "2021-10-20 06:35:46",
-  "updated_at": "2021-10-20 06:37:11"
+  "created_at": "2021-10-20T06:35:46.000000Z",
+  "updated_at": "2021-10-20T06:37:11.000000Z"
 }
\ No newline at end of file
diff --git a/dev/api/responses/books-create.json b/dev/api/responses/books-create.json
index 124305c8c..ede6fcc8e 100644
--- a/dev/api/responses/books-create.json
+++ b/dev/api/responses/books-create.json
@@ -5,7 +5,7 @@
   "updated_by": 1,
   "owned_by": 1,
   "slug": "my-new-book",
-  "updated_at": "2020-01-12 14:05:11",
-  "created_at": "2020-01-12 14:05:11",
+  "updated_at": "2020-01-12T14:05:11.000000Z",
+  "created_at": "2020-01-12T14:05:11.000000Z",
   "id": 15
 }
\ No newline at end of file
diff --git a/dev/api/responses/books-list.json b/dev/api/responses/books-list.json
index 9900b5b04..45a8c542f 100644
--- a/dev/api/responses/books-list.json
+++ b/dev/api/responses/books-list.json
@@ -5,8 +5,8 @@
       "name": "BookStack User Guide",
       "slug": "bookstack-user-guide",
       "description": "This is a general guide on using BookStack on a day-to-day basis.",
-      "created_at": "2019-05-05 21:48:46",
-      "updated_at": "2019-12-11 20:57:31",
+      "created_at": "2019-05-05T21:48:46.000000Z",
+      "updated_at": "2019-12-11T20:57:31.000000Z",
       "created_by": 1,
       "updated_by": 1,
       "owned_by": 1,
@@ -17,8 +17,8 @@
       "name": "Inventore inventore quia voluptatem.",
       "slug": "inventore-inventore-quia-voluptatem",
       "description": "Veniam nihil voluptas enim laborum corporis quos sint. Ab rerum voluptas ut iste voluptas magni quibusdam ut. Amet omnis enim voluptate neque facilis.",
-      "created_at": "2019-05-05 22:10:14",
-      "updated_at": "2019-12-11 20:57:23",
+      "created_at": "2019-05-05T22:10:14.000000Z",
+      "updated_at": "2019-12-11T20:57:23.000000Z",
       "created_by": 4,
       "updated_by": 3,
       "owned_by": 3,
diff --git a/dev/api/responses/books-read.json b/dev/api/responses/books-read.json
index 0b0bce4e8..7de85addc 100644
--- a/dev/api/responses/books-read.json
+++ b/dev/api/responses/books-read.json
@@ -3,8 +3,8 @@
   "name": "My own book",
   "slug": "my-own-book",
   "description": "This is my own little book",
-  "created_at": "2020-01-12 14:09:59",
-  "updated_at": "2020-01-12 14:11:51",
+  "created_at": "2020-01-12T14:09:59.000000Z",
+  "updated_at": "2020-01-12T14:11:51.000000Z",
   "created_by": {
     "id": 1,
     "name": "Admin"
@@ -29,8 +29,8 @@
     "id": 452,
     "name": "sjovall_m117hUWMu40.jpg",
     "url": "http:\/\/bookstack.local\/uploads\/images\/cover_book\/2020-01\/sjovall_m117hUWMu40.jpg",
-    "created_at": "2020-01-12 14:11:51",
-    "updated_at": "2020-01-12 14:11:51",
+    "created_at": "2020-01-12T14:11:51.000000Z",
+    "updated_at": "2020-01-12T14:11:51.000000Z",
     "created_by": 1,
     "updated_by": 1,
     "path": "\/uploads\/images\/cover_book\/2020-01\/sjovall_m117hUWMu40.jpg",
diff --git a/dev/api/responses/books-update.json b/dev/api/responses/books-update.json
index fd93dc9ae..30c910aa3 100644
--- a/dev/api/responses/books-update.json
+++ b/dev/api/responses/books-update.json
@@ -3,8 +3,8 @@
   "name": "My own book",
   "slug": "my-own-book",
   "description": "This is my own little book - updated",
-  "created_at": "2020-01-12 14:09:59",
-  "updated_at": "2020-01-12 14:16:10",
+  "created_at": "2020-01-12T14:09:59.000000Z",
+  "updated_at": "2020-01-12T14:16:10.000000Z",
   "created_by": 1,
   "updated_by": 1,
   "owned_by": 1,
diff --git a/dev/api/responses/chapters-create.json b/dev/api/responses/chapters-create.json
index a990f278b..81b422c25 100644
--- a/dev/api/responses/chapters-create.json
+++ b/dev/api/responses/chapters-create.json
@@ -7,16 +7,16 @@
   "updated_by": 1,
   "owned_by": 1,
   "slug": "my-fantastic-new-chapter",
-  "updated_at": "2020-05-22 22:59:55",
-  "created_at": "2020-05-22 22:59:55",
+  "updated_at": "2020-05-22T22:59:55.000000Z",
+  "created_at": "2020-05-22T22:59:55.000000Z",
   "id": 74,
   "book": {
     "id": 1,
     "name": "BookStack User Guide",
     "slug": "bookstack-user-guide",
     "description": "This is a general guide on using BookStack on a day-to-day basis.",
-    "created_at": "2019-05-05 21:48:46",
-    "updated_at": "2019-12-11 20:57:31",
+    "created_at": "2019-05-05T21:48:46.000000Z",
+    "updated_at": "2019-12-11T20:57:31.000000Z",
     "created_by": 1,
     "updated_by": 1
   },
@@ -25,15 +25,15 @@
       "name": "Category",
       "value": "Top Content",
       "order": 0,
-      "created_at": "2020-05-22 22:59:55",
-      "updated_at": "2020-05-22 22:59:55"
+      "created_at": "2020-05-22T22:59:55.000000Z",
+      "updated_at": "2020-05-22T22:59:55.000000Z"
     },
     {
       "name": "Rating",
       "value": "Highest",
       "order": 0,
-      "created_at": "2020-05-22 22:59:55",
-      "updated_at": "2020-05-22 22:59:55"
+      "created_at": "2020-05-22T22:59:55.000000Z",
+      "updated_at": "2020-05-22T22:59:55.000000Z"
     }
   ]
 }
\ No newline at end of file
diff --git a/dev/api/responses/chapters-list.json b/dev/api/responses/chapters-list.json
index 72ed7534d..9790286b0 100644
--- a/dev/api/responses/chapters-list.json
+++ b/dev/api/responses/chapters-list.json
@@ -7,8 +7,8 @@
       "slug": "content-creation",
       "description": "How to create documentation on whatever subject you need to write about.",
       "priority": 3,
-      "created_at": "2019-05-05 21:49:56",
-      "updated_at": "2019-09-28 11:24:23",
+      "created_at": "2019-05-05:",
+      "updated_at": "2019-09-28T11:24:23.000000Z",
       "created_by": 1,
       "updated_by": 1,
       "owned_by": 1
@@ -20,8 +20,8 @@
       "slug": "managing-content",
       "description": "How to keep things organised and orderly in the system for easier navigation and better user experience.",
       "priority": 5,
-      "created_at": "2019-05-05 21:58:07",
-      "updated_at": "2019-10-17 15:05:34",
+      "created_at": "2019-05-05T21:58:07.000000Z",
+      "updated_at": "2019-10-17T15:05:34.000000Z",
       "created_by": 3,
       "updated_by": 3,
       "owned_by": 3
diff --git a/dev/api/responses/chapters-read.json b/dev/api/responses/chapters-read.json
index 41fed80ef..a51b406c7 100644
--- a/dev/api/responses/chapters-read.json
+++ b/dev/api/responses/chapters-read.json
@@ -5,8 +5,8 @@
   "name": "Content Creation",
   "description": "How to create documentation on whatever subject you need to write about.",
   "priority": 3,
-  "created_at": "2019-05-05 21:49:56",
-  "updated_at": "2019-09-28 11:24:23",
+  "created_at": "2019-05-05T21:49:56.000000Z",
+  "updated_at": "2019-09-28T11:24:23.000000Z",
   "created_by": {
     "id": 1,
     "name": "Admin"
@@ -34,8 +34,8 @@
       "name": "How to create page content",
       "slug": "how-to-create-page-content",
       "priority": 0,
-      "created_at": "2019-05-05 21:49:58",
-      "updated_at": "2019-08-26 14:32:59",
+      "created_at": "2019-05-05T21:49:58.000000Z",
+      "updated_at": "2019-08-26T14:32:59.000000Z",
       "created_by": 1,
       "updated_by": 1,
       "draft": false,
@@ -49,8 +49,8 @@
       "name": "Good book structure",
       "slug": "good-book-structure",
       "priority": 1,
-      "created_at": "2019-05-05 22:01:55",
-      "updated_at": "2019-06-06 12:03:04",
+      "created_at": "2019-05-05T22:01:55.000000Z",
+      "updated_at": "2019-06-06T12:03:04.000000Z",
       "created_by": 3,
       "updated_by": 3,
       "draft": false,
diff --git a/dev/api/responses/chapters-update.json b/dev/api/responses/chapters-update.json
index 11dedd0ca..9ce88dab2 100644
--- a/dev/api/responses/chapters-update.json
+++ b/dev/api/responses/chapters-update.json
@@ -5,8 +5,8 @@
   "name": "My fantastic updated chapter",
   "description": "This is an updated chapter that I've altered via the API",
   "priority": 7,
-  "created_at": "2020-05-22 23:03:35",
-  "updated_at": "2020-05-22 23:07:20",
+  "created_at": "2020-05-22T23:03:35.000000Z",
+  "updated_at": "2020-05-22T23:07:20.000000Z",
   "created_by": 1,
   "updated_by": 1,
   "owned_by": 1,
@@ -15,8 +15,8 @@
     "name": "BookStack User Guide",
     "slug": "bookstack-user-guide",
     "description": "This is a general guide on using BookStack on a day-to-day basis.",
-    "created_at": "2019-05-05 21:48:46",
-    "updated_at": "2019-12-11 20:57:31",
+    "created_at": "2019-05-05T21:48:46.000000Z",
+    "updated_at": "2019-12-11T20:57:31.000000Z",
     "created_by": 1,
     "updated_by": 1
   },
@@ -25,15 +25,15 @@
       "name": "Category",
       "value": "Kinda Good Content",
       "order": 0,
-      "created_at": "2020-05-22 23:07:20",
-      "updated_at": "2020-05-22 23:07:20"
+      "created_at": "2020-05-22T23:07:20.000000Z",
+      "updated_at": "2020-05-22T23:07:20.000000Z"
     },
     {
       "name": "Rating",
       "value": "Medium",
       "order": 0,
-      "created_at": "2020-05-22 23:07:20",
-      "updated_at": "2020-05-22 23:07:20"
+      "created_at": "2020-05-22T23:07:20.000000Z",
+      "updated_at": "2020-05-22T23:07:20.000000Z"
     }
   ]
 }
\ No newline at end of file
diff --git a/dev/api/responses/pages-create.json b/dev/api/responses/pages-create.json
index 0b19fb473..eeaa5303a 100644
--- a/dev/api/responses/pages-create.json
+++ b/dev/api/responses/pages-create.json
@@ -6,8 +6,8 @@
 	"slug": "my-api-page",
 	"html": "<p id=\"bkmrk-my-new-api-page\">my new API page</p>",
 	"priority": 14,
-	"created_at": "2020-11-28 15:01:39",
-	"updated_at": "2020-11-28 15:01:39",
+	"created_at": "2020-11-28T15:01:39.000000Z",
+	"updated_at": "2020-11-28T15:01:39.000000Z",
 	"created_by": {
 		"id": 1,
 		"name": "Admin"
diff --git a/dev/api/responses/pages-list.json b/dev/api/responses/pages-list.json
index 9c162c6b6..2ff4aeb3a 100644
--- a/dev/api/responses/pages-list.json
+++ b/dev/api/responses/pages-list.json
@@ -9,8 +9,8 @@
 			"priority": 0,
 			"draft": false,
 			"template": false,
-			"created_at": "2019-05-05 21:49:58",
-			"updated_at": "2020-07-04 15:50:58",
+			"created_at": "2019-05-05T21:49:58.000000Z",
+			"updated_at": "2020-07-04T15:50:58.000000Z",
 			"created_by": 1,
 			"updated_by": 1,
 			"owned_by": 1
@@ -24,8 +24,8 @@
 			"priority": 2,
 			"draft": false,
 			"template": false,
-			"created_at": "2019-05-05 21:53:30",
-			"updated_at": "2019-06-06 12:03:04",
+			"created_at": "2019-05-05T21:53:30.000000Z",
+			"updated_at": "2019-06-06T12:03:04.000000Z",
 			"created_by": 1,
 			"updated_by": 1,
 			"owned_by": 1
@@ -39,8 +39,8 @@
 			"priority": 3,
 			"draft": false,
 			"template": false,
-			"created_at": "2019-05-05 21:53:49",
-			"updated_at": "2019-12-18 21:56:52",
+			"created_at": "2019-05-05T21:53:49.000000Z",
+			"updated_at": "2019-12-18T21:56:52.000000Z",
 			"created_by": 1,
 			"updated_by": 1,
 			"owned_by": 1
diff --git a/dev/api/responses/pages-read.json b/dev/api/responses/pages-read.json
index 93f7770ac..9a21cd44c 100644
--- a/dev/api/responses/pages-read.json
+++ b/dev/api/responses/pages-read.json
@@ -6,8 +6,8 @@
 	"slug": "a-page-written-in-markdown",
 	"html": "<h1 id=\"bkmrk-how-this-is-built\">How this is built</h1>\r\n<p id=\"bkmrk-this-page-is-written\">This page is written in markdown. BookStack stores the page data in HTML.</p>\r\n<p id=\"bkmrk-here%27s-a-cute-pictur\">Here's a cute picture of my cat:</p>\r\n<p id=\"bkmrk-\"><a href=\"http://example.com/uploads/images/gallery/2020-04/yXSrubes.jpg\"><img src=\"http://example.com/uploads/images/gallery/2020-04/scaled-1680-/yXSrubes.jpg\" alt=\"yXSrubes.jpg\"></a></p>",
 	"priority": 13,
-	"created_at": "2020-02-02 21:40:38",
-	"updated_at": "2020-11-28 14:43:20",
+	"created_at": "2020-02-02T21:40:38.000000Z",
+	"updated_at": "2020-11-28T14:43:20.000000Z",
 	"created_by": {
 		"id": 1,
 		"name": "Admin"
diff --git a/dev/api/responses/pages-update.json b/dev/api/responses/pages-update.json
index ae5c0ea3f..0b8b2374c 100644
--- a/dev/api/responses/pages-update.json
+++ b/dev/api/responses/pages-update.json
@@ -6,8 +6,8 @@
 	"slug": "my-updated-api-page",
 	"html": "<p id=\"bkmrk-my-new-api-page---up\">my new API page - Updated</p>",
 	"priority": 16,
-	"created_at": "2020-11-28 15:10:54",
-	"updated_at": "2020-11-28 15:13:03",
+	"created_at": "2020-11-28T15:10:54.000000Z",
+	"updated_at": "2020-11-28T15:13:03.000000Z",
 	"created_by": {
 		"id": 1,
 		"name": "Admin"
diff --git a/dev/api/responses/shelves-create.json b/dev/api/responses/shelves-create.json
index fafa4c9cd..9988c782c 100644
--- a/dev/api/responses/shelves-create.json
+++ b/dev/api/responses/shelves-create.json
@@ -5,7 +5,7 @@
   "updated_by": 1,
   "owned_by": 1,
   "slug": "my-shelf",
-  "updated_at": "2020-04-10 13:24:09",
-  "created_at": "2020-04-10 13:24:09",
+  "updated_at": "2020-04-10T13:24:09.000000Z",
+  "created_at": "2020-04-10T13:24:09.000000Z",
   "id": 14
 }
\ No newline at end of file
diff --git a/dev/api/responses/shelves-list.json b/dev/api/responses/shelves-list.json
index f5e9d03bb..82ead7d93 100644
--- a/dev/api/responses/shelves-list.json
+++ b/dev/api/responses/shelves-list.json
@@ -5,8 +5,8 @@
       "name": "Qui qui aspernatur autem molestiae libero necessitatibus molestias.",
       "slug": "qui-qui-aspernatur-autem-molestiae-libero-necessitatibus-molestias",
       "description": "Enim dolor ut quia error dolores est. Aut distinctio consequuntur non nisi nostrum. Labore cupiditate error labore aliquid provident impedit voluptatibus. Quaerat impedit excepturi eius qui eius voluptatem reiciendis.",
-      "created_at": "2019-05-05 22:10:16",
-      "updated_at": "2020-04-10 13:00:45",
+      "created_at": "2019-05-05T22:10:16.000000Z",
+      "updated_at": "2020-04-10T13:00:45.000000Z",
       "created_by": 4,
       "updated_by": 1,
       "owned_by": 1,
@@ -17,8 +17,8 @@
       "name": "Ipsum aut inventore fuga libero non facilis.",
       "slug": "ipsum-aut-inventore-fuga-libero-non-facilis",
       "description": "Labore culpa modi perspiciatis harum sit. Maxime non et nam est. Quae ut laboriosam repellendus sunt quisquam. Velit at est perspiciatis nesciunt adipisci nobis illo. Sed possimus odit optio officiis nisi voluptates officiis dolor.",
-      "created_at": "2019-05-05 22:10:16",
-      "updated_at": "2020-04-10 13:00:58",
+      "created_at": "2019-05-05T22:10:16.000000Z",
+      "updated_at": "2020-04-10T13:00:58.000000Z",
       "created_by": 4,
       "updated_by": 1,
       "owned_by": 1,
@@ -29,8 +29,8 @@
       "name": "Omnis reiciendis aut molestias sint accusantium.",
       "slug": "omnis-reiciendis-aut-molestias-sint-accusantium",
       "description": "Qui ea occaecati alias est dolores voluptatem doloribus. Ad reiciendis corporis vero nostrum omnis et. Non doloribus ut eaque ut quos dolores.",
-      "created_at": "2019-05-05 22:10:16",
-      "updated_at": "2020-04-10 13:00:53",
+      "created_at": "2019-05-05T22:10:16.000000Z",
+      "updated_at": "2020-04-10T13:00:53.000000Z",
       "created_by": 4,
       "updated_by": 1,
       "owned_by": 4,
diff --git a/dev/api/responses/shelves-read.json b/dev/api/responses/shelves-read.json
index d663e82c5..f2afcdac0 100644
--- a/dev/api/responses/shelves-read.json
+++ b/dev/api/responses/shelves-read.json
@@ -15,8 +15,8 @@
     "id": 1,
     "name": "Admin"
   },
-  "created_at": "2020-04-10 13:24:09",
-  "updated_at": "2020-04-10 13:31:04",
+  "created_at": "2020-04-10T13:24:09.000000Z",
+  "updated_at": "2020-04-10T13:31:04.000000Z",
   "tags": [
     {
       "id": 16,
@@ -29,8 +29,8 @@
     "id": 501,
     "name": "anafrancisconi_Sp04AfFCPNM.jpg",
     "url": "http://bookstack.local/uploads/images/cover_book/2020-04/anafrancisconi_Sp04AfFCPNM.jpg",
-    "created_at": "2020-04-10 13:31:04",
-    "updated_at": "2020-04-10 13:31:04",
+    "created_at": "2020-04-10T13:31:04.000000Z",
+    "updated_at": "2020-04-10T13:31:04.000000Z",
     "created_by": 1,
     "updated_by": 1,
     "path": "/uploads/images/cover_book/2020-04/anafrancisconi_Sp04AfFCPNM.jpg",
diff --git a/dev/api/responses/shelves-update.json b/dev/api/responses/shelves-update.json
index 4bde44b54..551dacb1f 100644
--- a/dev/api/responses/shelves-update.json
+++ b/dev/api/responses/shelves-update.json
@@ -7,6 +7,6 @@
   "updated_by": 1,
   "owned_by": 1,
   "image_id": 501,
-  "created_at": "2020-04-10 13:24:09",
-  "updated_at": "2020-04-10 13:48:22"
+  "created_at": "2020-04-10T13:24:09.000000Z",
+  "updated_at": "2020-04-10T13:48:22.000000Z"
 }
\ No newline at end of file

From 9c680efaad1e116be926968f6f329e97d00b4c47 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Thu, 4 Nov 2021 22:29:36 +0000
Subject: [PATCH 5/6] Updated php packages, Added php8.1 to GH actions

---
 .github/workflows/phpunit.yml         |  4 +-
 .github/workflows/test-migrations.yml |  4 +-
 composer.json                         | 12 ++---
 composer.lock                         | 73 ++++++++++++++-------------
 4 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index f12de6436..7cb1307a1 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -13,12 +13,12 @@ jobs:
     runs-on: ubuntu-20.04
     strategy:
       matrix:
-        php: ['7.3', '7.4', '8.0']
+        php: ['7.3', '7.4', '8.0', '8.1']
     steps:
     - uses: actions/checkout@v1
 
     - name: Setup PHP
-      uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8
+      uses: shivammathur/setup-php@v2
       with:
         php-version: ${{ matrix.php }}
         extensions: gd, mbstring, json, curl, xml, mysql, ldap
diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml
index c24a01984..846992e7b 100644
--- a/.github/workflows/test-migrations.yml
+++ b/.github/workflows/test-migrations.yml
@@ -13,12 +13,12 @@ jobs:
     runs-on: ubuntu-20.04
     strategy:
       matrix:
-        php: ['7.3', '7.4', '8.0']
+        php: ['7.3', '7.4', '8.0', '8.1']
     steps:
       - uses: actions/checkout@v1
 
       - name: Setup PHP
-        uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8
+        uses: shivammathur/setup-php@v2
         with:
           php-version: ${{ matrix.php }}
           extensions: gd, mbstring, json, curl, xml, mysql, ldap
diff --git a/composer.json b/composer.json
index c4d9cd904..23ce97cd4 100644
--- a/composer.json
+++ b/composer.json
@@ -25,9 +25,9 @@
         "intervention/image": "^2.7",
         "laravel/framework": "^8.68",
         "laravel/socialite": "^5.2",
-        "laravel/tinker": "^2.5",
+        "laravel/tinker": "^2.6",
         "laravel/ui": "^3.3",
-        "league/commonmark": "^1.5",
+        "league/commonmark": "^1.6",
         "league/flysystem-aws-s3-v3": "^1.0.29",
         "league/html-to-markdown": "^5.0.0",
         "league/oauth2-client": "^2.6",
@@ -44,12 +44,12 @@
         "ssddanbrown/htmldiff": "^1.0.1"
     },
     "require-dev": {
-        "fakerphp/faker": "^1.13.0",
+        "fakerphp/faker": "^1.16",
         "itsgoingd/clockwork": "^5.1",
-        "mockery/mockery": "^1.4.2",
-        "phpunit/phpunit": "^9.5.3",
+        "mockery/mockery": "^1.4",
+        "phpunit/phpunit": "^9.5",
         "symfony/dom-crawler": "^5.3",
-        "nunomaduro/collision": "^5.0"
+        "nunomaduro/collision": "^5.10"
     },
     "autoload": {
         "psr-4": {
diff --git a/composer.lock b/composer.lock
index 7231c82c4..005f30fa3 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "0dfe612653577a14906a0bb031c67a97",
+    "content-hash": "48be80b0326176faa9775dca18a00fa2",
     "packages": [
         {
             "name": "aws/aws-crt-php",
@@ -58,16 +58,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.199.7",
+            "version": "3.200.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "fda176884d2952cffc7e67209470bff49609339c"
+                "reference": "9b3f45c51fe1d07845446675109bb0a8a98c806e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fda176884d2952cffc7e67209470bff49609339c",
-                "reference": "fda176884d2952cffc7e67209470bff49609339c",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9b3f45c51fe1d07845446675109bb0a8a98c806e",
+                "reference": "9b3f45c51fe1d07845446675109bb0a8a98c806e",
                 "shasum": ""
             },
             "require": {
@@ -143,9 +143,9 @@
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.199.7"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.200.0"
             },
-            "time": "2021-10-29T18:25:02+00:00"
+            "time": "2021-11-04T18:42:25+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -1843,16 +1843,16 @@
         },
         {
             "name": "laravel/framework",
-            "version": "v8.68.1",
+            "version": "v8.69.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f"
+                "reference": "545181da688db64fed6d8427e55f630a90ca0d32"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/abe985ff1fb82dd04aab03bc1dc56e83fe61a59f",
-                "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/545181da688db64fed6d8427e55f630a90ca0d32",
+                "reference": "545181da688db64fed6d8427e55f630a90ca0d32",
                 "shasum": ""
             },
             "require": {
@@ -2011,7 +2011,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2021-10-27T12:31:46+00:00"
+            "time": "2021-11-02T13:53:22+00:00"
         },
         {
             "name": "laravel/serializable-closure",
@@ -2211,16 +2211,16 @@
         },
         {
             "name": "laravel/ui",
-            "version": "v3.3.0",
+            "version": "v3.3.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/ui.git",
-                "reference": "07d725813350c695c779382cbd6dac0ab8665537"
+                "reference": "a449e3364d9780a80a49894a3af9795c85af806f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/ui/zipball/07d725813350c695c779382cbd6dac0ab8665537",
-                "reference": "07d725813350c695c779382cbd6dac0ab8665537",
+                "url": "https://api.github.com/repos/laravel/ui/zipball/a449e3364d9780a80a49894a3af9795c85af806f",
+                "reference": "a449e3364d9780a80a49894a3af9795c85af806f",
                 "shasum": ""
             },
             "require": {
@@ -2263,9 +2263,9 @@
                 "ui"
             ],
             "support": {
-                "source": "https://github.com/laravel/ui/tree/v3.3.0"
+                "source": "https://github.com/laravel/ui/tree/v3.3.1"
             },
-            "time": "2021-05-25T16:45:33+00:00"
+            "time": "2021-11-02T17:04:20+00:00"
         },
         {
             "name": "league/commonmark",
@@ -2966,16 +2966,16 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "2.53.1",
+            "version": "2.54.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045"
+                "reference": "eed83939f1aed3eee517d03a33f5ec587ac529b5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045",
-                "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/eed83939f1aed3eee517d03a33f5ec587ac529b5",
+                "reference": "eed83939f1aed3eee517d03a33f5ec587ac529b5",
                 "shasum": ""
             },
             "require": {
@@ -2986,6 +2986,7 @@
                 "symfony/translation": "^3.4 || ^4.0 || ^5.0"
             },
             "require-dev": {
+                "doctrine/dbal": "^2.0 || ^3.0",
                 "doctrine/orm": "^2.7",
                 "friendsofphp/php-cs-fixer": "^3.0",
                 "kylekatarnls/multi-tester": "^2.0",
@@ -3056,20 +3057,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-06T09:29:23+00:00"
+            "time": "2021-11-01T21:22:20+00:00"
         },
         {
             "name": "nikic/php-parser",
-            "version": "v4.13.0",
+            "version": "v4.13.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "50953a2691a922aa1769461637869a0a2faa3f53"
+                "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53",
-                "reference": "50953a2691a922aa1769461637869a0a2faa3f53",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd",
+                "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd",
                 "shasum": ""
             },
             "require": {
@@ -3110,9 +3111,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1"
             },
-            "time": "2021-09-20T12:20:58+00:00"
+            "time": "2021-11-03T20:52:16+00:00"
         },
         {
             "name": "onelogin/php-saml",
@@ -7681,22 +7682,22 @@
         },
         {
             "name": "itsgoingd/clockwork",
-            "version": "v5.1.0",
+            "version": "v5.1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/itsgoingd/clockwork.git",
-                "reference": "b963dee47429a49c9669981cfa9a8362ce209278"
+                "reference": "2daf30fa6dfc5a1ccfdb2142df59243a72c473d8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/b963dee47429a49c9669981cfa9a8362ce209278",
-                "reference": "b963dee47429a49c9669981cfa9a8362ce209278",
+                "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/2daf30fa6dfc5a1ccfdb2142df59243a72c473d8",
+                "reference": "2daf30fa6dfc5a1ccfdb2142df59243a72c473d8",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
                 "php": ">=5.6",
-                "psr/log": "1.*"
+                "psr/log": "1.* || ^2.0"
             },
             "type": "library",
             "extra": {
@@ -7738,7 +7739,7 @@
             ],
             "support": {
                 "issues": "https://github.com/itsgoingd/clockwork/issues",
-                "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.0"
+                "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.1"
             },
             "funding": [
                 {
@@ -7746,7 +7747,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-08-07T23:04:17+00:00"
+            "time": "2021-11-01T17:38:35+00:00"
         },
         {
             "name": "mockery/mockery",

From 6f75aa9cdcf419ad9046b7d93596204d80fe75b3 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Thu, 4 Nov 2021 22:38:55 +0000
Subject: [PATCH 6/6] Reverted shift change to old migration

---
 .../2018_08_04_115700_create_bookshelves_table.php  | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/database/migrations/2018_08_04_115700_create_bookshelves_table.php b/database/migrations/2018_08_04_115700_create_bookshelves_table.php
index 8dc2a72e9..bb1aec95b 100644
--- a/database/migrations/2018_08_04_115700_create_bookshelves_table.php
+++ b/database/migrations/2018_08_04_115700_create_bookshelves_table.php
@@ -2,6 +2,7 @@
 
 use Illuminate\Database\Migrations\Migration;
 use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Schema;
 
 class CreateBookshelvesTable extends Migration
@@ -120,11 +121,11 @@ class CreateBookshelvesTable extends Migration
         Schema::dropIfExists('bookshelves');
 
         // Drop related polymorphic items
-        DB::table('activities')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
-        DB::table('views')->where('viewable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
-        DB::table('entity_permissions')->where('restrictable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
-        DB::table('tags')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
-        DB::table('search_terms')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
-        DB::table('comments')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete();
+        DB::table('activities')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
+        DB::table('views')->where('viewable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
+        DB::table('entity_permissions')->where('restrictable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
+        DB::table('tags')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
+        DB::table('search_terms')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
+        DB::table('comments')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete();
     }
 }