From cbf9d701af4e510be51fd1f5d2fd8a179534a523 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Sat, 14 Sep 2019 14:12:39 +0100
Subject: [PATCH] Updated to laravel 6

---
 .travis.yml                                   |   2 +-
 app/Config/logging.php                        |   6 +
 app/Http/Kernel.php                           |   1 +
 composer.json                                 |  45 +-
 composer.lock                                 | 698 +++++++++++-------
 database/factories/ModelFactory.php           |  12 +-
 phpunit.xml                                   |   3 +-
 resources/views/auth/login.blade.php          |   4 +-
 resources/views/auth/register.blade.php       |   2 +-
 .../views/partials/breadcrumbs.blade.php      |   4 +-
 tests/Auth/SocialAuthTest.php                 |   2 +-
 tests/Entity/PageContentTest.php              |   2 +-
 tests/SharedTestHelpers.php                   |  59 +-
 tests/Unit/ConfigTest.php                     |  31 +-
 tests/Unit/PageRepoTest.php                   |  14 +-
 tests/Unit/UrlTest.php                        |  14 +-
 tests/Uploads/AttachmentTest.php              |   2 +-
 17 files changed, 573 insertions(+), 328 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 8311f7d20..10a5d1e6b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,8 @@
 dist: bionic
 language: php
 php:
-  - '7.1.3'
   - '7.2'
+  - '7.3'
 
 services:
   - mysql
diff --git a/app/Config/logging.php b/app/Config/logging.php
index c952ac02f..9c3218a01 100644
--- a/app/Config/logging.php
+++ b/app/Config/logging.php
@@ -1,5 +1,6 @@
 <?php
 
