From 9ca088a4e2a952250583d920d2a1cc0aaca51189 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 6 Feb 2023 20:00:44 +0000 Subject: [PATCH] Fixed static analysis issues --- .../Tools/Markdown/CustomListItemRenderer.php | 24 +++++++------- .../Markdown/CustomStrikeThroughExtension.php | 6 ++-- .../Markdown/CustomStrikethroughRenderer.php | 18 +++++----- .../Tools/Markdown/MarkdownToHtml.php | 12 ++++--- app/Http/Request.php | 8 ++--- app/Theming/ThemeEvents.php | 4 +-- app/Uploads/AttachmentService.php | 4 +-- app/Uploads/ImageService.php | 33 ++++++++----------- app/Util/LanguageManager.php | 2 +- phpstan.neon.dist | 2 +- 10 files changed, 52 insertions(+), 61 deletions(-) diff --git a/app/Entities/Tools/Markdown/CustomListItemRenderer.php b/app/Entities/Tools/Markdown/CustomListItemRenderer.php index be4cac4a7..0c506d7f9 100644 --- a/app/Entities/Tools/Markdown/CustomListItemRenderer.php +++ b/app/Entities/Tools/Markdown/CustomListItemRenderer.php @@ -2,18 +2,18 @@ namespace BookStack\Entities\Tools\Markdown; -use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\Block\Element\ListItem; -use League\CommonMark\Block\Element\Paragraph; -use League\CommonMark\Block\Renderer\BlockRendererInterface; -use League\CommonMark\Block\Renderer\ListItemRenderer; -use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; +use League\CommonMark\Extension\CommonMark\Renderer\Block\ListItemRenderer; use League\CommonMark\Extension\TaskList\TaskListItemMarker; -use League\CommonMark\HtmlElement; +use League\CommonMark\Node\Block\Paragraph; +use League\CommonMark\Node\Node; +use League\CommonMark\Renderer\ChildNodeRendererInterface; +use League\CommonMark\Renderer\NodeRendererInterface; +use League\CommonMark\Util\HtmlElement; -class CustomListItemRenderer implements BlockRendererInterface +class CustomListItemRenderer implements NodeRendererInterface { - protected $baseRenderer; + protected ListItemRenderer $baseRenderer; public function __construct() { @@ -23,11 +23,11 @@ class CustomListItemRenderer implements BlockRendererInterface /** * @return HtmlElement|string|null */ - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) + public function render(Node $node, ChildNodeRendererInterface $childRenderer) { - $listItem = $this->baseRenderer->render($block, $htmlRenderer, $inTightList); + $listItem = $this->baseRenderer->render($node, $childRenderer); - if ($this->startsTaskListItem($block)) { + if ($node instanceof ListItem && $this->startsTaskListItem($node) && $listItem instanceof HtmlElement) { $listItem->setAttribute('class', 'task-list-item'); } diff --git a/app/Entities/Tools/Markdown/CustomStrikeThroughExtension.php b/app/Entities/Tools/Markdown/CustomStrikeThroughExtension.php index a8ccfc4f9..ee4e93397 100644 --- a/app/Entities/Tools/Markdown/CustomStrikeThroughExtension.php +++ b/app/Entities/Tools/Markdown/CustomStrikeThroughExtension.php @@ -2,16 +2,16 @@ namespace BookStack\Entities\Tools\Markdown; -use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Extension\Strikethrough\Strikethrough; use League\CommonMark\Extension\Strikethrough\StrikethroughDelimiterProcessor; class CustomStrikeThroughExtension implements ExtensionInterface { - public function register(ConfigurableEnvironmentInterface $environment) + public function register(EnvironmentBuilderInterface $environment): void { $environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor()); - $environment->addInlineRenderer(Strikethrough::class, new CustomStrikethroughRenderer()); + $environment->addRenderer(Strikethrough::class, new CustomStrikethroughRenderer()); } } diff --git a/app/Entities/Tools/Markdown/CustomStrikethroughRenderer.php b/app/Entities/Tools/Markdown/CustomStrikethroughRenderer.php index ca9f434af..01b09377b 100644 --- a/app/Entities/Tools/Markdown/CustomStrikethroughRenderer.php +++ b/app/Entities/Tools/Markdown/CustomStrikethroughRenderer.php @@ -2,25 +2,23 @@ namespace BookStack\Entities\Tools\Markdown; -use League\CommonMark\ElementRendererInterface; use League\CommonMark\Extension\Strikethrough\Strikethrough; -use League\CommonMark\HtmlElement; -use League\CommonMark\Inline\Element\AbstractInline; -use League\CommonMark\Inline\Renderer\InlineRendererInterface; +use League\CommonMark\Node\Node; +use League\CommonMark\Renderer\ChildNodeRendererInterface; +use League\CommonMark\Renderer\NodeRendererInterface; +use League\CommonMark\Util\HtmlElement; /** * This is a somewhat clone of the League\CommonMark\Extension\Strikethrough\StrikethroughRender * class but modified slightly to use HTML tags instead of in order to * match front-end markdown-it rendering. */ -class CustomStrikethroughRenderer implements InlineRendererInterface +class CustomStrikethroughRenderer implements NodeRendererInterface { - public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) + public function render(Node $node, ChildNodeRendererInterface $childRenderer) { - if (!($inline instanceof Strikethrough)) { - throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline)); - } + Strikethrough::assertInstanceOf($node); - return new HtmlElement('s', $inline->getData('attributes', []), $htmlRenderer->renderInlines($inline->children())); + return new HtmlElement('s', $node->data->get('attributes'), $childRenderer->renderNodes($node->children())); } } diff --git a/app/Entities/Tools/Markdown/MarkdownToHtml.php b/app/Entities/Tools/Markdown/MarkdownToHtml.php index 06587ce1f..0cee9d9a3 100644 --- a/app/Entities/Tools/Markdown/MarkdownToHtml.php +++ b/app/Entities/Tools/Markdown/MarkdownToHtml.php @@ -4,8 +4,9 @@ namespace BookStack\Entities\Tools\Markdown; use BookStack\Facades\Theme; use BookStack\Theming\ThemeEvents; -use League\CommonMark\Block\Element\ListItem; -use League\CommonMark\Environment; +use League\CommonMark\Environment\Environment; +use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; +use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Extension\Table\TableExtension; use League\CommonMark\Extension\TaskList\TaskListExtension; use League\CommonMark\MarkdownConverter; @@ -21,15 +22,16 @@ class MarkdownToHtml public function convert(): string { - $environment = Environment::createCommonMarkEnvironment(); + $environment = new Environment(); + $environment->addExtension(new CommonMarkCoreExtension()); $environment->addExtension(new TableExtension()); $environment->addExtension(new TaskListExtension()); $environment->addExtension(new CustomStrikeThroughExtension()); $environment = Theme::dispatch(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, $environment) ?? $environment; $converter = new MarkdownConverter($environment); - $environment->addBlockRenderer(ListItem::class, new CustomListItemRenderer(), 10); + $environment->addRenderer(ListItem::class, new CustomListItemRenderer(), 10); - return $converter->convertToHtml($this->markdown); + return $converter->convert($this->markdown)->getContent(); } } diff --git a/app/Http/Request.php b/app/Http/Request.php index 4cbdf34ba..c2d430279 100644 --- a/app/Http/Request.php +++ b/app/Http/Request.php @@ -9,10 +9,8 @@ class Request extends LaravelRequest /** * Override the default request methods to get the scheme and host * to directly use the custom APP_URL, if set. - * - * @return string */ - public function getSchemeAndHttpHost() + public function getSchemeAndHttpHost(): string { $appUrl = config('app.url', null); @@ -27,10 +25,8 @@ class Request extends LaravelRequest * Override the default request methods to get the base URL * to directly use the custom APP_URL, if set. * The base URL never ends with a / but should start with one if not empty. - * - * @return string */ - public function getBaseUrl() + public function getBaseUrl(): string { $appUrl = config('app.url', null); diff --git a/app/Theming/ThemeEvents.php b/app/Theming/ThemeEvents.php index 0a8efaee4..91f4fcd67 100644 --- a/app/Theming/ThemeEvents.php +++ b/app/Theming/ThemeEvents.php @@ -65,8 +65,8 @@ class ThemeEvents * Provides the commonmark library environment for customization before it's used to render markdown content. * If the listener returns a non-null value, that will be used as an environment instead. * - * @param \League\CommonMark\ConfigurableEnvironmentInterface $environment - * @returns \League\CommonMark\ConfigurableEnvironmentInterface|null + * @param \League\CommonMark\Environment\Environment $environment + * @returns \League\CommonMark\Environment\Environment|null */ const COMMONMARK_ENVIRONMENT_CONFIGURE = 'commonmark_environment_configure'; diff --git a/app/Uploads/AttachmentService.php b/app/Uploads/AttachmentService.php index 88bb41efb..ddabec09f 100644 --- a/app/Uploads/AttachmentService.php +++ b/app/Uploads/AttachmentService.php @@ -9,7 +9,7 @@ use Illuminate\Contracts\Filesystem\Filesystem as Storage; use Illuminate\Filesystem\FilesystemManager; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; -use League\Flysystem\Util; +use League\Flysystem\WhitespacePathNormalizer; use Symfony\Component\HttpFoundation\File\UploadedFile; class AttachmentService @@ -54,7 +54,7 @@ class AttachmentService */ protected function adjustPathForStorageDisk(string $path): string { - $path = Util::normalizePath(str_replace('uploads/files/', '', $path)); + $path = (new WhitespacePathNormalizer())->normalizePath(str_replace('uploads/files/', '', $path)); if ($this->getStorageDiskName() === 'local_secure_attachments') { return $path; diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 55c327e7a..a217287fd 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -20,7 +20,7 @@ use Illuminate\Support\Str; use Intervention\Image\Exception\NotSupportedException; use Intervention\Image\Image as InterventionImage; use Intervention\Image\ImageManager; -use League\Flysystem\Util; +use League\Flysystem\WhitespacePathNormalizer; use Psr\SimpleCache\InvalidArgumentException; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\StreamedResponse; @@ -29,10 +29,9 @@ class ImageService { protected ImageManager $imageTool; protected Cache $cache; - protected $storageUrl; protected FilesystemManager $fileSystem; - protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; + protected static array $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; public function __construct(ImageManager $imageTool, FilesystemManager $fileSystem, Cache $cache) { @@ -73,7 +72,7 @@ class ImageService */ protected function adjustPathForStorageDisk(string $path, string $imageType = ''): string { - $path = Util::normalizePath(str_replace('uploads/images/', '', $path)); + $path = (new WhitespacePathNormalizer())->normalizePath(str_replace('uploads/images/', '', $path)); if ($this->usingSecureImages($imageType)) { return $path; @@ -661,25 +660,21 @@ class ImageService */ private function getPublicUrl(string $filePath): string { - if (is_null($this->storageUrl)) { - $storageUrl = config('filesystems.url'); + $storageUrl = config('filesystems.url'); - // Get the standard public s3 url if s3 is set as storage type - // Uses the nice, short URL if bucket name has no periods in otherwise the longer - // region-based url will be used to prevent http issues. - if ($storageUrl == false && config('filesystems.images') === 's3') { - $storageDetails = config('filesystems.disks.s3'); - if (strpos($storageDetails['bucket'], '.') === false) { - $storageUrl = 'https://' . $storageDetails['bucket'] . '.s3.amazonaws.com'; - } else { - $storageUrl = 'https://s3-' . $storageDetails['region'] . '.amazonaws.com/' . $storageDetails['bucket']; - } + // Get the standard public s3 url if s3 is set as storage type + // Uses the nice, short URL if bucket name has no periods in otherwise the longer + // region-based url will be used to prevent http issues. + if (!$storageUrl && config('filesystems.images') === 's3') { + $storageDetails = config('filesystems.disks.s3'); + if (strpos($storageDetails['bucket'], '.') === false) { + $storageUrl = 'https://' . $storageDetails['bucket'] . '.s3.amazonaws.com'; + } else { + $storageUrl = 'https://s3-' . $storageDetails['region'] . '.amazonaws.com/' . $storageDetails['bucket']; } - - $this->storageUrl = $storageUrl; } - $basePath = ($this->storageUrl == false) ? url('/') : $this->storageUrl; + $basePath = $storageUrl ?: url('/'); return rtrim($basePath, '/') . $filePath; } diff --git a/app/Util/LanguageManager.php b/app/Util/LanguageManager.php index ed68f647c..0cbf3f397 100644 --- a/app/Util/LanguageManager.php +++ b/app/Util/LanguageManager.php @@ -130,7 +130,7 @@ class LanguageManager ]); if (!empty($locales)) { - setlocale(LC_TIME, ...$locales); + setlocale(LC_TIME, $locales[0], ...array_slice($locales, 1)); } } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index ff184f7cd..936d5a91a 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -9,7 +9,7 @@ parameters: # The level 8 is the highest level level: 1 - phpVersion: 70400 + phpVersion: 80002 bootstrapFiles: - bootstrap/phpstan.php