From 5508c171db9ab34feb62694d912d4521cfa7b2ef Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 17 Feb 2025 12:45:37 +0000 Subject: [PATCH 1/2] PHP: Addressed 8.4 deprecations within app itself --- app/Access/Ldap.php | 8 ++++---- app/Access/SocialDriverManager.php | 2 +- app/App/helpers.php | 6 +++--- app/Entities/Controllers/BookController.php | 4 ++-- app/Entities/Controllers/PageController.php | 4 ++-- app/Entities/Queries/QueryPopular.php | 4 ++-- app/Entities/Repos/RevisionRepo.php | 2 +- app/Theming/ThemeService.php | 2 +- app/Uploads/ImageRepo.php | 20 +++++++++++++------- app/Uploads/ImageService.php | 4 ++-- app/Users/Controllers/UserApiController.php | 4 ++-- app/Util/SsrUrlValidator.php | 7 ++++++- dev/docs/logical-theme-system.md | 1 + tests/Entity/PageEditorTest.php | 10 +++++----- 14 files changed, 45 insertions(+), 33 deletions(-) diff --git a/app/Access/Ldap.php b/app/Access/Ldap.php index 702d629cef0..d14f688218c 100644 --- a/app/Access/Ldap.php +++ b/app/Access/Ldap.php @@ -54,7 +54,7 @@ public function setVersion($ldapConnection, int $version): bool * * @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 @@ public function search($ldapConnection, string $baseDn, string $filter, array $a * * @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 @@ public function getEntries($ldapConnection, $ldapSearchResult): array|false * * @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 @@ public function searchAndGetEntries($ldapConnection, string $baseDn, string $fil * * @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 536b2e63d37..dafc0e82d14 100644 --- a/app/Access/SocialDriverManager.php +++ b/app/Access/SocialDriverManager.php @@ -92,7 +92,7 @@ public function addSocialDriver( 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 204b3f06a72..eec86553fb4 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/Entities/Controllers/BookController.php b/app/Entities/Controllers/BookController.php index a1c586f47e7..b1685081a3d 100644 --- a/app/Entities/Controllers/BookController.php +++ b/app/Entities/Controllers/BookController.php @@ -70,7 +70,7 @@ public function index(Request $request) /** * 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 @@ public function create(string $shelfSlug = null) * @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 eab53bb2510..230a84721f8 100644 --- a/app/Entities/Controllers/PageController.php +++ b/app/Entities/Controllers/PageController.php @@ -41,7 +41,7 @@ public function __construct( * * @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 @@ public function create(string $bookSlug, string $chapterSlug = null) * * @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 85f88a1d19c..065ae82ef82 100644 --- a/app/Entities/Queries/QueryPopular.php +++ b/app/Entities/Queries/QueryPopular.php @@ -18,7 +18,7 @@ public function __construct( ) { } - 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 @@ public function run(int $count, int $page, array $filterModels = null): Collecti ->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 daf55777ce3..d5549a0f14a 100644 --- a/app/Entities/Repos/RevisionRepo.php +++ b/app/Entities/Repos/RevisionRepo.php @@ -46,7 +46,7 @@ public function getNewDraftForCurrentUser(Page $page): PageRevision /** * 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 639854d6ad1..4bdb6836b02 100644 --- a/app/Theming/ThemeService.php +++ b/app/Theming/ThemeService.php @@ -93,7 +93,7 @@ public function readThemeActions(): void /** * @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 845067fdc29..a16b87bd75b 100644 --- a/app/Uploads/ImageRepo.php +++ b/app/Uploads/ImageRepo.php @@ -49,9 +49,9 @@ public function getPaginatedByType( 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 @@ public function getEntityFiltered( $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 @@ public function getEntityFiltered( * * @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 @@ public function updateImageFile(Image $image, UploadedFile $file): void * * @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 038e6aa417c..4d6d4919742 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -31,8 +31,8 @@ public function saveNewFromUpload( 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 c84f1531d6a..bb2570b3108 100644 --- a/app/Users/Controllers/UserApiController.php +++ b/app/Users/Controllers/UserApiController.php @@ -33,7 +33,7 @@ public function __construct(UserRepo $userRepo) }); } - protected function rules(int $userId = null): array + protected function rules(?int $userId = null): array { return [ 'create' => [ @@ -54,7 +54,7 @@ protected function rules(int $userId = null): array '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 0b3a6a31de9..076a653fc86 100644 --- a/app/Util/SsrUrlValidator.php +++ b/app/Util/SsrUrlValidator.php @@ -4,11 +4,16 @@ 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/dev/docs/logical-theme-system.md b/dev/docs/logical-theme-system.md index 84bd26a5387..0063c4e8bac 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 21abd4ba1e6..bb3d7419306 100644 --- a/tests/Entity/PageEditorTest.php +++ b/tests/Entity/PageEditorTest.php @@ -191,20 +191,20 @@ public function test_editor_type_switch_options_show() { $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() From 5050719ea3933efcaaf3f69e51b25fcca0383f5b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 17 Feb 2025 13:37:58 +0000 Subject: [PATCH 2/2] PHP: Updated DOMPDF version --- app/Config/exports.php | 1 + composer.json | 2 +- composer.lock | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/Config/exports.php b/app/Config/exports.php index ba535ca7e4e..2e22bc759e3 100644 --- a/app/Config/exports.php +++ b/app/Config/exports.php @@ -114,6 +114,7 @@ * @var array */ 'allowed_protocols' => [ + "data://" => ["rules" => []], 'file://' => ['rules' => []], 'http://' => ['rules' => []], 'https://' => ['rules' => []], diff --git a/composer.json b/composer.json index 6fcf26aaadf..b77c90dd31c 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 1f3808cdcb8..9f5c9cf2809 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",