+use Monolog\Handler\NullHandler;
 use Monolog\Handler\StreamHandler;
 
 /**
@@ -71,6 +72,11 @@ return [
             'driver' => 'errorlog',
             'level' => 'debug',
         ],
+
+        'null' => [
+            'driver' => 'monolog',
+            'handler' => NullHandler::class,
+        ],
     ],
 
 ];
\ No newline at end of file
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 67e01cd04..004f30139 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -29,6 +29,7 @@ class Kernel extends HttpKernel
             \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
             \Illuminate\Session\Middleware\StartSession::class,
             \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+            \Illuminate\Routing\Middleware\ThrottleRequests::class,
             \BookStack\Http\Middleware\VerifyCsrfToken::class,
             \Illuminate\Routing\Middleware\SubstituteBindings::class,
             \BookStack\Http\Middleware\Localization::class
diff --git a/composer.json b/composer.json
index b8c3e5536..d9d115017 100644
--- a/composer.json
+++ b/composer.json
@@ -5,39 +5,38 @@
     "license": "MIT",
     "type": "project",
     "require": {
-        "php": "^7.1.3",
-        "ext-json": "*",
-        "ext-tidy": "*",
-        "ext-dom": "*",
-        "ext-xml": "*",
-        "ext-mbstring": "*",
-        "ext-gd": "*",
+        "php": "^7.2",
         "ext-curl": "*",
-        "laravel/framework": "5.8.*",
-        "fideloper/proxy": "^4.0",
-        "intervention/image": "^2.5",
-        "laravel/socialite": "^4.2",
-        "league/flysystem-aws-s3-v3": "^1.0",
+        "ext-dom": "*",
+        "ext-gd": "*",
+        "ext-json": "*",
+        "ext-mbstring": "*",
+        "ext-tidy": "*",
+        "ext-xml": "*",
         "barryvdh/laravel-dompdf": "^0.8.5",
         "barryvdh/laravel-snappy": "^0.4.5",
-        "predis/predis": "^1.1",
+        "doctrine/dbal": "^2.9",
+        "fideloper/proxy": "^4.0",
         "gathercontent/htmldiff": "^0.2.1",
-        "socialiteproviders/slack": "^3.0",
+        "intervention/image": "^2.5",
+        "laravel/framework": "^6.0",
+        "laravel/socialite": "^4.2",
+        "league/flysystem-aws-s3-v3": "^1.0",
+        "predis/predis": "^1.1",
+        "socialiteproviders/discord": "^2.0",
+        "socialiteproviders/gitlab": "^3.0",
         "socialiteproviders/microsoft-azure": "^3.0",
         "socialiteproviders/okta": "^1.0",
-        "socialiteproviders/gitlab": "^3.0",
-        "socialiteproviders/twitch": "^3.0",
-        "socialiteproviders/discord": "^2.0",
-        "doctrine/dbal": "^2.9"
+        "socialiteproviders/slack": "^3.0",
+        "socialiteproviders/twitch": "^3.0"
     },
     "require-dev": {
-        "beyondcode/laravel-dump-server": "^1.0",
-        "filp/whoops": "^2.0",
+        "facade/ignition": "^1.4",
         "fzaninotto/faker": "^1.4",
         "mockery/mockery": "^1.0",
-        "phpunit/phpunit": "^7.5",
+        "phpunit/phpunit": "^8.0",
         "nunomaduro/collision": "^3.0",
-        "laravel/browser-kit-testing": "^4.2.1",
+        "laravel/browser-kit-testing": "^5.1",
         "barryvdh/laravel-ide-helper": "^2.6.4",
         "barryvdh/laravel-debugbar": "^3.2.8",
         "squizlabs/php_codesniffer": "^3.4"
@@ -89,7 +88,7 @@
         "preferred-install": "dist",
         "sort-packages": true,
         "platform": {
-            "php": "7.1.3"
+            "php": "7.2.0"
         }
     },
     "extra": {
diff --git a/composer.lock b/composer.lock
index bf072fef8..5c3cb66b1 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "e1ffc91b76f0e5949245144507d6dddc",
+    "content-hash": "322b6b585d85e066f97711fe8f1f7ccd",
     "packages": [
         {
             "name": "aws/aws-sdk-php",
@@ -557,28 +557,30 @@
         },
         {
             "name": "doctrine/lexer",
-            "version": "1.0.2",
+            "version": "1.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/lexer.git",
-                "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8"
+                "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8",
-                "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8",
+                "url": "https://api.github.com/repos/doctrine/lexer/zipball/e17f069ede36f7534b95adec71910ed1b49c74ea",
+                "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.2"
+                "php": "^7.2"
             },
             "require-dev": {
-                "phpunit/phpunit": "^4.5"
+                "doctrine/coding-standard": "^6.0",
+                "phpstan/phpstan": "^0.11.8",
+                "phpunit/phpunit": "^8.2"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.0.x-dev"
+                    "dev-master": "1.1.x-dev"
                 }
             },
             "autoload": {
@@ -591,14 +593,14 @@
                 "MIT"
             ],
             "authors": [
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
                 {
                     "name": "Guilherme Blanco",
                     "email": "guilhermeblanco@gmail.com"
                 },
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
                 {
                     "name": "Johannes Schmitt",
                     "email": "schmittjoh@gmail.com"
@@ -613,7 +615,7 @@
                 "parser",
                 "php"
             ],
-            "time": "2019-06-08T11:03:04+00:00"
+            "time": "2019-07-30T19:33:28+00:00"
         },
         {
             "name": "dompdf/dompdf",
@@ -1265,90 +1267,45 @@
             ],
             "time": "2018-12-14T14:59:37+00:00"
         },
-        {
-            "name": "kylekatarnls/update-helper",
-            "version": "1.2.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/kylekatarnls/update-helper.git",
-                "reference": "5786fa188e0361b9adf9e8199d7280d1b2db165e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/kylekatarnls/update-helper/zipball/5786fa188e0361b9adf9e8199d7280d1b2db165e",
-                "reference": "5786fa188e0361b9adf9e8199d7280d1b2db165e",
-                "shasum": ""
-            },
-            "require": {
-                "composer-plugin-api": "^1.1.0 || ^2.0.0",
-                "php": ">=5.3.0"
-            },
-            "require-dev": {
-                "codeclimate/php-test-reporter": "dev-master",
-                "composer/composer": "2.0.x-dev || ^2.0.0-dev",
-                "phpunit/phpunit": ">=4.8.35 <6.0"
-            },
-            "type": "composer-plugin",
-            "extra": {
-                "class": "UpdateHelper\\ComposerPlugin"
-            },
-            "autoload": {
-                "psr-0": {
-                    "UpdateHelper\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Kyle",
-                    "email": "kylekatarnls@gmail.com"
-                }
-            ],
-            "description": "Update helper",
-            "time": "2019-07-29T11:03:54+00:00"
-        },
         {
             "name": "laravel/framework",
-            "version": "v5.8.35",
+            "version": "v6.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "5a9e4d241a8b815e16c9d2151e908992c38db197"
+                "reference": "56789e9dec750e0fbe8e9e6ae90a01a4e6887902"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/5a9e4d241a8b815e16c9d2151e908992c38db197",
-                "reference": "5a9e4d241a8b815e16c9d2151e908992c38db197",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/56789e9dec750e0fbe8e9e6ae90a01a4e6887902",
+                "reference": "56789e9dec750e0fbe8e9e6ae90a01a4e6887902",
                 "shasum": ""
             },
             "require": {
                 "doctrine/inflector": "^1.1",
                 "dragonmantank/cron-expression": "^2.0",
-                "egulias/email-validator": "^2.0",
+                "egulias/email-validator": "^2.1.10",
                 "erusev/parsedown": "^1.7",
                 "ext-json": "*",
                 "ext-mbstring": "*",
                 "ext-openssl": "*",
                 "league/flysystem": "^1.0.8",
-                "monolog/monolog": "^1.12",
-                "nesbot/carbon": "^1.26.3 || ^2.0",
+                "monolog/monolog": "^1.12|^2.0",
+                "nesbot/carbon": "^2.0",
                 "opis/closure": "^3.1",
-                "php": "^7.1.3",
+                "php": "^7.2",
                 "psr/container": "^1.0",
                 "psr/simple-cache": "^1.0",
                 "ramsey/uuid": "^3.7",
                 "swiftmailer/swiftmailer": "^6.0",
-                "symfony/console": "^4.2",
-                "symfony/debug": "^4.2",
-                "symfony/finder": "^4.2",
-                "symfony/http-foundation": "^4.2",
-                "symfony/http-kernel": "^4.2",
-                "symfony/process": "^4.2",
-                "symfony/routing": "^4.2",
-                "symfony/var-dumper": "^4.2",
+                "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/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"
             },
@@ -1388,47 +1345,44 @@
             "require-dev": {
                 "aws/aws-sdk-php": "^3.0",
                 "doctrine/dbal": "^2.6",
-                "filp/whoops": "^2.1.4",
+                "filp/whoops": "^2.4",
                 "guzzlehttp/guzzle": "^6.3",
                 "league/flysystem-cached-adapter": "^1.0",
-                "mockery/mockery": "^1.0",
+                "mockery/mockery": "^1.2.3",
                 "moontoast/math": "^1.1",
-                "orchestra/testbench-core": "3.8.*",
+                "orchestra/testbench-core": "^4.0",
                 "pda/pheanstalk": "^4.0",
-                "phpunit/phpunit": "^7.5|^8.0",
+                "phpunit/phpunit": "^8.3",
                 "predis/predis": "^1.1.1",
-                "symfony/css-selector": "^4.2",
-                "symfony/dom-crawler": "^4.2",
+                "symfony/cache": "^4.3",
                 "true/punycode": "^2.1"
             },
             "suggest": {
-                "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (^3.0).",
+                "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.0).",
                 "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).",
                 "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().",
+                "ext-memcached": "Required to use the memcache cache driver.",
                 "ext-pcntl": "Required to use all features of the queue worker.",
                 "ext-posix": "Required to use all features of the queue worker.",
-                "filp/whoops": "Required for friendly error pages in development (^2.1.4).",
+                "ext-redis": "Required to use the Redis cache and queue drivers.",
+                "filp/whoops": "Required for friendly error pages in development (^2.4).",
                 "fzaninotto/faker": "Required to use the eloquent factory builder (^1.4).",
-                "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (^6.0).",
+                "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.0).",
                 "laravel/tinker": "Required to use the tinker console command (^1.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-rackspace": "Required to use the Flysystem Rackspace driver (^1.0).",
                 "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).",
                 "moontoast/math": "Required to use ordered UUIDs (^1.1).",
-                "nexmo/client": "Required to use the Nexmo transport (^1.0).",
                 "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).",
-                "predis/predis": "Required to use the redis cache and queue drivers (^1.0).",
                 "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^3.0).",
-                "symfony/css-selector": "Required to use some of the crawler integration testing tools (^4.2).",
-                "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (^4.2).",
-                "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^1.1).",
+                "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).",
                 "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)."
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "5.8-dev"
+                    "dev-master": "6.x-dev"
                 }
             },
             "autoload": {
@@ -1456,7 +1410,7 @@
                 "framework",
                 "laravel"
             ],
-            "time": "2019-09-03T16:44:30+00:00"
+            "time": "2019-09-10T18:46:24+00:00"
         },
         {
             "name": "laravel/socialite",
@@ -1718,21 +1672,21 @@
         },
         {
             "name": "monolog/monolog",
-            "version": "1.25.1",
+            "version": "2.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Seldaek/monolog.git",
-                "reference": "70e65a5470a42cfec1a7da00d30edb6e617e8dcf"
+                "reference": "68545165e19249013afd1d6f7485aecff07a2d22"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/70e65a5470a42cfec1a7da00d30edb6e617e8dcf",
-                "reference": "70e65a5470a42cfec1a7da00d30edb6e617e8dcf",
+                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/68545165e19249013afd1d6f7485aecff07a2d22",
+                "reference": "68545165e19249013afd1d6f7485aecff07a2d22",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.0",
-                "psr/log": "~1.0"
+                "php": "^7.2",
+                "psr/log": "^1.0.1"
             },
             "provide": {
                 "psr/log-implementation": "1.0.0"
@@ -1740,33 +1694,36 @@
             "require-dev": {
                 "aws/aws-sdk-php": "^2.4.9 || ^3.0",
                 "doctrine/couchdb": "~1.0@dev",
-                "graylog2/gelf-php": "~1.0",
-                "jakub-onderka/php-parallel-lint": "0.9",
+                "elasticsearch/elasticsearch": "^6.0",
+                "graylog2/gelf-php": "^1.4.2",
+                "jakub-onderka/php-parallel-lint": "^0.9",
                 "php-amqplib/php-amqplib": "~2.4",
                 "php-console/php-console": "^3.1.3",
-                "phpunit/phpunit": "~4.5",
-                "phpunit/phpunit-mock-objects": "2.3.0",
+                "phpspec/prophecy": "^1.6.1",
+                "phpunit/phpunit": "^8.3",
+                "predis/predis": "^1.1",
+                "rollbar/rollbar": "^1.3",
                 "ruflin/elastica": ">=0.90 <3.0",
-                "sentry/sentry": "^0.13",
                 "swiftmailer/swiftmailer": "^5.3|^6.0"
             },
             "suggest": {
                 "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
                 "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+                "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
                 "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
-                "ext-mongo": "Allow sending log messages to a MongoDB server",
+                "ext-mbstring": "Allow to work properly with unicode symbols",
+                "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
                 "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
-                "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
+                "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
                 "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
                 "php-console/php-console": "Allow sending log messages to Google Chrome",
                 "rollbar/rollbar": "Allow sending log messages to Rollbar",
-                "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
-                "sentry/sentry": "Allow sending log messages to a Sentry server"
+                "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.0.x-dev"
+                    "dev-master": "2.x-dev"
                 }
             },
             "autoload": {
@@ -1792,7 +1749,7 @@
                 "logging",
                 "psr-3"
             ],
-            "time": "2019-09-06T13:49:17+00:00"
+            "time": "2019-08-30T09:56:44+00:00"
         },
         {
             "name": "mtdowling/jmespath.php",
@@ -1851,34 +1808,36 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "1.39.0",
+            "version": "2.24.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "dd62a58af4e0775a45ea5f99d0363d81b7d9a1e0"
+                "reference": "934459c5ac0658bc765ad1e53512c7c77adcac29"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/dd62a58af4e0775a45ea5f99d0363d81b7d9a1e0",
-                "reference": "dd62a58af4e0775a45ea5f99d0363d81b7d9a1e0",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/934459c5ac0658bc765ad1e53512c7c77adcac29",
+                "reference": "934459c5ac0658bc765ad1e53512c7c77adcac29",
                 "shasum": ""
             },
             "require": {
-                "kylekatarnls/update-helper": "^1.1",
-                "php": ">=5.3.9",
-                "symfony/translation": "~2.6 || ~3.0 || ~4.0"
+                "ext-json": "*",
+                "php": "^7.1.8 || ^8.0",
+                "symfony/translation": "^3.4 || ^4.0"
             },
             "require-dev": {
-                "composer/composer": "^1.2",
-                "friendsofphp/php-cs-fixer": "~2",
-                "phpunit/phpunit": "^4.8.35 || ^5.7"
+                "friendsofphp/php-cs-fixer": "^2.14 || ^3.0",
+                "kylekatarnls/multi-tester": "^1.1",
+                "phpmd/phpmd": "dev-php-7.1-compatibility",
+                "phpstan/phpstan": "^0.11",
+                "phpunit/phpunit": "^7.5 || ^8.0",
+                "squizlabs/php_codesniffer": "^3.4"
             },
             "bin": [
-                "bin/upgrade-carbon"
+                "bin/carbon"
             ],
             "type": "library",
             "extra": {
-                "update-helper": "Carbon\\Upgrade",
                 "laravel": {
                     "providers": [
                         "Carbon\\Laravel\\ServiceProvider"
@@ -1887,7 +1846,7 @@
             },
             "autoload": {
                 "psr-4": {
-                    "": "src/"
+                    "Carbon\\": "src/Carbon/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -1899,16 +1858,20 @@
                     "name": "Brian Nesbitt",
                     "email": "brian@nesbot.com",
                     "homepage": "http://nesbot.com"
+                },
+                {
+                    "name": "kylekatarnls",
+                    "homepage": "http://github.com/kylekatarnls"
                 }
             ],
-            "description": "A simple API extension for DateTime.",
+            "description": "A API extension for DateTime that supports 281 different languages.",
             "homepage": "http://carbon.nesbot.com",
             "keywords": [
                 "date",
                 "datetime",
                 "time"
             ],
-            "time": "2019-06-11T09:07:59+00:00"
+            "time": "2019-08-31T16:37:55+00:00"
         },
         {
             "name": "opis/closure",
@@ -4499,67 +4462,6 @@
             ],
             "time": "2018-12-13T10:34:14+00:00"
         },
-        {
-            "name": "beyondcode/laravel-dump-server",
-            "version": "1.3.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/beyondcode/laravel-dump-server.git",
-                "reference": "fcc88fa66895f8c1ff83f6145a5eff5fa2a0739a"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/beyondcode/laravel-dump-server/zipball/fcc88fa66895f8c1ff83f6145a5eff5fa2a0739a",
-                "reference": "fcc88fa66895f8c1ff83f6145a5eff5fa2a0739a",
-                "shasum": ""
-            },
-            "require": {
-                "illuminate/console": "5.6.*|5.7.*|5.8.*|^6.0",
-                "illuminate/http": "5.6.*|5.7.*|5.8.*|^6.0",
-                "illuminate/support": "5.6.*|5.7.*|5.8.*|^6.0",
-                "php": "^7.1",
-                "symfony/var-dumper": "^4.1.1"
-            },
-            "require-dev": {
-                "larapack/dd": "^1.0",
-                "phpunit/phpunit": "^7.0"
-            },
-            "type": "library",
-            "extra": {
-                "laravel": {
-                    "providers": [
-                        "BeyondCode\\DumpServer\\DumpServerServiceProvider"
-                    ]
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "BeyondCode\\DumpServer\\": "src"
-                },
-                "files": [
-                    "helpers.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Marcel Pociot",
-                    "email": "marcel@beyondco.de",
-                    "homepage": "https://beyondco.de",
-                    "role": "Developer"
-                }
-            ],
-            "description": "Symfony Var-Dump Server for Laravel",
-            "homepage": "https://github.com/beyondcode/laravel-dump-server",
-            "keywords": [
-                "beyondcode",
-                "laravel-dump-server"
-            ],
-            "time": "2019-08-11T13:17:40+00:00"
-        },
         {
             "name": "composer/ca-bundle",
             "version": "1.2.4",
@@ -4918,6 +4820,172 @@
             ],
             "time": "2019-03-17T17:37:11+00:00"
         },
+        {
+            "name": "facade/flare-client-php",
+            "version": "1.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/facade/flare-client-php.git",
+                "reference": "7128b251b48f24ef64e5cddd7f8d40cc3a06fd3e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/facade/flare-client-php/zipball/7128b251b48f24ef64e5cddd7f8d40cc3a06fd3e",
+                "reference": "7128b251b48f24ef64e5cddd7f8d40cc3a06fd3e",
+                "shasum": ""
+            },
+            "require": {
+                "facade/ignition-contracts": "~1.0",
+                "illuminate/pipeline": "~5.5|~5.6|~5.7|~5.8|^6.0",
+                "php": "^7.1",
+                "symfony/http-foundation": "~3.3|~4.1",
+                "symfony/var-dumper": "^3.4|^4.0"
+            },
+            "require-dev": {
+                "larapack/dd": "^1.1",
+                "phpunit/phpunit": "^7.0",
+                "spatie/phpunit-snapshot-assertions": "^2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Facade\\FlareClient\\": "src"
+                },
+                "files": [
+                    "src/helpers.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Send PHP errors to Flare",
+            "homepage": "https://github.com/facade/flare-client-php",
+            "keywords": [
+                "exception",
+                "facade",
+                "flare",
+                "reporting"
+            ],
+            "time": "2019-09-11T14:19:56+00:00"
+        },
+        {
+            "name": "facade/ignition",
+            "version": "1.6.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/facade/ignition.git",
+                "reference": "97244f6d511332f3574acab8242c09ddcfda892b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/facade/ignition/zipball/97244f6d511332f3574acab8242c09ddcfda892b",
+                "reference": "97244f6d511332f3574acab8242c09ddcfda892b",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "facade/flare-client-php": "^1.0.4",
+                "facade/ignition-contracts": "^1.0",
+                "filp/whoops": "^2.4",
+                "illuminate/support": "~5.5.0 || ~5.6.0 || ~5.7.0 || ~5.8.0 || ^6.0",
+                "monolog/monolog": "^1.12 || ^2.0",
+                "php": "^7.1",
+                "scrivo/highlight.php": "^9.15",
+                "symfony/console": "^3.4 || ^4.0",
+                "symfony/var-dumper": "^3.4 || ^4.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^2.14",
+                "mockery/mockery": "^1.2",
+                "orchestra/testbench": "^3.5 || ^3.6 || ^3.7 || ^3.8 || ^4.0"
+            },
+            "suggest": {
+                "laravel/telescope": "^2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                },
+                "laravel": {
+                    "providers": [
+                        "Facade\\Ignition\\IgnitionServiceProvider"
+                    ],
+                    "aliases": {
+                        "Flare": "Facade\\Ignition\\Facades\\Flare"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Facade\\Ignition\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "A beautiful error page for Laravel applications.",
+            "homepage": "https://github.com/facade/ignition",
+            "keywords": [
+                "error",
+                "flare",
+                "laravel",
+                "page"
+            ],
+            "time": "2019-09-13T13:38:04+00:00"
+        },
+        {
+            "name": "facade/ignition-contracts",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/facade/ignition-contracts.git",
+                "reference": "f445db0fb86f48e205787b2592840dd9c80ded28"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/facade/ignition-contracts/zipball/f445db0fb86f48e205787b2592840dd9c80ded28",
+                "reference": "f445db0fb86f48e205787b2592840dd9c80ded28",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.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"
+            ],
+            "time": "2019-08-30T14:06:08+00:00"
+        },
         {
             "name": "filp/whoops",
             "version": "2.5.0",
@@ -5233,30 +5301,41 @@
         },
         {
             "name": "laravel/browser-kit-testing",
-            "version": "v4.2.1",
+            "version": "v5.1.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/browser-kit-testing.git",
-                "reference": "b042ed965910a4ba69c0ebe8863d4029af3e242e"
+                "reference": "cb0cf22cf38fe8796842adc8b9ad550ded2a1377"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/b042ed965910a4ba69c0ebe8863d4029af3e242e",
-                "reference": "b042ed965910a4ba69c0ebe8863d4029af3e242e",
+                "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/cb0cf22cf38fe8796842adc8b9ad550ded2a1377",
+                "reference": "cb0cf22cf38fe8796842adc8b9ad550ded2a1377",
                 "shasum": ""
             },
             "require": {
-                "illuminate/support": "^5.6",
+                "ext-dom": "*",
+                "ext-json": "*",
+                "illuminate/contracts": "~5.7.0|~5.8.0|^6.0",
+                "illuminate/database": "~5.7.0|~5.8.0|^6.0",
+                "illuminate/http": "~5.7.0|~5.8.0|^6.0",
+                "illuminate/support": "~5.7.0|~5.8.0|^6.0",
                 "mockery/mockery": "^1.0",
                 "php": ">=7.1.3",
-                "phpunit/phpunit": "^7.0",
-                "symfony/css-selector": "~4.0",
-                "symfony/dom-crawler": "~4.0"
+                "phpunit/phpunit": "^7.0|^8.0",
+                "symfony/console": "^4.2",
+                "symfony/css-selector": "^4.2",
+                "symfony/dom-crawler": "^4.2",
+                "symfony/http-foundation": "^4.2",
+                "symfony/http-kernel": "^4.2"
+            },
+            "require-dev": {
+                "laravel/framework": "~5.7.0|~5.8.0|^6.0"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.0-dev"
+                    "dev-master": "5.0-dev"
                 }
             },
             "autoload": {
@@ -5279,7 +5358,7 @@
                 "laravel",
                 "testing"
             ],
-            "time": "2019-02-05T13:27:14+00:00"
+            "time": "2019-07-30T14:57:44+00:00"
         },
         {
             "name": "maximebf/debugbar",
@@ -5836,40 +5915,40 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "6.1.4",
+            "version": "7.0.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
+                "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
-                "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7743bbcfff2a907e9ee4a25be13d0f8ec5e73800",
+                "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800",
                 "shasum": ""
             },
             "require": {
                 "ext-dom": "*",
                 "ext-xmlwriter": "*",
-                "php": "^7.1",
-                "phpunit/php-file-iterator": "^2.0",
+                "php": "^7.2",
+                "phpunit/php-file-iterator": "^2.0.2",
                 "phpunit/php-text-template": "^1.2.1",
-                "phpunit/php-token-stream": "^3.0",
+                "phpunit/php-token-stream": "^3.1.0",
                 "sebastian/code-unit-reverse-lookup": "^1.0.1",
-                "sebastian/environment": "^3.1 || ^4.0",
+                "sebastian/environment": "^4.2.2",
                 "sebastian/version": "^2.0.1",
-                "theseer/tokenizer": "^1.1"
+                "theseer/tokenizer": "^1.1.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^7.0"
+                "phpunit/phpunit": "^8.2.2"
             },
             "suggest": {
-                "ext-xdebug": "^2.6.0"
+                "ext-xdebug": "^2.7.2"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "6.1-dev"
+                    "dev-master": "7.0-dev"
                 }
             },
             "autoload": {
@@ -5895,7 +5974,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2018-10-31T16:06:48+00:00"
+            "time": "2019-07-25T05:31:54+00:00"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -6088,53 +6167,52 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "7.5.15",
+            "version": "8.3.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "d79c053d972856b8b941bb233e39dc521a5093f0"
+                "reference": "302faed7059fde575cf3403a78c730c5e3a62750"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d79c053d972856b8b941bb233e39dc521a5093f0",
-                "reference": "d79c053d972856b8b941bb233e39dc521a5093f0",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/302faed7059fde575cf3403a78c730c5e3a62750",
+                "reference": "302faed7059fde575cf3403a78c730c5e3a62750",
                 "shasum": ""
             },
             "require": {
-                "doctrine/instantiator": "^1.1",
+                "doctrine/instantiator": "^1.2.0",
                 "ext-dom": "*",
                 "ext-json": "*",
                 "ext-libxml": "*",
                 "ext-mbstring": "*",
                 "ext-xml": "*",
-                "myclabs/deep-copy": "^1.7",
-                "phar-io/manifest": "^1.0.2",
-                "phar-io/version": "^2.0",
-                "php": "^7.1",
-                "phpspec/prophecy": "^1.7",
-                "phpunit/php-code-coverage": "^6.0.7",
-                "phpunit/php-file-iterator": "^2.0.1",
+                "ext-xmlwriter": "*",
+                "myclabs/deep-copy": "^1.9.1",
+                "phar-io/manifest": "^1.0.3",
+                "phar-io/version": "^2.0.1",
+                "php": "^7.2",
+                "phpspec/prophecy": "^1.8.1",
+                "phpunit/php-code-coverage": "^7.0.7",
+                "phpunit/php-file-iterator": "^2.0.2",
                 "phpunit/php-text-template": "^1.2.1",
-                "phpunit/php-timer": "^2.1",
-                "sebastian/comparator": "^3.0",
-                "sebastian/diff": "^3.0",
-                "sebastian/environment": "^4.0",
-                "sebastian/exporter": "^3.1",
-                "sebastian/global-state": "^2.0",
+                "phpunit/php-timer": "^2.1.2",
+                "sebastian/comparator": "^3.0.2",
+                "sebastian/diff": "^3.0.2",
+                "sebastian/environment": "^4.2.2",
+                "sebastian/exporter": "^3.1.1",
+                "sebastian/global-state": "^3.0.0",
                 "sebastian/object-enumerator": "^3.0.3",
-                "sebastian/resource-operations": "^2.0",
+                "sebastian/resource-operations": "^2.0.1",
+                "sebastian/type": "^1.1.3",
                 "sebastian/version": "^2.0.1"
             },
-            "conflict": {
-                "phpunit/phpunit-mock-objects": "*"
-            },
             "require-dev": {
                 "ext-pdo": "*"
             },
             "suggest": {
                 "ext-soap": "*",
                 "ext-xdebug": "*",
-                "phpunit/php-invoker": "^2.0"
+                "phpunit/php-invoker": "^2.0.0"
             },
             "bin": [
                 "phpunit"
@@ -6142,7 +6220,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "7.5-dev"
+                    "dev-master": "8.3-dev"
                 }
             },
             "autoload": {
@@ -6168,7 +6246,74 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2019-08-21T07:05:16+00:00"
+            "time": "2019-09-14T09:12:03+00:00"
+        },
+        {
+            "name": "scrivo/highlight.php",
+            "version": "v9.15.10.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/scrivo/highlight.php.git",
+                "reference": "9ad3adb4456dc91196327498dbbce6aa1ba1239e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/9ad3adb4456dc91196327498dbbce6aa1ba1239e",
+                "reference": "9ad3adb4456dc91196327498dbbce6aa1ba1239e",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "php": ">=5.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8|^5.7",
+                "symfony/finder": "^2.8"
+            },
+            "suggest": {
+                "ext-dom": "Needed to make use of the features in the utilities namespace"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Highlight\\": "",
+                    "HighlightUtilities\\": ""
+                },
+                "files": [
+                    "HighlightUtilities/functions.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Geert Bergman",
+                    "role": "Project Author",
+                    "homepage": "http://www.scrivo.org/"
+                },
+                {
+                    "name": "Vladimir Jimenez",
+                    "role": "Contributor",
+                    "homepage": "https://allejo.io"
+                },
+                {
+                    "name": "Martin Folkers",
+                    "role": "Contributor",
+                    "homepage": "https://twobrain.io"
+                }
+            ],
+            "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js",
+            "keywords": [
+                "code",
+                "highlight",
+                "highlight.js",
+                "highlight.php",
+                "syntax"
+            ],
+            "time": "2019-08-27T04:27:48+00:00"
         },
         {
             "name": "sebastian/code-unit-reverse-lookup",
@@ -6390,16 +6535,16 @@
         },
         {
             "name": "sebastian/exporter",
-            "version": "3.1.1",
+            "version": "3.1.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/exporter.git",
-                "reference": "06a9a5947f47b3029d76118eb5c22802e5869687"
+                "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687",
-                "reference": "06a9a5947f47b3029d76118eb5c22802e5869687",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e",
+                "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e",
                 "shasum": ""
             },
             "require": {
@@ -6453,27 +6598,30 @@
                 "export",
                 "exporter"
             ],
-            "time": "2019-08-11T12:43:14+00:00"
+            "time": "2019-09-14T09:02:43+00:00"
         },
         {
             "name": "sebastian/global-state",
-            "version": "2.0.0",
+            "version": "3.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/global-state.git",
-                "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
+                "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
-                "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
+                "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.0"
+                "php": "^7.2",
+                "sebastian/object-reflector": "^1.1.1",
+                "sebastian/recursion-context": "^3.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^6.0"
+                "ext-dom": "*",
+                "phpunit/phpunit": "^8.0"
             },
             "suggest": {
                 "ext-uopz": "*"
@@ -6481,7 +6629,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.0-dev"
+                    "dev-master": "3.0-dev"
                 }
             },
             "autoload": {
@@ -6504,7 +6652,7 @@
             "keywords": [
                 "global state"
             ],
-            "time": "2017-04-27T15:39:26+00:00"
+            "time": "2019-02-01T05:30:01+00:00"
         },
         {
             "name": "sebastian/object-enumerator",
@@ -6693,6 +6841,52 @@
             "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
             "time": "2018-10-04T04:07:39+00:00"
         },
+        {
+            "name": "sebastian/type",
+            "version": "1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/type.git",
+                "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3",
+                "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Collection of value objects that represent the types of the PHP type system",
+            "homepage": "https://github.com/sebastianbergmann/type",
+            "time": "2019-07-02T08:10:15+00:00"
+        },
         {
             "name": "sebastian/version",
             "version": "2.0.1",
@@ -7088,17 +7282,17 @@
     "prefer-stable": true,
     "prefer-lowest": false,
     "platform": {
-        "php": "^7.1.3",
-        "ext-json": "*",
-        "ext-tidy": "*",
+        "php": "^7.2",
+        "ext-curl": "*",
         "ext-dom": "*",
-        "ext-xml": "*",
-        "ext-mbstring": "*",
         "ext-gd": "*",
-        "ext-curl": "*"
+        "ext-json": "*",
+        "ext-mbstring": "*",
+        "ext-tidy": "*",
+        "ext-xml": "*"
     },
     "platform-dev": [],
     "platform-overrides": {
-        "php": "7.1.3"
+        "php": "7.2.0"
     }
 }
diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php
index de6b0b276..ddf3c295d 100644
--- a/database/factories/ModelFactory.php
+++ b/database/factories/ModelFactory.php
@@ -15,8 +15,8 @@ $factory->define(\BookStack\Auth\User::class, function ($faker) {
     return [
         'name' => $faker->name,
         'email' => $faker->email,
-        'password' => str_random(10),
-        'remember_token' => str_random(10),
+        'password' => Str::random(10),
+        'remember_token' => Str::random(10),
         'email_confirmed' => 1
     ];
 });
@@ -24,7 +24,7 @@ $factory->define(\BookStack\Auth\User::class, function ($faker) {
 $factory->define(\BookStack\Entities\Bookshelf::class, function ($faker) {
     return [
         'name' => $faker->sentence,
-        'slug' => str_random(10),
+        'slug' => Str::random(10),
         'description' => $faker->paragraph
     ];
 });
@@ -32,7 +32,7 @@ $factory->define(\BookStack\Entities\Bookshelf::class, function ($faker) {
 $factory->define(\BookStack\Entities\Book::class, function ($faker) {
     return [
         'name' => $faker->sentence,
-        'slug' => str_random(10),
+        'slug' => Str::random(10),
         'description' => $faker->paragraph
     ];
 });
@@ -40,7 +40,7 @@ $factory->define(\BookStack\Entities\Book::class, function ($faker) {
 $factory->define(\BookStack\Entities\Chapter::class, function ($faker) {
     return [
         'name' => $faker->sentence,
-        'slug' => str_random(10),
+        'slug' => Str::random(10),
         'description' => $faker->paragraph
     ];
 });
@@ -49,7 +49,7 @@ $factory->define(\BookStack\Entities\Page::class, function ($faker) {
     $html = '<p>' . implode('</p>', $faker->paragraphs(5)) . '</p>';
     return [
         'name' => $faker->sentence,
-        'slug' => str_random(10),
+        'slug' => Str::random(10),
         'html' => $html,
         'text' => strip_tags($html),
         'revision_count' => 1
diff --git a/phpunit.xml b/phpunit.xml
index 21f81e32c..7de7233af 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -28,7 +28,8 @@
         <server name="QUEUE_CONNECTION" value="sync"/>
         <server name="DB_CONNECTION" value="mysql_testing"/>
         <server name="BCRYPT_ROUNDS" value="4"/>
-        <server name="MAIL_DRIVER" value="log"/>
+        <server name="MAIL_DRIVER" value="array"/>
+        <server name="LOG_CHANNEL" value="null"/>
         <server name="AUTH_METHOD" value="standard"/>
         <server name="DISABLE_EXTERNAL_SERVICES" value="true"/>
         <server name="AVATAR_URL" value=""/>
diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php
index 438339e92..2f3cc1f73 100644
--- a/resources/views/auth/login.blade.php
+++ b/resources/views/auth/login.blade.php
@@ -7,7 +7,7 @@
         <div class="my-l">&nbsp;</div>
 
         <div class="card content-wrap auto-height">
-            <h1 class="list-heading">{{ title_case(trans('auth.log_in')) }}</h1>
+            <h1 class="list-heading">{{ Str::title(trans('auth.log_in')) }}</h1>
 
             <form action="{{ url('/login') }}" method="POST" id="login-form" class="mt-l">
                 {!! csrf_field() !!}
@@ -28,7 +28,7 @@
                     </div>
 
                     <div class="text-right">
-                        <button class="button" tabindex="1">{{ title_case(trans('auth.log_in')) }}</button>
+                        <button class="button" tabindex="1">{{ Str::title(trans('auth.log_in')) }}</button>
                     </div>
                 </div>
 
diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php
index 60ceba93c..0e996a00d 100644
--- a/resources/views/auth/register.blade.php
+++ b/resources/views/auth/register.blade.php
@@ -6,7 +6,7 @@
         <div class="my-l">&nbsp;</div>
 
         <div class="card content-wrap auto-height">
-            <h1 class="list-heading">{{ title_case(trans('auth.sign_up')) }}</h1>
+            <h1 class="list-heading">{{ Str::title(trans('auth.sign_up')) }}</h1>
 
             <form action="{{ url("/register") }}" method="POST" class="mt-l stretch-inputs">
                 {!! csrf_field() !!}
diff --git a/resources/views/partials/breadcrumbs.blade.php b/resources/views/partials/breadcrumbs.blade.php
index 5e11a9190..58ccd5125 100644
--- a/resources/views/partials/breadcrumbs.blade.php
+++ b/resources/views/partials/breadcrumbs.blade.php
@@ -2,7 +2,7 @@
     <?php $breadcrumbCount = 0; ?>
 
     {{-- Show top level books item --}}
-    @if (count($crumbs) > 0 && array_first($crumbs) instanceof  \BookStack\Entities\Book)
+    @if (count($crumbs) > 0 && ($crumbs[0] ?? null) instanceof  \BookStack\Entities\Book)
         <a href="{{  url('/books')  }}" class="text-book icon-list-item outline-hover">
             <span>@icon('books')</span>
             <span>{{ trans('entities.books') }}</span>
@@ -11,7 +11,7 @@
     @endif
 
     {{-- Show top level shelves item --}}
-    @if (count($crumbs) > 0 && array_first($crumbs) instanceof  \BookStack\Entities\Bookshelf)
+    @if (count($crumbs) > 0 && ($crumbs[0] ?? null) instanceof  \BookStack\Entities\Bookshelf)
         <a href="{{  url('/shelves')  }}" class="text-bookshelf icon-list-item outline-hover">
             <span>@icon('bookshelf')</span>
             <span>{{ trans('entities.shelves') }}</span>
diff --git a/tests/Auth/SocialAuthTest.php b/tests/Auth/SocialAuthTest.php
index b8ca81174..526c0e199 100644
--- a/tests/Auth/SocialAuthTest.php
+++ b/tests/Auth/SocialAuthTest.php
@@ -153,7 +153,7 @@ class SocialAuthTest extends TestCase
         config()->set('services.google.select_account', 'true');
 
         $resp = $this->get('/login/service/google');
-        $this->assertContains('prompt=select_account', $resp->headers->get('Location'));
+        $this->assertStringContainsString('prompt=select_account', $resp->headers->get('Location'));
     }
 
 }
diff --git a/tests/Entity/PageContentTest.php b/tests/Entity/PageContentTest.php
index e812d5bfe..a0fcb5ca8 100644
--- a/tests/Entity/PageContentTest.php
+++ b/tests/Entity/PageContentTest.php
@@ -50,7 +50,7 @@ class PageContentTest extends TestCase
         $resp->assertStatus(302);
 
         $page = Page::find($page->id);
-        $this->assertContains($includeTag, $page->html);
+        $this->assertStringContainsString($includeTag, $page->html);
         $this->assertEquals('', $page->text);
     }
 
diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php
index 1d87e942a..eb3f7b4bb 100644
--- a/tests/SharedTestHelpers.php
+++ b/tests/SharedTestHelpers.php
@@ -1,8 +1,6 @@
 <?php namespace Tests;
 
 use BookStack\Entities\Book;
-use BookStack\Entities\Bookshelf;
-use BookStack\Entities\Chapter;
 use BookStack\Entities\Entity;
 use BookStack\Entities\Page;
 use BookStack\Entities\Repos\EntityRepo;
@@ -12,6 +10,7 @@ use BookStack\Auth\Permissions\PermissionService;
 use BookStack\Entities\Repos\PageRepo;
 use BookStack\Settings\SettingService;
 use BookStack\Uploads\HttpFetcher;
+use Illuminate\Support\Env;
 
 trait SharedTestHelpers
 {
@@ -77,6 +76,7 @@ trait SharedTestHelpers
     /**
      * Regenerate the permission for an entity.
      * @param Entity $entity
+     * @throws \Throwable
      */
     protected function regenEntityPermissions(Entity $entity)
     {
@@ -116,6 +116,7 @@ trait SharedTestHelpers
      * Create and return a new test page
      * @param array $input
      * @return Page
+     * @throws \Throwable
      */
     public function newPage($input = ['name' => 'test page', 'html' => 'My new test page']) {
         $book = Book::first();
@@ -204,4 +205,58 @@ trait SharedTestHelpers
             ->andReturn($returnData);
     }
 
+    /**
+     * Run a set test with the given env variable.
+     * Remembers the original and resets the value after test.
+     * @param string $name
+     * @param $value
+     * @param callable $callback
+     */
+    protected function runWithEnv(string $name, $value, callable $callback)
+    {
+        Env::disablePutenv();
+        $originalVal = $_ENV[$name] ?? null;
+
+        if (is_null($value)) {
+            unset($_ENV[$name]);
+            unset($_SERVER[$name]);
+        } else {
+            $_ENV[$name] = $value;
+            $_SERVER[$name] = $value;
+        }
+
+        $this->refreshApplication();
+        $callback();
+
+        if (is_null($originalVal)) {
+            unset($_SERVER[$name]);
+            unset($_ENV[$name]);
+        } else {
+            $_SERVER[$name] = $originalVal;
+            $_ENV[$name] = $originalVal;
+        }
+    }
+
+    /**
+     * Check the keys and properties in the given map to include
+     * exist, albeit not exclusively, within the map to check.
+     * @param array $mapToInclude
+     * @param array $mapToCheck
+     * @param string $message
+     */
+    protected function assertArrayMapIncludes(array $mapToInclude, array $mapToCheck, string $message = '') : void
+    {
+        $passed = true;
+
+        foreach ($mapToInclude as $key => $value) {
+            if (!isset($mapToCheck[$key]) || $mapToCheck[$key] !== $mapToInclude[$key]) {
+                $passed = false;
+            }
+        }
+
+        $toIncludeStr = print_r($mapToInclude, true);
+        $toCheckStr = print_r($mapToCheck, true);
+        self::assertThat($passed, self::isTrue(), "Failed asserting that given map:\n\n{$toCheckStr}\n\nincludes:\n\n{$toIncludeStr}");
+    }
+
 }
