Fixed static analysis issues

This commit is contained in:
Dan Brown 2023-02-06 20:00:44 +00:00
parent 008e7a4d25
commit 9ca088a4e2
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
10 changed files with 52 additions and 61 deletions

View File

@ -2,18 +2,18 @@
namespace BookStack\Entities\Tools\Markdown; namespace BookStack\Entities\Tools\Markdown;
use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem;
use League\CommonMark\Block\Element\ListItem; use League\CommonMark\Extension\CommonMark\Renderer\Block\ListItemRenderer;
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\TaskList\TaskListItemMarker; 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() public function __construct()
{ {
@ -23,11 +23,11 @@ class CustomListItemRenderer implements BlockRendererInterface
/** /**
* @return HtmlElement|string|null * @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'); $listItem->setAttribute('class', 'task-list-item');
} }

View File

@ -2,16 +2,16 @@
namespace BookStack\Entities\Tools\Markdown; namespace BookStack\Entities\Tools\Markdown;
use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Extension\ExtensionInterface;
use League\CommonMark\Extension\Strikethrough\Strikethrough; use League\CommonMark\Extension\Strikethrough\Strikethrough;
use League\CommonMark\Extension\Strikethrough\StrikethroughDelimiterProcessor; use League\CommonMark\Extension\Strikethrough\StrikethroughDelimiterProcessor;
class CustomStrikeThroughExtension implements ExtensionInterface class CustomStrikeThroughExtension implements ExtensionInterface
{ {
public function register(ConfigurableEnvironmentInterface $environment) public function register(EnvironmentBuilderInterface $environment): void
{ {
$environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor()); $environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor());
$environment->addInlineRenderer(Strikethrough::class, new CustomStrikethroughRenderer()); $environment->addRenderer(Strikethrough::class, new CustomStrikethroughRenderer());
} }
} }

View File

@ -2,25 +2,23 @@
namespace BookStack\Entities\Tools\Markdown; namespace BookStack\Entities\Tools\Markdown;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\Extension\Strikethrough\Strikethrough; use League\CommonMark\Extension\Strikethrough\Strikethrough;
use League\CommonMark\HtmlElement; use League\CommonMark\Node\Node;
use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Inline\Renderer\InlineRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
/** /**
* This is a somewhat clone of the League\CommonMark\Extension\Strikethrough\StrikethroughRender * This is a somewhat clone of the League\CommonMark\Extension\Strikethrough\StrikethroughRender
* class but modified slightly to use <s> HTML tags instead of <del> in order to * class but modified slightly to use <s> HTML tags instead of <del> in order to
* match front-end markdown-it rendering. * 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)) { Strikethrough::assertInstanceOf($node);
throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
}
return new HtmlElement('s', $inline->getData('attributes', []), $htmlRenderer->renderInlines($inline->children())); return new HtmlElement('s', $node->data->get('attributes'), $childRenderer->renderNodes($node->children()));
} }
} }

View File

@ -4,8 +4,9 @@ namespace BookStack\Entities\Tools\Markdown;
use BookStack\Facades\Theme; use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use League\CommonMark\Block\Element\ListItem; use League\CommonMark\Environment\Environment;
use League\CommonMark\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\Table\TableExtension;
use League\CommonMark\Extension\TaskList\TaskListExtension; use League\CommonMark\Extension\TaskList\TaskListExtension;
use League\CommonMark\MarkdownConverter; use League\CommonMark\MarkdownConverter;
@ -21,15 +22,16 @@ class MarkdownToHtml
public function convert(): string public function convert(): string
{ {
$environment = Environment::createCommonMarkEnvironment(); $environment = new Environment();
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new TableExtension()); $environment->addExtension(new TableExtension());
$environment->addExtension(new TaskListExtension()); $environment->addExtension(new TaskListExtension());
$environment->addExtension(new CustomStrikeThroughExtension()); $environment->addExtension(new CustomStrikeThroughExtension());
$environment = Theme::dispatch(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, $environment) ?? $environment; $environment = Theme::dispatch(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, $environment) ?? $environment;
$converter = new MarkdownConverter($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();
} }
} }

View File

@ -9,10 +9,8 @@ class Request extends LaravelRequest
/** /**
* Override the default request methods to get the scheme and host * Override the default request methods to get the scheme and host
* to directly use the custom APP_URL, if set. * to directly use the custom APP_URL, if set.
*
* @return string
*/ */
public function getSchemeAndHttpHost() public function getSchemeAndHttpHost(): string
{ {
$appUrl = config('app.url', null); $appUrl = config('app.url', null);
@ -27,10 +25,8 @@ class Request extends LaravelRequest
* Override the default request methods to get the base URL * Override the default request methods to get the base URL
* to directly use the custom APP_URL, if set. * to directly use the custom APP_URL, if set.
* The base URL never ends with a / but should start with one if not empty. * 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); $appUrl = config('app.url', null);

View File

@ -65,8 +65,8 @@ class ThemeEvents
* Provides the commonmark library environment for customization before it's used to render markdown content. * 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. * If the listener returns a non-null value, that will be used as an environment instead.
* *
* @param \League\CommonMark\ConfigurableEnvironmentInterface $environment * @param \League\CommonMark\Environment\Environment $environment
* @returns \League\CommonMark\ConfigurableEnvironmentInterface|null * @returns \League\CommonMark\Environment\Environment|null
*/ */
const COMMONMARK_ENVIRONMENT_CONFIGURE = 'commonmark_environment_configure'; const COMMONMARK_ENVIRONMENT_CONFIGURE = 'commonmark_environment_configure';

View File

@ -9,7 +9,7 @@ use Illuminate\Contracts\Filesystem\Filesystem as Storage;
use Illuminate\Filesystem\FilesystemManager; use Illuminate\Filesystem\FilesystemManager;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use League\Flysystem\Util; use League\Flysystem\WhitespacePathNormalizer;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
class AttachmentService class AttachmentService
@ -54,7 +54,7 @@ class AttachmentService
*/ */
protected function adjustPathForStorageDisk(string $path): string 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') { if ($this->getStorageDiskName() === 'local_secure_attachments') {
return $path; return $path;

View File

@ -20,7 +20,7 @@ use Illuminate\Support\Str;
use Intervention\Image\Exception\NotSupportedException; use Intervention\Image\Exception\NotSupportedException;
use Intervention\Image\Image as InterventionImage; use Intervention\Image\Image as InterventionImage;
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
use League\Flysystem\Util; use League\Flysystem\WhitespacePathNormalizer;
use Psr\SimpleCache\InvalidArgumentException; use Psr\SimpleCache\InvalidArgumentException;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\StreamedResponse;
@ -29,10 +29,9 @@ class ImageService
{ {
protected ImageManager $imageTool; protected ImageManager $imageTool;
protected Cache $cache; protected Cache $cache;
protected $storageUrl;
protected FilesystemManager $fileSystem; 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) public function __construct(ImageManager $imageTool, FilesystemManager $fileSystem, Cache $cache)
{ {
@ -73,7 +72,7 @@ class ImageService
*/ */
protected function adjustPathForStorageDisk(string $path, string $imageType = ''): string 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)) { if ($this->usingSecureImages($imageType)) {
return $path; return $path;
@ -661,13 +660,12 @@ class ImageService
*/ */
private function getPublicUrl(string $filePath): string 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 // 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 // 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. // region-based url will be used to prevent http issues.
if ($storageUrl == false && config('filesystems.images') === 's3') { if (!$storageUrl && config('filesystems.images') === 's3') {
$storageDetails = config('filesystems.disks.s3'); $storageDetails = config('filesystems.disks.s3');
if (strpos($storageDetails['bucket'], '.') === false) { if (strpos($storageDetails['bucket'], '.') === false) {
$storageUrl = 'https://' . $storageDetails['bucket'] . '.s3.amazonaws.com'; $storageUrl = 'https://' . $storageDetails['bucket'] . '.s3.amazonaws.com';
@ -676,10 +674,7 @@ class ImageService
} }
} }
$this->storageUrl = $storageUrl; $basePath = $storageUrl ?: url('/');
}
$basePath = ($this->storageUrl == false) ? url('/') : $this->storageUrl;
return rtrim($basePath, '/') . $filePath; return rtrim($basePath, '/') . $filePath;
} }

View File

@ -130,7 +130,7 @@ class LanguageManager
]); ]);
if (!empty($locales)) { if (!empty($locales)) {
setlocale(LC_TIME, ...$locales); setlocale(LC_TIME, $locales[0], ...array_slice($locales, 1));
} }
} }
} }

View File

@ -9,7 +9,7 @@ parameters:
# The level 8 is the highest level # The level 8 is the highest level
level: 1 level: 1
phpVersion: 70400 phpVersion: 80002
bootstrapFiles: bootstrapFiles:
- bootstrap/phpstan.php - bootstrap/phpstan.php