Merge pull request #5400 from BookStackApp/laravel11

Laravel 11 Upgrade
This commit is contained in:
Dan Brown 2025-01-13 13:27:32 +00:00 committed by GitHub
commit b9751807e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 1036 additions and 1235 deletions

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
php: ['8.1', '8.2', '8.3', '8.4']
php: ['8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v4

View File

@ -13,10 +13,10 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
matrix:
php: ['8.1', '8.2', '8.3', '8.4']
php: ['8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v4

View File

@ -8,27 +8,15 @@ use Illuminate\Database\Eloquent\Model;
class ExternalBaseUserProvider implements UserProvider
{
/**
* The user model.
*
* @var string
*/
protected $model;
/**
* LdapUserProvider constructor.
*/
public function __construct(string $model)
{
$this->model = $model;
public function __construct(
protected string $model
) {
}
/**
* Create a new instance of the model.
*
* @return Model
*/
public function createModel()
public function createModel(): Model
{
$class = '\\' . ltrim($this->model, '\\');
@ -37,12 +25,8 @@ class ExternalBaseUserProvider implements UserProvider
/**
* Retrieve a user by their unique identifier.
*
* @param mixed $identifier
*
* @return Authenticatable|null
*/
public function retrieveById($identifier)
public function retrieveById(mixed $identifier): ?Authenticatable
{
return $this->createModel()->newQuery()->find($identifier);
}
@ -50,12 +34,9 @@ class ExternalBaseUserProvider implements UserProvider
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* @param mixed $identifier
* @param string $token
*
* @return Authenticatable|null
*/
public function retrieveByToken($identifier, $token)
public function retrieveByToken(mixed $identifier, $token): null
{
return null;
}
@ -75,12 +56,8 @@ class ExternalBaseUserProvider implements UserProvider
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
*
* @return Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
public function retrieveByCredentials(array $credentials): ?Authenticatable
{
// Search current user base by looking up a uid
$model = $this->createModel();
@ -92,15 +69,15 @@ class ExternalBaseUserProvider implements UserProvider
/**
* Validate a user against the given credentials.
*
* @param Authenticatable $user
* @param array $credentials
*
* @return bool
*/
public function validateCredentials(Authenticatable $user, array $credentials)
public function validateCredentials(Authenticatable $user, array $credentials): bool
{
// Should be done in the guard.
return false;
}
public function rehashPasswordIfRequired(Authenticatable $user, #[\SensitiveParameter] array $credentials, bool $force = false)
{
// No action to perform, any passwords are external in the auth system
}
}

View File

@ -26,7 +26,6 @@ class Comment extends Model implements Loggable
use HasCreatorAndUpdater;
protected $fillable = ['parent_id'];
protected $appends = ['created', 'updated'];
/**
* Get the entity that this comment belongs to.
@ -54,22 +53,6 @@ class Comment extends Model implements Loggable
return $this->updated_at->timestamp > $this->created_at->timestamp;
}
/**
* Get created date as a relative diff.
*/
public function getCreatedAttribute(): string
{
return $this->created_at->diffForHumans();
}
/**
* Get updated date as a relative diff.
*/
public function getUpdatedAttribute(): string
{
return $this->updated_at->diffForHumans();
}
public function logDescriptor(): string
{
return "Comment #{$this->local_id} (ID: {$this->id}) for {$this->entity_type} (ID: {$this->entity_id})";

View File

@ -42,4 +42,12 @@ class EventServiceProvider extends ServiceProvider
{
return false;
}
/**
* Overrides the registration of Laravel's default email verification system
*/
protected function configureEmailVerification(): void
{
//
}
}

View File

@ -1,37 +0,0 @@
<?php
/**
* Broadcasting 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.
*/
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' => 'null',
// 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' => [
// Default options removed since we don't use broadcasting.
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];

View File

@ -35,10 +35,6 @@ return [
// Available caches stores
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
'serialize' => false,
@ -49,6 +45,7 @@ return [
'table' => 'cache',
'connection' => null,
'lock_connection' => null,
'lock_table' => null,
],
'file' => [

View File

@ -33,12 +33,14 @@ return [
'driver' => 'local',
'root' => public_path(),
'visibility' => 'public',
'serve' => false,
'throw' => true,
],
'local_secure_attachments' => [
'driver' => 'local',
'root' => storage_path('uploads/files/'),
'serve' => false,
'throw' => true,
],
@ -46,6 +48,7 @@ return [
'driver' => 'local',
'root' => storage_path('uploads/images/'),
'visibility' => 'public',
'serve' => false,
'throw' => true,
],

View File

@ -38,7 +38,7 @@ return [
'password' => env('MAIL_PASSWORD'),
'verify_peer' => env('MAIL_VERIFY_SSL', true),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN'),
'local_domain' => null,
'tls_required' => ($mailEncryption === 'tls' || $mailEncryption === 'ssl'),
],
@ -64,12 +64,4 @@ return [
],
],
],
// Email markdown configuration
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
],
];

View File

@ -23,6 +23,7 @@ return [
'database' => [
'driver' => 'database',
'connection' => null,
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,

View File

@ -5,7 +5,6 @@ namespace BookStack\Uploads;
use BookStack\Exceptions\FileUploadException;
use Exception;
use Illuminate\Contracts\Filesystem\Filesystem as Storage;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Filesystem\FilesystemManager;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

View File

@ -8,7 +8,7 @@
"license": "MIT",
"type": "project",
"require": {
"php": "^8.1.0",
"php": "^8.2.0",
"ext-curl": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
@ -18,12 +18,11 @@
"ext-xml": "*",
"ext-zip": "*",
"bacon/bacon-qr-code": "^3.0",
"doctrine/dbal": "^3.5",
"dompdf/dompdf": "^3.0",
"guzzlehttp/guzzle": "^7.4",
"intervention/image": "^3.5",
"knplabs/knp-snappy": "^1.5",
"laravel/framework": "^10.48.23",
"laravel/framework": "^v11.37",
"laravel/socialite": "^5.10",
"laravel/tinker": "^2.8",
"league/commonmark": "^2.3",
@ -40,17 +39,17 @@
"socialiteproviders/okta": "^4.2",
"socialiteproviders/twitch": "^5.3",
"ssddanbrown/htmldiff": "^1.0.2",
"ssddanbrown/symfony-mailer": "6.4.x-dev"
"ssddanbrown/symfony-mailer": "7.2.x-dev"
},
"require-dev": {
"fakerphp/faker": "^1.21",
"itsgoingd/clockwork": "^5.1",
"mockery/mockery": "^1.5",
"nunomaduro/collision": "^7.0",
"larastan/larastan": "^2.7",
"phpunit/phpunit": "^10.0",
"nunomaduro/collision": "^8.1",
"larastan/larastan": "^v3.0",
"phpunit/phpunit": "^11.5",
"squizlabs/php_codesniffer": "^3.7",
"ssddanbrown/asserthtml": "^3.0"
"ssddanbrown/asserthtml": "^3.1"
},
"autoload": {
"psr-4": {
@ -104,7 +103,7 @@
"preferred-install": "dist",
"sort-packages": true,
"platform": {
"php": "8.1.0"
"php": "8.2.0"
}
},
"extra": {

2032
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -26,25 +26,19 @@ return new class extends Migration
*/
public function down(): void
{
$sm = Schema::getConnection()->getDoctrineSchemaManager();
$prefix = DB::getTablePrefix();
$pages = $sm->introspectTable($prefix . 'pages');
$books = $sm->introspectTable($prefix . 'books');
$chapters = $sm->introspectTable($prefix . 'chapters');
if ($pages->hasIndex('search')) {
if (Schema::hasIndex('pages', 'search')) {
Schema::table('pages', function (Blueprint $table) {
$table->dropIndex('search');
});
}
if ($books->hasIndex('search')) {
if (Schema::hasIndex('books', 'search')) {
Schema::table('books', function (Blueprint $table) {
$table->dropIndex('search');
});
}
if ($chapters->hasIndex('search')) {
if (Schema::hasIndex('chapters', 'search')) {
Schema::table('chapters', function (Blueprint $table) {
$table->dropIndex('search');
});

View File

@ -26,25 +26,19 @@ return new class extends Migration
*/
public function down(): void
{
$sm = Schema::getConnection()->getDoctrineSchemaManager();
$prefix = DB::getTablePrefix();
$pages = $sm->introspectTable($prefix . 'pages');
$books = $sm->introspectTable($prefix . 'books');
$chapters = $sm->introspectTable($prefix . 'chapters');
if ($pages->hasIndex('name_search')) {
if (Schema::hasIndex('pages', 'name_search')) {
Schema::table('pages', function (Blueprint $table) {
$table->dropIndex('name_search');
});
}
if ($books->hasIndex('name_search')) {
if (Schema::hasIndex('books', 'name_search')) {
Schema::table('books', function (Blueprint $table) {
$table->dropIndex('name_search');
});
}
if ($chapters->hasIndex('name_search')) {
if (Schema::hasIndex('chapters', 'name_search')) {
Schema::table('chapters', function (Blueprint $table) {
$table->dropIndex('name_search');
});

View File

@ -25,27 +25,21 @@ return new class extends Migration
$table->index('score');
});
$sm = Schema::getConnection()->getDoctrineSchemaManager();
$prefix = DB::getTablePrefix();
$pages = $sm->introspectTable($prefix . 'pages');
$books = $sm->introspectTable($prefix . 'books');
$chapters = $sm->introspectTable($prefix . 'chapters');
if ($pages->hasIndex('search')) {
if (Schema::hasIndex('pages', 'search')) {
Schema::table('pages', function (Blueprint $table) {
$table->dropIndex('search');
$table->dropIndex('name_search');
});
}
if ($books->hasIndex('search')) {
if (Schema::hasIndex('books', 'search')) {
Schema::table('books', function (Blueprint $table) {
$table->dropIndex('search');
$table->dropIndex('name_search');
});
}
if ($chapters->hasIndex('search')) {
if (Schema::hasIndex('chapters', 'search')) {
Schema::table('chapters', function (Blueprint $table) {
$table->dropIndex('search');
$table->dropIndex('name_search');

View File

@ -8,7 +8,7 @@ return new class extends Migration
/**
* Mapping of old polymorphic types to new simpler values.
*/
protected $changeMap = [
protected array $changeMap = [
'BookStack\\Bookshelf' => 'bookshelf',
'BookStack\\Book' => 'book',
'BookStack\\Chapter' => 'chapter',
@ -18,7 +18,7 @@ return new class extends Migration
/**
* Mapping of tables and columns that contain polymorphic types.
*/
protected $columnsByTable = [
protected array $columnsByTable = [
'activities' => 'entity_type',
'comments' => 'entity_type',
'deletions' => 'deletable_type',

View File

@ -9,7 +9,9 @@ parameters:
# The level 8 is the highest level
level: 1
phpVersion: 80200
phpVersion:
min: 80200
max: 80400
bootstrapFiles:
- bootstrap/phpstan.php
@ -19,6 +21,4 @@ parameters:
excludePaths:
- ./Config/**/*.php
- ./dev/**/*.php
checkMissingIterableValueType: false
- ./dev/**/*.php

View File

@ -5,45 +5,16 @@ use Illuminate\Contracts\Http\Kernel;
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.
|
*/
// Determine if the application is in maintenance mode...
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
| 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.
|
*/
// Register the Composer autoloader...
require __DIR__ . '/../vendor/autoload.php';
/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| 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.
|
*/
// Run the application
$app = require_once __DIR__ . '/../bootstrap/app.php';
$app->alias('request', Request::class);

View File

@ -300,7 +300,7 @@ class PageTest extends TestCase
]);
$resp = $this->asAdmin()->get('/pages/recently-updated');
$this->withHtml($resp)->assertElementContains('.entity-list .page:nth-child(1)', 'Updated 1 second ago by ' . $user->name);
$this->withHtml($resp)->assertElementContains('.entity-list .page:nth-child(1)', 'Updated 0 seconds ago by ' . $user->name);
}
public function test_recently_updated_pages_view_shows_parent_chain()