\ No newline at end of file
diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php
index ec9967227..7b9f64e6a 100644
--- a/tests/Unit/ConfigTest.php
+++ b/tests/Unit/ConfigTest.php
@@ -12,22 +12,19 @@ class ConfigTest extends TestCase
 
     public function test_filesystem_images_falls_back_to_storage_type_var()
     {
-        putenv('STORAGE_TYPE=local_secure');
-
-        $this->checkEnvConfigResult('STORAGE_IMAGE_TYPE', 's3', 'filesystems.images', 's3');
-        $this->checkEnvConfigResult('STORAGE_IMAGE_TYPE', null, 'filesystems.images', 'local_secure');
-
-        putenv('STORAGE_TYPE=local');
+        $this->runWithEnv('STORAGE_TYPE', 'local_secure', function() {
+            $this->checkEnvConfigResult('STORAGE_IMAGE_TYPE', 's3', 'filesystems.images', 's3');
+            $this->checkEnvConfigResult('STORAGE_IMAGE_TYPE', null, 'filesystems.images', 'local_secure');
+        });
     }
 
     public function test_filesystem_attachments_falls_back_to_storage_type_var()
     {
         putenv('STORAGE_TYPE=local_secure');
-
-        $this->checkEnvConfigResult('STORAGE_ATTACHMENT_TYPE', 's3', 'filesystems.attachments', 's3');
-        $this->checkEnvConfigResult('STORAGE_ATTACHMENT_TYPE', null, 'filesystems.attachments', 'local_secure');
-
-        putenv('STORAGE_TYPE=local');
+        $this->runWithEnv('STORAGE_TYPE', 'local_secure', function() {
+            $this->checkEnvConfigResult('STORAGE_ATTACHMENT_TYPE', 's3', 'filesystems.attachments', 's3');
+            $this->checkEnvConfigResult('STORAGE_ATTACHMENT_TYPE', null, 'filesystems.attachments', 'local_secure');
+        });
     }
 
     public function test_app_url_blank_if_old_default_value()
