diff --git a/app/Access/Ldap.php b/app/Access/Ldap.php
index 702d629ce..d14f68821 100644
--- a/app/Access/Ldap.php
+++ b/app/Access/Ldap.php
@@ -54,7 +54,7 @@ class Ldap
      *
      * @return \LDAP\Result|array|false
      */
-    public function search($ldapConnection, string $baseDn, string $filter, array $attributes = null)
+    public function search($ldapConnection, string $baseDn, string $filter, array $attributes = [])
     {
         return ldap_search($ldapConnection, $baseDn, $filter, $attributes);
     }
@@ -66,7 +66,7 @@ class Ldap
      *
      * @return \LDAP\Result|array|false
      */
-    public function read($ldapConnection, string $baseDn, string $filter, array $attributes = null)
+    public function read($ldapConnection, string $baseDn, string $filter, array $attributes = [])
     {
         return ldap_read($ldapConnection, $baseDn, $filter, $attributes);
     }
@@ -87,7 +87,7 @@ class Ldap
      *
      * @param resource|\LDAP\Connection   $ldapConnection
      */
-    public function searchAndGetEntries($ldapConnection, string $baseDn, string $filter, array $attributes = null): array|false
+    public function searchAndGetEntries($ldapConnection, string $baseDn, string $filter, array $attributes = []): array|false
     {
         $search = $this->search($ldapConnection, $baseDn, $filter, $attributes);
 
@@ -99,7 +99,7 @@ class Ldap
      *
      * @param resource|\LDAP\Connection $ldapConnection
      */
-    public function bind($ldapConnection, string $bindRdn = null, string $bindPassword = null): bool
+    public function bind($ldapConnection, ?string $bindRdn = null, ?string $bindPassword = null): bool
     {
         return ldap_bind($ldapConnection, $bindRdn, $bindPassword);
     }
diff --git a/app/Access/SocialDriverManager.php b/app/Access/SocialDriverManager.php
index 536b2e63d..dafc0e82d 100644
--- a/app/Access/SocialDriverManager.php
+++ b/app/Access/SocialDriverManager.php
@@ -92,7 +92,7 @@ class SocialDriverManager
         string $driverName,
         array $config,
         string $socialiteHandler,
-        callable $configureForRedirect = null
+        ?callable $configureForRedirect = null
     ) {
         $this->validDrivers[] = $driverName;
         config()->set('services.' . $driverName, $config);
diff --git a/app/App/helpers.php b/app/App/helpers.php
index 204b3f06a..eec86553f 100644
--- a/app/App/helpers.php
+++ b/app/App/helpers.php
@@ -43,9 +43,9 @@ function user(): User
  * Check if the current user has a permission. If an ownable element
  * is passed in the jointPermissions are checked against that particular item.
  */
-function userCan(string $permission, Model $ownable = null): bool
+function userCan(string $permission, ?Model $ownable = null): bool
 {
-    if ($ownable === null) {
+    if (is_null($ownable)) {
         return user()->can($permission);
     }
 
@@ -71,7 +71,7 @@ function userCanOnAny(string $action, string $entityClass = ''): bool
  *
  * @return mixed|SettingService
  */
-function setting(string $key = null, $default = null)
+function setting(?string $key = null, mixed $default = null): mixed
 {
     $settingService = app()->make(SettingService::class);
 
diff --git a/app/Config/exports.php b/app/Config/exports.php
index ba535ca7e..2e22bc759 100644
--- a/app/Config/exports.php
+++ b/app/Config/exports.php
@@ -114,6 +114,7 @@ return [
          * @var array
          */
         'allowed_protocols' => [
+            "data://" => ["rules" => []],
             'file://'  => ['rules' => []],
             'http://'  => ['rules' => []],
             'https://' => ['rules' => []],
diff --git a/app/Entities/Controllers/BookController.php b/app/Entities/Controllers/BookController.php
index a1c586f47..b1685081a 100644
--- a/app/Entities/Controllers/BookController.php
+++ b/app/Entities/Controllers/BookController.php
@@ -70,7 +70,7 @@ class BookController extends Controller
     /**
      * Show the form for creating a new book.
      */
-    public function create(string $shelfSlug = null)
+    public function create(?string $shelfSlug = null)
     {
         $this->checkPermission('book-create-all');
 
@@ -93,7 +93,7 @@ class BookController extends Controller
      * @throws ImageUploadException
      * @throws ValidationException
      */
-    public function store(Request $request, string $shelfSlug = null)
+    public function store(Request $request, ?string $shelfSlug = null)
     {
         $this->checkPermission('book-create-all');
         $validated = $this->validate($request, [
diff --git a/app/Entities/Controllers/PageController.php b/app/Entities/Controllers/PageController.php
index eab53bb25..230a84721 100644
--- a/app/Entities/Controllers/PageController.php
+++ b/app/Entities/Controllers/PageController.php
@@ -41,7 +41,7 @@ class PageController extends Controller
      *
      * @throws Throwable
      */
-    public function create(string $bookSlug, string $chapterSlug = null)
+    public function create(string $bookSlug, ?string $chapterSlug = null)
     {
         if ($chapterSlug) {
             $parent = $this->entityQueries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
@@ -69,7 +69,7 @@ class PageController extends Controller
      *
      * @throws ValidationException
      */
-    public function createAsGuest(Request $request, string $bookSlug, string $chapterSlug = null)
+    public function createAsGuest(Request $request, string $bookSlug, ?string $chapterSlug = null)
     {
         $this->validate($request, [
             'name' => ['required', 'string', 'max:255'],
diff --git a/app/Entities/Queries/QueryPopular.php b/app/Entities/Queries/QueryPopular.php
index 85f88a1d1..065ae82ef 100644
--- a/app/Entities/Queries/QueryPopular.php
+++ b/app/Entities/Queries/QueryPopular.php
@@ -18,7 +18,7 @@ class QueryPopular
     ) {
     }
 
-    public function run(int $count, int $page, array $filterModels = null): Collection
+    public function run(int $count, int $page, array $filterModels): Collection
     {
         $query = $this->permissions
             ->restrictEntityRelationQuery(View::query(), 'views', 'viewable_id', 'viewable_type')
@@ -26,7 +26,7 @@ class QueryPopular
             ->groupBy('viewable_id', 'viewable_type')
             ->orderBy('view_count', 'desc');
 
-        if ($filterModels) {
+        if (!empty($filterModels)) {
             $query->whereIn('viewable_type', $this->entityProvider->getMorphClasses($filterModels));
         }
 
diff --git a/app/Entities/Repos/RevisionRepo.php b/app/Entities/Repos/RevisionRepo.php
index daf55777c..d5549a0f1 100644
--- a/app/Entities/Repos/RevisionRepo.php
+++ b/app/Entities/Repos/RevisionRepo.php
@@ -46,7 +46,7 @@ class RevisionRepo
     /**
      * Store a new revision in the system for the given page.
      */
-    public function storeNewForPage(Page $page, string $summary = null): PageRevision
+    public function storeNewForPage(Page $page, ?string $summary = null): PageRevision
     {
         $revision = new PageRevision();
 
diff --git a/app/Theming/ThemeService.php b/app/Theming/ThemeService.php
index 639854d6a..4bdb6836b 100644
--- a/app/Theming/ThemeService.php
+++ b/app/Theming/ThemeService.php
@@ -93,7 +93,7 @@ class ThemeService
     /**
      * @see SocialDriverManager::addSocialDriver
      */
-    public function addSocialDriver(string $driverName, array $config, string $socialiteHandler, callable $configureForRedirect = null): void
+    public function addSocialDriver(string $driverName, array $config, string $socialiteHandler, ?callable $configureForRedirect = null): void
     {
         $driverManager = app()->make(SocialDriverManager::class);
         $driverManager->addSocialDriver($driverName, $config, $socialiteHandler, $configureForRedirect);
diff --git a/app/Uploads/ImageRepo.php b/app/Uploads/ImageRepo.php
index 845067fdc..a16b87bd7 100644
--- a/app/Uploads/ImageRepo.php
+++ b/app/Uploads/ImageRepo.php
@@ -49,9 +49,9 @@ class ImageRepo
         string $type,
         int $page = 0,
         int $pageSize = 24,
-        int $uploadedTo = null,
-        string $search = null,
-        callable $whereClause = null
+        ?int $uploadedTo = null,
+        ?string $search = null,
+        ?callable $whereClause = null
     ): array {
         $imageQuery = Image::query()->where('type', '=', strtolower($type));
 
@@ -91,7 +91,7 @@ class ImageRepo
             $parentFilter = function (Builder $query) use ($filterType, $contextPage) {
                 if ($filterType === 'page') {
                     $query->where('uploaded_to', '=', $contextPage->id);
-                } elseif ($filterType === 'book') {
+                } else if ($filterType === 'book') {
                     $validPageIds = $contextPage->book->pages()
                         ->scopes('visible')
                         ->pluck('id')
@@ -109,8 +109,14 @@ class ImageRepo
      *
      * @throws ImageUploadException
      */
-    public function saveNew(UploadedFile $uploadFile, string $type, int $uploadedTo = 0, int $resizeWidth = null, int $resizeHeight = null, bool $keepRatio = true): Image
-    {
+    public function saveNew(
+        UploadedFile $uploadFile,
+        string $type,
+        int $uploadedTo = 0,
+        ?int $resizeWidth = null,
+        ?int $resizeHeight = null,
+        bool $keepRatio = true
+    ): Image {
         $image = $this->imageService->saveNewFromUpload($uploadFile, $type, $uploadedTo, $resizeWidth, $resizeHeight, $keepRatio);
 
         if ($type !== 'system') {
@@ -184,7 +190,7 @@ class ImageRepo
      *
      * @throws Exception
      */
-    public function destroyImage(Image $image = null): void
+    public function destroyImage(?Image $image = null): void
     {
         if ($image) {
             $this->imageService->destroy($image);
diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php
index 038e6aa41..4d6d49197 100644
--- a/app/Uploads/ImageService.php
+++ b/app/Uploads/ImageService.php
@@ -31,8 +31,8 @@ class ImageService
         UploadedFile $uploadedFile,
         string $type,
         int $uploadedTo = 0,
-        int $resizeWidth = null,
-        int $resizeHeight = null,
+        ?int $resizeWidth = null,
+        ?int $resizeHeight = null,
         bool $keepRatio = true,
         string $imageName = '',
     ): Image {
diff --git a/app/Users/Controllers/UserApiController.php b/app/Users/Controllers/UserApiController.php
index c84f1531d..bb2570b31 100644
--- a/app/Users/Controllers/UserApiController.php
+++ b/app/Users/Controllers/UserApiController.php
@@ -33,7 +33,7 @@ class UserApiController extends ApiController
         });
     }
 
-    protected function rules(int $userId = null): array
+    protected function rules(?int $userId = null): array
     {
         return [
             'create' => [
@@ -54,7 +54,7 @@ class UserApiController extends ApiController
                     'string',
                     'email',
                     'min:2',
-                    (new Unique('users', 'email'))->ignore($userId ?? null),
+                    (new Unique('users', 'email'))->ignore($userId),
                 ],
                 'external_auth_id' => ['string'],
                 'language'         => ['string', 'max:15', 'alpha_dash'],
diff --git a/app/Util/SsrUrlValidator.php b/app/Util/SsrUrlValidator.php
index 0b3a6a31d..076a653fc 100644
--- a/app/Util/SsrUrlValidator.php
+++ b/app/Util/SsrUrlValidator.php
@@ -4,11 +4,16 @@ namespace BookStack\Util;
 
 use BookStack\Exceptions\HttpFetchException;
 
+/**
+ * Validate the host we're connecting to when making a server-side-request.
+ * Will use the given hosts config if given during construction otherwise
+ * will look to the app configured config.
+ */
 class SsrUrlValidator
 {
     protected string $config;
 
-    public function __construct(string $config = null)
+    public function __construct(?string $config = null)
     {
         $this->config = $config ?? config('app.ssr_hosts') ?? '';
     }
diff --git a/composer.json b/composer.json
index 6fcf26aaa..b77c90dd3 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,7 @@
         "ext-xml": "*",
         "ext-zip": "*",
         "bacon/bacon-qr-code": "^3.0",
-        "dompdf/dompdf": "^3.0",
+        "dompdf/dompdf": "^3.1",
         "guzzlehttp/guzzle": "^7.4",
         "intervention/image": "^3.5",
         "knplabs/knp-snappy": "^1.5",
diff --git a/composer.lock b/composer.lock
index 1f3808cdc..9f5c9cf28 100644
--- a/composer.lock
+++ b/composer.lock
@@ -636,16 +636,16 @@
         },
         {
             "name": "dompdf/dompdf",
-            "version": "v3.0.2",
+            "version": "v3.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dompdf/dompdf.git",
-                "reference": "baf4084b27c7f4b5b7a221b19a94d11327664eb8"
+                "reference": "a51bd7a063a65499446919286fb18b518177155a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dompdf/dompdf/zipball/baf4084b27c7f4b5b7a221b19a94d11327664eb8",
-                "reference": "baf4084b27c7f4b5b7a221b19a94d11327664eb8",
+                "url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a",
+                "reference": "a51bd7a063a65499446919286fb18b518177155a",
                 "shasum": ""
             },
             "require": {
@@ -694,9 +694,9 @@
             "homepage": "https://github.com/dompdf/dompdf",
             "support": {
                 "issues": "https://github.com/dompdf/dompdf/issues",
-                "source": "https://github.com/dompdf/dompdf/tree/v3.0.2"
+                "source": "https://github.com/dompdf/dompdf/tree/v3.1.0"
             },
-            "time": "2024-12-27T20:27:37+00:00"
+            "time": "2025-01-15T14:09:04+00:00"
         },
         {
             "name": "dompdf/php-font-lib",
diff --git a/dev/docs/logical-theme-system.md b/dev/docs/logical-theme-system.md
index 84bd26a53..0063c4e8b 100644
--- a/dev/docs/logical-theme-system.md
+++ b/dev/docs/logical-theme-system.md
@@ -49,6 +49,7 @@ This method allows you to register a custom social authentication driver within
 - string $driverName
 - array $config
 - string $socialiteHandler
+- callable|null $configureForRedirect = null
 
 **Example**
 
diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php
index 21abd4ba1..bb3d74193 100644
--- a/tests/Entity/PageEditorTest.php
+++ b/tests/Entity/PageEditorTest.php
@@ -191,20 +191,20 @@ class PageEditorTest extends TestCase
     {
         $resp = $this->asAdmin()->get($this->page->getUrl('/edit'));
         $editLink = $this->page->getUrl('/edit') . '?editor=';
-        $this->withHtml($resp)->assertElementContains("a[href=\"${editLink}markdown-clean\"]", '(Clean Content)');
-        $this->withHtml($resp)->assertElementContains("a[href=\"${editLink}markdown-stable\"]", '(Stable Content)');
-        $this->withHtml($resp)->assertElementContains("a[href=\"${editLink}wysiwyg2024\"]", '(In Alpha Testing)');
+        $this->withHtml($resp)->assertElementContains("a[href=\"{$editLink}markdown-clean\"]", '(Clean Content)');
+        $this->withHtml($resp)->assertElementContains("a[href=\"{$editLink}markdown-stable\"]", '(Stable Content)');
+        $this->withHtml($resp)->assertElementContains("a[href=\"{$editLink}wysiwyg2024\"]", '(In Alpha Testing)');
 
         $resp = $this->asAdmin()->get($this->page->getUrl('/edit?editor=markdown-stable'));
         $editLink = $this->page->getUrl('/edit') . '?editor=';
-        $this->withHtml($resp)->assertElementContains("a[href=\"${editLink}wysiwyg\"]", 'Switch to WYSIWYG Editor');
+        $this->withHtml($resp)->assertElementContains("a[href=\"{$editLink}wysiwyg\"]", 'Switch to WYSIWYG Editor');
     }
 
     public function test_editor_type_switch_options_dont_show_if_without_change_editor_permissions()
     {
         $resp = $this->asEditor()->get($this->page->getUrl('/edit'));
         $editLink = $this->page->getUrl('/edit') . '?editor=';
-        $this->withHtml($resp)->assertElementNotExists("a[href*=\"${editLink}\"]");
+        $this->withHtml($resp)->assertElementNotExists("a[href*=\"{$editLink}\"]");
     }
 
     public function test_page_editor_type_switch_does_not_work_without_change_editor_permissions()