Done a round of phpstan fixes

This commit is contained in:
Dan Brown 2021-11-06 00:32:01 +00:00
parent 5c6a6b50a0
commit 8d7c8ac8bf
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
24 changed files with 72 additions and 84 deletions

View File

@ -90,8 +90,9 @@ class CommentRepo
*/
protected function getNextLocalId(Entity $entity): int
{
$comments = $entity->comments(false)->orderBy('local_id', 'desc')->first();
/** @var Comment $comment */
$comment = $entity->comments(false)->orderBy('local_id', 'desc')->first();
return ($comments->local_id ?? 0) + 1;
return ($comment->local_id ?? 0) + 1;
}
}

View File

@ -94,7 +94,7 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
}
// Attach avatar if non-existent
if (is_null($user->avatar)) {
if (!$user->avatar()->exists()) {
$this->ldapService->saveAndAttachAvatar($user, $userDetails);
}

View File

@ -10,14 +10,10 @@ namespace BookStack\Auth\Access;
class Ldap
{
/**
* Connect to a LDAP server.
*
* @param string $hostName
* @param int $port
*
* Connect to an LDAP server.
* @return resource
*/
public function connect($hostName, $port)
public function connect(string $hostName, int $port)
{
return ldap_connect($hostName, $port);
}
@ -26,12 +22,9 @@ class Ldap
* Set the value of a LDAP option for the given connection.
*
* @param resource $ldapConnection
* @param int $option
* @param mixed $value
*
* @return bool
*/
public function setOption($ldapConnection, $option, $value)
public function setOption($ldapConnection, int $option, $value): bool
{
return ldap_set_option($ldapConnection, $option, $value);
}
@ -47,12 +40,9 @@ class Ldap
/**
* Set the version number for the given ldap connection.
*
* @param $ldapConnection
* @param $version
*
* @return bool
* @param resource $ldapConnection
*/
public function setVersion($ldapConnection, $version)
public function setVersion($ldapConnection, int $version): bool
{
return $this->setOption($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, $version);
}

View File

@ -49,9 +49,10 @@ class ResetMfa extends Command
return 1;
}
/** @var User $user */
$field = $id ? 'id' : 'email';
$value = $id ?: $email;
/** @var User $user */
$user = User::query()
->where($field, '=', $value)
->first();

View File

@ -3,13 +3,14 @@
namespace BookStack\Entities\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
/**
* Class Chapter.
*
* @property Collection<Page> $pages
* @property mixed description
* @property string $description
*/
class Chapter extends BookChild
{
@ -22,12 +23,8 @@ class Chapter extends BookChild
/**
* Get the pages that this chapter contains.
*
* @param string $dir
*
* @return mixed
*/
public function pages($dir = 'ASC')
public function pages(string $dir = 'ASC'): HasMany
{
return $this->hasMany(Page::class)->orderBy('priority', $dir);
}
@ -35,7 +32,7 @@ class Chapter extends BookChild
/**
* Get the url of this chapter.
*/
public function getUrl($path = ''): string
public function getUrl(string $path = ''): string
{
$parts = [
'books',

View File

@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
* @property Model deletable
* @property Model $deletable
*/
class Deletion extends Model implements Loggable
{
@ -22,7 +22,7 @@ class Deletion extends Model implements Loggable
}
/**
* The the user that performed the deletion.
* Get the user that performed the deletion.
*/
public function deleter(): BelongsTo
{
@ -48,7 +48,11 @@ class Deletion extends Model implements Loggable
{
$deletable = $this->deletable()->first();
return "Deletion ({$this->id}) for {$deletable->getType()} ({$deletable->id}) {$deletable->name}";
if ($deletable instanceof Entity) {
return "Deletion ({$this->id}) for {$deletable->getType()} ({$deletable->id}) {$deletable->name}";
}
return "Deletion ({$this->id})";
}
/**

View File

@ -106,7 +106,7 @@ class Page extends BookChild
/**
* Get the url of this page.
*/
public function getUrl($path = ''): string
public function getUrl(string $path = ''): string
{
$parts = [
'books',

View File

@ -22,6 +22,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @property string $html
* @property int $revision_number
* @property Page $page
*
* @property-read ?User $createdBy
*/
class PageRevision extends Model
{

View File

@ -35,7 +35,13 @@ class PageEditActivity
$pageDraftEdits = $this->activePageEditingQuery(60)->get();
$count = $pageDraftEdits->count();
$userMessage = $count > 1 ? trans('entities.pages_draft_edit_active.start_a', ['count' => $count]) : trans('entities.pages_draft_edit_active.start_b', ['userName' => $pageDraftEdits->first()->createdBy->name]);
$userMessage = trans('entities.pages_draft_edit_active.start_a', ['count' => $count]);
if ($count === 1) {
/** @var PageRevision $firstDraft */
$firstDraft = $pageDraftEdits->first();
$userMessage = trans('entities.pages_draft_edit_active.start_b', ['userName' => $firstDraft->createdBy->name ?? '']);
}
$timeMessage = trans('entities.pages_draft_edit_active.time_b', ['minCount'=> 60]);
return trans('entities.pages_draft_edit_active.message', ['start' => $userMessage, 'time' => $timeMessage]);

View File

@ -47,7 +47,7 @@ class SearchRunner
/**
* Search all entities in the system.
* The provided count is for each entity to search,
* Total returned could can be larger and not guaranteed.
* Total returned could be larger and not guaranteed.
*/
public function searchEntities(SearchOptions $searchOpts, string $entityType = 'all', int $page = 1, int $count = 20, string $action = 'view'): array
{
@ -68,11 +68,15 @@ class SearchRunner
if (!in_array($entityType, $entityTypes)) {
continue;
}
$search = $this->searchEntityTable($searchOpts, $entityType, $page, $count, $action);
/** @var int $entityTotal */
$entityTotal = $this->searchEntityTable($searchOpts, $entityType, $page, $count, $action, true);
if ($entityTotal > $page * $count) {
if ($entityTotal > ($page * $count)) {
$hasMore = true;
}
$total += $entityTotal;
$results = $results->merge($search);
}

View File

@ -5,6 +5,7 @@ namespace BookStack\Entities\Tools;
use BookStack\Entities\EntityProvider;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Page;
use Illuminate\Support\Collection;
class SiblingFetcher
@ -18,18 +19,18 @@ class SiblingFetcher
$entities = [];
// Page in chapter
if ($entity->isA('page') && $entity->chapter) {
if ($entity instanceof Page && $entity->chapter) {
$entities = $entity->chapter->getVisiblePages();
}
// Page in book or chapter
if (($entity->isA('page') && !$entity->chapter) || $entity->isA('chapter')) {
if (($entity instanceof Page && !$entity->chapter) || $entity->isA('chapter')) {
$entities = $entity->book->getDirectChildren();
}
// Book
// Gets just the books in a shelf if shelf is in context
if ($entity->isA('book')) {
if ($entity instanceof Book) {
$contextShelf = (new ShelfContext())->getContextualShelfForBook($entity);
if ($contextShelf) {
$entities = $contextShelf->visibleBooks()->get();
@ -38,8 +39,8 @@ class SiblingFetcher
}
}
// Shelve
if ($entity->isA('bookshelf')) {
// Shelf
if ($entity instanceof Bookshelf) {
$entities = Bookshelf::visible()->get();
}

View File

@ -4,13 +4,14 @@ namespace BookStack\Entities\Tools;
use BookStack\Entities\Models\BookChild;
use BookStack\Interfaces\Sluggable;
use BookStack\Model;
use Illuminate\Support\Str;
class SlugGenerator
{
/**
* Generate a fresh slug for the given entity.
* The slug will generated so it does not conflict within the same parent item.
* The slug will be generated so that it doesn't conflict within the same parent item.
*/
public function generate(Sluggable $model): string
{
@ -38,6 +39,7 @@ class SlugGenerator
/**
* Check if a slug is already in-use for this
* type of model within the same parent.
* @param Sluggable&Model $model
*/
protected function slugInUse(string $slug, Sluggable $model): bool
{

View File

@ -10,10 +10,7 @@ use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
class ConfirmEmailController extends Controller
{
@ -57,33 +54,23 @@ class ConfirmEmailController extends Controller
/**
* Confirms an email via a token and logs the user into the system.
*
* @param $token
*
* @throws ConfirmationEmailException
* @throws Exception
*
* @return RedirectResponse|Redirector
*/
public function confirm($token)
public function confirm(string $token)
{
try {
$userId = $this->emailConfirmationService->checkTokenAndGetUserId($token);
} catch (Exception $exception) {
if ($exception instanceof UserTokenNotFoundException) {
$this->showErrorNotification(trans('errors.email_confirmation_invalid'));
} catch (UserTokenNotFoundException $exception) {
$this->showErrorNotification(trans('errors.email_confirmation_invalid'));
return redirect('/register');
}
return redirect('/register');
} catch (UserTokenExpiredException $exception) {
$user = $this->userRepo->getById($exception->userId);
$this->emailConfirmationService->sendConfirmation($user);
$this->showErrorNotification(trans('errors.email_confirmation_expired'));
if ($exception instanceof UserTokenExpiredException) {
$user = $this->userRepo->getById($exception->userId);
$this->emailConfirmationService->sendConfirmation($user);
$this->showErrorNotification(trans('errors.email_confirmation_expired'));
return redirect('/register/confirm');
}
throw $exception;
return redirect('/register/confirm');
}
$user = $this->userRepo->getById($userId);
@ -99,10 +86,6 @@ class ConfirmEmailController extends Controller
/**
* Resend the confirmation email.
*
* @param Request $request
*
* @return View
*/
public function resend(Request $request)
{

View File

@ -165,7 +165,7 @@ abstract class Controller extends BaseController
/**
* Log an activity in the system.
*
* @param string|Loggable
* @param $detail string|Loggable
*/
protected function logActivity(string $type, $detail = ''): void
{

View File

@ -66,7 +66,7 @@ class FavouriteController extends Controller
* @throws \Illuminate\Validation\ValidationException
* @throws \Exception
*/
protected function getValidatedModelFromRequest(Request $request): Favouritable
protected function getValidatedModelFromRequest(Request $request): Entity
{
$modelInfo = $this->validate($request, [
'type' => ['required', 'string'],

View File

@ -12,7 +12,7 @@ class CheckUserHasPermission
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param $permission
* @param string $permission
*
* @return mixed
*/

View File

@ -2,18 +2,12 @@
namespace BookStack\Interfaces;
use Illuminate\Database\Eloquent\Builder;
/**
* Interface Sluggable.
*
* Assigned to models that can have slugs.
* Must have the below properties.
*
* @property int $id
* @property string $name
*
* @method Builder newQuery
*/
interface Sluggable
{

View File

@ -9,12 +9,9 @@ class Model extends EloquentModel
/**
* Provides public access to get the raw attribute value from the model.
* Used in areas where no mutations are required but performance is critical.
*
* @param $key
*
* @return mixed
*/
public function getRawAttribute($key)
public function getRawAttribute(string $key)
{
return parent::getAttributeFromArray($key);
}

View File

@ -6,8 +6,8 @@ use BookStack\Auth\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int created_by
* @property int updated_by
* @property int $created_by
* @property int $updated_by
*/
trait HasCreatorAndUpdater
{

View File

@ -6,7 +6,7 @@ use BookStack\Auth\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int owned_by
* @property int $owned_by
*/
trait HasOwner
{

View File

@ -236,7 +236,7 @@ class ImageRepo
->get(['id', 'name', 'slug', 'book_id']);
foreach ($pages as $page) {
$page->url = $page->getUrl();
$page->setAttribute('url', $page->getUrl());
}
return $pages->all();

View File

@ -8,6 +8,7 @@ use Exception;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Contracts\Filesystem\Filesystem as Storage;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Filesystem\FilesystemManager;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
@ -436,10 +437,12 @@ class ImageService
*/
public function pathExistsInLocalSecure(string $imagePath): bool
{
/** @var FilesystemAdapter $disk */
$disk = $this->getStorageDisk('gallery');
// Check local_secure is active
return $this->usingSecureImages()
&& $disk instanceof FilesystemAdapter
// Check the image file exists
&& $disk->exists($imagePath)
// Check the file is likely an image file

View File

@ -4,6 +4,7 @@ namespace BookStack\Util;
use DOMAttr;
use DOMDocument;
use DOMElement;
use DOMNodeList;
use DOMXPath;
@ -92,7 +93,9 @@ class HtmlContentFilter
/** @var DOMAttr $attr */
foreach ($attrs as $attr) {
$attrName = $attr->nodeName;
$attr->parentNode->removeAttribute($attrName);
/** @var DOMElement $parentNode */
$parentNode = $attr->parentNode;
$parentNode->removeAttribute($attrName);
}
}
}

View File

@ -15,7 +15,7 @@ parameters:
- bootstrap/phpstan.php
ignoreErrors:
# - '#Unsafe usage of new static#'
# - '#PHPDoc tag @throws with type .*?Psr\\SimpleCache\\InvalidArgumentException.*? is not subtype of Throwable#'
excludePaths:
- ./Config/**/*.php