@@ -49,15 +46,9 @@ class ConfigTest extends TestCase
      */
     protected function checkEnvConfigResult(string $envName, $envVal, string $configKey, string $expectedResult)
     {
-        $originalVal = getenv($envName);
-        
-        $envString = $envName . (is_null($envVal) ? '' : '=') . ($envVal ?? '');
-        putenv($envString);
-        $this->refreshApplication();
-        $this->assertEquals($expectedResult, config($configKey));
-
-        $envString = $envName . (empty($originalVal) ? '' : '=') . ($originalVal ?? '');
-        putenv($envString);
+        $this->runWithEnv($envName, $envVal, function() use ($configKey, $expectedResult) {
+            $this->assertEquals($expectedResult, config($configKey));
+        });
     }
 
 }
\ No newline at end of file
diff --git a/tests/Unit/PageRepoTest.php b/tests/Unit/PageRepoTest.php
index c5e094b63..38ffbf616 100644
--- a/tests/Unit/PageRepoTest.php
+++ b/tests/Unit/PageRepoTest.php
@@ -22,19 +22,19 @@ class PageRepoTest extends TestCase
         $navMap = $this->pageRepo->getPageNav($content);
 
         $this->assertCount(3, $navMap);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h1',
             'link' => '#testa',
             'text' => 'Hello',
             'level' => 1,
         ], $navMap[0]);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h2',
             'link' => '#testb',
             'text' => 'There',
             'level' => 2,
         ], $navMap[1]);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h3',
             'link' => '#testc',
             'text' => 'Donkey',
@@ -48,7 +48,7 @@ class PageRepoTest extends TestCase
         $navMap = $this->pageRepo->getPageNav($content);
 
         $this->assertCount(1, $navMap);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h1',
             'link' => '#testa',
             'text' => 'Hello'
@@ -61,15 +61,15 @@ class PageRepoTest extends TestCase
         $navMap = $this->pageRepo->getPageNav($content);
 
         $this->assertCount(3, $navMap);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h4',
             'level' => 1,
         ], $navMap[0]);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h5',
             'level' => 2,
         ], $navMap[1]);
-        $this->assertArraySubset([
+        $this->assertArrayMapIncludes([
             'nodeName' => 'h6',
             'level' => 3,
         ], $navMap[2]);
diff --git a/tests/Unit/UrlTest.php b/tests/Unit/UrlTest.php
index 1667f5f7b..c2386443c 100644
--- a/tests/Unit/UrlTest.php
+++ b/tests/Unit/UrlTest.php
@@ -16,18 +16,16 @@ class UrlTest extends TestCase
 
     public function test_url_helper_takes_custom_url_into_account()
     {
-        putenv('APP_URL=http://example.com/bookstack');
-        $this->refreshApplication();
-        $this->assertEquals('http://example.com/bookstack/books', url('/books'));
-        putenv('APP_URL=');
+        $this->runWithEnv('APP_URL', 'http://example.com/bookstack', function() {
+            $this->assertEquals('http://example.com/bookstack/books', url('/books'));
+        });
     }
 
     public function test_url_helper_sets_correct_scheme_even_when_request_scheme_is_different()
     {
-        putenv('APP_URL=https://example.com/');
-        $this->refreshApplication();
-        $this->get('http://example.com/login')->assertSee('https://example.com/dist/styles.css');
-        putenv('APP_URL=');
+        $this->runWithEnv('APP_URL', 'https://example.com/', function() {
+            $this->get('http://example.com/login')->assertSee('https://example.com/dist/styles.css');
+        });
     }
 
 }
\ No newline at end of file
diff --git a/tests/Uploads/AttachmentTest.php b/tests/Uploads/AttachmentTest.php
index 35ffda821..0d51e050f 100644
--- a/tests/Uploads/AttachmentTest.php
+++ b/tests/Uploads/AttachmentTest.php
@@ -78,7 +78,7 @@ class AttachmentTest extends TestCase
         $upload->assertStatus(200);
 
         $attachment = Attachment::query()->orderBy('id', 'desc')->first();
-        $this->assertNotContains($fileName, $attachment->path);
+        $this->assertStringNotContainsString($fileName, $attachment->path);
         $this->assertStringEndsWith('.txt', $attachment->path);
     }